Using the Plugin Dev Environment
The HollaEx Kit provides a way for developers to easily develop and run plugin scripts. This can be done using the dev.js file in the plugins directory.
1
2
/**
3
* Add your mock publicMeta and meta values in the object below
4
* In production, these values are stored in the configuration JSON file
5
6
* Example mock configurations are included below
7
**/
8
9
this.configValues = {
10
// // ------------ CONFIG VALUES EXAMPLE START ------------
11
12
// publicMeta: {
13
// public_value: {
14
// type: 'string',
15
// description: 'Public meta value',
16
// required: false,
17
// value: 'i am public'
18
// }
19
// },
20
// meta: {
21
// private_value: {
22
// type: 'string',
23
// description: 'Private meta value',
24
// required: true,
25
// value: 'i am private'
26
// }
27
// }
28
29
// // ------------ CONFIG VALUES EXAMPLE END ------------
30
};
31
32
const pluginScript = () => {
33
/**
34
* Add the plugin script here
35
* The script within this function should be in the script.js file for a plugin
36
37
* An example of a plugin script is included below
38
**/
39
40
// // ------------ PLUGIN EXAMPLE START ------------
41
42
// const { app, loggerPlugin, toolsLib } = this.pluginLibraries; // this.pluginLibraries holds app, loggerPlugin, and toolsLib in the plugin script
43
// const { publicMeta, meta } = this.configValues; // this.configValues holds publicMeta and meta in the plugin script
44
45
// const lodash = require('lodash');
46
// const moment = require('moment');
47
// const { public_value: { value: PUBLIC_VALUE } } = publicMeta;
48
// const { private_value: { value: PRIVATE_VALUE } } = meta;
49
50
// // All endpoints for a plugin should follow the format: '/plugins/<PLUGIN_NAME>/...'. For this example, the plugin name is 'test'
51
// const HEALTH_ENDPOINT = '/plugins/test/health';
52
// const CONFIG_VALUES_ENDPOINT = '/plugins/test/config-values';
53
54
// // We recommend creating an init function that checks for all required configuration values and all other requirements for this plugin to run
55
// const init = async () => {
56
// loggerPlugin.verbose(
57
// 'DEV PLUGIN initializing...'
58
// );
59
60
// if (!lodash.isString(PRIVATE_VALUE)) {
61
// throw new Error('Private Value must be configured for this plugin to run');
62
// }
63
64
// loggerPlugin.verbose(
65
// 'DEV PLUGIN initialized'
66
// );
67
// };
68
69
// init()
70
// .then(() => {
71
// app.get(HEALTH_ENDPOINT, async (req, res) => {
72
// loggerPlugin.info(
73
// req.uuid,
74
// HEALTH_ENDPOINT
75
// );
76
77
// return res.json({
78
// status: 'running',
79
// current_time: moment().toISOString(),
80
// exchange_name: toolsLib.getKitConfig().info.name
81
// });
82
// });
83
84
// app.get(CONFIG_VALUES_ENDPOINT, async (req, res) => {
85
// loggerPlugin.info(
86
// req.uuid,
87
// CONFIG_VALUES_ENDPOINT
88
// );
89
90
// return res.json({
91
// public_value: PUBLIC_VALUE,
92
// private_value: PRIVATE_VALUE
93
// });
94
// });
95
// })
96
// .catch((err) => {
97
// // It's important to catch all errors in a script. If a thrown error is not caught, the plugin process will exit and continuously try to restart
98
// loggerPlugin.error(
99
// 'DEV PLUGIN initialization error',
100
// err.message
101
// );
102
// });
103
104
// // ------------ PLUGIN EXAMPLE END ------------
105
};
106
107
108
109
110
111
112
113
114
// BELOW IS THE SCRIPT FOR RUNNING THE PLUGIN DEV ENVIRONMENT THAT IS NOT NECESSARY IN THE PLUGIN ITSELF
115
116
const { checkStatus } = require('../init');
117
118
const initializeDevPlugin = async () => {
119
await checkStatus();
120
121
const morgan = require('morgan');
122
const { logEntryRequest, stream, loggerPlugin } = require('../config/logger');
123
const { domainMiddleware, helmetMiddleware } = require('../config/middleware');
124
const morganType = process.env.NODE_ENV === 'development' ? 'dev' : 'combined';
125
const PORT = 10012;
126
const cors = require('cors');
127
const toolsLib = require('../utils/toolsLib');
128
const express = require('express');
129
130
const app = express();
131
app.use(morgan(morganType, { stream }));
132
app.listen(PORT);
133
app.use(cors());
134
app.use(express.urlencoded({ extended: true }));
135
app.use(express.json());
136
app.use(logEntryRequest);
137
app.use(domainMiddleware);
138
helmetMiddleware(app);
139
140
const pluginLibraries = {
141
app,
142
loggerPlugin,
143
toolsLib
144
};
145
146
this.pluginLibraries = pluginLibraries;
147
};
148
149
(async () => {
150
await initializeDevPlugin();
151
pluginScript();
152
})();
Copied!

Breakdown

Config Values

1
2
/**
3
* Add your mock publicMeta and meta values in the object below
4
* In production, these values are stored in the configuration JSON file
5
6
* Example mock configurations are included below
7
**/
8
9
this.configValues = {
10
// // ------------ CONFIG VALUES EXAMPLE START ------------
11
12
// publicMeta: {
13
// public_value: {
14
// type: 'string',
15
// description: 'Public meta value',
16
// required: false,
17
// value: 'i am public'
18
// }
19
// },
20
// meta: {
21
// private_value: {
22
// type: 'string',
23
// description: 'Private meta value',
24
// required: true,
25
// value: 'i am private'
26
// }
27
// }
28
29
// // ------------ CONFIG VALUES EXAMPLE END ------------
30
};
Copied!
The object this.configValues should hold the public_meta and meta configuration values that would normally be in your plugin's config file. We are creating this.configValues in memory here to replicate the expected plugin config values.

Plugin Script

1
const pluginScript = () => {
2
/**
3
* Add the plugin script here
4
* The script within this function should be in the script.js file for a plugin
5
6
* An example of a plugin script is included below
7
**/
8
9
// // ------------ PLUGIN EXAMPLE START ------------
10
11
// const { app, loggerPlugin, toolsLib } = this.pluginLibraries; // this.pluginLibraries holds app, loggerPlugin, and toolsLib in the plugin script
12
// const { publicMeta, meta } = this.configValues; // this.configValues holds publicMeta and meta in the plugin script
13
14
// const lodash = require('lodash');
15
// const moment = require('moment');
16
// const { public_value: { value: PUBLIC_VALUE } } = publicMeta;
17
// const { private_value: { value: PRIVATE_VALUE } } = meta;
18
19
// // All endpoints for a plugin should follow the format: '/plugins/<PLUGIN_NAME>/...'. For this example, the plugin name is 'test'
20
// const HEALTH_ENDPOINT = '/plugins/test/health';
21
// const CONFIG_VALUES_ENDPOINT = '/plugins/test/config-values';
22
23
// // We recommend creating an init function that checks for all required configuration values and all other requirements for this plugin to run
24
// const init = async () => {
25
// loggerPlugin.verbose(
26
// 'DEV PLUGIN initializing...'
27
// );
28
29
// if (!lodash.isString(PRIVATE_VALUE)) {
30
// throw new Error('Private Value must be configured for this plugin to run');
31
// }
32
33
// loggerPlugin.verbose(
34
// 'DEV PLUGIN initialized'
35
// );
36
// };
37
38
// init()
39
// .then(() => {
40
// app.get(HEALTH_ENDPOINT, async (req, res) => {
41
// loggerPlugin.info(
42
// req.uuid,
43
// HEALTH_ENDPOINT
44
// );
45
46
// return res.json({
47
// status: 'running',
48
// current_time: moment().toISOString(),
49
// exchange_name: toolsLib.getKitConfig().info.name
50
// });
51
// });
52
53
// app.get(CONFIG_VALUES_ENDPOINT, async (req, res) => {
54
// loggerPlugin.info(
55
// req.uuid,
56
// CONFIG_VALUES_ENDPOINT
57
// );
58
59
// return res.json({
60
// public_value: PUBLIC_VALUE,
61
// private_value: PRIVATE_VALUE
62
// });
63
// });
64
// })
65
// .catch((err) => {
66
// // It's important to catch all errors in a script. If a thrown error is not caught, the plugin process will exit and continuously try to restart
67
// loggerPlugin.error(
68
// 'DEV PLUGIN initialization error',
69
// err.message
70
// );
71
// });
72
73
// // ------------ PLUGIN EXAMPLE END ------------
74
};
Copied!
In the pluginScript function, you can put the actual script that will run for the plugin. This function will have access to all the libraries and default objects (pluginLibraries, configValues, etc) that would be available in a production plugin. Add your plugin's script here to run it in your local environment.

Running the plugin

To run the plugin, you can simply go into the server docker container and run node plugins/dev.js. This will execute the file and run the script you have in the pluginScript function. The file will be accessible via the 10012 port e.g. localhost:10012/plugins/....
To test this out, undo the commented code for this.configValues and pluginScript and then run the dev.js file.