@abtnode/core 1.16.15-beta-d8e7b6c0 → 1.16.15-beta-9318a201

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.
@@ -8,7 +8,6 @@ const { toBase58 } = require('@ocap/util');
8
8
  const defaultLogger = require('@abtnode/logger')('@abtnode/core:blocklet-downloader');
9
9
 
10
10
  const { forEachComponentV2Sync, getComponentBundleId } = require('@blocklet/meta/lib/util');
11
- const validateBlockletEntry = require('@blocklet/meta/lib/entry');
12
11
 
13
12
  const { BlockletSource, BLOCKLET_META_FILE, BLOCKLET_META_FILE_ALT, BLOCKLET_MODES } = require('@blocklet/constant');
14
13
 
@@ -54,14 +53,6 @@ const needDownload = (
54
53
  return true;
55
54
  }
56
55
 
57
- // check bundle broken
58
- try {
59
- validateBlockletEntry(bundleDir, component.meta);
60
- } catch (err) {
61
- logger.error('bundle is broken', { bundleId, msg: err.message });
62
- return true;
63
- }
64
-
65
56
  if (!isSourceAccessible(component)) {
66
57
  return false;
67
58
  }
@@ -2,7 +2,6 @@ const path = require('path');
2
2
  const fs = require('fs-extra');
3
3
  const { Throttle } = require('stream-throttle');
4
4
 
5
- const validateBlockletEntry = require('@blocklet/meta/lib/entry');
6
5
  const { BLOCKLET_BUNDLE_FOLDER } = require('@blocklet/constant');
7
6
 
8
7
  const defaultLogger = require('@abtnode/logger')('@abtnode/core:resolve-download');
@@ -71,7 +70,7 @@ const resolveDownload = async (
71
70
  await fs.move(dir, downloadDir, { overwrite: true });
72
71
  fs.removeSync(tmp);
73
72
 
74
- meta = getBlockletMeta(downloadDir, { ensureMain: true });
73
+ meta = getBlockletMeta(downloadDir);
75
74
  const { did, name, version } = meta;
76
75
 
77
76
  // validate
@@ -79,7 +78,6 @@ const resolveDownload = async (
79
78
  logger.error('Meta has differences', { originalMeta, meta });
80
79
  throw new Error('There are differences between the meta from tarball file and the original meta');
81
80
  }
82
- await validateBlockletEntry(downloadDir, meta);
83
81
 
84
82
  if (typeof onProgress === 'function') {
85
83
  onProgress({ name: 'blocklet.zip' });
@@ -152,7 +150,7 @@ const resolveDiffDownload = async (
152
150
  };
153
151
  await walkDiff(diffDir);
154
152
  fs.removeSync(diffDir);
155
- const meta = getBlockletMeta(downloadDir, { ensureMain: true });
153
+ const meta = getBlockletMeta(downloadDir);
156
154
 
157
155
  await ensureBlockletExpanded(meta, downloadDir);
158
156
 
@@ -41,12 +41,13 @@ const {
41
41
  getRolesFromAuthConfig,
42
42
  isInProgress,
43
43
  isBeforeInstalled,
44
- getComponentsInternalInfo,
45
44
  forEachComponentV2,
46
45
  forEachComponentV2Sync,
47
46
  findComponentByIdV2,
48
47
  isGatewayBlocklet,
48
+ hasStartEngine,
49
49
  } = require('@blocklet/meta/lib/util');
50
+ const { getComponentsInternalInfo } = require('@blocklet/meta/lib/blocklet');
50
51
  const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
51
52
  const { titleSchema, updateMountPointSchema, environmentNameSchema } = require('@blocklet/meta/lib/schema');
52
53
  const { emailConfigSchema } = require('@blocklet/sdk/lib/validators/email');
@@ -383,7 +384,7 @@ class DiskBlockletManager extends BaseBlockletManager {
383
384
  logger.info('dev component', { folder, rootDid, mountPoint });
384
385
 
385
386
  const meta = getBlockletMeta(folder, { defaultStoreUrl });
386
- if (meta.group !== 'static' && (!meta.scripts || !meta.scripts.dev)) {
387
+ if (meta.group !== 'static' && hasStartEngine(meta) && (!meta.scripts || !meta.scripts.dev)) {
387
388
  throw new Error('Incorrect blocklet.yml: missing `scripts.dev` field');
388
389
  }
389
390
 
@@ -522,6 +523,7 @@ class DiskBlockletManager extends BaseBlockletManager {
522
523
 
523
524
  if (checkHealthImmediately) {
524
525
  await this._onCheckIfStarted(params, { throwOnError });
526
+ blocklet.status = BlockletStatus.running;
525
527
  } else {
526
528
  this.startQueue.push({
527
529
  entity: 'blocklet',
@@ -613,6 +615,13 @@ class DiskBlockletManager extends BaseBlockletManager {
613
615
  // send notification to wallet
614
616
  this.emit(BlockletEvents.stopped, { ...res, componentDids });
615
617
 
618
+ this.emit(BlockletInternalEvents.componentStopped, {
619
+ appDid: blocklet.appDid,
620
+ components: componentDids?.length
621
+ ? componentDids.map((x) => ({ did: x }))
622
+ : blocklet.children.map((x) => ({ did: x.meta.did })),
623
+ });
624
+ // for backward compatibility
616
625
  this.emit(BlockletInternalEvents.componentsUpdated, {
617
626
  appDid: blocklet.appDid,
618
627
  components: getComponentsInternalInfo(res),
@@ -939,6 +948,11 @@ class DiskBlockletManager extends BaseBlockletManager {
939
948
  componentDids: [child.meta.did],
940
949
  });
941
950
 
951
+ this.emit(BlockletInternalEvents.componentRemoved, {
952
+ appDid: blocklet.appDid,
953
+ components: [{ did: child.meta.did }],
954
+ });
955
+ // for backward compatibility
942
956
  this.emit(BlockletInternalEvents.componentsUpdated, {
943
957
  appDid: blocklet.appDid,
944
958
  components: getComponentsInternalInfo(newBlocklet),
@@ -1395,6 +1409,11 @@ class DiskBlockletManager extends BaseBlockletManager {
1395
1409
  await states.blocklet.updateBlocklet(rootDid, { mountPoint: blocklet.mountPoint, children: blocklet.children });
1396
1410
 
1397
1411
  this.emit(BlockletEvents.upgraded, { blocklet, context: { ...context, createAuditLog: false } }); // trigger router refresh
1412
+ this.emit(BlockletInternalEvents.componentUpdated, {
1413
+ appDid: blocklet.appDid,
1414
+ components: getComponentsInternalInfo(blocklet).filter((x) => x.did === component.meta.did),
1415
+ });
1416
+ // for backward compatibility
1398
1417
  this.emit(BlockletInternalEvents.componentsUpdated, {
1399
1418
  appDid: blocklet.appDid,
1400
1419
  components: getComponentsInternalInfo(blocklet),
@@ -1514,6 +1533,10 @@ class DiskBlockletManager extends BaseBlockletManager {
1514
1533
  return;
1515
1534
  }
1516
1535
 
1536
+ if (!hasStartEngine(component.meta)) {
1537
+ return;
1538
+ }
1539
+
1517
1540
  try {
1518
1541
  const status = await getProcessState(component.env.processId);
1519
1542
  const oldStatus = component.status;
@@ -2044,6 +2067,11 @@ class DiskBlockletManager extends BaseBlockletManager {
2044
2067
 
2045
2068
  const res = await this.getBlocklet(did);
2046
2069
 
2070
+ this.emit(BlockletInternalEvents.componentStarted, {
2071
+ appDid: blocklet.appDid,
2072
+ components: (componentDids || []).map((x) => ({ did: x })),
2073
+ });
2074
+ // for backward compatibility
2047
2075
  this.emit(BlockletInternalEvents.componentsUpdated, {
2048
2076
  appDid: blocklet.appDid,
2049
2077
  components: getComponentsInternalInfo(res),
@@ -2051,11 +2079,14 @@ class DiskBlockletManager extends BaseBlockletManager {
2051
2079
 
2052
2080
  this.emit(BlockletEvents.statusChange, res);
2053
2081
  this.emit(BlockletEvents.started, { ...res, componentDids });
2082
+
2083
+ const componentNames = getComponentNamesWithVersion(blocklet, componentDids);
2084
+ const description = componentNames
2085
+ ? `${getComponentNamesWithVersion(blocklet, componentDids)} is successfully started for ${blocklet.meta.title}.`
2086
+ : `${blocklet.meta.title} is successfully started`;
2054
2087
  this._createNotification(did, {
2055
2088
  title: '',
2056
- description: `${getComponentNamesWithVersion(blocklet, componentDids)} is successfully started for ${
2057
- blocklet.meta.title
2058
- }.`,
2089
+ description,
2059
2090
  entityType: 'blocklet',
2060
2091
  entityId: did,
2061
2092
  severity: 'success',
@@ -2074,9 +2105,10 @@ class DiskBlockletManager extends BaseBlockletManager {
2074
2105
  await this.deleteProcess({ did, componentDids }, context);
2075
2106
  const doc = await states.blocklet.setBlockletStatus(did, BlockletStatus.error, { componentDids });
2076
2107
 
2077
- const description = `${getComponentNamesWithVersion(blocklet, componentDids)} start failed for ${title}: ${
2078
- error.message
2079
- }`;
2108
+ const componentNames = getComponentNamesWithVersion(blocklet, componentDids);
2109
+ const description = componentNames
2110
+ ? `${getComponentNamesWithVersion(blocklet, componentDids)} start failed for ${title}: ${error.message}`
2111
+ : `${blocklet.meta.title} start failed: ${error.message}`;
2080
2112
 
2081
2113
  this._createNotification(did, {
2082
2114
  title: '',
@@ -2671,7 +2703,6 @@ class DiskBlockletManager extends BaseBlockletManager {
2671
2703
  logger.info('updated blocklet for upgrading', { did, version, source, name });
2672
2704
 
2673
2705
  if (oldBlocklet.status === BlockletStatus.running) {
2674
- // start new process
2675
2706
  try {
2676
2707
  await this.start({ did, componentDids }, context);
2677
2708
  logger.info('started blocklet for upgrading', { did, version, componentDids });
@@ -2723,6 +2754,18 @@ class DiskBlockletManager extends BaseBlockletManager {
2723
2754
 
2724
2755
  await this._rollbackCache.remove({ did: blocklet.meta.did });
2725
2756
 
2757
+ if (oldBlocklet.status === BlockletStatus.running) {
2758
+ this.emit(
2759
+ action === INSTALL_ACTIONS.INSTALL_COMPONENT
2760
+ ? BlockletInternalEvents.componentInstalled
2761
+ : BlockletInternalEvents.componentUpgraded,
2762
+ {
2763
+ appDid: blocklet.appDid,
2764
+ components: getComponentsInternalInfo(blocklet).filter((c) => componentDids.includes(c.did)),
2765
+ }
2766
+ );
2767
+ }
2768
+ // for backward compatibility
2726
2769
  this.emit(BlockletInternalEvents.componentsUpdated, {
2727
2770
  appDid: blocklet.appDid,
2728
2771
  components: getComponentsInternalInfo(blocklet),
@@ -92,15 +92,20 @@ const installComponentFromUpload = async ({
92
92
  if (index >= 0) {
93
93
  // if upgrade, do not update mountPoint
94
94
  newChild.mountPoint = newBlocklet.children[index].mountPoint;
95
+ newChild.installedAt = newBlocklet.children[index].installedAt || new Date();
95
96
  newBlocklet.children.splice(index, 1, newChild);
96
97
  } else {
98
+ newChild.installedAt = new Date();
97
99
  newBlocklet.children.push(newChild);
98
100
  }
99
101
 
100
102
  const action = index >= 0 ? INSTALL_ACTIONS.UPGRADE_COMPONENT : INSTALL_ACTIONS.INSTALL_COMPONENT;
101
103
 
102
104
  const { dynamicComponents } = await parseComponents(newChild);
103
- const newChildren = filterDuplicateComponents(dynamicComponents, newBlocklet.children);
105
+ const newChildren = filterDuplicateComponents(dynamicComponents, newBlocklet.children).map((x) => ({
106
+ ...x,
107
+ installedAt: new Date(),
108
+ }));
104
109
 
105
110
  newBlocklet.children.push(...newChildren);
106
111
 
@@ -215,6 +215,12 @@ class SpacesBackup extends BaseBackup {
215
215
  return object.name !== '.DS_Store';
216
216
  },
217
217
  onAfterUpload: async (data) => {
218
+ // @note: 当备份失败时 && 偶然会存在一些其他的备份请求后来发送成功了,此时会造成备份进度紊乱(明明失败了,错误信息显示上传某个文件成功了)的情况,所以失败的备份不需要再发送事件了
219
+ const currentBackup = await states.backup.findOne({ id: this.input.backup.id });
220
+ if (currentBackup.status === 1) {
221
+ return;
222
+ }
223
+
218
224
  logger.info('backup progress', { appDid: this.input.appDid, data });
219
225
  const percent = (data.completed * 100) / data.total;
220
226
  // 0.8 是因为上传文件到 spaces 占进度的 80%,+ 20 是因为需要累加之前的进度
@@ -225,7 +231,6 @@ class SpacesBackup extends BaseBackup {
225
231
  progress,
226
232
  message: progressMessage,
227
233
  });
228
-
229
234
  this.input.event.emit(BlockletEvents.backupProgress, {
230
235
  appDid: this.input.appDid,
231
236
  meta: { did: this.input.appDid },
@@ -2,10 +2,10 @@ const EventEmitter = require('events');
2
2
 
3
3
  const cloneDeep = require('lodash/cloneDeep');
4
4
  const pLimit = require('p-limit');
5
- const { forEachBlocklet } = require('@blocklet/meta/lib/util');
5
+ const { forEachBlocklet, isGatewayBlocklet, hasStartEngine } = require('@blocklet/meta/lib/util');
6
6
  const getComponentProcessId = require('@blocklet/meta/lib/get-component-process-id');
7
7
  const { EVENTS } = require('@abtnode/constant');
8
- const { BlockletStatus, BlockletGroup } = require('@blocklet/constant');
8
+ const { BlockletStatus } = require('@blocklet/constant');
9
9
  const defaultLogger = require('@abtnode/logger')('blocklet-runtime-monitor');
10
10
 
11
11
  const { getRuntimeInfo } = require('../util/blocklet');
@@ -109,7 +109,8 @@ class BlockletRuntimeMonitor extends EventEmitter {
109
109
  await forEachBlocklet(
110
110
  blocklet,
111
111
  async (component, { id: componentId, ancestors }) => {
112
- if (component.meta.group !== BlockletGroup.gateway && component.status === BlockletStatus.running) {
112
+ const { meta } = component;
113
+ if (!isGatewayBlocklet(meta) && hasStartEngine(meta) && component.status === BlockletStatus.running) {
113
114
  const processId = getComponentProcessId(component, ancestors);
114
115
  try {
115
116
  const runtimeInfo = await getRuntimeInfo(processId);
@@ -199,6 +199,7 @@ Router.formatSites = (sites = []) => {
199
199
  site.rules.push({
200
200
  dynamic: true,
201
201
  from: {
202
+ root: true,
202
203
  pathPrefix: '/',
203
204
  groupPathPrefix: '/',
204
205
  pathSuffix: '/(robots.txt|sitemap.xml)',
@@ -30,7 +30,7 @@ const {
30
30
  BLOCKLET_INTERFACE_TYPE_WEB,
31
31
  BlockletGroup,
32
32
  } = require('@blocklet/constant');
33
- const { forEachChildSync } = require('@blocklet/meta/lib/util');
33
+ const { forEachChildSync, hasStartEngine, isGatewayBlocklet } = require('@blocklet/meta/lib/util');
34
34
 
35
35
  const {
36
36
  validateAddSite,
@@ -625,7 +625,8 @@ class RouterManager extends EventEmitter {
625
625
  }
626
626
 
627
627
  forEachChildSync(blocklet, (component, { id, ancestors }) => {
628
- if (component.meta.group === BlockletGroup.gateway) {
628
+ const { meta } = component;
629
+ if (isGatewayBlocklet(meta) || !hasStartEngine(meta)) {
629
630
  return;
630
631
  }
631
632
 
@@ -249,6 +249,9 @@ class BlockletState extends BaseState {
249
249
  const ports = await this.getBlockletPorts({ interfaces: sanitized.interfaces || [] });
250
250
  const children = await this.fillChildrenPorts(rawChildren, { defaultPort: getMaxPort(ports) });
251
251
  fixChildren(children);
252
+ children.forEach((x) => {
253
+ x.installedAt = new Date();
254
+ });
252
255
 
253
256
  // add to db
254
257
  doc = await this.insert({
@@ -646,6 +649,7 @@ class BlockletState extends BaseState {
646
649
  mode,
647
650
  status: BlockletStatus.added,
648
651
  children: child.children,
652
+ installedAt: new Date(),
649
653
  });
650
654
 
651
655
  fixChildren(newChildren);
@@ -28,7 +28,6 @@ const sleep = require('@abtnode/util/lib/sleep');
28
28
  const getPm2ProcessInfo = require('@abtnode/util/lib/get-pm2-process-info');
29
29
  const { formatEnv } = require('@abtnode/util/lib/security');
30
30
  const ensureEndpointHealthy = require('@abtnode/util/lib/ensure-endpoint-healthy');
31
- const CustomError = require('@abtnode/util/lib/custom-error');
32
31
  const getFolderSize = require('@abtnode/util/lib/get-folder-size');
33
32
  const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
34
33
  const hashFiles = require('@abtnode/util/lib/hash-files');
@@ -51,6 +50,7 @@ const {
51
50
  } = require('@blocklet/resolver');
52
51
  const formatBackSlash = require('@abtnode/util/lib/format-back-slash');
53
52
  const { isPortsOccupiedByOtherProcess, killProcessOccupiedPorts } = require('@abtnode/util/lib/port');
53
+ const { getComponentApiKey } = require('@abtnode/util/lib/blocklet');
54
54
  const { toSvg: createDidLogo } =
55
55
  process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
56
56
  const { createBlockiesSvg } = require('@blocklet/meta/lib/blockies');
@@ -61,7 +61,6 @@ const {
61
61
  BlockletStatus,
62
62
  BlockletSource,
63
63
  BlockletGroup,
64
- BLOCKLET_GROUPS,
65
64
  BLOCKLET_MODES,
66
65
  BLOCKLET_BUNDLE_FILE,
67
66
  BLOCKLET_ENTRY_FILE,
@@ -88,11 +87,12 @@ const {
88
87
  getComponentName,
89
88
  isEnvShareable,
90
89
  getBlockletAppIdList,
91
- isBeforeInstalled,
92
90
  getChainInfo,
93
91
  isInProgress,
94
92
  isRunning,
93
+ hasStartEngine,
95
94
  } = require('@blocklet/meta/lib/util');
95
+ const { getComponentsInternalInfo } = require('@blocklet/meta/lib/blocklet');
96
96
  const { titleSchema, descriptionSchema, logoSchema } = require('@blocklet/meta/lib/schema');
97
97
  const { getBlockletMetaFromUrl } = require('@blocklet/meta/lib/util-meta');
98
98
  const getComponentProcessId = require('@blocklet/meta/lib/get-component-process-id');
@@ -141,47 +141,20 @@ const PRIVATE_NODE_ENVS = [
141
141
  ];
142
142
 
143
143
  /**
144
- * @returns { dataDir, logsDir, cacheDir, appMain, appDir, mainDir, appCwd }
144
+ * @returns { dataDir, logsDir, cacheDir, appDir }
145
145
  * dataDir: dataDirs.data/name (root component) or dataDirs.data/name/childName (child component)
146
146
  * logsDir: dataDirs.log/name
147
147
  * cacheDir: dataDirs.cache/name (root component) or dataDirs.cache/name/childName (child component)
148
148
  * appDir: component bundle dir
149
- * mainDir: appDir (dapp) or appDir/main (static). Used for for static component
150
- * appMain: app entry file or script (run appMain to start component process)
151
- * appCwd: cwd of appMain
152
149
  */
153
- const getComponentDirs = (
154
- component,
155
- { dataDirs, ensure = false, e2eMode = false, validate = false, ancestors = [] } = {}
156
- ) => {
157
- // FIXME 这个函数做了太多的事
158
- // get data dirs
159
-
150
+ const getComponentDirs = (component, { dataDirs, ensure = false, ancestors = [] } = {}) => {
160
151
  const componentName = getComponentName(component, ancestors);
161
152
 
162
153
  const logsDir = path.join(dataDirs.logs, componentName);
163
154
  const dataDir = path.join(dataDirs.data, componentName);
164
155
  const cacheDir = path.join(dataDirs.cache, componentName);
165
156
 
166
- // get app dirs
167
-
168
- const { main, group } = component.meta;
169
-
170
- let startFromDevEntry = '';
171
- if (component.mode === BLOCKLET_MODES.DEVELOPMENT && component.meta.scripts) {
172
- startFromDevEntry = component.meta.scripts.dev;
173
- if (e2eMode && component.meta.scripts.e2eDev) {
174
- startFromDevEntry = component.meta.scripts.e2eDev;
175
- }
176
- }
177
-
178
- if (validate && !main && !startFromDevEntry && group !== BlockletGroup.gateway) {
179
- throw new Error('Incorrect blocklet.yml: missing `main` field');
180
- }
181
-
182
157
  let appDir = null;
183
- let mainDir = null;
184
-
185
158
  if (component.source === BlockletSource.local) {
186
159
  appDir = component.deployedFrom;
187
160
  } else {
@@ -203,37 +176,57 @@ const getComponentDirs = (
203
176
  }
204
177
  }
205
178
 
206
- mainDir = appDir;
179
+ return { dataDir, logsDir, cacheDir, appDir };
180
+ };
207
181
 
208
- if (validate && !startFromDevEntry && !isBeforeInstalled(component.status)) {
209
- try {
210
- validateBlockletEntry(appDir, component.meta);
211
- } catch (err) {
212
- throw new CustomError('BLOCKLET_CORRUPTED', err.message);
213
- }
182
+ /**
183
+ * @returns { cwd, script, args, environmentObj, interpreter, interpreterArgs }
184
+ */
185
+ const getComponentStartEngine = (component, { e2eMode = false } = {}) => {
186
+ if (!hasStartEngine(component.meta)) {
187
+ return {};
214
188
  }
215
189
 
216
- if (validate && !BLOCKLET_GROUPS.includes(group)) {
217
- throw new CustomError('BLOCKLET_CORRUPTED', `Unsupported blocklet type ${group}`);
190
+ const { appDir } = component.env;
191
+
192
+ const cwd = appDir;
193
+
194
+ // get app dirs
195
+ const { main, group } = component.meta;
196
+
197
+ let startFromDevEntry = '';
198
+ if (component.mode === BLOCKLET_MODES.DEVELOPMENT && component.meta.scripts) {
199
+ startFromDevEntry = component.meta.scripts.dev;
200
+ if (e2eMode && component.meta.scripts.e2eDev) {
201
+ startFromDevEntry = component.meta.scripts.e2eDev;
202
+ }
218
203
  }
219
204
 
220
- let appMain = null;
221
- let appCwd = null;
205
+ const blockletEngineInfo = getBlockletEngine(component.meta);
206
+
207
+ let script = null;
208
+ let interpreter = '';
209
+ let interpreterArgs = '';
210
+ const environmentObj = {};
211
+ let args = [];
212
+
222
213
  if (startFromDevEntry) {
223
- appMain = startFromDevEntry;
224
- appCwd = appDir;
214
+ script = startFromDevEntry;
225
215
  } else if (group === 'dapp') {
226
- appMain = getBlockletEngine(component.meta).script || BLOCKLET_ENTRY_FILE;
227
- appCwd = appDir;
216
+ script = blockletEngineInfo.script || BLOCKLET_ENTRY_FILE;
217
+ args = blockletEngineInfo.args || [];
228
218
  } else if (group === 'static') {
229
- mainDir = path.join(appDir, main);
219
+ script = require.resolve('@abtnode/static-server');
220
+ environmentObj.BLOCKLET_MAIN_DIR = path.join(appDir, main);
221
+ }
230
222
 
231
- // We use the same start script for all static blocklets
232
- appMain = require.resolve('@abtnode/static-server');
233
- appCwd = path.resolve(appMain, '../../');
223
+ if (component.mode !== BLOCKLET_MODES.DEVELOPMENT) {
224
+ const engine = getEngine(blockletEngineInfo.interpreter);
225
+ interpreter = engine.interpreter === 'node' ? '' : engine.interpreter;
226
+ interpreterArgs = engine.args || '';
234
227
  }
235
228
 
236
- return { dataDir, logsDir, cacheDir, appMain, appDir, mainDir, appCwd };
229
+ return { cwd, script, args, environmentObj, interpreter, interpreterArgs };
237
230
  };
238
231
 
239
232
  /**
@@ -372,7 +365,6 @@ const getComponentSystemEnvironments = (blocklet) => {
372
365
  BLOCKLET_LOG_DIR: blocklet.env.logsDir,
373
366
  BLOCKLET_CACHE_DIR: blocklet.env.cacheDir,
374
367
  BLOCKLET_APP_DIR: blocklet.env.appDir,
375
- BLOCKLET_MAIN_DIR: blocklet.env.mainDir,
376
368
  ...portEnvironments,
377
369
  };
378
370
  };
@@ -409,22 +401,7 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
409
401
  }
410
402
  });
411
403
 
412
- const mountPoints = [];
413
- for (const x of root.children || []) {
414
- const mountPoint = {
415
- title: x.meta.title,
416
- did: x.meta.bundleDid,
417
- name: x.meta.bundleName,
418
- mountPoint: x.mountPoint || '',
419
- };
420
-
421
- const webInterface = findWebInterface(x);
422
- if (webInterface && x.environmentObj[webInterface.port]) {
423
- mountPoint.port = x.environmentObj[webInterface.port];
424
- }
425
-
426
- mountPoints.push(mountPoint);
427
- }
404
+ const componentsInternalInfo = getComponentsInternalInfo(root);
428
405
 
429
406
  // use index 1 as the path to derive deterministic encryption key for blocklet
430
407
  const tmp = get(nodeEnvironments, 'ABT_NODE_SK')
@@ -433,17 +410,24 @@ const getRuntimeEnvironments = (blocklet, nodeEnvironments, ancestors) => {
433
410
 
434
411
  const BLOCKLET_APP_IDS = getBlockletAppIdList(root).join(',');
435
412
 
413
+ const componentApiKey = getComponentApiKey({
414
+ serverSk: nodeEnvironments.ABT_NODE_SK,
415
+ app: root,
416
+ component: blocklet,
417
+ });
418
+
436
419
  const env = {
437
420
  ...blocklet.configObj,
438
421
  ...getSharedConfigObj(blocklet, ancestors),
439
422
  ...blocklet.environmentObj,
440
423
  ...devEnvironments,
441
424
  BLOCKLET_WEB_PORTS: JSON.stringify(ports),
442
- BLOCKLET_MOUNT_POINTS: JSON.stringify(mountPoints),
425
+ BLOCKLET_MOUNT_POINTS: JSON.stringify(componentsInternalInfo),
443
426
  BLOCKLET_MODE: blocklet.mode || BLOCKLET_MODES.PRODUCTION,
444
427
  BLOCKLET_APP_EK: tmp?.secretKey,
445
428
  BLOCKLET_APP_VERSION: root.meta.version,
446
429
  BLOCKLET_APP_IDS,
430
+ BLOCKLET_COMPONENT_API_KEY: componentApiKey,
447
431
  ...nodeEnvironments,
448
432
  ...safeNodeEnvironments,
449
433
  };
@@ -513,6 +497,8 @@ const startBlockletProcess = async (
513
497
  throw new Error('blocklet should not be empty');
514
498
  }
515
499
 
500
+ const now = Date.now();
501
+
516
502
  await forEachBlocklet(
517
503
  blocklet,
518
504
  async (b, { ancestors }) => {
@@ -520,7 +506,11 @@ const startBlockletProcess = async (
520
506
  return;
521
507
  }
522
508
 
523
- const { appMain, processId, appCwd, logsDir } = b.env;
509
+ if (!hasStartEngine(b.meta)) {
510
+ return;
511
+ }
512
+
513
+ const { processId, logsDir, appDir } = b.env;
524
514
 
525
515
  if (skippedProcessIds.includes(processId)) {
526
516
  logger.info(`skip start skipped process ${processId}`);
@@ -532,6 +522,14 @@ const startBlockletProcess = async (
532
522
  return;
533
523
  }
534
524
 
525
+ if (b.mode !== BLOCKLET_MODES.DEVELOPMENT) {
526
+ validateBlockletEntry(appDir, b.meta);
527
+ }
528
+
529
+ const { cwd, script, args, environmentObj, interpreter, interpreterArgs } = getComponentStartEngine(b, {
530
+ e2eMode,
531
+ });
532
+
535
533
  // get env
536
534
  const env = getRuntimeEnvironments(b, nodeEnvironments, ancestors);
537
535
  const startedAt = Date.now();
@@ -553,7 +551,7 @@ const startBlockletProcess = async (
553
551
  const options = {
554
552
  namespace: 'blocklets',
555
553
  name: processId,
556
- cwd: appCwd,
554
+ cwd,
557
555
  // FIXME @linchen [] does not work, so use () here
558
556
  log_date_format: '(YYYY-MM-DD HH:mm:ss)',
559
557
  output: path.join(logsDir, 'output.log'),
@@ -563,9 +561,15 @@ const startBlockletProcess = async (
563
561
  max_memory_restart: `${maxMemoryRestart}M`,
564
562
  max_restarts: b.mode === BLOCKLET_MODES.DEVELOPMENT ? 0 : 3,
565
563
  env: {
564
+ ...environmentObj,
566
565
  ...env,
567
566
  NODE_ENV: 'production',
567
+ BLOCKLET_START_AT: now,
568
568
  },
569
+ script,
570
+ args,
571
+ interpreter,
572
+ interpreterArgs,
569
573
  };
570
574
 
571
575
  const clusterMode = get(b.meta, 'capabilities.clusterMode', false);
@@ -580,10 +584,9 @@ const startBlockletProcess = async (
580
584
  options.env.NODE_ENV = e2eMode ? 'e2e' : 'development';
581
585
  options.env.BROWSER = 'none';
582
586
  options.env.PORT = options.env[BLOCKLET_DEFAULT_PORT_NAME];
583
- options.script = appMain;
584
587
 
585
588
  if (process.platform === 'win32') {
586
- const [cmd, ...args] = options.script.split(' ').filter(Boolean);
589
+ const [cmd, ...argList] = options.script.split(' ').filter(Boolean);
587
590
 
588
591
  if (!SCRIPT_ENGINES_WHITE_LIST.includes(cmd)) {
589
592
  throw new Error(`${cmd} script is not supported, ${SCRIPT_ENGINES_WHITE_LIST.join(', ')} are supported`);
@@ -597,16 +600,8 @@ const startBlockletProcess = async (
597
600
  const cmdBinPath = pkg.bin[cmd];
598
601
 
599
602
  options.script = path.resolve(cmdPath, cmdBinPath);
600
- options.args = [...args].join(' ');
603
+ options.args = [...argList].join(' ');
601
604
  }
602
- } else {
603
- const blockletEngineInfo = getBlockletEngine(b.meta);
604
- options.args = blockletEngineInfo.args || [];
605
-
606
- const engine = getEngine(blockletEngineInfo.interpreter);
607
- options.interpreter = engine.interpreter === 'node' ? '' : engine.interpreter;
608
- options.interpreterArgs = engine.args || '';
609
- options.script = blockletEngineInfo.script || appMain;
610
605
  }
611
606
 
612
607
  await pm2.startAsync(options);
@@ -657,6 +652,10 @@ const deleteBlockletProcess = async (blocklet, { preDelete = noop, skippedProces
657
652
  return;
658
653
  }
659
654
 
655
+ if (!hasStartEngine(b.meta)) {
656
+ return;
657
+ }
658
+
660
659
  await preDelete(b, { ancestors });
661
660
  await deleteProcess(b.env.processId);
662
661
  },
@@ -732,7 +731,7 @@ const reloadProcess = (processId) =>
732
731
  });
733
732
 
734
733
  const validateBlocklet = (blocklet) =>
735
- forEachBlocklet(blocklet, (b) => {
734
+ forEachComponentV2(blocklet, (b) => {
736
735
  isRequirementsSatisfied(b.meta.requirements);
737
736
  validateEngine(getBlockletEngineNameByPlatform(b.meta));
738
737
  });
@@ -760,6 +759,10 @@ const checkBlockletProcessHealthy = async (blocklet, { minConsecutiveTime, timeo
760
759
  return;
761
760
  }
762
761
 
762
+ if (!hasStartEngine(b.meta)) {
763
+ return;
764
+ }
765
+
763
766
  if (shouldSkipComponent(b.meta.did, componentDids)) {
764
767
  logger.info('skip check component healthy not selected', { id: b.env.id, processId: b.env.processId });
765
768
  return;
@@ -1270,7 +1273,6 @@ const getBlocklet = async ({
1270
1273
  ...getComponentDirs(component, {
1271
1274
  dataDirs,
1272
1275
  ensure: ensureIntegrity,
1273
- validate: ensureIntegrity,
1274
1276
  ancestors,
1275
1277
  e2eMode: level === 0 ? e2eMode : false,
1276
1278
  }),
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.15-beta-d8e7b6c0",
6
+ "version": "1.16.15-beta-9318a201",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,19 +19,19 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "Apache-2.0",
21
21
  "dependencies": {
22
- "@abtnode/analytics": "1.16.15-beta-d8e7b6c0",
23
- "@abtnode/auth": "1.16.15-beta-d8e7b6c0",
24
- "@abtnode/certificate-manager": "1.16.15-beta-d8e7b6c0",
25
- "@abtnode/constant": "1.16.15-beta-d8e7b6c0",
26
- "@abtnode/cron": "1.16.15-beta-d8e7b6c0",
27
- "@abtnode/logger": "1.16.15-beta-d8e7b6c0",
28
- "@abtnode/models": "1.16.15-beta-d8e7b6c0",
29
- "@abtnode/queue": "1.16.15-beta-d8e7b6c0",
30
- "@abtnode/rbac": "1.16.15-beta-d8e7b6c0",
31
- "@abtnode/router-provider": "1.16.15-beta-d8e7b6c0",
32
- "@abtnode/static-server": "1.16.15-beta-d8e7b6c0",
33
- "@abtnode/timemachine": "1.16.15-beta-d8e7b6c0",
34
- "@abtnode/util": "1.16.15-beta-d8e7b6c0",
22
+ "@abtnode/analytics": "1.16.15-beta-9318a201",
23
+ "@abtnode/auth": "1.16.15-beta-9318a201",
24
+ "@abtnode/certificate-manager": "1.16.15-beta-9318a201",
25
+ "@abtnode/constant": "1.16.15-beta-9318a201",
26
+ "@abtnode/cron": "1.16.15-beta-9318a201",
27
+ "@abtnode/logger": "1.16.15-beta-9318a201",
28
+ "@abtnode/models": "1.16.15-beta-9318a201",
29
+ "@abtnode/queue": "1.16.15-beta-9318a201",
30
+ "@abtnode/rbac": "1.16.15-beta-9318a201",
31
+ "@abtnode/router-provider": "1.16.15-beta-9318a201",
32
+ "@abtnode/static-server": "1.16.15-beta-9318a201",
33
+ "@abtnode/timemachine": "1.16.15-beta-9318a201",
34
+ "@abtnode/util": "1.16.15-beta-9318a201",
35
35
  "@arcblock/did": "1.18.89",
36
36
  "@arcblock/did-auth": "1.18.89",
37
37
  "@arcblock/did-ext": "^1.18.89",
@@ -42,11 +42,11 @@
42
42
  "@arcblock/pm2-events": "^0.0.5",
43
43
  "@arcblock/validator": "^1.18.89",
44
44
  "@arcblock/vc": "1.18.89",
45
- "@blocklet/constant": "1.16.15-beta-d8e7b6c0",
46
- "@blocklet/meta": "1.16.15-beta-d8e7b6c0",
47
- "@blocklet/resolver": "1.16.15-beta-d8e7b6c0",
48
- "@blocklet/sdk": "1.16.15-beta-d8e7b6c0",
49
- "@did-space/client": "^0.2.141",
45
+ "@blocklet/constant": "1.16.15-beta-9318a201",
46
+ "@blocklet/meta": "1.16.15-beta-9318a201",
47
+ "@blocklet/resolver": "1.16.15-beta-9318a201",
48
+ "@blocklet/sdk": "1.16.15-beta-9318a201",
49
+ "@did-space/client": "^0.2.163",
50
50
  "@fidm/x509": "^1.2.1",
51
51
  "@ocap/mcrypto": "1.18.89",
52
52
  "@ocap/util": "1.18.89",
@@ -98,5 +98,5 @@
98
98
  "jest": "^27.5.1",
99
99
  "unzipper": "^0.10.11"
100
100
  },
101
- "gitHead": "87ebe2e8267e634e2217d7ca28231d0b01636ae6"
101
+ "gitHead": "f3722cbd4fe10c5fa083cad7e859ecff6095060d"
102
102
  }