@abtnode/core 1.15.17 → 1.16.0-beta-b16cb035

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.
Files changed (119) hide show
  1. package/lib/api/node.js +67 -69
  2. package/lib/api/team.js +386 -55
  3. package/lib/blocklet/downloader/blocklet-downloader.js +226 -0
  4. package/lib/blocklet/downloader/bundle-downloader.js +272 -0
  5. package/lib/blocklet/downloader/constants.js +3 -0
  6. package/lib/blocklet/downloader/resolve-download.js +199 -0
  7. package/lib/blocklet/extras.js +83 -26
  8. package/lib/blocklet/hooks.js +18 -65
  9. package/lib/blocklet/manager/base.js +10 -16
  10. package/lib/blocklet/manager/disk.js +1679 -1566
  11. package/lib/blocklet/manager/helper/install-application-from-backup.js +177 -0
  12. package/lib/blocklet/manager/helper/install-application-from-dev.js +94 -0
  13. package/lib/blocklet/manager/helper/install-application-from-general.js +188 -0
  14. package/lib/blocklet/manager/helper/install-component-from-dev.js +84 -0
  15. package/lib/blocklet/manager/helper/install-component-from-upload.js +181 -0
  16. package/lib/blocklet/manager/helper/install-component-from-url.js +173 -0
  17. package/lib/blocklet/manager/helper/migrate-application-to-struct-v2.js +450 -0
  18. package/lib/blocklet/manager/helper/rollback-cache.js +41 -0
  19. package/lib/blocklet/manager/helper/upgrade-components.js +152 -0
  20. package/lib/blocklet/migration.js +30 -52
  21. package/lib/blocklet/storage/backup/audit-log.js +27 -0
  22. package/lib/blocklet/storage/backup/base.js +62 -0
  23. package/lib/blocklet/storage/backup/blocklet-extras.js +92 -0
  24. package/lib/blocklet/storage/backup/blocklet.js +70 -0
  25. package/lib/blocklet/storage/backup/blocklets.js +74 -0
  26. package/lib/blocklet/storage/backup/data.js +19 -0
  27. package/lib/blocklet/storage/backup/logs.js +24 -0
  28. package/lib/blocklet/storage/backup/routing-rule.js +19 -0
  29. package/lib/blocklet/storage/backup/spaces.js +240 -0
  30. package/lib/blocklet/storage/restore/base.js +67 -0
  31. package/lib/blocklet/storage/restore/blocklet-extras.js +86 -0
  32. package/lib/blocklet/storage/restore/blocklet.js +56 -0
  33. package/lib/blocklet/storage/restore/blocklets.js +43 -0
  34. package/lib/blocklet/storage/restore/logs.js +21 -0
  35. package/lib/blocklet/storage/restore/spaces.js +156 -0
  36. package/lib/blocklet/storage/utils/hash.js +51 -0
  37. package/lib/blocklet/storage/utils/zip.js +43 -0
  38. package/lib/cert.js +206 -0
  39. package/lib/event.js +237 -64
  40. package/lib/index.js +191 -83
  41. package/lib/migrations/1.0.21-update-config.js +1 -1
  42. package/lib/migrations/1.0.22-max-memory.js +1 -1
  43. package/lib/migrations/1.0.25.js +1 -1
  44. package/lib/migrations/1.0.32-update-config.js +1 -1
  45. package/lib/migrations/1.0.33-blocklets.js +1 -1
  46. package/lib/migrations/1.5.20-registry.js +15 -0
  47. package/lib/migrations/1.6.17-blocklet-children.js +48 -0
  48. package/lib/migrations/1.6.21-rename-ip-echo-domain.js +35 -0
  49. package/lib/migrations/1.6.4-security.js +59 -0
  50. package/lib/migrations/1.6.5-security.js +60 -0
  51. package/lib/migrations/1.6.9-update-node-info-and-certificate.js +38 -0
  52. package/lib/migrations/1.7.1-blocklet-setup.js +18 -0
  53. package/lib/migrations/1.7.12-blocklet-meta.js +51 -0
  54. package/lib/migrations/1.7.15-blocklet-bundle-source.js +42 -0
  55. package/lib/migrations/1.7.20-blocklet-component.js +41 -0
  56. package/lib/migrations/1.8.33-blocklet-mem-limit.js +20 -0
  57. package/lib/migrations/README.md +1 -1
  58. package/lib/migrations/index.js +6 -2
  59. package/lib/monitor/blocklet-runtime-monitor.js +200 -0
  60. package/lib/monitor/get-history-list.js +37 -0
  61. package/lib/monitor/node-runtime-monitor.js +228 -0
  62. package/lib/router/helper.js +572 -497
  63. package/lib/router/index.js +85 -21
  64. package/lib/router/manager.js +146 -187
  65. package/lib/states/README.md +36 -1
  66. package/lib/states/access-key.js +39 -17
  67. package/lib/states/audit-log.js +462 -0
  68. package/lib/states/base.js +4 -213
  69. package/lib/states/blocklet-extras.js +194 -138
  70. package/lib/states/blocklet.js +361 -104
  71. package/lib/states/cache.js +8 -6
  72. package/lib/states/challenge.js +5 -5
  73. package/lib/states/index.js +19 -36
  74. package/lib/states/migration.js +4 -4
  75. package/lib/states/node.js +135 -46
  76. package/lib/states/notification.js +22 -35
  77. package/lib/states/session.js +17 -9
  78. package/lib/states/site.js +50 -25
  79. package/lib/states/user.js +74 -20
  80. package/lib/states/webhook.js +10 -6
  81. package/lib/team/manager.js +124 -7
  82. package/lib/util/blocklet.js +1223 -246
  83. package/lib/util/chain.js +1 -1
  84. package/lib/util/default-node-config.js +5 -23
  85. package/lib/util/disk-monitor.js +13 -10
  86. package/lib/util/domain-status.js +84 -15
  87. package/lib/util/get-accessible-external-node-ip.js +2 -2
  88. package/lib/util/get-domain-for-blocklet.js +13 -0
  89. package/lib/util/get-meta-from-url.js +33 -0
  90. package/lib/util/index.js +207 -272
  91. package/lib/util/ip.js +6 -0
  92. package/lib/util/maintain.js +233 -0
  93. package/lib/util/public-to-store.js +85 -0
  94. package/lib/util/ready.js +1 -1
  95. package/lib/util/requirement.js +28 -9
  96. package/lib/util/reset-node.js +22 -7
  97. package/lib/util/router.js +13 -0
  98. package/lib/util/rpc.js +16 -0
  99. package/lib/util/store.js +179 -0
  100. package/lib/util/sysinfo.js +44 -0
  101. package/lib/util/ua.js +54 -0
  102. package/lib/validators/blocklet-extra.js +24 -0
  103. package/lib/validators/node.js +25 -12
  104. package/lib/validators/permission.js +16 -1
  105. package/lib/validators/role.js +17 -3
  106. package/lib/validators/router.js +40 -20
  107. package/lib/validators/trusted-passport.js +1 -0
  108. package/lib/validators/util.js +22 -5
  109. package/lib/webhook/index.js +45 -35
  110. package/lib/webhook/sender/index.js +5 -0
  111. package/lib/webhook/sender/slack/index.js +1 -1
  112. package/lib/webhook/sender/wallet/index.js +48 -0
  113. package/package.json +54 -36
  114. package/lib/blocklet/registry.js +0 -205
  115. package/lib/states/https-cert.js +0 -67
  116. package/lib/util/get-ip-dns-domain-for-blocklet.js +0 -19
  117. package/lib/util/service.js +0 -66
  118. package/lib/util/upgrade.js +0 -178
  119. /package/lib/{queue.js → util/queue.js} +0 -0
@@ -1,17 +1,23 @@
1
1
  const uniqBy = require('lodash/uniqBy');
2
- const { BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/meta/lib/constants');
2
+ const cloneDeep = require('lodash/cloneDeep');
3
+ const security = require('@abtnode/util/lib/security');
4
+ const { BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
3
5
 
4
- const mergeConfigs = (oldConfigs, newConfigs = []) => {
5
- const metaConfigs = (oldConfigs || []).filter((x) => !x.custom);
6
- const customConfigs = (oldConfigs || []).filter((x) => x.custom);
7
-
8
- const metaConfigsToKeep = metaConfigs.filter((x) => newConfigs.find((n) => n.key === x.key || n.name === x.key));
6
+ const removeDeletedMetaConfigs = (oldConfigs, newConfigs) =>
7
+ oldConfigs.filter((old) => newConfigs.some(({ key, name }) => [key, name].includes(old.key)));
9
8
 
9
+ const mergeConfigs = ({ old: oldConfigs, cur: newConfigs = [], did = '', dek = '' }) => {
10
+ const enableSecurity = dek && did;
10
11
  const isUpdatingCustomConfig = newConfigs.every((x) => x.key);
11
- const configs = isUpdatingCustomConfig ? metaConfigs : metaConfigsToKeep;
12
+
13
+ const customConfigs = (oldConfigs || []).filter((x) => x.custom);
14
+ const appConfigs = (oldConfigs || []).filter((x) => !x.custom && !!BLOCKLET_CONFIGURABLE_KEY[x.key]);
15
+
16
+ const allMetaConfigs = (oldConfigs || []).filter((x) => !x.custom && !BLOCKLET_CONFIGURABLE_KEY[x.key]);
17
+ const metaConfigs = isUpdatingCustomConfig ? allMetaConfigs : removeDeletedMetaConfigs(allMetaConfigs, newConfigs);
12
18
 
13
19
  // oldConfig 表示从数据库中可以用的字段
14
- const oldConfig = [...configs, ...customConfigs].reduce((acc, x) => {
20
+ const oldConfig = [...metaConfigs, ...appConfigs, ...customConfigs].reduce((acc, x) => {
15
21
  acc[x.key] = {
16
22
  value: x.value,
17
23
  required: x.required,
@@ -19,6 +25,7 @@ const mergeConfigs = (oldConfigs, newConfigs = []) => {
19
25
  secure: x.secure || false,
20
26
  validation: x.validation || '',
21
27
  custom: x.custom,
28
+ shared: x.shared,
22
29
  };
23
30
  return acc;
24
31
  }, {});
@@ -27,26 +34,35 @@ const mergeConfigs = (oldConfigs, newConfigs = []) => {
27
34
  const uniqConfigs = uniqBy(newConfigs, (x) => x.key || x.name);
28
35
 
29
36
  // `BLOCKLET_*` and `ABT_NODE_*` vars can only be set by Blocklet Server Daemon with only a few exceptions.
30
- const newConfig = uniqConfigs.filter((x) => {
31
- const key = x.key || x.name;
32
-
33
- if (!key) {
34
- return false;
35
- }
37
+ const newConfig = cloneDeep(
38
+ uniqConfigs.filter((x) => {
39
+ const key = x.key || x.name;
36
40
 
37
- if (BLOCKLET_CONFIGURABLE_KEY[key]) {
38
- return true;
39
- }
41
+ if (!key) {
42
+ return false;
43
+ }
40
44
 
41
- if (key.toString().startsWith('ABT_NODE_') || key.toString().startsWith('BLOCKLET_')) {
42
- return false;
43
- }
45
+ if (BLOCKLET_CONFIGURABLE_KEY[key]) {
46
+ return true;
47
+ }
44
48
 
45
- return true;
46
- });
49
+ return !(key.toString().startsWith('ABT_NODE_') || key.toString().startsWith('BLOCKLET_'));
50
+ })
51
+ );
52
+
53
+ if (enableSecurity) {
54
+ newConfig.forEach((x) => {
55
+ if (x.secure) {
56
+ x.value = security.encrypt(x.value, did, dek);
57
+ if (x.default) {
58
+ x.default = security.encrypt(x.default, did, dek);
59
+ }
60
+ }
61
+ });
62
+ }
47
63
 
48
64
  newConfig.forEach((config) => {
49
- const { name, key, value, default: defaultVal, required, description, secure, validation, custom } = config;
65
+ const { name, key, value, default: defaultVal, required, description, secure, validation, custom, shared } = config;
50
66
  // 新增、更新或者删除
51
67
  if (key) {
52
68
  const originalVal = oldConfig[key] || {};
@@ -58,6 +74,7 @@ const mergeConfigs = (oldConfigs, newConfigs = []) => {
58
74
  validation: validation || '',
59
75
  secure: secure === undefined ? false : secure,
60
76
  custom: custom === undefined ? false : custom,
77
+ shared,
61
78
  };
62
79
  return;
63
80
  }
@@ -65,15 +82,21 @@ const mergeConfigs = (oldConfigs, newConfigs = []) => {
65
82
  if (name) {
66
83
  // 重装时 name 和 value不覆盖
67
84
  if (oldConfig[name]) {
85
+ const oldSecure = oldConfig[name].secure;
86
+ const oldValue =
87
+ enableSecurity && oldSecure ? security.decrypt(oldConfig[name].value, did, dek) : oldConfig[name].value;
88
+
89
+ const newSecure = secure === undefined ? false : secure;
90
+
68
91
  oldConfig[name] = {
69
- value: oldConfig[name].value,
92
+ value: enableSecurity && newSecure ? security.encrypt(oldValue, did, dek) : oldValue,
70
93
  required: required === undefined ? false : required,
71
94
  description: description || '',
72
95
  validation: validation || '',
73
- secure: secure === undefined ? false : secure,
96
+ secure: newSecure,
74
97
  custom: custom === undefined ? false : custom,
98
+ shared,
75
99
  };
76
-
77
100
  return;
78
101
  }
79
102
 
@@ -85,6 +108,7 @@ const mergeConfigs = (oldConfigs, newConfigs = []) => {
85
108
  validation: validation || '',
86
109
  secure: secure === undefined ? false : secure,
87
110
  custom: custom === undefined ? false : custom,
111
+ shared,
88
112
  };
89
113
  }
90
114
  });
@@ -100,11 +124,44 @@ const mergeConfigs = (oldConfigs, newConfigs = []) => {
100
124
  secure: mergedObj[key].secure,
101
125
  validation: mergedObj[key].validation,
102
126
  custom: mergedObj[key].custom,
127
+ shared: mergedObj[key].shared,
103
128
  }));
104
129
 
105
130
  return mergedConfig;
106
131
  };
107
132
 
133
+ const parseConfigs = ({ data, did, dek }) => {
134
+ const enableSecurity = dek && did;
135
+
136
+ if (enableSecurity && Array.isArray(data)) {
137
+ return cloneDeep(data).map((x) => {
138
+ if (x.secure) {
139
+ x.value = security.decrypt(x.value, did, dek);
140
+ }
141
+
142
+ return x;
143
+ });
144
+ }
145
+
146
+ return data;
147
+ };
148
+
149
+ const encryptConfigs = ({ data, did, dek }) => {
150
+ const enableSecurity = dek && did;
151
+
152
+ if (enableSecurity && Array.isArray(data)) {
153
+ data.forEach((x) => {
154
+ if (x.secure) {
155
+ x.value = security.encrypt(x.value, did, dek);
156
+ }
157
+ });
158
+ }
159
+
160
+ return data;
161
+ };
162
+
108
163
  module.exports = {
109
164
  mergeConfigs,
165
+ parseConfigs,
166
+ encryptConfigs,
110
167
  };
@@ -1,70 +1,25 @@
1
- const childProcess = require('child_process');
2
1
  const get = require('lodash/get');
3
2
  const camelCase = require('lodash/camelCase');
3
+ const runScript = require('@abtnode/util/lib/run-script');
4
4
 
5
5
  // eslint-disable-next-line global-require
6
6
  const logger = require('@abtnode/logger')(`${require('../../package.json').name}:blocklet:hooks`);
7
7
 
8
8
  const { getSafeEnv } = require('../util');
9
9
 
10
- const runAsync = ({ appDir, env, hook, progress = false }) => {
11
- const safeEnv = getSafeEnv(env);
12
- const child = childProcess.exec(hook, {
13
- cwd: appDir,
14
- env: safeEnv,
15
- stdio: 'inherit',
16
- });
17
-
18
- if (progress) {
19
- child.stdout.pipe(process.stdout);
20
- child.stderr.pipe(process.stderr);
21
- }
22
-
23
- return new Promise((resolve, reject) => {
24
- const errorMessages = [];
25
- let hasUnhandledRejection = false;
26
-
27
- child.stderr.on('data', (err) => {
28
- // Check if has unhandledRejection in childProcess
29
- // https://stackoverflow.com/questions/32784649/gracefully-handle-errors-in-child-processes-in-nodejs
30
- if (err.includes('UnhandledPromiseRejectionWarning')) {
31
- hasUnhandledRejection = true;
32
- }
33
- errorMessages.push(err);
34
- });
35
-
36
- child.on('exit', (code) => {
37
- if (errorMessages.length > 0) {
38
- if (code !== 0 || hasUnhandledRejection) {
39
- return reject(new Error(errorMessages.join('\r\n')));
40
- }
41
-
42
- if (!progress) {
43
- errorMessages.forEach((message) => process.stderr.write(message));
44
- }
45
- }
46
-
47
- return resolve();
48
- });
49
- });
50
- };
51
-
52
- /**
53
- * @param {*} args.did root blocklet did
54
- */
55
- const runUserHook = async (name, args) => {
56
- const { appDir, hooks, env, exitOnError = true, progress = false, notification, did } = args;
57
- const hook = get(hooks, `[${name}]`) || get(hooks, `[${camelCase(name)}]`);
10
+ const runUserHook = async (processId, hookName, args) => {
11
+ const { appDir, hooks, env, exitOnError = true, silent = false, notification, did } = args;
12
+ const hook = get(hooks, `[${hookName}]`) || get(hooks, `[${camelCase(hookName)}]`);
58
13
 
59
14
  try {
60
15
  if (!hook) {
61
16
  return;
62
17
  }
63
18
 
64
- logger.info(`run hook:${name}:`, { hook });
65
- await runAsync({ appDir, env, hook, progress });
19
+ logger.info(`run hook:${hookName}:`, { processId, hook });
20
+ await runScript(hook, [processId, hookName].join(':'), { cwd: appDir, env: getSafeEnv(env), silent });
66
21
  } catch (error) {
67
- logger.error(`run ${hook} error:`, { error });
22
+ logger.error(`run ${hook} error:`, { processId, error });
68
23
 
69
24
  if (notification) {
70
25
  notification.create({
@@ -77,33 +32,31 @@ const runUserHook = async (name, args) => {
77
32
  }
78
33
 
79
34
  if (exitOnError) {
80
- throw new Error(`Run [${name}] failed: ${error.message}`);
35
+ throw new Error(`Run [${processId} - ${hookName}] failed: ${error.message}`);
81
36
  }
82
37
  }
83
38
  };
84
39
 
85
- const preDeploy = (...args) => runUserHook('pre-deploy', ...args);
86
- const preInstall = (...args) => runUserHook('pre-install', ...args);
87
- const postInstall = (...args) => runUserHook('post-install', ...args);
88
-
89
- const preStart = async (blocklet, option) => {
40
+ const preInstall = (processId, ...args) => runUserHook(processId, 'pre-install', ...args);
41
+ const postInstall = (processId, ...args) => runUserHook(processId, 'post-install', ...args);
42
+ const preConfig = (processId, ...args) => runUserHook(processId, 'pre-config', ...args);
43
+ const preStart = async (blocklet, options) => {
90
44
  // check required environments
91
45
  let environments = get(blocklet, 'meta.environments', []);
92
46
  if (!Array.isArray(environments)) {
93
47
  environments = [environments];
94
48
  }
95
49
 
96
- const tmp = environments.filter((e) => e.required && option.env[e.name] === undefined).map((e) => e.name);
50
+ const tmp = environments.filter((e) => e.required && options.env[e.name] === undefined).map((e) => e.name);
97
51
  if (tmp.length > 0) {
98
52
  throw new Error(`Required environments is not set: ${tmp.join(',')}`);
99
53
  }
100
54
 
101
- return runUserHook('pre-start', option);
55
+ return runUserHook(blocklet.env.processId, 'pre-start', options);
102
56
  };
103
57
 
104
- const preUninstall = (...args) => runUserHook('pre-uninstall', ...args);
105
- const preStop = (...args) => runUserHook('pre-stop', ...args);
106
-
107
- const preConfig = (...args) => runUserHook('pre-config', ...args);
58
+ const postStart = (blocklet, ...args) => runUserHook(blocklet.env.processId, 'post-start', ...args);
59
+ const preUninstall = (processId, ...args) => runUserHook(processId, 'pre-uninstall', ...args);
60
+ const preStop = (processId, ...args) => runUserHook(processId, 'pre-stop', ...args);
108
61
 
109
- module.exports = { preDeploy, preInstall, postInstall, preStart, preUninstall, preStop, preConfig };
62
+ module.exports = { preInstall, postInstall, preStart, postStart, preUninstall, preStop, preConfig };
@@ -8,37 +8,39 @@ class BaseBlockletManager extends EventEmitter {
8
8
  constructor() {
9
9
  super();
10
10
 
11
+ this.setMaxListeners(100);
12
+
11
13
  // HACK: do not emit any events from CLI
12
14
  if (isCLI() && process.env.NODE_ENV !== 'test') {
13
15
  this.emit = (name) => logger.debug('stopped blocklet manager event in CLI', name);
14
16
  }
15
17
  }
16
18
 
17
- async install(did, userVersion = 'latest') {
19
+ async install() {
18
20
  throw new Error('Install must be implemented in sub class');
19
21
  }
20
22
 
21
- async start(did, autoDisconnect = true) {
23
+ async start() {
22
24
  throw new Error('Install must be implemented in sub class');
23
25
  }
24
26
 
25
- async stop(did, autoDisconnect = true) {
27
+ async stop() {
26
28
  throw new Error('Stop must be implemented in sub class');
27
29
  }
28
30
 
29
- async restart(did) {
31
+ async restart() {
30
32
  throw new Error('Restart must be implemented in sub class');
31
33
  }
32
34
 
33
- async reload(did) {
35
+ async reload() {
34
36
  throw new Error('Reload must be implemented in sub class');
35
37
  }
36
38
 
37
- async delete(did, disconnect = true) {
39
+ async delete() {
38
40
  throw new Error('Delete must be implemented in sub class');
39
41
  }
40
42
 
41
- async detail(did) {
43
+ async detail() {
42
44
  throw new Error('Detail must be implemented in sub class');
43
45
  }
44
46
 
@@ -46,17 +48,9 @@ class BaseBlockletManager extends EventEmitter {
46
48
  throw new Error('List must be implemented in sub class');
47
49
  }
48
50
 
49
- async config(did, configs) {
51
+ async config() {
50
52
  throw new Error('Config must be implemented in sub class');
51
53
  }
52
-
53
- async upgrade(did, version) {
54
- throw new Error('Upgrade must be implemented in sub class');
55
- }
56
-
57
- async deploy(folder) {
58
- throw new Error('Deploy must be implemented in sub class');
59
- }
60
54
  }
61
55
 
62
56
  module.exports = BaseBlockletManager;