@abtnode/core 1.16.8-beta-ca58a421 → 1.16.8-beta-81db8efa
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/lib/api/node.js +22 -4
- package/lib/blocklet/manager/disk.js +150 -120
- package/lib/blocklet/storage/backup/spaces.js +2 -4
- package/lib/blocklet/storage/restore/spaces.js +1 -1
- package/lib/event.js +43 -0
- package/lib/index.js +2 -0
- package/lib/migrations/1.16.8-component-title.js +66 -0
- package/lib/states/audit-log.js +24 -2
- package/lib/util/spaces.js +18 -5
- package/package.json +20 -19
package/lib/api/node.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
/* eslint-disable no-underscore-dangle */
|
|
3
3
|
const assert = require('assert');
|
|
4
4
|
const os = require('os');
|
|
5
|
+
const LRU = require('lru-cache');
|
|
5
6
|
const isDocker = require('@abtnode/util/lib/is-docker');
|
|
6
7
|
const isGitpod = require('@abtnode/util/lib/is-gitpod');
|
|
7
8
|
const getFolderSize = require('@abtnode/util/lib/get-folder-size');
|
|
8
9
|
const canPackageReadWrite = require('@abtnode/util/lib/can-pkg-rw');
|
|
9
10
|
const { toDelegateAddress } = require('@arcblock/did-util');
|
|
11
|
+
const { SERVER_CACHE_TTL } = require('@abtnode/constant');
|
|
10
12
|
|
|
11
13
|
const logger = require('@abtnode/logger')('@abtnode/core:api:node');
|
|
12
14
|
|
|
@@ -36,6 +38,11 @@ class NodeAPI {
|
|
|
36
38
|
historyLength: MONITOR_HISTORY_LENGTH,
|
|
37
39
|
});
|
|
38
40
|
|
|
41
|
+
this.cache = new LRU({
|
|
42
|
+
max: 1,
|
|
43
|
+
maxAge: SERVER_CACHE_TTL,
|
|
44
|
+
});
|
|
45
|
+
|
|
39
46
|
this.state = state;
|
|
40
47
|
}
|
|
41
48
|
|
|
@@ -59,15 +66,26 @@ class NodeAPI {
|
|
|
59
66
|
}
|
|
60
67
|
}
|
|
61
68
|
|
|
62
|
-
async getInfo() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
async getInfo({ useCache } = {}) {
|
|
70
|
+
let info;
|
|
71
|
+
if (useCache && this.cache.has('info')) {
|
|
72
|
+
info = this.cache.get('info');
|
|
73
|
+
} else {
|
|
74
|
+
info = await this.state.read();
|
|
75
|
+
const env = await this.state.getEnvironments();
|
|
76
|
+
info.environments = Object.keys(env).map((x) => ({ key: x, value: env[x] }));
|
|
77
|
+
this.cache.set('info', info);
|
|
78
|
+
}
|
|
79
|
+
|
|
66
80
|
info.uptime = process.uptime() * 1000;
|
|
67
81
|
|
|
68
82
|
return info;
|
|
69
83
|
}
|
|
70
84
|
|
|
85
|
+
deleteCache() {
|
|
86
|
+
this.cache.del('del');
|
|
87
|
+
}
|
|
88
|
+
|
|
71
89
|
async getDiskInfo() {
|
|
72
90
|
let diskInfo = { app: 0, cache: 0, log: 0, data: 0, blocklets: 0 };
|
|
73
91
|
try {
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
const fs = require('fs-extra');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const flat = require('flat');
|
|
6
|
+
const LRU = require('lru-cache');
|
|
6
7
|
const get = require('lodash/get');
|
|
7
8
|
const omit = require('lodash/omit');
|
|
8
9
|
const merge = require('lodash/merge');
|
|
9
10
|
const pick = require('lodash/pick');
|
|
10
11
|
const isEmpty = require('lodash/isEmpty');
|
|
11
|
-
const cloneDeep = require('lodash/cloneDeep');
|
|
12
12
|
const { isNFTExpired, getNftExpirationDate } = require('@abtnode/util/lib/nft');
|
|
13
13
|
const didDocument = require('@abtnode/util/lib/did-document');
|
|
14
14
|
const { sign } = require('@arcblock/jwt');
|
|
@@ -22,6 +22,7 @@ const {
|
|
|
22
22
|
BLOCKLET_INSTALL_TYPE,
|
|
23
23
|
NODE_MODES,
|
|
24
24
|
APP_STRUCT_VERSION,
|
|
25
|
+
BLOCKLET_CACHE_TTL,
|
|
25
26
|
} = require('@abtnode/constant');
|
|
26
27
|
|
|
27
28
|
const getBlockletEngine = require('@blocklet/meta/lib/engine');
|
|
@@ -41,6 +42,7 @@ const {
|
|
|
41
42
|
const getComponentProcessId = require('@blocklet/meta/lib/get-component-process-id');
|
|
42
43
|
const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
|
|
43
44
|
const { titleSchema, updateMountPointSchema, environmentNameSchema } = require('@blocklet/meta/lib/schema');
|
|
45
|
+
const { emailConfigSchema } = require('@blocklet/sdk/lib/validators/email');
|
|
44
46
|
const Lock = require('@abtnode/util/lib/lock');
|
|
45
47
|
|
|
46
48
|
const {
|
|
@@ -82,7 +84,6 @@ const {
|
|
|
82
84
|
checkBlockletProcessHealthy,
|
|
83
85
|
validateBlocklet,
|
|
84
86
|
validateBlockletChainInfo,
|
|
85
|
-
statusMap,
|
|
86
87
|
pruneBlockletBundle,
|
|
87
88
|
getDiskInfo,
|
|
88
89
|
getRuntimeEnvironments,
|
|
@@ -128,7 +129,7 @@ const UpgradeComponents = require('./helper/upgrade-components');
|
|
|
128
129
|
const BlockletDownloader = require('../downloader/blocklet-downloader');
|
|
129
130
|
const RollbackCache = require('./helper/rollback-cache');
|
|
130
131
|
const { migrateApplicationToStructV2 } = require('./helper/migrate-application-to-struct-v2');
|
|
131
|
-
const { getBackupFilesUrlFromEndpoint,
|
|
132
|
+
const { getBackupFilesUrlFromEndpoint, getBackupEndpoint } = require('../../util/spaces');
|
|
132
133
|
const { validateAddSpaceGateway, validateUpdateSpaceGateway } = require('../../validators/space-gateway');
|
|
133
134
|
|
|
134
135
|
const { formatEnvironments, shouldUpdateBlockletStatus, getBlockletMeta, validateOwner } = util;
|
|
@@ -221,7 +222,10 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
221
222
|
this.teamManager = teamManager;
|
|
222
223
|
|
|
223
224
|
// cached installed blocklets for performance
|
|
224
|
-
this.cachedBlocklets =
|
|
225
|
+
this.cachedBlocklets = new LRU({
|
|
226
|
+
max: 100,
|
|
227
|
+
maxAge: BLOCKLET_CACHE_TTL,
|
|
228
|
+
});
|
|
225
229
|
|
|
226
230
|
this.runtimeMonitor = new BlockletRuntimeMonitor({ historyLength: MONITOR_HISTORY_LENGTH, states });
|
|
227
231
|
|
|
@@ -944,7 +948,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
944
948
|
}
|
|
945
949
|
|
|
946
950
|
// Get blocklet by blockletDid or appDid
|
|
947
|
-
async detail({ did, attachConfig = true, attachRuntimeInfo
|
|
951
|
+
async detail({ did, attachConfig = true, attachRuntimeInfo, useCache }, context) {
|
|
948
952
|
if (!did) {
|
|
949
953
|
throw new Error('did should not be empty');
|
|
950
954
|
}
|
|
@@ -953,49 +957,36 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
953
957
|
return states.blocklet.getBlocklet(did);
|
|
954
958
|
}
|
|
955
959
|
|
|
956
|
-
if (
|
|
957
|
-
|
|
958
|
-
const blocklet = await this.getBlocklet(did, { throwOnNotExist: false });
|
|
959
|
-
return blocklet;
|
|
960
|
-
} catch (e) {
|
|
961
|
-
logger.error('get blocklet detail error', { error: e });
|
|
962
|
-
return states.blocklet.getBlocklet(did);
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
const nodeInfo = await states.node.read();
|
|
960
|
+
if (attachRuntimeInfo) {
|
|
961
|
+
const nodeInfo = await states.node.read();
|
|
967
962
|
|
|
968
|
-
|
|
969
|
-
|
|
963
|
+
return this._attachRuntimeInfo({ did, nodeInfo, diskInfo: true, context });
|
|
964
|
+
}
|
|
970
965
|
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
await Promise.all(
|
|
975
|
-
blocklets.map((x) => {
|
|
976
|
-
if (isBeforeInstalled(x.status)) {
|
|
977
|
-
return x;
|
|
978
|
-
}
|
|
966
|
+
if (useCache && this.cachedBlocklets.has(did)) {
|
|
967
|
+
return this.cachedBlocklets.get(did);
|
|
968
|
+
}
|
|
979
969
|
|
|
980
|
-
|
|
981
|
-
|
|
970
|
+
try {
|
|
971
|
+
const blocklet = await this.getBlocklet(did, { throwOnNotExist: false });
|
|
982
972
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
)
|
|
992
|
-
).filter(Boolean);
|
|
973
|
+
if (blocklet) {
|
|
974
|
+
if (blocklet.appDid) {
|
|
975
|
+
this.cachedBlocklets.set(blocklet.appDid, blocklet);
|
|
976
|
+
}
|
|
977
|
+
if (blocklet.appPid) {
|
|
978
|
+
this.cachedBlocklets.set(blocklet.appPid, blocklet);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
993
981
|
|
|
994
|
-
|
|
995
|
-
|
|
982
|
+
return blocklet;
|
|
983
|
+
} catch (e) {
|
|
984
|
+
logger.error('get blocklet detail error', { error: e });
|
|
985
|
+
return states.blocklet.getBlocklet(did);
|
|
986
|
+
}
|
|
996
987
|
}
|
|
997
988
|
|
|
998
|
-
async list({ includeRuntimeInfo = true,
|
|
989
|
+
async list({ includeRuntimeInfo = true, query, filter } = {}, context) {
|
|
999
990
|
const condition = { ...flat(query || {}) };
|
|
1000
991
|
if (filter === 'external-only') {
|
|
1001
992
|
condition.controller = {
|
|
@@ -1012,7 +1003,7 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1012
1003
|
const blocklets = await states.blocklet.getBlocklets(condition);
|
|
1013
1004
|
|
|
1014
1005
|
if (includeRuntimeInfo) {
|
|
1015
|
-
return this.
|
|
1006
|
+
return this._attachBlockletListRuntimeInfo({ blocklets }, context);
|
|
1016
1007
|
}
|
|
1017
1008
|
|
|
1018
1009
|
return blocklets;
|
|
@@ -1235,6 +1226,22 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1235
1226
|
return newState;
|
|
1236
1227
|
}
|
|
1237
1228
|
|
|
1229
|
+
async configNotification({ did, notification = {} }) {
|
|
1230
|
+
const newConfig = JSON.parse(notification);
|
|
1231
|
+
const { error, value: validateConfig } = emailConfigSchema.validate(newConfig);
|
|
1232
|
+
if (error) {
|
|
1233
|
+
logger.error('configNotification validate error', { error });
|
|
1234
|
+
throw new Error(error.message);
|
|
1235
|
+
}
|
|
1236
|
+
const oldConfig = await states.blockletExtras.getSettings(did, 'notification', {});
|
|
1237
|
+
const mergeConfig = { ...oldConfig, ...validateConfig };
|
|
1238
|
+
await states.blockletExtras.setSettings(did, { notification: mergeConfig });
|
|
1239
|
+
const newState = await this.getBlocklet(did);
|
|
1240
|
+
this.emit(BlockletEvents.updated, newState);
|
|
1241
|
+
return newState;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// TODO: this method can be removed if title is not changed anymore
|
|
1238
1245
|
async updateComponentTitle({ did, rootDid: inputRootDid, title }) {
|
|
1239
1246
|
await titleSchema.validateAsync(title);
|
|
1240
1247
|
|
|
@@ -1595,6 +1602,14 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1595
1602
|
return states.backup.getBlockletBackups({ did });
|
|
1596
1603
|
}
|
|
1597
1604
|
|
|
1605
|
+
deleteCache(did) {
|
|
1606
|
+
const cache = this.cachedBlocklets.get(did);
|
|
1607
|
+
if (cache) {
|
|
1608
|
+
this.cachedBlocklets.del(cache.appDid);
|
|
1609
|
+
this.cachedBlocklets.del(cache.appPid);
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1598
1613
|
// ============================================================================================
|
|
1599
1614
|
// Private API that are used by self of helper function
|
|
1600
1615
|
// ============================================================================================
|
|
@@ -1890,11 +1905,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1890
1905
|
await spacesBackup.backup();
|
|
1891
1906
|
|
|
1892
1907
|
await states.backup.success(backup._id, {
|
|
1893
|
-
targetUrl: getBackupFilesUrlFromEndpoint(
|
|
1908
|
+
targetUrl: getBackupFilesUrlFromEndpoint(getBackupEndpoint(blocklet?.environments)),
|
|
1894
1909
|
});
|
|
1895
1910
|
|
|
1896
1911
|
// 备份成功了
|
|
1897
|
-
this.emit(BlockletEvents.backupProgress, {
|
|
1912
|
+
this.emit(BlockletEvents.backupProgress, {
|
|
1913
|
+
appDid,
|
|
1914
|
+
meta: { did: appPid },
|
|
1915
|
+
completed: true,
|
|
1916
|
+
progress: 100,
|
|
1917
|
+
context,
|
|
1918
|
+
blocklet,
|
|
1919
|
+
});
|
|
1898
1920
|
} catch (error) {
|
|
1899
1921
|
await states.backup.fail(backup._id, {
|
|
1900
1922
|
message: error?.message,
|
|
@@ -1905,6 +1927,8 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1905
1927
|
completed: true,
|
|
1906
1928
|
progress: -1,
|
|
1907
1929
|
message: error?.message,
|
|
1930
|
+
context,
|
|
1931
|
+
blocklet,
|
|
1908
1932
|
});
|
|
1909
1933
|
throw error;
|
|
1910
1934
|
}
|
|
@@ -1921,59 +1945,69 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
1921
1945
|
*/
|
|
1922
1946
|
// eslint-disable-next-line no-unused-vars
|
|
1923
1947
|
async _onRestoreFromSpaces({ input, context }) {
|
|
1924
|
-
if (input.delay) {
|
|
1925
|
-
await sleep(input.delay);
|
|
1926
|
-
}
|
|
1927
|
-
|
|
1928
1948
|
const appPid = input.appDid;
|
|
1929
1949
|
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
});
|
|
1950
|
+
try {
|
|
1951
|
+
if (input.delay) {
|
|
1952
|
+
await sleep(input.delay);
|
|
1953
|
+
}
|
|
1935
1954
|
|
|
1936
|
-
|
|
1955
|
+
this.emit(BlockletEvents.restoreProgress, {
|
|
1956
|
+
appDid: input.appDid,
|
|
1957
|
+
meta: { did: appPid },
|
|
1958
|
+
status: RESTORE_PROGRESS_STATUS.start,
|
|
1959
|
+
});
|
|
1937
1960
|
|
|
1938
|
-
|
|
1939
|
-
|
|
1961
|
+
const userDid = context.user.did;
|
|
1962
|
+
const spacesRestore = new SpacesRestore({ ...input, appPid, event: this, userDid, referrer: context.referrer });
|
|
1963
|
+
const params = await spacesRestore.restore();
|
|
1940
1964
|
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1965
|
+
const removeRestoreDir = () => {
|
|
1966
|
+
if (fs.existsSync(spacesRestore.restoreDir)) {
|
|
1967
|
+
fs.remove(spacesRestore.restoreDir).catch((err) => {
|
|
1968
|
+
logger.error('failed to remove restore dir', { error: err, dir: spacesRestore.restoreDir });
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
};
|
|
1972
|
+
|
|
1973
|
+
this.emit(BlockletEvents.restoreProgress, {
|
|
1974
|
+
appDid: input.appDid,
|
|
1975
|
+
meta: { did: appPid },
|
|
1976
|
+
status: RESTORE_PROGRESS_STATUS.installing,
|
|
1977
|
+
});
|
|
1978
|
+
|
|
1979
|
+
try {
|
|
1980
|
+
await installApplicationFromBackup({
|
|
1981
|
+
url: `file://${spacesRestore.restoreDir}`,
|
|
1982
|
+
moveDir: true,
|
|
1983
|
+
...merge(...params),
|
|
1984
|
+
manager: this,
|
|
1985
|
+
states,
|
|
1986
|
+
controller: input.controller,
|
|
1987
|
+
context: { ...context, startImmediately: true },
|
|
1945
1988
|
});
|
|
1946
|
-
}
|
|
1947
|
-
};
|
|
1948
1989
|
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1990
|
+
removeRestoreDir();
|
|
1991
|
+
} catch (error) {
|
|
1992
|
+
removeRestoreDir();
|
|
1993
|
+
throw error;
|
|
1994
|
+
}
|
|
1954
1995
|
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
...merge(...params),
|
|
1960
|
-
manager: this,
|
|
1961
|
-
states,
|
|
1962
|
-
controller: input.controller,
|
|
1963
|
-
context: { ...context, startImmediately: true },
|
|
1996
|
+
this.emit(BlockletEvents.restoreProgress, {
|
|
1997
|
+
appDid: input.appDid,
|
|
1998
|
+
meta: { did: appPid },
|
|
1999
|
+
status: RESTORE_PROGRESS_STATUS.completed,
|
|
1964
2000
|
});
|
|
1965
|
-
|
|
1966
|
-
removeRestoreDir();
|
|
1967
2001
|
} catch (error) {
|
|
1968
|
-
|
|
2002
|
+
this.emit(BlockletEvents.restoreProgress, {
|
|
2003
|
+
appDid: input.appDid,
|
|
2004
|
+
meta: { did: appPid },
|
|
2005
|
+
status: RESTORE_PROGRESS_STATUS.error,
|
|
2006
|
+
message: error.message,
|
|
2007
|
+
});
|
|
2008
|
+
|
|
1969
2009
|
throw error;
|
|
1970
2010
|
}
|
|
1971
|
-
|
|
1972
|
-
this.emit(BlockletEvents.restoreProgress, {
|
|
1973
|
-
appDid: input.appDid,
|
|
1974
|
-
meta: { did: appPid },
|
|
1975
|
-
status: RESTORE_PROGRESS_STATUS.completed,
|
|
1976
|
-
});
|
|
1977
2011
|
}
|
|
1978
2012
|
|
|
1979
2013
|
async _updateBlockletEnvironment(did) {
|
|
@@ -2026,7 +2060,27 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2026
2060
|
return states.blocklet.updateBlocklet(did, blocklet);
|
|
2027
2061
|
}
|
|
2028
2062
|
|
|
2029
|
-
async
|
|
2063
|
+
async _attachBlockletListRuntimeInfo({ blocklets }, context) {
|
|
2064
|
+
const nodeInfo = await states.node.read();
|
|
2065
|
+
return (
|
|
2066
|
+
await Promise.all(
|
|
2067
|
+
blocklets.map((x) => {
|
|
2068
|
+
if (isBeforeInstalled(x.status)) {
|
|
2069
|
+
return x;
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
return this._attachRuntimeInfo({
|
|
2073
|
+
did: x.meta.did,
|
|
2074
|
+
nodeInfo,
|
|
2075
|
+
diskInfo: false,
|
|
2076
|
+
context,
|
|
2077
|
+
});
|
|
2078
|
+
})
|
|
2079
|
+
)
|
|
2080
|
+
).filter(Boolean);
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
async _attachRuntimeInfo({ did, nodeInfo, diskInfo = true, context }) {
|
|
2030
2084
|
if (!did) {
|
|
2031
2085
|
throw new Error('did should not be empty');
|
|
2032
2086
|
}
|
|
@@ -2038,24 +2092,6 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2038
2092
|
return null;
|
|
2039
2093
|
}
|
|
2040
2094
|
|
|
2041
|
-
const fromCache = !!cachedBlocklet;
|
|
2042
|
-
|
|
2043
|
-
// if from cached data, only use cache data of runtime info (engine, diskInfo, runtimeInfo...)
|
|
2044
|
-
if (fromCache) {
|
|
2045
|
-
const cached = {};
|
|
2046
|
-
forEachBlockletSync(cachedBlocklet, (component, { id }) => {
|
|
2047
|
-
cached[id] = component;
|
|
2048
|
-
});
|
|
2049
|
-
|
|
2050
|
-
Object.assign(blocklet, pick(cachedBlocklet, ['appRuntimeInfo', 'diskInfo']));
|
|
2051
|
-
|
|
2052
|
-
forEachBlockletSync(blocklet, (component, { id }) => {
|
|
2053
|
-
if (cached[id]) {
|
|
2054
|
-
Object.assign(component, pick(cached[id], ['runtimeInfo']));
|
|
2055
|
-
}
|
|
2056
|
-
});
|
|
2057
|
-
}
|
|
2058
|
-
|
|
2059
2095
|
// 处理 domainAliases#value SLOT_FOR_IP_DNS_SITE
|
|
2060
2096
|
if (blocklet?.site?.domainAliases?.length) {
|
|
2061
2097
|
const nodeIp = await getAccessibleExternalNodeIp(nodeInfo);
|
|
@@ -2068,24 +2104,18 @@ class BlockletManager extends BaseBlockletManager {
|
|
|
2068
2104
|
// app runtime info, app status
|
|
2069
2105
|
blocklet.appRuntimeInfo = this.runtimeMonitor.getRuntimeInfo(blocklet.meta.did);
|
|
2070
2106
|
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
component.engine = getEngine(getBlockletEngineNameByPlatform(component.meta)).describe();
|
|
2075
|
-
|
|
2076
|
-
if (level === 0) {
|
|
2077
|
-
component.diskInfo = await getDiskInfo(component, {
|
|
2078
|
-
useFakeDiskInfo: !diskInfo,
|
|
2079
|
-
});
|
|
2080
|
-
}
|
|
2107
|
+
// app disk info, component runtime info, component engine
|
|
2108
|
+
await forEachBlocklet(blocklet, async (component, { level }) => {
|
|
2109
|
+
component.engine = getEngine(getBlockletEngineNameByPlatform(component.meta)).describe();
|
|
2081
2110
|
|
|
2082
|
-
|
|
2111
|
+
if (level === 0) {
|
|
2112
|
+
component.diskInfo = await getDiskInfo(component, {
|
|
2113
|
+
useFakeDiskInfo: !diskInfo,
|
|
2114
|
+
});
|
|
2115
|
+
}
|
|
2083
2116
|
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
}
|
|
2087
|
-
});
|
|
2088
|
-
}
|
|
2117
|
+
component.runtimeInfo = this.runtimeMonitor.getRuntimeInfo(blocklet.meta.did, component.env.id);
|
|
2118
|
+
});
|
|
2089
2119
|
|
|
2090
2120
|
return blocklet;
|
|
2091
2121
|
} catch (err) {
|
|
@@ -218,11 +218,9 @@ class SpacesBackup extends BaseBackup {
|
|
|
218
218
|
const { locale } = this.input;
|
|
219
219
|
// @FIXME: get locale @jianchao
|
|
220
220
|
if (statusCode === 403) {
|
|
221
|
-
throw new Error(
|
|
222
|
-
`${translate(locale, 'backup.space.error.title')}: ${translate(locale, 'backup.space.error.forbidden')}`
|
|
223
|
-
);
|
|
221
|
+
throw new Error(translate(locale, 'backup.space.error.forbidden'));
|
|
224
222
|
}
|
|
225
|
-
throw new Error(
|
|
223
|
+
throw new Error(message);
|
|
226
224
|
}
|
|
227
225
|
}
|
|
228
226
|
|
package/lib/event.js
CHANGED
|
@@ -12,6 +12,7 @@ const eventHub =
|
|
|
12
12
|
process.env.NODE_ENV === 'test' ? require('@arcblock/event-hub/single') : require('@arcblock/event-hub');
|
|
13
13
|
|
|
14
14
|
const states = require('./states');
|
|
15
|
+
const { getBackupEndpoint, getBackupFilesUrlFromEndpoint, getDIDSpacesUrlFromEndpoint } = require('./util/spaces');
|
|
15
16
|
|
|
16
17
|
const routingSnapshotPrefix = (blocklet) => (blocklet.mode === BLOCKLET_MODES.DEVELOPMENT ? '[DEV] ' : '');
|
|
17
18
|
|
|
@@ -25,6 +26,7 @@ module.exports = ({
|
|
|
25
26
|
handleRouting,
|
|
26
27
|
domainStatus,
|
|
27
28
|
teamAPI,
|
|
29
|
+
nodeAPI,
|
|
28
30
|
teamManager,
|
|
29
31
|
certManager,
|
|
30
32
|
routerManager,
|
|
@@ -53,12 +55,34 @@ module.exports = ({
|
|
|
53
55
|
teamManager.deleteTeam(data?.meta?.did, { closeDatabase: false });
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
// clear cache
|
|
59
|
+
if (
|
|
60
|
+
[
|
|
61
|
+
BlockletEvents.updated,
|
|
62
|
+
BlockletEvents.started,
|
|
63
|
+
BlockletEvents.removed,
|
|
64
|
+
BlockletEvents.statusChange,
|
|
65
|
+
BlockletEvents.installed,
|
|
66
|
+
].includes(name)
|
|
67
|
+
) {
|
|
68
|
+
const did = get(data, 'meta.did');
|
|
69
|
+
if (did) {
|
|
70
|
+
logger.info('delete blocklet cache on update', { did });
|
|
71
|
+
blockletManager.deleteCache(did);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
56
75
|
if (typeof eventHandler === 'function') {
|
|
57
76
|
eventHandler({ name, data });
|
|
58
77
|
}
|
|
59
78
|
});
|
|
60
79
|
});
|
|
61
80
|
|
|
81
|
+
eventHub.on(EVENTS.NODE_UPDATED, () => {
|
|
82
|
+
logger.info('node update');
|
|
83
|
+
nodeAPI.deleteCache();
|
|
84
|
+
});
|
|
85
|
+
|
|
62
86
|
// Wipe sensitive data
|
|
63
87
|
// Emit events to event hub
|
|
64
88
|
// Emit events to node listener
|
|
@@ -259,6 +283,25 @@ module.exports = ({
|
|
|
259
283
|
logger.error('Reload gateway failed on blocklet.connectedSpace', { error: err });
|
|
260
284
|
});
|
|
261
285
|
logger.info('Reload gateway after blocklet connected to space', { event: eventName, did: blocklet.appDid });
|
|
286
|
+
} else if (BlockletEvents.backupProgress === eventName && payload?.completed) {
|
|
287
|
+
try {
|
|
288
|
+
const backupEndpoint = getBackupEndpoint(blocklet?.environments);
|
|
289
|
+
|
|
290
|
+
await node.createAuditLog({
|
|
291
|
+
action: 'backupToSpaces',
|
|
292
|
+
args: {
|
|
293
|
+
did: blocklet.meta.did,
|
|
294
|
+
url: getDIDSpacesUrlFromEndpoint(backupEndpoint),
|
|
295
|
+
backupUrl: getBackupFilesUrlFromEndpoint(backupEndpoint),
|
|
296
|
+
success: payload?.progress === 100,
|
|
297
|
+
errorMessage: payload?.message,
|
|
298
|
+
},
|
|
299
|
+
context: payload?.context ?? {},
|
|
300
|
+
result: cloneDeep(blocklet),
|
|
301
|
+
});
|
|
302
|
+
} catch (error) {
|
|
303
|
+
logger.error('Failed to createAuditLog for backupToSpaces failed', { error });
|
|
304
|
+
}
|
|
262
305
|
}
|
|
263
306
|
|
|
264
307
|
if (
|
package/lib/index.js
CHANGED
|
@@ -254,6 +254,7 @@ function ABTNode(options) {
|
|
|
254
254
|
configPublicToStore: blockletManager.configPublicToStore.bind(blockletManager),
|
|
255
255
|
configNavigations: blockletManager.configNavigations.bind(blockletManager),
|
|
256
256
|
configOAuth: blockletManager.configOAuth.bind(blockletManager),
|
|
257
|
+
configNotification: blockletManager.configNotification.bind(blockletManager),
|
|
257
258
|
updateWhoCanAccess: blockletManager.updateWhoCanAccess.bind(blockletManager),
|
|
258
259
|
updateComponentTitle: blockletManager.updateComponentTitle.bind(blockletManager),
|
|
259
260
|
updateComponentMountPoint: blockletManager.updateComponentMountPoint.bind(blockletManager),
|
|
@@ -471,6 +472,7 @@ function ABTNode(options) {
|
|
|
471
472
|
handleRouting,
|
|
472
473
|
domainStatus,
|
|
473
474
|
teamAPI,
|
|
475
|
+
nodeAPI,
|
|
474
476
|
teamManager,
|
|
475
477
|
certManager,
|
|
476
478
|
routerManager,
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* eslint-disable no-await-in-loop */
|
|
2
|
+
/* eslint-disable no-continue */
|
|
3
|
+
|
|
4
|
+
const blocklets = {
|
|
5
|
+
z8ia4e5vAeDsQEE2P26bQqz9oWR1Lxg9qUMaV: 'Static Demo',
|
|
6
|
+
z8iZyVVn6XsvcuiYhtdw3GoasMbtqR9BjvJz3: 'Blockchain Explorer',
|
|
7
|
+
z8iZqkCjLP6TZpR12tT3jESWxB8SGzNsx8nZa: 'NFT Store',
|
|
8
|
+
z8ia1WEiBZ7hxURf6LwH21Wpg99vophFwSJdu: 'Discuss Kit',
|
|
9
|
+
z8ia5AUWNBoc5Jw6Zf2ru97W1y6PZVFiFa7h9: 'Coming Soon Page',
|
|
10
|
+
z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o: 'Pages Kit',
|
|
11
|
+
z8iZscGk6ohCejHEiX16C7apdFC7JrPYD1J4Z: 'Virtual Gift Card',
|
|
12
|
+
z8ia2birZzhjbXqKnxPUUivmqErdsf3724tr6: 'NFT Maker',
|
|
13
|
+
z8ia1ieY5KhEC4LMRETzS5nUwD7PvAND8qkfX: 'NFT Blender',
|
|
14
|
+
z8iZqeUACK955YaBWqEd8aKg3tTki1GpvE2Wu: 'ArcBridge Node',
|
|
15
|
+
z8ia29UsENBg6tLZUKi2HABj38Cw1LmHZocbQ: 'Blocklet Store',
|
|
16
|
+
z8ia2KGe3icfgRcVc9C1qCbWTBbpP2TrfPu7T: 'FS Chain Manager',
|
|
17
|
+
z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ: 'AI Kit',
|
|
18
|
+
z8iZvmERrWxqReWe1HZmkAaZvFeRpkXutfKDk: 'NFT Marketplace',
|
|
19
|
+
z8iZpnScvjjeeyYZQoHSdXm4GQTqcfTTGkyPP: 'DID Wallet',
|
|
20
|
+
z8iZrihfHTTBCBpDqCzrjFer5jop383b5hdPh: 'DID Spaces Enterprise',
|
|
21
|
+
z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9: 'Image Bin',
|
|
22
|
+
z8iZu6GDcVFaSsT7LjrBJC9uAfM6HKyQaCD9U: 'Tower Blocks',
|
|
23
|
+
z8iZyhourKXqn8JKHbFcQDqWoAMsR6ZEi5nCW: 'Mine Sweeper',
|
|
24
|
+
z8ia48jeqzdNhr9smse1tQCmt72G5PnSZaTax: 'MultiSig Vault',
|
|
25
|
+
z8iZngXotuUXxsm6imc7naUUy1G5ycVs7A34H: 'Uptime Kuma',
|
|
26
|
+
z8iZvMrKPa7qy2nxfrKremuSm8bE9Wb9Tu2NA: 'AI Assistant',
|
|
27
|
+
z8ia2kJi2hdqASNBZzRiWQaZ8vshaxgQS67EW: 'DID Spaces Personal',
|
|
28
|
+
z8iZpog7mcgcgBZzTiXJCWESvmnRrQmnd3XBB: 'AI Studio',
|
|
29
|
+
z8iZxVUfZZBPpLhVov5YqsaorNX9F2vKAKeMc: 'Excalidraw',
|
|
30
|
+
z8iZoLRKRXHzqdJ2vFZEi4H5UXT9ADsurxZRK: 'Tweet Token',
|
|
31
|
+
z8ia5gwZog5Ut4TfUJP4k82fXKQN8iWZp2bfG: 'Token Prize Pool',
|
|
32
|
+
z8iZorY6mvb5tZrxXTqhBmwu89xjEEazrgT3t: 'Meilisearch',
|
|
33
|
+
z8iZy4P83i6AgnNdNUexsh2kBcsDHoqcwPavn: 'DID Pay',
|
|
34
|
+
z8iZqTiD6tFwEub6t685e3dj18Ekbo8xvqBSV: 'Vote',
|
|
35
|
+
z8iZkFBbrVQxZHvcWWB3Sa2TrfGmSeFz9MSU7: 'Server Launcher',
|
|
36
|
+
z8iZhW61syFGfgMGDm7ttbDATUf4zbNrzxfJG: 'Blocklet Launcher',
|
|
37
|
+
z8iZqxnmW2i3AbgmjuFki1J6KE8e5i5zBWB9k: 'Nostr Verifier',
|
|
38
|
+
z8iZwyBfqwNcGbLCiUnFAQLEzT8sJd2TSjbM2: 'Static Demo',
|
|
39
|
+
z8iZva6oERHPw7qveUwTBKcY8DqUUtcXheBX8: 'Form Builder',
|
|
40
|
+
z8iZrdP3XNxaqzcHqTRewE3BdJiCfeMfNLzTc: 'AD Kit',
|
|
41
|
+
z8ia2XJkmoZDwRBYzrvLqeZAHWz38Ptrz51xf: 'Tweet Assistant',
|
|
42
|
+
z8ia2YJVK83HuwqykTVVe61mtNWEWeR6kVERi: 'aistro',
|
|
43
|
+
z8ia5nxBkFetpK1BzaumvDStQiKyAuHdymnoh: 'Wait Genie',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
module.exports = async ({ states, printInfo }) => {
|
|
47
|
+
printInfo('Try to update component title...');
|
|
48
|
+
|
|
49
|
+
const apps = await states.blocklet.find({});
|
|
50
|
+
|
|
51
|
+
for (const app of apps || []) {
|
|
52
|
+
let shouldUpdate = false;
|
|
53
|
+
for (const component of app.children || []) {
|
|
54
|
+
const title = blocklets[component?.meta?.bundleDid];
|
|
55
|
+
if (component?.meta && title && title !== component.meta.title) {
|
|
56
|
+
component.meta.title = title;
|
|
57
|
+
shouldUpdate = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (shouldUpdate) {
|
|
62
|
+
await states.blocklet.update({ _id: app._id }, { $set: { children: app.children } });
|
|
63
|
+
printInfo(`Blocklet in blocklet.db updated: ${app.meta?.title}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
package/lib/states/audit-log.js
CHANGED
|
@@ -12,6 +12,14 @@ const BaseState = require('./base');
|
|
|
12
12
|
const { parse } = require('../util/ua');
|
|
13
13
|
|
|
14
14
|
const getServerInfo = (info) => `[${info.name}](${joinUrl(info.routing.adminPath, '/settings/about')})`;
|
|
15
|
+
/**
|
|
16
|
+
* @description
|
|
17
|
+
* @param {import('@abtnode/client').BlockletState} blocklet
|
|
18
|
+
* @param {{
|
|
19
|
+
* routing: { adminPath: string }
|
|
20
|
+
* }} info
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
15
23
|
const getBlockletInfo = (blocklet, info) => `[${getDisplayName(blocklet)} v${blocklet.meta.version}](${joinUrl(info.routing.adminPath, '/blocklets/', blocklet.meta.did, '/overview')})`; // prettier-ignore
|
|
16
24
|
const expandTeam = async (teamDid, info, node) => {
|
|
17
25
|
if (!teamDid) {
|
|
@@ -81,7 +89,7 @@ const expandUser = async (teamDid, userDid, passportId, info, node) => {
|
|
|
81
89
|
* Create log content in markdown format
|
|
82
90
|
*
|
|
83
91
|
* @param {string} action - GraphQL query/mutation name
|
|
84
|
-
* @param {
|
|
92
|
+
* @param {Record<string, string>} args - GraphQL arguments
|
|
85
93
|
* @param {object} context - request context: user, ip, user-agent, etc.
|
|
86
94
|
* @param {object} result - GraphQL resolve result
|
|
87
95
|
* @param {object} info - server info
|
|
@@ -116,12 +124,22 @@ const getLogContent = async (action, args, context, result, info, node) => {
|
|
|
116
124
|
case 'deleteComponent':
|
|
117
125
|
return `removed component ${args.did} from blocklet ${getBlockletInfo(result, info)}`;
|
|
118
126
|
case 'configBlocklet':
|
|
119
|
-
return `updated following config for blocklet ${getBlockletInfo(result, info)}:\n${args.configs.map(x =>
|
|
127
|
+
return `updated following config for blocklet ${getBlockletInfo(result, info)}:\n${args.configs.map(x => `* ${x.key}: ${x.value}`).join('\n')}`; // prettier-ignore
|
|
120
128
|
case 'upgradeBlocklet':
|
|
121
129
|
if (result.resultStatus === 'failed') {
|
|
122
130
|
return `upgrade blocklet failed: ${getBlockletInfo(result, info)}`;
|
|
123
131
|
}
|
|
124
132
|
return `upgraded blocklet ${getBlockletInfo(result, info)} to v${result.meta.version}`;
|
|
133
|
+
case 'backupToSpaces':
|
|
134
|
+
if (args?.success) {
|
|
135
|
+
return `Backup ${getBlockletInfo(result, info)} to ${
|
|
136
|
+
args.url
|
|
137
|
+
} successfully:\n- Backup files have been stored [here](${args.backupUrl})`;
|
|
138
|
+
}
|
|
139
|
+
return `Backup ${getBlockletInfo(result, info)} to ${
|
|
140
|
+
args.url
|
|
141
|
+
} failed:\n- The reason for the error is: <span style='color:red'>${args.errorMessage}</span>`;
|
|
142
|
+
|
|
125
143
|
case 'upgradeComponents':
|
|
126
144
|
return `upgraded components for blocklet ${getBlockletInfo(result, info)}`;
|
|
127
145
|
case 'configPublicToStore':
|
|
@@ -136,6 +154,8 @@ const getLogContent = async (action, args, context, result, info, node) => {
|
|
|
136
154
|
)}`;
|
|
137
155
|
case 'configOAuth':
|
|
138
156
|
return `updated following OAuth for blocklet ${getBlockletInfo(result, info)}:\n${args.oauth}`;
|
|
157
|
+
case 'configNotification':
|
|
158
|
+
return `updated following notification setting for blocklet ${getBlockletInfo(result, info)}`;
|
|
139
159
|
case 'updateComponentTitle':
|
|
140
160
|
return `update component title to **${args.title}** for blocklet ${getBlockletInfo(result, info)}`;
|
|
141
161
|
case 'updateComponentMountPoint':
|
|
@@ -295,8 +315,10 @@ const getLogCategory = (action) => {
|
|
|
295
315
|
case 'configPublicToStore':
|
|
296
316
|
case 'configNavigations':
|
|
297
317
|
case 'configOAuth':
|
|
318
|
+
case 'configNotification':
|
|
298
319
|
case 'updateComponentTitle':
|
|
299
320
|
case 'updateComponentMountPoint':
|
|
321
|
+
case 'backupToSpaces':
|
|
300
322
|
return 'blocklet';
|
|
301
323
|
|
|
302
324
|
// store,此处应该返回 server
|
package/lib/util/spaces.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
const { BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
|
|
2
|
+
const isUrl = require('is-url');
|
|
3
|
+
const isArray = require('lodash/isArray');
|
|
2
4
|
const isEmpty = require('lodash/isEmpty');
|
|
3
5
|
const joinUrl = require('url-join');
|
|
4
6
|
|
|
@@ -7,10 +9,12 @@ const joinUrl = require('url-join');
|
|
|
7
9
|
* @param {import('@abtnode/client').ConfigEntry[]} configs
|
|
8
10
|
* @return {string | null}
|
|
9
11
|
*/
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const getBackupEndpoint = (configs) => {
|
|
13
|
+
if (!isArray(configs) || isEmpty(configs)) {
|
|
14
|
+
return '';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return configs.find((config) => config.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_BACKUP_ENDPOINT)?.value || null;
|
|
14
18
|
};
|
|
15
19
|
|
|
16
20
|
/**
|
|
@@ -33,7 +37,16 @@ function getBackupFilesUrlFromEndpoint(endpoint) {
|
|
|
33
37
|
return joinUrl(prefix, 'space', spaceDid, 'apps', appDid, 'explorer', `?key=/apps/${appDid}/.did-objects/${appDid}/`);
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
function getDIDSpacesUrlFromEndpoint(endpoint) {
|
|
41
|
+
if (!isUrl(endpoint)) {
|
|
42
|
+
throw new Error(`Endpoint(${endpoint}) is not a valid url`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return endpoint.replace(/\/api\/space\/.+/, '');
|
|
46
|
+
}
|
|
47
|
+
|
|
36
48
|
module.exports = {
|
|
37
|
-
|
|
49
|
+
getBackupEndpoint,
|
|
38
50
|
getBackupFilesUrlFromEndpoint,
|
|
51
|
+
getDIDSpacesUrlFromEndpoint,
|
|
39
52
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.8-beta-
|
|
6
|
+
"version": "1.16.8-beta-81db8efa",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,18 +19,18 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/auth": "1.16.8-beta-
|
|
23
|
-
"@abtnode/certificate-manager": "1.16.8-beta-
|
|
24
|
-
"@abtnode/constant": "1.16.8-beta-
|
|
25
|
-
"@abtnode/cron": "1.16.8-beta-
|
|
26
|
-
"@abtnode/db": "1.16.8-beta-
|
|
27
|
-
"@abtnode/logger": "1.16.8-beta-
|
|
28
|
-
"@abtnode/queue": "1.16.8-beta-
|
|
29
|
-
"@abtnode/rbac": "1.16.8-beta-
|
|
30
|
-
"@abtnode/router-provider": "1.16.8-beta-
|
|
31
|
-
"@abtnode/static-server": "1.16.8-beta-
|
|
32
|
-
"@abtnode/timemachine": "1.16.8-beta-
|
|
33
|
-
"@abtnode/util": "1.16.8-beta-
|
|
22
|
+
"@abtnode/auth": "1.16.8-beta-81db8efa",
|
|
23
|
+
"@abtnode/certificate-manager": "1.16.8-beta-81db8efa",
|
|
24
|
+
"@abtnode/constant": "1.16.8-beta-81db8efa",
|
|
25
|
+
"@abtnode/cron": "1.16.8-beta-81db8efa",
|
|
26
|
+
"@abtnode/db": "1.16.8-beta-81db8efa",
|
|
27
|
+
"@abtnode/logger": "1.16.8-beta-81db8efa",
|
|
28
|
+
"@abtnode/queue": "1.16.8-beta-81db8efa",
|
|
29
|
+
"@abtnode/rbac": "1.16.8-beta-81db8efa",
|
|
30
|
+
"@abtnode/router-provider": "1.16.8-beta-81db8efa",
|
|
31
|
+
"@abtnode/static-server": "1.16.8-beta-81db8efa",
|
|
32
|
+
"@abtnode/timemachine": "1.16.8-beta-81db8efa",
|
|
33
|
+
"@abtnode/util": "1.16.8-beta-81db8efa",
|
|
34
34
|
"@arcblock/did": "1.18.78",
|
|
35
35
|
"@arcblock/did-auth": "1.18.78",
|
|
36
36
|
"@arcblock/did-ext": "^1.18.78",
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"@arcblock/event-hub": "1.18.78",
|
|
40
40
|
"@arcblock/jwt": "^1.18.78",
|
|
41
41
|
"@arcblock/pm2-events": "^0.0.5",
|
|
42
|
-
"@arcblock/validator": "^1.18.
|
|
42
|
+
"@arcblock/validator": "^1.18.78",
|
|
43
43
|
"@arcblock/vc": "1.18.78",
|
|
44
|
-
"@blocklet/constant": "1.16.8-beta-
|
|
45
|
-
"@blocklet/meta": "1.16.8-beta-
|
|
46
|
-
"@blocklet/sdk": "1.16.8-beta-
|
|
47
|
-
"@did-space/client": "^0.2.
|
|
44
|
+
"@blocklet/constant": "1.16.8-beta-81db8efa",
|
|
45
|
+
"@blocklet/meta": "1.16.8-beta-81db8efa",
|
|
46
|
+
"@blocklet/sdk": "1.16.8-beta-81db8efa",
|
|
47
|
+
"@did-space/client": "^0.2.91",
|
|
48
48
|
"@fidm/x509": "^1.2.1",
|
|
49
49
|
"@ocap/mcrypto": "1.18.78",
|
|
50
50
|
"@ocap/util": "1.18.78",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"js-yaml": "^4.1.0",
|
|
72
72
|
"kill-port": "^2.0.1",
|
|
73
73
|
"lodash": "^4.17.21",
|
|
74
|
+
"lru-cache": "^6.0.0",
|
|
74
75
|
"moment-timezone": "^0.5.37",
|
|
75
76
|
"node-stream-zip": "^1.15.0",
|
|
76
77
|
"p-limit": "^3.1.0",
|
|
@@ -94,5 +95,5 @@
|
|
|
94
95
|
"express": "^4.18.2",
|
|
95
96
|
"jest": "^27.5.1"
|
|
96
97
|
},
|
|
97
|
-
"gitHead": "
|
|
98
|
+
"gitHead": "8c4e3190de79a1fb2aaa14646255d938324cc5c2"
|
|
98
99
|
}
|