hola-server 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/core/bash.js ADDED
@@ -0,0 +1,283 @@
1
+ const { exec } = require("child_process");
2
+ const { is_log_debug, is_log_error, log_debug, log_error } = require('../db/db');
3
+
4
+ const LOG_BASH = "bash";
5
+
6
+ /**
7
+ * Run script and get stdout
8
+ * @param {host info,contains user,ip and password} host
9
+ * @param {commands to run} script
10
+ * @returns
11
+ */
12
+ const run_script = async (host, script) => {
13
+ return new Promise((resolve) => {
14
+ exec(`sshpass -p '${host.pwd}' ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p ${host.port} ${host.user}@${host.ip} /bin/bash <<'EOT' \n ${script} \nEOT\n`, { maxBuffer: 1024 * 150000 }, (error, stdout) => {
15
+ if (error) {
16
+ if (is_log_error()) {
17
+ log_error(LOG_BASH, "error running on host:" + host.name + " the script:" + script + ",error:" + error);
18
+ }
19
+ resolve({ err: "error running the script:" + script + ",error:" + error });
20
+ } else {
21
+ if (is_log_debug()) {
22
+ log_debug(LOG_BASH, "executing on host:" + host.name + ", script:" + script + ",stdout:" + stdout);
23
+ }
24
+ resolve({ stdout: stdout });
25
+ }
26
+ });
27
+ });
28
+ };
29
+
30
+ const run_script_file = async (host, script_file) => {
31
+ return new Promise((resolve) => {
32
+ exec(`sshpass -p '${host.pwd}' ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p ${host.port} ${host.user}@${host.ip} /bin/bash < ${script_file}`, (error, stdout) => {
33
+ if (error) {
34
+ if (is_log_error()) {
35
+ log_error(LOG_BASH, "error running on host:" + host.name + " the script_file:" + script_file + ",error:" + error);
36
+ }
37
+ resolve({ err: "error running the script:" + script_file + ",error:" + error });
38
+ } else {
39
+ if (is_log_debug()) {
40
+ log_debug(LOG_BASH, "executing on host:" + host.name + ", script_file:" + script_file + ",stdout:" + stdout);
41
+ }
42
+ resolve({ stdout: stdout });
43
+ }
44
+ });
45
+ });
46
+ };
47
+
48
+ /**
49
+ * Run command in local host
50
+ * @param {command to execute} cmd
51
+ * @returns
52
+ */
53
+ const run_local_cmd = async (cmd, log_extra) => {
54
+ return new Promise((resolve) => {
55
+ exec(cmd, { maxBuffer: 1024 * 15000000 }, (error, stdout) => {
56
+ if (error) {
57
+ if (is_log_error()) {
58
+ log_error(LOG_BASH, "error running on local host with cmd:" + cmd + ",error:" + error, log_extra);
59
+ }
60
+ resolve({ err: "error running the cmd:" + cmd + ",error:" + error }, log_extra);
61
+ } else {
62
+ if (is_log_debug()) {
63
+ log_debug(LOG_BASH, "executing on local host with cmd:" + cmd + ",stdout:" + stdout, log_extra);
64
+ }
65
+ resolve({ stdout: stdout });
66
+ }
67
+ });
68
+ });
69
+ };
70
+
71
+ /**
72
+ * Scp remote file to local file
73
+ * @param {remote host} host
74
+ * @param {remote file path} remote_file
75
+ * @param {local file path} locale_file
76
+ * @returns
77
+ */
78
+ const scp = async (host, remote_file, local_file) => {
79
+ return new Promise((resolve) => {
80
+ exec(`sshpass -p '${host.pwd}' scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P ${host.port} -q ${host.user}@${host.ip}:${remote_file} ${local_file}`, (error, stdout) => {
81
+ if (error) {
82
+ if (is_log_error()) {
83
+ log_error(LOG_BASH, "error scp on host:" + host.name + " remote:" + remote_file + ",local:" + local_file + ",error:" + error);
84
+ }
85
+ resolve({ err: "error scp:" + remote_file + " to locale:" + local_file + ",err:" + error });
86
+ } else {
87
+ if (is_log_debug()) {
88
+ log_debug(LOG_BASH, "executing scp on host:" + host.name + ", remote:" + remote_file + ",local:" + local_file + ",stdout:" + stdout);
89
+ }
90
+ resolve({ stdout: stdout });
91
+ }
92
+ });
93
+ });
94
+ };
95
+
96
+ /**
97
+ *Just run simple command and get result directly
98
+ * @param {host info,contains user,ip and password} host
99
+ * @param {command to run} cmd
100
+ * @returns
101
+ */
102
+ const run_simple_cmd = async (host, cmd) => {
103
+ const { err, stdout } = await run_script(host, cmd);
104
+ if (err) {
105
+ return null;
106
+ } else {
107
+ return stdout.trim();
108
+ }
109
+ }
110
+
111
+ /**
112
+ *Just run simple command and get result directly
113
+ * @param {command to run} cmd
114
+ * @returns
115
+ */
116
+ const run_simple_local_cmd = async (cmd) => {
117
+ const { err, stdout } = await run_local_cmd(cmd);
118
+ if (err) {
119
+ return null;
120
+ } else {
121
+ return stdout.trim();
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Use regular expression to match the pattern to get some part of value
127
+ Speed: Unknown
128
+ Manufacturer: NO DIMM
129
+ Serial Number: NO DIMM
130
+ Asset Tag:
131
+ Part Number: NO DIMM
132
+ Rank: Unknown
133
+ Configured Memory Speed: Unknown
134
+ Minimum Voltage: 1.2 V
135
+ Maximum Voltage: 1.2 V
136
+ Configured Voltage: 1.2 V
137
+
138
+ * @param {stdout of the run_cmd} stdout
139
+ * @param {key to retrieve info} key
140
+ * @returns
141
+ */
142
+ const get_info = (stdout, key) => {
143
+ const word_key = key.split(" ").join("\\s+");
144
+ const regex = new RegExp(`\n\\s?${word_key}\\s?:(.*)\\s`, 'g');
145
+ if (is_log_debug()) {
146
+ log_debug(LOG_BASH, "get_info and regex:" + JSON.stringify(regex));
147
+ }
148
+
149
+ const results = stdout.matchAll(regex);
150
+
151
+ const matched = [];
152
+ for (let result of results) {
153
+ matched.push(result[1].trim());
154
+ }
155
+
156
+ if (is_log_debug()) {
157
+ log_debug(LOG_BASH, "get_info and matched:" + JSON.stringify(matched));
158
+ }
159
+ return matched;
160
+ }
161
+
162
+ /**
163
+ * Get the lines of array
164
+ * @param {array of lines} array
165
+ * @param {array of line number to get,use range to define the lines} lines
166
+ * @returns
167
+ */
168
+ const get_lines = (array, lines) => {
169
+ const result = [];
170
+ lines.forEach(line => {
171
+ result.push(array[line]);
172
+ });
173
+ return result;
174
+ }
175
+
176
+ /**
177
+ * Read all the lines to object such as lscpu to retrieve all the cpu info
178
+ Core(s) per socket: 28
179
+ Socket(s): 2
180
+ NUMA node(s): 2
181
+ Vendor ID: GenuineIntel
182
+ CPU family: 6
183
+ Model: 85
184
+ Model name: Intel(R) Xeon(R) Gold 6258R CPU @ 2.70GHz
185
+ Stepping: 7
186
+ CPU MHz: 2965.749
187
+ CPU max MHz: 4000.0000
188
+ CPU min MHz: 1000.0000
189
+ BogoMIPS: 5400.00
190
+ Virtualization: VT-x
191
+ L1d cache: 32K
192
+ L1i cache: 32K
193
+
194
+ * @param {stdout of the run_cmd} stdout
195
+ * @param {delimiter to split} delimiter
196
+ * @param {lines to retrieve} lines
197
+ * @param {only retrieve the value that has the same property in config} config
198
+ * @returns
199
+ */
200
+ const read_key_value_line = (stdout, delimiter = ":", lines, config, exclude_mode) => {
201
+ const obj = {};
202
+ if (!stdout) {
203
+ return obj;
204
+ }
205
+
206
+ const contents = stdout.toString().split(/(?:\r\n|\r|\n)/g);
207
+ const line_texts = lines ? get_lines(contents, lines) : contents;
208
+ line_texts.forEach(content => {
209
+ const key_value = content.split(delimiter);
210
+ if (key_value.length == 2) {
211
+ const key = key_value[0].trim();
212
+ if (key && !config || (exclude_mode != true && config && config[key]) || exclude_mode == true && config && !config[`!${key}`]) {
213
+ obj[key] = key_value[1].trim();
214
+ }
215
+ }
216
+ });
217
+ return obj;
218
+ }
219
+
220
+
221
+ /**
222
+ * Use delimeter to split the line and retrieve the info
223
+ *
224
+ MODEL SIZE
225
+ INTEL SSDSC2KB03 3.5T
226
+ INTEL SSDPE2KE032T7 2.9T
227
+
228
+ * @param {stdout of the run_cmd} stdout
229
+ * @param {the attribute keys} keys
230
+ * @param {the lines to ignore} ignore
231
+ * @param {delimiter to split the line} delimiter
232
+ * @returns
233
+ */
234
+ const read_obj_line = (stdout, keys, ignore = 1, delimiter = " ") => {
235
+ const results = [];
236
+ if (!stdout) {
237
+ return results;
238
+ }
239
+
240
+ const contents = stdout.toString().split(/(?:\r\n|\r|\n)/g);
241
+ const line_texts = contents.slice(ignore);
242
+ line_texts.forEach(content => {
243
+ const values = content.split(delimiter);
244
+ if (values && values.length > 0 && values[0].trim().length > 0) {
245
+ const obj = {};
246
+ const attrs = values.filter(f => f.trim().length > 0);
247
+ for (let i = 0; i < keys.length; i++) {
248
+ const key = keys[i];
249
+ const value = attrs[i];
250
+ value && (obj[key] = value.trim());
251
+ }
252
+ results.push(obj);
253
+ }
254
+ });
255
+ return results;
256
+ }
257
+
258
+ /**
259
+ * Retrive attributes value and put it to obj
260
+ * @param {host info,contains user,ip and password} host
261
+ * @param {*} attrs {name:"attr name",cmd:"command to get the attr"}
262
+ */
263
+ const get_system_attributes = async (host, attrs) => {
264
+ const obj = {};
265
+ for (let i = 0; i < attrs.length; i++) {
266
+ const attr = attrs[i];
267
+ const value = await run_simple_cmd(host, attr.cmd);
268
+ value && (obj[attr.name] = value);
269
+ }
270
+ return obj;
271
+ }
272
+
273
+ const stop_process = async (host, process_name, stop_cmd, using_full) => {
274
+ const grep_cmd = using_full == true ? `pgrep -f "${process_name}" | wc -l` : `pgrep ${process_name} | wc -l`;
275
+ const { stdout } = await run_script(host, grep_cmd);
276
+ const has_process = stdout && parseInt(stdout) > 0;
277
+ if (has_process) {
278
+ await run_script(host, stop_cmd);
279
+ }
280
+ return has_process;
281
+ }
282
+
283
+ module.exports = { stop_process, scp, run_script, run_script_file, run_simple_cmd, run_local_cmd, run_simple_local_cmd, get_info, get_system_attributes, read_key_value_line, read_obj_line };
package/core/chart.js ADDED
@@ -0,0 +1,36 @@
1
+ const { has_value } = require("./validate");
2
+
3
+ const set_chart_header = (arr1, prefix) => {
4
+ if (!arr1 || arr1.length < 1) {
5
+ return;
6
+ }
7
+ const headers = arr1[0];
8
+ if (!headers || headers.length < 1) {
9
+ return;
10
+ }
11
+ for (let i = 1; i < headers.length; i++) {
12
+ headers[i] = `${prefix}${headers[i]}`;
13
+ }
14
+ }
15
+
16
+ const merge_chart_data = (arr1, arr2) => {
17
+ if (!arr1 || arr1.length < 2 || !arr2 || arr2.length < 2) {
18
+ return;
19
+ }
20
+
21
+ const max = Math.max(arr1.length, arr2.length);
22
+ const arr1_cols = arr1[0].length;
23
+ const arr2_cols = arr2[0].length;
24
+ for (let i = 0; i < max; i++) {
25
+ if (!has_value(arr1[i])) {
26
+ arr1[i] = [...new Array(arr1_cols)].map(o => "");
27
+ arr1[i][0] = arr2[i][0];
28
+ }
29
+ if (!has_value(arr2[i])) {
30
+ arr2[i] = [...new Array(arr2_cols)].map(o => "");
31
+ }
32
+ arr1[i] = [...arr1[i], ...arr2[i].splice(1)];
33
+ }
34
+ }
35
+
36
+ module.exports = { set_chart_header, merge_chart_data }
package/core/cron.js ADDED
@@ -0,0 +1,10 @@
1
+ const node_cron = require('node-cron');
2
+
3
+ const init_cron = async (crons, tasks) => {
4
+ crons.forEach((cron, index) => {
5
+ const schedule = node_cron.schedule(cron, () => { tasks[index](); }, { scheduled: true, timezone: "Asia/Shanghai" });
6
+ schedule.start();
7
+ });
8
+ }
9
+
10
+ module.exports = { init_cron };
package/core/file.js CHANGED
@@ -1,4 +1,6 @@
1
1
  const fs = require('fs');
2
+ const fs_promises = require('fs').promises;
3
+
2
4
  const unzipper = require('unzipper');
3
5
 
4
6
  const file_extension = file_name => file_name ? file_name.split('.').pop() : "";
@@ -28,4 +30,9 @@ const is_file_exist = (path) => {
28
30
  return true;
29
31
  }
30
32
 
31
- module.exports = { file_extension, file_prefix, read_from_zip_by_extension, read_from_zip_by_prefix, is_file_exist }
33
+ const get_file_size = async (path) => {
34
+ const stats = await fs_promises.stat(path);
35
+ return stats.size;
36
+ }
37
+
38
+ module.exports = { file_extension, file_prefix, read_from_zip_by_extension, read_from_zip_by_prefix, is_file_exist, get_file_size }
package/core/lhs.js ADDED
@@ -0,0 +1,27 @@
1
+
2
+ const vm = require('node:vm');
3
+ const { range, scale, space } = require("./number");
4
+
5
+ const get_context = () => { return { range: range, scale: scale, space: space } }
6
+
7
+ const run_in_context = (code, ctx) => {
8
+ vm.createContext(ctx);
9
+ vm.runInContext(code, ctx);
10
+ return ctx;
11
+ }
12
+
13
+ const verify_template = (template, knob) => {
14
+ try {
15
+ run_in_context("__output__=`" + template + "`;", knob);
16
+ } catch (err) {
17
+ return err.message;
18
+ }
19
+ return null;
20
+ }
21
+
22
+ const execute_template = (template, knob) => {
23
+ const ctx = run_in_context("__output__=`" + template + "`;", knob);
24
+ return ctx["__output__"];
25
+ }
26
+
27
+ module.exports = { get_context, run_in_context, verify_template, execute_template }
package/core/msg.js ADDED
@@ -0,0 +1,11 @@
1
+ const wxm = require('wxmnode');
2
+
3
+ const init_wxm = (name, password) => {
4
+ wxm.init(name, password);
5
+ }
6
+
7
+ const send_msg = async (content, type, detail) => {
8
+ return await wxm.sendMsg(content, type, detail);
9
+ }
10
+
11
+ module.exports = { init_wxm, send_msg }
package/index.js CHANGED
@@ -8,8 +8,13 @@ const { EntityMeta, get_entity_meta } = require('./core/meta');
8
8
 
9
9
 
10
10
  const array = require('./core/array');
11
+ const bash = require('./core/bash');
12
+ const chart = require('./core/chart');
13
+ const cron = require('./core/cron');
11
14
  const date = require('./core/date');
12
15
  const file = require('./core/file');
16
+ const lhs = require('./core/lhs');
17
+ const msg = require('./core/msg');
13
18
  const number = require('./core/number');
14
19
  const obj = require('./core/obj');
15
20
  const random = require('./core/random');
@@ -26,6 +31,6 @@ const { log_debug, log_info, log_warn, log_error, is_log_debug, is_log_info, is_
26
31
 
27
32
  module.exports = {
28
33
  init_settings, init_express_server, init_router, register_type, get_type, get_db,
29
- Entity, EntityMeta, get_entity_meta, array, date, file, number, obj, random, thread, validate, code, err, params, context, gridfs, gen_i18n,
34
+ Entity, EntityMeta, get_entity_meta, array, bash, chart, cron, date, file, lhs, msg, number, obj, random, thread, validate, code, err, params, context, gridfs, gen_i18n,
30
35
  log_debug, log_info, log_warn, log_error, is_log_debug, is_log_info, is_log_warn, is_log_error, get_session_userid, oid_queries, oid_query
31
36
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hola-server",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "description": "a meta programming framework used to build nodejs restful api",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -18,7 +18,9 @@
18
18
  "mongodb": "^4.7.0",
19
19
  "mongoist": "^2.5.4",
20
20
  "multer": "^1.4.5-lts.1",
21
- "unzipper": "^0.10.11"
21
+ "unzipper": "^0.10.11",
22
+ "node-cron": "^3.0.2",
23
+ "wxmnode": "^1.0.5"
22
24
  },
23
25
  "devDependencies": {
24
26
  "chai": "^4.3.6",