@abtnode/core 1.16.14-beta-a898bfcb → 1.16.14-beta-d802cd3c
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/team.js +5 -3
- package/lib/blocklet/manager/disk.js +312 -140
- package/lib/blocklet/manager/helper/install-application-from-backup.js +7 -6
- package/lib/blocklet/manager/helper/install-application-from-general.js +5 -5
- package/lib/blocklet/manager/helper/install-component-from-upload.js +3 -1
- package/lib/blocklet/manager/helper/install-component-from-url.js +20 -5
- package/lib/blocklet/manager/helper/upgrade-components.js +14 -5
- package/lib/event.js +32 -32
- package/lib/index.js +4 -0
- package/lib/states/audit-log.js +64 -70
- package/lib/states/notification.js +2 -2
- package/lib/util/blocklet.js +12 -2
- package/lib/util/get-domain-for-blocklet.js +2 -2
- package/lib/util/launcher.js +11 -5
- package/lib/util/log.js +403 -0
- package/lib/util/store.js +7 -7
- package/lib/webhook/index.js +25 -14
- package/package.json +35 -32
package/lib/util/launcher.js
CHANGED
|
@@ -2,8 +2,13 @@ const path = require('path');
|
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const joinUrl = require('url-join');
|
|
4
4
|
const pick = require('lodash/pick');
|
|
5
|
-
const
|
|
6
|
-
|
|
5
|
+
const {
|
|
6
|
+
getUserAvatarUrl,
|
|
7
|
+
extractUserAvatar,
|
|
8
|
+
getAvatarFile,
|
|
9
|
+
getAvatarByUrl,
|
|
10
|
+
getAppAvatarUrl,
|
|
11
|
+
} = require('@abtnode/util/lib/user');
|
|
7
12
|
const { Hasher } = require('@ocap/mcrypto');
|
|
8
13
|
const { getDisplayName } = require('@blocklet/meta/lib/util');
|
|
9
14
|
const getBlockletInfo = require('@blocklet/meta/lib/info');
|
|
@@ -99,7 +104,7 @@ const setupAppOwner = async (node, sessionId) => {
|
|
|
99
104
|
throw new Error(`Owner user not found from launcher: ${launcherUrl}`);
|
|
100
105
|
}
|
|
101
106
|
appOwnerProfile = pick(user, ['fullName', 'email', 'avatar']);
|
|
102
|
-
const avatarBase64 = await getAvatarByUrl(
|
|
107
|
+
const avatarBase64 = await getAvatarByUrl(joinUrl(launcherUrl, user.avatar));
|
|
103
108
|
appOwnerProfile.avatar = await extractUserAvatar(avatarBase64, { dataDir });
|
|
104
109
|
logger.info('Create owner from launcher for blocklet', { appDid, ownerDid, ownerPk, sessionId, appOwnerProfile });
|
|
105
110
|
} else {
|
|
@@ -115,7 +120,7 @@ const setupAppOwner = async (node, sessionId) => {
|
|
|
115
120
|
fs.mkdirpSync(path.dirname(destFile));
|
|
116
121
|
fs.copyFileSync(srcFile, destFile);
|
|
117
122
|
} else {
|
|
118
|
-
appOwnerProfile.avatar = extractUserAvatar(user.avatar, { dataDir });
|
|
123
|
+
appOwnerProfile.avatar = await extractUserAvatar(user.avatar, { dataDir });
|
|
119
124
|
}
|
|
120
125
|
logger.info('Create owner from session for blocklet', { appDid, ownerDid, ownerPk, sessionId, appOwnerProfile });
|
|
121
126
|
}
|
|
@@ -125,6 +130,7 @@ const setupAppOwner = async (node, sessionId) => {
|
|
|
125
130
|
const vc = createPassportVC({
|
|
126
131
|
issuerName: getDisplayName(blocklet),
|
|
127
132
|
issuerWallet: wallet,
|
|
133
|
+
issuerAvatarUrl: getAppAvatarUrl(appUrl),
|
|
128
134
|
ownerDid,
|
|
129
135
|
passport: await createPassport({
|
|
130
136
|
name: role,
|
|
@@ -138,7 +144,7 @@ const setupAppOwner = async (node, sessionId) => {
|
|
|
138
144
|
userDid: ownerDid,
|
|
139
145
|
teamDid: appDid,
|
|
140
146
|
}),
|
|
141
|
-
ownerProfile: { ...appOwnerProfile, avatar:
|
|
147
|
+
ownerProfile: { ...appOwnerProfile, avatar: getUserAvatarUrl(appUrl, appOwnerProfile.avatar) },
|
|
142
148
|
preferredColor: 'default',
|
|
143
149
|
expirationDate: undefined,
|
|
144
150
|
});
|
package/lib/util/log.js
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const createArchive = require('archiver');
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const glob = require('fast-glob');
|
|
6
|
+
const isEqual = require('lodash/isEqual');
|
|
7
|
+
const { Tail } = require('tail');
|
|
8
|
+
const readLastLines = require('read-last-lines');
|
|
9
|
+
const { BLOCKLET_MODES } = require('@blocklet/constant');
|
|
10
|
+
const { findComponentByIdV2 } = require('@blocklet/meta/lib/util');
|
|
11
|
+
const dayjs = require('@abtnode/util/lib/dayjs');
|
|
12
|
+
const logger = require('@abtnode/logger')(require('../../package.json').name);
|
|
13
|
+
|
|
14
|
+
class StreamLog {
|
|
15
|
+
constructor() {
|
|
16
|
+
this._files = null; // Object { <level>: <filePath> }
|
|
17
|
+
this._tails = null; // Object { <level>: <Tail> }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {Object} files Object { <level>: <filePath> }
|
|
22
|
+
* @return {Boolean} if files change
|
|
23
|
+
*/
|
|
24
|
+
setFiles(files) {
|
|
25
|
+
if (!isEqual(this._files, files)) {
|
|
26
|
+
this.clearTails();
|
|
27
|
+
this._files = files;
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getRecent(lineNum, callback) {
|
|
34
|
+
if (!this._files) {
|
|
35
|
+
callback(new Error('files is empty'));
|
|
36
|
+
}
|
|
37
|
+
Object.entries(this._files).forEach(([level, file]) => {
|
|
38
|
+
if (!file || !fs.existsSync(file)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
readLastLines
|
|
42
|
+
.read(file, lineNum || 0)
|
|
43
|
+
.then((data) => {
|
|
44
|
+
callback(null, level, data);
|
|
45
|
+
})
|
|
46
|
+
.catch((error) => {
|
|
47
|
+
callback(error, level);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
ensureTails() {
|
|
53
|
+
if (this._tails) {
|
|
54
|
+
return this._tails;
|
|
55
|
+
}
|
|
56
|
+
if (!this._files) {
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
this._tails = {};
|
|
61
|
+
Object.entries(this._files).forEach(([level, file]) => {
|
|
62
|
+
if (!file || !fs.existsSync(file)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 测试发现 Windows 下 fs.watch 没有效果,但是 fs.watch 的性能更好,所以只在 windows 下使用 fs.watchFile
|
|
67
|
+
this._tails[level] = new Tail(file, {
|
|
68
|
+
useWatchFile: process.platform === 'win32',
|
|
69
|
+
fsWatchOptions: { interval: 1500 },
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
return this._tails;
|
|
73
|
+
} catch (error) {
|
|
74
|
+
this._tails = null;
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
clearTails() {
|
|
80
|
+
if (this._tails) {
|
|
81
|
+
Object.values(this._tails).forEach((tail) => {
|
|
82
|
+
tail.unwatch();
|
|
83
|
+
});
|
|
84
|
+
this._tails = null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const createFile = (files) => {
|
|
90
|
+
Object.values(files).forEach((file) => {
|
|
91
|
+
if (!fs.existsSync(file)) {
|
|
92
|
+
try {
|
|
93
|
+
const dir = path.dirname(file);
|
|
94
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
95
|
+
} catch (err) {
|
|
96
|
+
// Do nothing
|
|
97
|
+
}
|
|
98
|
+
fs.writeFileSync(file, '', 'utf8');
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const getLogFiles = async ({ name, node }) => {
|
|
104
|
+
const dt = new Date();
|
|
105
|
+
const { yyyy, mm, dd } = {
|
|
106
|
+
yyyy: dt.getFullYear(),
|
|
107
|
+
mm: `${dt.getMonth() + 1}`.padStart(2, 0),
|
|
108
|
+
dd: `${dt.getDate()}`.padStart(2, 0),
|
|
109
|
+
};
|
|
110
|
+
const date = `${yyyy}-${mm}-${dd}`;
|
|
111
|
+
|
|
112
|
+
if (name === 'abtnode') {
|
|
113
|
+
const logDir = path.join(node.dataDirs.logs, '_abtnode');
|
|
114
|
+
|
|
115
|
+
const info = path.join(logDir, `daemon-${date}.log`);
|
|
116
|
+
const error = path.join(logDir, `daemon-error-${date}.log`);
|
|
117
|
+
const access = path.join(logDir, 'access.log');
|
|
118
|
+
const stdout = path.join(logDir, 'daemon.stdout.log');
|
|
119
|
+
const stderr = path.join(logDir, 'daemon.stderr.log');
|
|
120
|
+
|
|
121
|
+
createFile({
|
|
122
|
+
info,
|
|
123
|
+
error,
|
|
124
|
+
access,
|
|
125
|
+
stdout,
|
|
126
|
+
stderr,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
info,
|
|
131
|
+
error,
|
|
132
|
+
access,
|
|
133
|
+
stdout,
|
|
134
|
+
stderr,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (name === 'blocklet-services') {
|
|
139
|
+
const logDir = path.join(node.dataDirs.logs, '_abtnode');
|
|
140
|
+
const info = path.join(logDir, 'service.log');
|
|
141
|
+
const error = path.join(logDir, 'service.error.log');
|
|
142
|
+
createFile({ info, error });
|
|
143
|
+
return { info, error };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (name.indexOf('blocklet-') === 0) {
|
|
147
|
+
const did = name.substring('blocklet-'.length);
|
|
148
|
+
const [appId, componentId] = did.split('/');
|
|
149
|
+
const blocklet = await node.getBlocklet({ did: appId, useCache: true });
|
|
150
|
+
let { name: blockletName } = blocklet.meta;
|
|
151
|
+
|
|
152
|
+
if (componentId) {
|
|
153
|
+
const component = findComponentByIdV2(blocklet, componentId);
|
|
154
|
+
if (component) {
|
|
155
|
+
blockletName = path.join(blockletName, component.meta.name);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const dir = path.join(node.dataDirs.logs, blockletName);
|
|
160
|
+
const info = path.join(dir, `info-${date}.log`);
|
|
161
|
+
const error = path.join(dir, `info-error-${date}.log`);
|
|
162
|
+
const access = path.join(dir, 'access.log');
|
|
163
|
+
const stdout = path.join(dir, 'output.log');
|
|
164
|
+
const stderr = path.join(dir, 'error.log');
|
|
165
|
+
|
|
166
|
+
createFile({
|
|
167
|
+
info,
|
|
168
|
+
error,
|
|
169
|
+
access,
|
|
170
|
+
stdout,
|
|
171
|
+
stderr,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
info,
|
|
176
|
+
error,
|
|
177
|
+
access,
|
|
178
|
+
stdout,
|
|
179
|
+
stderr,
|
|
180
|
+
recent: blocklet.mode === BLOCKLET_MODES.DEVELOPMENT ? 0 : 100,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (name.startsWith('service-gateway-')) {
|
|
185
|
+
const providerName = name.substring('service-gateway-'.length);
|
|
186
|
+
const provider = node.getRouterProvider(providerName);
|
|
187
|
+
if (!provider) {
|
|
188
|
+
logger.error('router engine is empty', { name, providerName });
|
|
189
|
+
return {};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return provider.getLogFilesForToday();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {};
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const getDownloadLogFilesFromServer = async ({ dates, nodeInfo, node } = {}) => {
|
|
199
|
+
const logDir = path.join(node.dataDirs.logs, '_abtnode');
|
|
200
|
+
|
|
201
|
+
const pm2Log = path.join(logDir, 'pm2.log');
|
|
202
|
+
const pm2LogSrc = path.join(process.env.PM2_HOME, 'pm2.log');
|
|
203
|
+
if (fs.existsSync(pm2LogSrc)) {
|
|
204
|
+
await fs.copy(pm2LogSrc, pm2Log);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const provider = node.getRouterProvider(nodeInfo.routing.provider);
|
|
208
|
+
if (!provider) {
|
|
209
|
+
logger.error('router engine is empty');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const list = [];
|
|
213
|
+
|
|
214
|
+
dates.forEach((d) => {
|
|
215
|
+
// log file created by @abtnode/log
|
|
216
|
+
// log file created by abt-node-log-rotate
|
|
217
|
+
list.push(path.join(logDir, `*-${d}*`));
|
|
218
|
+
|
|
219
|
+
// log file create by router
|
|
220
|
+
const routerLogDir = provider.getLogDir();
|
|
221
|
+
if (routerLogDir) {
|
|
222
|
+
list.push(path.join(routerLogDir, `*-${d}*`));
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// abt-node-daemon console & gateway
|
|
227
|
+
list.push(path.join(logDir, 'daemon.stdout.log*'));
|
|
228
|
+
list.push(path.join(logDir, 'daemon.stderr.log*'));
|
|
229
|
+
list.push(path.join(logDir, 'access.log*'));
|
|
230
|
+
|
|
231
|
+
// abt-node-service console & gateway
|
|
232
|
+
list.push(path.join(logDir, 'service.output.log*'));
|
|
233
|
+
list.push(path.join(logDir, 'service.error.log*'));
|
|
234
|
+
list.push(path.join(logDir, 'service.log*'));
|
|
235
|
+
|
|
236
|
+
// abt-node-db-hub console & backup
|
|
237
|
+
list.push(path.join(logDir, 'db.output.log*'));
|
|
238
|
+
list.push(path.join(logDir, 'db.error.log*'));
|
|
239
|
+
|
|
240
|
+
// abt-node-event-hub console
|
|
241
|
+
list.push(path.join(logDir, 'event.output.log*'));
|
|
242
|
+
list.push(path.join(logDir, 'event.error.log*'));
|
|
243
|
+
|
|
244
|
+
// abt-node-log-rotate console
|
|
245
|
+
list.push(path.join(logDir, 'pm2-logrotate.stdout.log*'));
|
|
246
|
+
list.push(path.join(logDir, 'pm2-logrotate.stderr.log*'));
|
|
247
|
+
|
|
248
|
+
// abt-node-updater console
|
|
249
|
+
list.push(path.join(logDir, 'updater.error.log*'));
|
|
250
|
+
list.push(path.join(logDir, 'updater.output.log*'));
|
|
251
|
+
|
|
252
|
+
// fallback log
|
|
253
|
+
list.push(path.join(logDir, 'stderr.log*'));
|
|
254
|
+
list.push(path.join(logDir, 'stdout.log*'));
|
|
255
|
+
|
|
256
|
+
// router
|
|
257
|
+
list.push(...Object.values(provider.getLogFilesForToday() || {}));
|
|
258
|
+
|
|
259
|
+
// pm2 log
|
|
260
|
+
list.push(pm2Log);
|
|
261
|
+
|
|
262
|
+
return glob(list);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const getDownloadLogFilesFromBlocklet = ({ dates, blocklet } = {}) => {
|
|
266
|
+
const appLogDir = path.join(blocklet.env.logsDir);
|
|
267
|
+
const componentLogDirs = blocklet.children.map((c) => path.join(c.env.logsDir));
|
|
268
|
+
|
|
269
|
+
const list = [];
|
|
270
|
+
|
|
271
|
+
[appLogDir, ...componentLogDirs].forEach((logDir) => {
|
|
272
|
+
dates.forEach((d) => {
|
|
273
|
+
// log file created by @abtnode/log
|
|
274
|
+
// log file created by abt-node-log-rotate
|
|
275
|
+
list.push(path.join(logDir, `*-${d}*`));
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
list.push(path.join(logDir, 'output.log*'));
|
|
279
|
+
list.push(path.join(logDir, 'error.log*'));
|
|
280
|
+
list.push(path.join(logDir, 'access.log*'));
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return glob(list);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const getDownloadLogFiles = async ({ did, node, days = 1, now } = {}) => {
|
|
287
|
+
const dates = [dayjs(now).format('YYYY-MM-DD')];
|
|
288
|
+
|
|
289
|
+
for (let i = 1; i <= days; i++) {
|
|
290
|
+
dates.unshift(dayjs(now).subtract(i, 'day').format('YYYY-MM-DD'));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const nodeInfo = await node.getNodeInfo({ useCache: true });
|
|
294
|
+
|
|
295
|
+
if (nodeInfo.did === did) {
|
|
296
|
+
return getDownloadLogFilesFromServer({ dates, node, nodeInfo });
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const blocklet = await node.getBlocklet({ did });
|
|
300
|
+
if (!blocklet) {
|
|
301
|
+
throw new Error('blocklet not found');
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return getDownloadLogFilesFromBlocklet({ dates, blocklet });
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const createStreamLogManager = ({ onLog, onGetLogFiles }) => {
|
|
308
|
+
const store = {}; // Object<name: streamLog>
|
|
309
|
+
|
|
310
|
+
const ensure = (name) => {
|
|
311
|
+
if (!store[name]) {
|
|
312
|
+
store[name] = new StreamLog();
|
|
313
|
+
}
|
|
314
|
+
return store[name];
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const destroy = (name) => {
|
|
318
|
+
logger.info('log stream: destroy', { name });
|
|
319
|
+
if (!store[name]) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const log = store[name];
|
|
323
|
+
try {
|
|
324
|
+
log.clearTails();
|
|
325
|
+
delete store[name];
|
|
326
|
+
} catch (error) {
|
|
327
|
+
logger.error('log stream: remove ref error ', error);
|
|
328
|
+
delete store[name];
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const add = async (name, topic, firstLogCb) => {
|
|
333
|
+
logger.info('log stream: add', { name });
|
|
334
|
+
const log = ensure(name);
|
|
335
|
+
try {
|
|
336
|
+
// update files
|
|
337
|
+
// push recent 100 log
|
|
338
|
+
const { recent = 100, ...logFiles } = await onGetLogFiles(name);
|
|
339
|
+
const changed = await log.setFiles(logFiles);
|
|
340
|
+
logger.info('log stream: added', { name, logFiles });
|
|
341
|
+
log.getRecent(recent, (error, level, data) => {
|
|
342
|
+
if (error) {
|
|
343
|
+
logger.error('log stream error ', error);
|
|
344
|
+
}
|
|
345
|
+
if (firstLogCb) {
|
|
346
|
+
firstLogCb(level, data, logFiles);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
// stream
|
|
350
|
+
if (changed) {
|
|
351
|
+
const tails = log.ensureTails();
|
|
352
|
+
Object.entries(tails).forEach(([level, tail]) => {
|
|
353
|
+
tail.on('line', (data) => {
|
|
354
|
+
onLog({ topic, level, logFiles, data });
|
|
355
|
+
});
|
|
356
|
+
tail.on('error', (error) => {
|
|
357
|
+
logger.error('log tail error ', { error });
|
|
358
|
+
destroy(name);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
} catch (error) {
|
|
363
|
+
logger.error('log stream error ', error);
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
add,
|
|
369
|
+
destroy,
|
|
370
|
+
};
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const createDownloadLogStream = async ({ node, did, days, now }) => {
|
|
374
|
+
const files = await getDownloadLogFiles({ node, did, days, now });
|
|
375
|
+
|
|
376
|
+
if (!files.length) {
|
|
377
|
+
throw new Error('Log file does not found');
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const cwd = path.dirname(node.dataDirs.logs);
|
|
381
|
+
|
|
382
|
+
const archive = createArchive('zip', { zlib: { level: 9 } });
|
|
383
|
+
files.forEach((x) => {
|
|
384
|
+
archive.file(x, {
|
|
385
|
+
name: x.replace(`${cwd}/logs`, '/logs').replace(`${cwd}`, '/logs').replace('/_abtnode', '/blocklet-server'),
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
archive.rawPipe = archive.pipe.bind(archive);
|
|
390
|
+
archive.pipe = (s) => {
|
|
391
|
+
archive.rawPipe(s);
|
|
392
|
+
archive.finalize();
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
return archive;
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
module.exports = {
|
|
399
|
+
createStreamLogManager,
|
|
400
|
+
getLogFiles,
|
|
401
|
+
getDownloadLogFiles,
|
|
402
|
+
createDownloadLogStream,
|
|
403
|
+
};
|
package/lib/util/store.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const joinUrl = require('url-join');
|
|
2
2
|
const pick = require('lodash/pick');
|
|
3
3
|
const isBase64 = require('is-base64');
|
|
4
4
|
|
|
@@ -47,7 +47,7 @@ const fixAndVerifyMetaFromStore = (meta) => {
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
const validateStoreUrl = async (registry) => {
|
|
50
|
-
const url =
|
|
50
|
+
const url = joinUrl(registry, BLOCKLET_STORE_API_PREFIX, `/blocklets.json?__t__=${Date.now()}`);
|
|
51
51
|
try {
|
|
52
52
|
const res = await request.get(url);
|
|
53
53
|
if (Array.isArray(res.data)) {
|
|
@@ -64,7 +64,7 @@ const validateStoreUrl = async (registry) => {
|
|
|
64
64
|
|
|
65
65
|
const getStoreMeta = async (registry) => {
|
|
66
66
|
try {
|
|
67
|
-
const url =
|
|
67
|
+
const url = joinUrl(registry, BLOCKLET_STORE_META_PATH, `?__t__=${Date.now()}`);
|
|
68
68
|
const { data } = await request.get(url);
|
|
69
69
|
|
|
70
70
|
if (!data) {
|
|
@@ -86,7 +86,7 @@ const getStoreMeta = async (registry) => {
|
|
|
86
86
|
} else if (isBase64(logoUrl, { allowMime: true })) {
|
|
87
87
|
result.logoUrl = logoUrl;
|
|
88
88
|
} else {
|
|
89
|
-
result.logoUrl =
|
|
89
|
+
result.logoUrl = joinUrl(registry, logoUrl);
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -141,14 +141,14 @@ const resolveTarballURL = ({ did, tarball = '', storeUrl = '' }) => {
|
|
|
141
141
|
return '';
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
return
|
|
144
|
+
return joinUrl(storeUrl, 'api', 'blocklets', did, tarball);
|
|
145
145
|
};
|
|
146
146
|
|
|
147
147
|
const getBlockletMetaUrl = ({ did, storeUrl }) =>
|
|
148
|
-
|
|
148
|
+
joinUrl(storeUrl, BLOCKLET_STORE_API_PREFIX, `/blocklets/${did}/blocklet.json`);
|
|
149
149
|
|
|
150
150
|
const getBlockletMeta = async ({ did, storeUrl }) => {
|
|
151
|
-
const url =
|
|
151
|
+
const url = joinUrl(storeUrl, BLOCKLET_STORE_API_PREFIX, `/blocklets/${did}/blocklet.json?__t__=${Date.now()}`);
|
|
152
152
|
|
|
153
153
|
const { data } = await request.get(url);
|
|
154
154
|
try {
|
package/lib/webhook/index.js
CHANGED
|
@@ -10,10 +10,18 @@ const IP = require('../util/ip');
|
|
|
10
10
|
const states = require('../states');
|
|
11
11
|
const { getBaseUrls } = require('../util');
|
|
12
12
|
|
|
13
|
-
const getSlackUrlInfo = async (actionPath = '/notifications', urls) => {
|
|
13
|
+
const getSlackUrlInfo = async ({ blockletUrl, path: actionPath = '/notifications', serverUrls: urls }) => {
|
|
14
14
|
const info = [];
|
|
15
15
|
|
|
16
|
-
if (
|
|
16
|
+
if (blockletUrl) {
|
|
17
|
+
info.push({
|
|
18
|
+
type: 'section',
|
|
19
|
+
text: {
|
|
20
|
+
type: 'mrkdwn',
|
|
21
|
+
text: 'Use the following links to visit your Blocklet dashboard:',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
} else if (actionPath && actionPath.startsWith('/blocklet/')) {
|
|
17
25
|
info.push({
|
|
18
26
|
type: 'section',
|
|
19
27
|
text: {
|
|
@@ -31,15 +39,18 @@ const getSlackUrlInfo = async (actionPath = '/notifications', urls) => {
|
|
|
31
39
|
});
|
|
32
40
|
}
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
let url = blockletUrl;
|
|
43
|
+
if (!url) {
|
|
44
|
+
const priorities = await evaluateURLs(
|
|
45
|
+
urls.map((item) => item.url),
|
|
46
|
+
{ checkAccessible: checkURLAccessible }
|
|
47
|
+
);
|
|
48
|
+
const priorityUrl = priorities[0].url;
|
|
49
|
+
|
|
50
|
+
const { protocol } = new URL(priorityUrl);
|
|
51
|
+
const normalized = `${priorityUrl}${actionPath}`.replace(`${protocol}//`, '').replace(/\/+/g, '/');
|
|
52
|
+
url = `${protocol}//${normalized}`;
|
|
53
|
+
}
|
|
43
54
|
|
|
44
55
|
info.push({
|
|
45
56
|
type: 'actions',
|
|
@@ -89,7 +100,7 @@ module.exports = ({ events, dataDirs, instance }) => {
|
|
|
89
100
|
const options = { ...message, nodeInfo, node: instance };
|
|
90
101
|
if (item.type === 'slack') {
|
|
91
102
|
// eslint-disable-next-line
|
|
92
|
-
options.urlInfo = await getSlackUrlInfo(message.action, baseUrls);
|
|
103
|
+
options.urlInfo = await getSlackUrlInfo({ blockletUrl: message.blockletUrl, path: message.action, serverUrls: baseUrls });
|
|
93
104
|
}
|
|
94
105
|
try {
|
|
95
106
|
// eslint-disable-next-line
|
|
@@ -118,8 +129,8 @@ module.exports = ({ events, dataDirs, instance }) => {
|
|
|
118
129
|
});
|
|
119
130
|
|
|
120
131
|
events.on(EVENTS.NOTIFICATION_CREATE, (data) => {
|
|
121
|
-
const { title, description, severity, action, entityType } = data;
|
|
122
|
-
queue.push({ title, description, status: severity, action, entityType });
|
|
132
|
+
const { title, description, severity, action, entityType, blockletUrl } = data;
|
|
133
|
+
queue.push({ title, description, status: severity, action, entityType, blockletUrl });
|
|
123
134
|
});
|
|
124
135
|
|
|
125
136
|
events.on(EVENTS.NODE_STARTED, async (message) => {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.14-beta-
|
|
6
|
+
"version": "1.16.14-beta-d802cd3c",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,38 +19,38 @@
|
|
|
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.14-beta-
|
|
23
|
-
"@abtnode/auth": "1.16.14-beta-
|
|
24
|
-
"@abtnode/certificate-manager": "1.16.14-beta-
|
|
25
|
-
"@abtnode/constant": "1.16.14-beta-
|
|
26
|
-
"@abtnode/cron": "1.16.14-beta-
|
|
27
|
-
"@abtnode/logger": "1.16.14-beta-
|
|
28
|
-
"@abtnode/models": "1.16.14-beta-
|
|
29
|
-
"@abtnode/queue": "1.16.14-beta-
|
|
30
|
-
"@abtnode/rbac": "1.16.14-beta-
|
|
31
|
-
"@abtnode/router-provider": "1.16.14-beta-
|
|
32
|
-
"@abtnode/static-server": "1.16.14-beta-
|
|
33
|
-
"@abtnode/timemachine": "1.16.14-beta-
|
|
34
|
-
"@abtnode/util": "1.16.14-beta-
|
|
35
|
-
"@arcblock/did": "1.18.
|
|
36
|
-
"@arcblock/did-auth": "1.18.
|
|
37
|
-
"@arcblock/did-ext": "^1.18.
|
|
38
|
-
"@arcblock/did-motif": "^1.1.
|
|
39
|
-
"@arcblock/did-util": "1.18.
|
|
40
|
-
"@arcblock/event-hub": "1.18.
|
|
41
|
-
"@arcblock/jwt": "^1.18.
|
|
22
|
+
"@abtnode/analytics": "1.16.14-beta-d802cd3c",
|
|
23
|
+
"@abtnode/auth": "1.16.14-beta-d802cd3c",
|
|
24
|
+
"@abtnode/certificate-manager": "1.16.14-beta-d802cd3c",
|
|
25
|
+
"@abtnode/constant": "1.16.14-beta-d802cd3c",
|
|
26
|
+
"@abtnode/cron": "1.16.14-beta-d802cd3c",
|
|
27
|
+
"@abtnode/logger": "1.16.14-beta-d802cd3c",
|
|
28
|
+
"@abtnode/models": "1.16.14-beta-d802cd3c",
|
|
29
|
+
"@abtnode/queue": "1.16.14-beta-d802cd3c",
|
|
30
|
+
"@abtnode/rbac": "1.16.14-beta-d802cd3c",
|
|
31
|
+
"@abtnode/router-provider": "1.16.14-beta-d802cd3c",
|
|
32
|
+
"@abtnode/static-server": "1.16.14-beta-d802cd3c",
|
|
33
|
+
"@abtnode/timemachine": "1.16.14-beta-d802cd3c",
|
|
34
|
+
"@abtnode/util": "1.16.14-beta-d802cd3c",
|
|
35
|
+
"@arcblock/did": "1.18.87",
|
|
36
|
+
"@arcblock/did-auth": "1.18.87",
|
|
37
|
+
"@arcblock/did-ext": "^1.18.87",
|
|
38
|
+
"@arcblock/did-motif": "^1.1.13",
|
|
39
|
+
"@arcblock/did-util": "1.18.87",
|
|
40
|
+
"@arcblock/event-hub": "1.18.87",
|
|
41
|
+
"@arcblock/jwt": "^1.18.87",
|
|
42
42
|
"@arcblock/pm2-events": "^0.0.5",
|
|
43
|
-
"@arcblock/validator": "^1.18.
|
|
44
|
-
"@arcblock/vc": "1.18.
|
|
45
|
-
"@blocklet/constant": "1.16.14-beta-
|
|
46
|
-
"@blocklet/meta": "1.16.14-beta-
|
|
47
|
-
"@blocklet/resolver": "1.16.14-beta-
|
|
48
|
-
"@blocklet/sdk": "1.16.14-beta-
|
|
43
|
+
"@arcblock/validator": "^1.18.87",
|
|
44
|
+
"@arcblock/vc": "1.18.87",
|
|
45
|
+
"@blocklet/constant": "1.16.14-beta-d802cd3c",
|
|
46
|
+
"@blocklet/meta": "1.16.14-beta-d802cd3c",
|
|
47
|
+
"@blocklet/resolver": "1.16.14-beta-d802cd3c",
|
|
48
|
+
"@blocklet/sdk": "1.16.14-beta-d802cd3c",
|
|
49
49
|
"@did-space/client": "^0.2.129",
|
|
50
50
|
"@fidm/x509": "^1.2.1",
|
|
51
|
-
"@ocap/mcrypto": "1.18.
|
|
52
|
-
"@ocap/util": "1.18.
|
|
53
|
-
"@ocap/wallet": "1.18.
|
|
51
|
+
"@ocap/mcrypto": "1.18.87",
|
|
52
|
+
"@ocap/util": "1.18.87",
|
|
53
|
+
"@ocap/wallet": "1.18.87",
|
|
54
54
|
"@slack/webhook": "^5.0.4",
|
|
55
55
|
"archiver": "^5.3.1",
|
|
56
56
|
"axios": "^0.27.2",
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
"node-stream-zip": "^1.15.0",
|
|
77
77
|
"p-limit": "^3.1.0",
|
|
78
78
|
"p-retry": "4.6.1",
|
|
79
|
+
"read-last-lines": "^1.8.0",
|
|
79
80
|
"semver": "^7.3.8",
|
|
80
81
|
"sequelize": "^6.31.0",
|
|
81
82
|
"shelljs": "^0.8.5",
|
|
@@ -83,6 +84,7 @@
|
|
|
83
84
|
"stream-throttle": "^0.1.3",
|
|
84
85
|
"stream-to-promise": "^3.0.0",
|
|
85
86
|
"systeminformation": "^5.17.12",
|
|
87
|
+
"tail": "^2.2.4",
|
|
86
88
|
"tar": "^6.1.11",
|
|
87
89
|
"transliteration": "^2.3.5",
|
|
88
90
|
"ua-parser-js": "^1.0.2",
|
|
@@ -94,7 +96,8 @@
|
|
|
94
96
|
"compression": "^1.7.4",
|
|
95
97
|
"expand-tilde": "^2.0.2",
|
|
96
98
|
"express": "^4.18.2",
|
|
97
|
-
"jest": "^27.5.1"
|
|
99
|
+
"jest": "^27.5.1",
|
|
100
|
+
"unzipper": "^0.10.11"
|
|
98
101
|
},
|
|
99
|
-
"gitHead": "
|
|
102
|
+
"gitHead": "f8e2dcefd8d6876e5dedee833ac976b4a0496b20"
|
|
100
103
|
}
|