@abtnode/core 1.16.15-beta-d8e7b6c0 → 1.16.15-beta-375899b6

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
 
@@ -613,6 +614,13 @@ class DiskBlockletManager extends BaseBlockletManager {
613
614
  // send notification to wallet
614
615
  this.emit(BlockletEvents.stopped, { ...res, componentDids });
615
616
 
617
+ this.emit(BlockletInternalEvents.componentStopped, {
618
+ appDid: blocklet.appDid,
619
+ components: componentDids?.length
620
+ ? componentDids.map((x) => ({ did: x }))
621
+ : blocklet.children.map((x) => ({ did: x.meta.did })),
622
+ });
623
+ // for backward compatibility
616
624
  this.emit(BlockletInternalEvents.componentsUpdated, {
617
625
  appDid: blocklet.appDid,
618
626
  components: getComponentsInternalInfo(res),
@@ -939,6 +947,11 @@ class DiskBlockletManager extends BaseBlockletManager {
939
947
  componentDids: [child.meta.did],
940
948
  });
941
949
 
950
+ this.emit(BlockletInternalEvents.componentRemoved, {
951
+ appDid: blocklet.appDid,
952
+ components: [{ did: child.meta.did }],
953
+ });
954
+ // for backward compatibility
942
955
  this.emit(BlockletInternalEvents.componentsUpdated, {
943
956
  appDid: blocklet.appDid,
944
957
  components: getComponentsInternalInfo(newBlocklet),
@@ -1395,6 +1408,11 @@ class DiskBlockletManager extends BaseBlockletManager {
1395
1408
  await states.blocklet.updateBlocklet(rootDid, { mountPoint: blocklet.mountPoint, children: blocklet.children });
1396
1409
 
1397
1410
  this.emit(BlockletEvents.upgraded, { blocklet, context: { ...context, createAuditLog: false } }); // trigger router refresh
1411
+ this.emit(BlockletInternalEvents.componentUpdated, {
1412
+ appDid: blocklet.appDid,
1413
+ components: getComponentsInternalInfo(blocklet).filter((x) => x.did === component.meta.did),
1414
+ });
1415
+ // for backward compatibility
1398
1416
  this.emit(BlockletInternalEvents.componentsUpdated, {
1399
1417
  appDid: blocklet.appDid,
1400
1418
  components: getComponentsInternalInfo(blocklet),
@@ -1514,6 +1532,10 @@ class DiskBlockletManager extends BaseBlockletManager {
1514
1532
  return;
1515
1533
  }
1516
1534
 
1535
+ if (!hasStartEngine(component.meta)) {
1536
+ return;
1537
+ }
1538
+
1517
1539
  try {
1518
1540
  const status = await getProcessState(component.env.processId);
1519
1541
  const oldStatus = component.status;
@@ -2044,6 +2066,11 @@ class DiskBlockletManager extends BaseBlockletManager {
2044
2066
 
2045
2067
  const res = await this.getBlocklet(did);
2046
2068
 
2069
+ this.emit(BlockletInternalEvents.componentStarted, {
2070
+ appDid: blocklet.appDid,
2071
+ components: (componentDids || []).map((x) => ({ did: x })),
2072
+ });
2073
+ // for backward compatibility
2047
2074
  this.emit(BlockletInternalEvents.componentsUpdated, {
2048
2075
  appDid: blocklet.appDid,
2049
2076
  components: getComponentsInternalInfo(res),
@@ -2051,11 +2078,14 @@ class DiskBlockletManager extends BaseBlockletManager {
2051
2078
 
2052
2079
  this.emit(BlockletEvents.statusChange, res);
2053
2080
  this.emit(BlockletEvents.started, { ...res, componentDids });
2081
+
2082
+ const componentNames = getComponentNamesWithVersion(blocklet, componentDids);
2083
+ const description = componentNames
2084
+ ? `${getComponentNamesWithVersion(blocklet, componentDids)} is successfully started for ${blocklet.meta.title}.`
2085
+ : `${blocklet.meta.title} is successfully started`;
2054
2086
  this._createNotification(did, {
2055
2087
  title: '',
2056
- description: `${getComponentNamesWithVersion(blocklet, componentDids)} is successfully started for ${
2057
- blocklet.meta.title
2058
- }.`,
2088
+ description,
2059
2089
  entityType: 'blocklet',
2060
2090
  entityId: did,
2061
2091
  severity: 'success',
@@ -2074,9 +2104,10 @@ class DiskBlockletManager extends BaseBlockletManager {
2074
2104
  await this.deleteProcess({ did, componentDids }, context);
2075
2105
  const doc = await states.blocklet.setBlockletStatus(did, BlockletStatus.error, { componentDids });
2076
2106
 
2077
- const description = `${getComponentNamesWithVersion(blocklet, componentDids)} start failed for ${title}: ${
2078
- error.message
2079
- }`;
2107
+ const componentNames = getComponentNamesWithVersion(blocklet, componentDids);
2108
+ const description = componentNames
2109
+ ? `${getComponentNamesWithVersion(blocklet, componentDids)} start failed for ${title}: ${error.message}`
2110
+ : `${blocklet.meta.title} start failed: ${error.message}`;
2080
2111
 
2081
2112
  this._createNotification(did, {
2082
2113
  title: '',
@@ -2671,7 +2702,6 @@ class DiskBlockletManager extends BaseBlockletManager {
2671
2702
  logger.info('updated blocklet for upgrading', { did, version, source, name });
2672
2703
 
2673
2704
  if (oldBlocklet.status === BlockletStatus.running) {
2674
- // start new process
2675
2705
  try {
2676
2706
  await this.start({ did, componentDids }, context);
2677
2707
  logger.info('started blocklet for upgrading', { did, version, componentDids });
@@ -2723,6 +2753,18 @@ class DiskBlockletManager extends BaseBlockletManager {
2723
2753
 
2724
2754
  await this._rollbackCache.remove({ did: blocklet.meta.did });
2725
2755
 
2756
+ if (oldBlocklet.status === BlockletStatus.running) {
2757
+ this.emit(
2758
+ action === INSTALL_ACTIONS.INSTALL_COMPONENT
2759
+ ? BlockletInternalEvents.componentInstalled
2760
+ : BlockletInternalEvents.componentUpgraded,
2761
+ {
2762
+ appDid: blocklet.appDid,
2763
+ components: getComponentsInternalInfo(blocklet).filter((c) => componentDids.includes(c.did)),
2764
+ }
2765
+ );
2766
+ }
2767
+ // for backward compatibility
2726
2768
  this.emit(BlockletInternalEvents.componentsUpdated, {
2727
2769
  appDid: blocklet.appDid,
2728
2770
  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
 
@@ -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,13 @@ 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;
514
+
515
+ validateBlockletEntry(appDir, b.meta);
524
516
 
525
517
  if (skippedProcessIds.includes(processId)) {
526
518
  logger.info(`skip start skipped process ${processId}`);
@@ -532,6 +524,10 @@ const startBlockletProcess = async (
532
524
  return;
533
525
  }
534
526
 
527
+ const { cwd, script, args, environmentObj, interpreter, interpreterArgs } = getComponentStartEngine(b, {
528
+ e2eMode,
529
+ });
530
+
535
531
  // get env
536
532
  const env = getRuntimeEnvironments(b, nodeEnvironments, ancestors);
537
533
  const startedAt = Date.now();
@@ -553,7 +549,7 @@ const startBlockletProcess = async (
553
549
  const options = {
554
550
  namespace: 'blocklets',
555
551
  name: processId,
556
- cwd: appCwd,
552
+ cwd,
557
553
  // FIXME @linchen [] does not work, so use () here
558
554
  log_date_format: '(YYYY-MM-DD HH:mm:ss)',
559
555
  output: path.join(logsDir, 'output.log'),
@@ -563,9 +559,15 @@ const startBlockletProcess = async (
563
559
  max_memory_restart: `${maxMemoryRestart}M`,
564
560
  max_restarts: b.mode === BLOCKLET_MODES.DEVELOPMENT ? 0 : 3,
565
561
  env: {
562
+ ...environmentObj,
566
563
  ...env,
567
564
  NODE_ENV: 'production',
565
+ BLOCKLET_START_AT: now,
568
566
  },
567
+ script,
568
+ args,
569
+ interpreter,
570
+ interpreterArgs,
569
571
  };
570
572
 
571
573
  const clusterMode = get(b.meta, 'capabilities.clusterMode', false);
@@ -580,10 +582,9 @@ const startBlockletProcess = async (
580
582
  options.env.NODE_ENV = e2eMode ? 'e2e' : 'development';
581
583
  options.env.BROWSER = 'none';
582
584
  options.env.PORT = options.env[BLOCKLET_DEFAULT_PORT_NAME];
583
- options.script = appMain;
584
585
 
585
586
  if (process.platform === 'win32') {
586
- const [cmd, ...args] = options.script.split(' ').filter(Boolean);
587
+ const [cmd, ...argList] = options.script.split(' ').filter(Boolean);
587
588
 
588
589
  if (!SCRIPT_ENGINES_WHITE_LIST.includes(cmd)) {
589
590
  throw new Error(`${cmd} script is not supported, ${SCRIPT_ENGINES_WHITE_LIST.join(', ')} are supported`);
@@ -597,16 +598,8 @@ const startBlockletProcess = async (
597
598
  const cmdBinPath = pkg.bin[cmd];
598
599
 
599
600
  options.script = path.resolve(cmdPath, cmdBinPath);
600
- options.args = [...args].join(' ');
601
+ options.args = [...argList].join(' ');
601
602
  }
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
603
  }
611
604
 
612
605
  await pm2.startAsync(options);
@@ -657,6 +650,10 @@ const deleteBlockletProcess = async (blocklet, { preDelete = noop, skippedProces
657
650
  return;
658
651
  }
659
652
 
653
+ if (!hasStartEngine(b.meta)) {
654
+ return;
655
+ }
656
+
660
657
  await preDelete(b, { ancestors });
661
658
  await deleteProcess(b.env.processId);
662
659
  },
@@ -732,7 +729,7 @@ const reloadProcess = (processId) =>
732
729
  });
733
730
 
734
731
  const validateBlocklet = (blocklet) =>
735
- forEachBlocklet(blocklet, (b) => {
732
+ forEachComponentV2(blocklet, (b) => {
736
733
  isRequirementsSatisfied(b.meta.requirements);
737
734
  validateEngine(getBlockletEngineNameByPlatform(b.meta));
738
735
  });
@@ -760,6 +757,10 @@ const checkBlockletProcessHealthy = async (blocklet, { minConsecutiveTime, timeo
760
757
  return;
761
758
  }
762
759
 
760
+ if (!hasStartEngine(b.meta)) {
761
+ return;
762
+ }
763
+
763
764
  if (shouldSkipComponent(b.meta.did, componentDids)) {
764
765
  logger.info('skip check component healthy not selected', { id: b.env.id, processId: b.env.processId });
765
766
  return;
@@ -1270,7 +1271,6 @@ const getBlocklet = async ({
1270
1271
  ...getComponentDirs(component, {
1271
1272
  dataDirs,
1272
1273
  ensure: ensureIntegrity,
1273
- validate: ensureIntegrity,
1274
1274
  ancestors,
1275
1275
  e2eMode: level === 0 ? e2eMode : false,
1276
1276
  }),
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-375899b6",
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-375899b6",
23
+ "@abtnode/auth": "1.16.15-beta-375899b6",
24
+ "@abtnode/certificate-manager": "1.16.15-beta-375899b6",
25
+ "@abtnode/constant": "1.16.15-beta-375899b6",
26
+ "@abtnode/cron": "1.16.15-beta-375899b6",
27
+ "@abtnode/logger": "1.16.15-beta-375899b6",
28
+ "@abtnode/models": "1.16.15-beta-375899b6",
29
+ "@abtnode/queue": "1.16.15-beta-375899b6",
30
+ "@abtnode/rbac": "1.16.15-beta-375899b6",
31
+ "@abtnode/router-provider": "1.16.15-beta-375899b6",
32
+ "@abtnode/static-server": "1.16.15-beta-375899b6",
33
+ "@abtnode/timemachine": "1.16.15-beta-375899b6",
34
+ "@abtnode/util": "1.16.15-beta-375899b6",
35
35
  "@arcblock/did": "1.18.89",
36
36
  "@arcblock/did-auth": "1.18.89",
37
37
  "@arcblock/did-ext": "^1.18.89",
@@ -42,10 +42,10 @@
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",
45
+ "@blocklet/constant": "1.16.15-beta-375899b6",
46
+ "@blocklet/meta": "1.16.15-beta-375899b6",
47
+ "@blocklet/resolver": "1.16.15-beta-375899b6",
48
+ "@blocklet/sdk": "1.16.15-beta-375899b6",
49
49
  "@did-space/client": "^0.2.141",
50
50
  "@fidm/x509": "^1.2.1",
51
51
  "@ocap/mcrypto": "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": "c999a7f47ecdca1494eb53fc177d28899b3effc9"
102
102
  }