@abtnode/core 1.16.44-beta-20250601-083116-288e5ea5 → 1.16.44-beta-20250605-131649-6eaf56d9
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/blocklet/manager/disk.js +36 -5
- package/lib/blocklet/migration-dist/migration.cjs +4 -1
- package/lib/blocklet/project/util.js +38 -2
- package/lib/blocklet/webhook/index.js +46 -1
- package/lib/blocklet/webhook/queues.js +57 -17
- package/lib/blocklet/webhook/util.js +7 -0
- package/lib/event/index.js +7 -1
- package/lib/index.js +2 -0
- package/lib/router/monitor.js +2 -1
- package/lib/states/audit-log.js +3 -0
- package/lib/util/blocklet.js +63 -3
- package/lib/util/index.js +8 -0
- package/package.json +36 -36
|
@@ -169,7 +169,9 @@ const {
|
|
|
169
169
|
getAppConfigsFromComponent,
|
|
170
170
|
removeAppConfigsFromComponent,
|
|
171
171
|
getConfigsFromInput,
|
|
172
|
+
getPackComponent,
|
|
172
173
|
getPackConfig,
|
|
174
|
+
copyPackImages,
|
|
173
175
|
filterRequiredComponents,
|
|
174
176
|
} = require('../../util/blocklet');
|
|
175
177
|
const states = require('../../states');
|
|
@@ -445,7 +447,7 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
445
447
|
title,
|
|
446
448
|
description,
|
|
447
449
|
action: `/blocklets/${did}/overview`,
|
|
448
|
-
blockletDashboardAction:
|
|
450
|
+
blockletDashboardAction: `${WELLKNOWN_SERVICE_PATH_PREFIX}/admin/blocklets`,
|
|
449
451
|
entityType: 'blocklet',
|
|
450
452
|
entityId: did,
|
|
451
453
|
severity,
|
|
@@ -1484,7 +1486,7 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
1484
1486
|
entityId: newBlocklet.meta.did,
|
|
1485
1487
|
severity: 'success',
|
|
1486
1488
|
action: `/blocklets/${newBlocklet.meta.did}/components`,
|
|
1487
|
-
blockletDashboardAction:
|
|
1489
|
+
blockletDashboardAction: `${WELLKNOWN_SERVICE_PATH_PREFIX}/admin/components`,
|
|
1488
1490
|
});
|
|
1489
1491
|
|
|
1490
1492
|
this.emit(BlockletEvents.componentRemoved, {
|
|
@@ -3080,6 +3082,8 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
3080
3082
|
// install blocklet
|
|
3081
3083
|
if (postAction === INSTALL_ACTIONS.INSTALL) {
|
|
3082
3084
|
await this._onInstall({ blocklet, componentDids, context, oldBlocklet });
|
|
3085
|
+
await this.getBlocklet(did);
|
|
3086
|
+
|
|
3083
3087
|
return;
|
|
3084
3088
|
}
|
|
3085
3089
|
|
|
@@ -3103,6 +3107,7 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
3103
3107
|
});
|
|
3104
3108
|
|
|
3105
3109
|
const newBlocklet = await this.getBlocklet(did);
|
|
3110
|
+
|
|
3106
3111
|
if (newBlocklet.controller) {
|
|
3107
3112
|
const eventType = 'install';
|
|
3108
3113
|
|
|
@@ -3527,7 +3532,7 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
3527
3532
|
};
|
|
3528
3533
|
|
|
3529
3534
|
const action = `/blocklets/${did}/components?checkUpdate=1`;
|
|
3530
|
-
const blockletDashboardAction =
|
|
3535
|
+
const blockletDashboardAction = `${WELLKNOWN_SERVICE_PATH_PREFIX}/admin/components?checkUpdate=1`;
|
|
3531
3536
|
const users = await this.teamManager.getOwnerAndAdminUsers(did, 1);
|
|
3532
3537
|
const nodeInfo = await states.node.read();
|
|
3533
3538
|
const { wallet } = getBlockletInfo(blocklet, nodeInfo.sk);
|
|
@@ -4022,8 +4027,34 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
4022
4027
|
// Inject pack configs
|
|
4023
4028
|
const packConfig = await getPackConfig(blocklet);
|
|
4024
4029
|
if (packConfig) {
|
|
4030
|
+
const packComponent = getPackComponent(blocklet);
|
|
4031
|
+
|
|
4032
|
+
// 同步图片资源
|
|
4033
|
+
await copyPackImages({
|
|
4034
|
+
appDataDir: path.join(this.dataDirs.data, blocklet.meta.name),
|
|
4035
|
+
packDir: packComponent.env.appDir,
|
|
4036
|
+
packConfig,
|
|
4037
|
+
});
|
|
4038
|
+
|
|
4039
|
+
// 同步 App 导航配置
|
|
4025
4040
|
await this.configNavigations({ did, navigations: packConfig.navigations });
|
|
4026
4041
|
|
|
4042
|
+
// 同步 App 品牌相关图片配置
|
|
4043
|
+
const configObj = packConfig.configObj || {};
|
|
4044
|
+
for (const key of util.APP_CONFIG_IMAGE_KEYS) {
|
|
4045
|
+
const value = configObj[key];
|
|
4046
|
+
if (value) {
|
|
4047
|
+
await this.config({
|
|
4048
|
+
did: [blocklet.meta.did],
|
|
4049
|
+
configs: [{ key, value }],
|
|
4050
|
+
skipHook: true,
|
|
4051
|
+
skipDidDocument: true,
|
|
4052
|
+
skipEmitEvents: true,
|
|
4053
|
+
});
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
|
|
4057
|
+
// 同步各子组件配置
|
|
4027
4058
|
for (const { did: componentDid, configs } of packConfig.components || []) {
|
|
4028
4059
|
if (blocklet.children.some((x) => x.meta.did === componentDid)) {
|
|
4029
4060
|
await this.config({
|
|
@@ -4081,7 +4112,7 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
4081
4112
|
deployedFrom || fromBlockletSource(source)
|
|
4082
4113
|
})`,
|
|
4083
4114
|
action: `/blocklets/${did}/overview`,
|
|
4084
|
-
blockletDashboardAction:
|
|
4115
|
+
blockletDashboardAction: `${WELLKNOWN_SERVICE_PATH_PREFIX}/admin/blocklets`,
|
|
4085
4116
|
entityType: 'blocklet',
|
|
4086
4117
|
entityId: did,
|
|
4087
4118
|
severity: 'success',
|
|
@@ -4322,7 +4353,7 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
4322
4353
|
componentDids
|
|
4323
4354
|
)} is ${actionName} successfully for ${title}`,
|
|
4324
4355
|
action: `/blocklets/${did}/overview`,
|
|
4325
|
-
blockletDashboardAction:
|
|
4356
|
+
blockletDashboardAction: `${WELLKNOWN_SERVICE_PATH_PREFIX}/admin/blocklets`,
|
|
4326
4357
|
entityType: 'blocklet',
|
|
4327
4358
|
entityId: did,
|
|
4328
4359
|
severity: 'success',
|
|
@@ -287,6 +287,8 @@ const EVENTS = {
|
|
|
287
287
|
RELOAD_GATEWAY: 'gateway.reload',
|
|
288
288
|
NOTIFICATION_CREATE_QUEUED: 'notification.create.queued',
|
|
289
289
|
UPDATE_DOMAIN_ALIAS: 'router.domain.alias.updated',
|
|
290
|
+
|
|
291
|
+
WEBHOOK_ATTEMPT: 'webhook.attempt',
|
|
290
292
|
};
|
|
291
293
|
|
|
292
294
|
const WHO_CAN_ACCESS = Object.freeze({
|
|
@@ -752,6 +754,7 @@ module.exports = Object.freeze({
|
|
|
752
754
|
// FIXME: 梁柱, 下面两个 get 接口, 可以不开放但是前端需要根据情况取消获取这两个接口的调用
|
|
753
755
|
getBlockletRuntimeHistory: true,
|
|
754
756
|
checkDomains: true,
|
|
757
|
+
isDidDomain: true,
|
|
755
758
|
},
|
|
756
759
|
// 这些接口可以跳过 ACCESS VERIFY
|
|
757
760
|
SKIP_ACCESS_VERIFY_METHODS: {
|
|
@@ -38885,7 +38888,7 @@ module.exports = require("zlib");
|
|
|
38885
38888
|
/***/ ((module) => {
|
|
38886
38889
|
|
|
38887
38890
|
"use strict";
|
|
38888
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.16.43","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib","test":"node tools/jest.js","coverage":"npm run test -- --coverage"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.16.43","@abtnode/auth":"1.16.43","@abtnode/certificate-manager":"1.16.43","@abtnode/client":"1.16.43","@abtnode/constant":"1.16.43","@abtnode/cron":"1.16.43","@abtnode/docker-utils":"1.16.43","@abtnode/logger":"1.16.43","@abtnode/models":"1.16.43","@abtnode/queue":"1.16.43","@abtnode/rbac":"1.16.43","@abtnode/router-provider":"1.16.43","@abtnode/static-server":"1.16.43","@abtnode/timemachine":"1.16.43","@abtnode/util":"1.16.43","@arcblock/did":"1.20.
|
|
38891
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.16.43","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib","test":"node tools/jest.js","coverage":"npm run test -- --coverage"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.16.43","@abtnode/auth":"1.16.43","@abtnode/certificate-manager":"1.16.43","@abtnode/client":"1.16.43","@abtnode/constant":"1.16.43","@abtnode/cron":"1.16.43","@abtnode/docker-utils":"1.16.43","@abtnode/logger":"1.16.43","@abtnode/models":"1.16.43","@abtnode/queue":"1.16.43","@abtnode/rbac":"1.16.43","@abtnode/router-provider":"1.16.43","@abtnode/static-server":"1.16.43","@abtnode/timemachine":"1.16.43","@abtnode/util":"1.16.43","@arcblock/did":"1.20.13","@arcblock/did-auth":"1.20.13","@arcblock/did-ext":"1.20.13","@arcblock/did-motif":"^1.1.13","@arcblock/did-util":"1.20.13","@arcblock/event-hub":"1.20.13","@arcblock/jwt":"1.20.13","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"1.20.13","@arcblock/vc":"1.20.13","@blocklet/constant":"1.16.43","@blocklet/did-space-js":"^1.0.57","@blocklet/env":"1.16.43","@blocklet/error":"^0.2.5","@blocklet/meta":"1.16.43","@blocklet/resolver":"1.16.43","@blocklet/sdk":"1.16.43","@blocklet/store":"1.16.43","@blocklet/theme":"^2.13.61","@fidm/x509":"^1.2.1","@ocap/mcrypto":"1.20.13","@ocap/util":"1.20.13","@ocap/wallet":"1.20.13","@slack/webhook":"^5.0.4","archiver":"^7.0.1","axios":"^1.7.9","axon":"^2.0.3","chalk":"^4.1.2","cross-spawn":"^7.0.3","dayjs":"^1.11.13","deep-diff":"^1.0.2","detect-port":"^1.5.1","envfile":"^7.1.0","escape-string-regexp":"^4.0.0","fast-glob":"^3.3.2","filesize":"^10.1.1","flat":"^5.0.2","fs-extra":"^11.2.0","get-port":"^5.1.1","hasha":"^5.2.2","is-base64":"^1.1.0","is-cidr":"4","is-ip":"3","is-url":"^1.2.4","joi":"17.12.2","joi-extension-semver":"^5.0.0","js-yaml":"^4.1.0","kill-port":"^2.0.1","lodash":"^4.17.21","lru-cache":"^11.0.2","node-stream-zip":"^1.15.0","p-all":"^3.0.0","p-limit":"^3.1.0","p-map":"^4.0.0","p-retry":"^4.6.2","p-wait-for":"^3.2.0","rate-limiter-flexible":"^5.0.5","read-last-lines":"^1.8.0","semver":"^7.6.3","sequelize":"^6.35.0","shelljs":"^0.8.5","slugify":"^1.6.6","ssri":"^8.0.1","stream-throttle":"^0.1.3","stream-to-promise":"^3.0.0","systeminformation":"^5.23.3","tail":"^2.2.4","tar":"^6.1.11","transliteration":"^2.3.5","ua-parser-js":"^1.0.2","ufo":"^1.5.3","uuid":"^9.0.1","valid-url":"^1.0.9","which":"^2.0.2","xbytes":"^1.8.0"},"devDependencies":{"expand-tilde":"^2.0.2","express":"^4.18.2","jest":"^29.7.0","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
|
|
38889
38892
|
|
|
38890
38893
|
/***/ }),
|
|
38891
38894
|
|
|
@@ -3,7 +3,7 @@ const fs = require('fs-extra');
|
|
|
3
3
|
const fg = require('fast-glob');
|
|
4
4
|
const { isValid: isValidDid } = require('@arcblock/did');
|
|
5
5
|
const { PROJECT, BLOCKLET_RESOURCE_DIR, BLOCKLET_META_FILE } = require('@blocklet/constant');
|
|
6
|
-
const { expandBundle } = require('../../util');
|
|
6
|
+
const { expandBundle, APP_CONFIG_IMAGE_KEYS } = require('../../util');
|
|
7
7
|
|
|
8
8
|
const COMPONENT_CONFIG_MAP_DIR = '.component_config';
|
|
9
9
|
|
|
@@ -46,6 +46,42 @@ const exportBlockletResources = async ({
|
|
|
46
46
|
await fs.remove(path.join(resourceDir, COMPONENT_CONFIG_MAP_DIR));
|
|
47
47
|
|
|
48
48
|
if (isPack) {
|
|
49
|
+
const navigations = app.settings.navigations || [];
|
|
50
|
+
const imagesDir = path.join(exportDir, 'images');
|
|
51
|
+
|
|
52
|
+
// 将 tabbar icons 复制到 images 目录
|
|
53
|
+
const bottomNavItems = navigations.filter((item) => item.section === 'bottomNavigation' && item.icon);
|
|
54
|
+
if (bottomNavItems.length > 0) {
|
|
55
|
+
const mediaDir = path.join(app.env.dataDir, 'media', 'blocklet-service');
|
|
56
|
+
if (fs.existsSync(mediaDir)) {
|
|
57
|
+
await fs.ensureDir(imagesDir);
|
|
58
|
+
|
|
59
|
+
await Promise.all(
|
|
60
|
+
bottomNavItems.map(async (item) => {
|
|
61
|
+
const iconFileName = path.basename(item.icon);
|
|
62
|
+
const iconFile = path.join(mediaDir, iconFileName);
|
|
63
|
+
if (fs.existsSync(iconFile)) {
|
|
64
|
+
await fs.copy(iconFile, path.join(imagesDir, iconFileName));
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 将 branding images 复制到 images 目录
|
|
72
|
+
const configObj = app.configObj || {};
|
|
73
|
+
await Promise.all(
|
|
74
|
+
APP_CONFIG_IMAGE_KEYS.map(async (key) => {
|
|
75
|
+
const value = configObj[key];
|
|
76
|
+
if (value && !value.startsWith('http')) {
|
|
77
|
+
const imgFile = path.join(app.env.dataDir, value);
|
|
78
|
+
if (fs.existsSync(imgFile)) {
|
|
79
|
+
await fs.copy(imgFile, path.join(imagesDir, value));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
|
|
49
85
|
// create pack resource
|
|
50
86
|
const packResourceDir = path.join(resourceDir, blockletDid, 'config');
|
|
51
87
|
await fs.ensureDir(packResourceDir);
|
|
@@ -58,7 +94,6 @@ const exportBlockletResources = async ({
|
|
|
58
94
|
}))
|
|
59
95
|
.filter(Boolean),
|
|
60
96
|
};
|
|
61
|
-
const navigations = app.settings.navigations || [];
|
|
62
97
|
const componentsConfigs = app.children
|
|
63
98
|
.filter((x) => {
|
|
64
99
|
if (selectedComponentDids.length) {
|
|
@@ -72,6 +107,7 @@ const exportBlockletResources = async ({
|
|
|
72
107
|
}));
|
|
73
108
|
await fs.outputJSON(path.join(packResourceDir, 'config.json'), {
|
|
74
109
|
site,
|
|
110
|
+
configObj,
|
|
75
111
|
navigations,
|
|
76
112
|
components: componentsConfigs,
|
|
77
113
|
});
|
|
@@ -2,7 +2,9 @@ const pick = require('lodash/pick');
|
|
|
2
2
|
const pickBy = require('lodash/pickBy');
|
|
3
3
|
const get = require('lodash/get');
|
|
4
4
|
const { EventEmitter } = require('events');
|
|
5
|
-
const {
|
|
5
|
+
const { EVENTS } = require('@abtnode/constant');
|
|
6
|
+
const { API_VERSION, STATUS } = require('./util');
|
|
7
|
+
const endpointQueueInit = require('./queues');
|
|
6
8
|
|
|
7
9
|
const DEFAULT_PAGE = 1;
|
|
8
10
|
const DEFAULT_PAGE_SIZE = 10;
|
|
@@ -25,6 +27,9 @@ class WebhooksAPI extends EventEmitter {
|
|
|
25
27
|
|
|
26
28
|
this.cache = new Map();
|
|
27
29
|
this.TTL = 5 * 60 * 1000;
|
|
30
|
+
|
|
31
|
+
const { webhookEndpointQueue } = endpointQueueInit.init({ states, teamManager });
|
|
32
|
+
this.webhookEndpointQueue = webhookEndpointQueue;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
async getUserInfo(userDid, teamDid, serverDid) {
|
|
@@ -161,6 +166,46 @@ class WebhooksAPI extends EventEmitter {
|
|
|
161
166
|
const list = await webhookAttemptState.list(page, pageSize, where);
|
|
162
167
|
return list;
|
|
163
168
|
}
|
|
169
|
+
|
|
170
|
+
async retryWebhookAttempt({ eventId, webhookId, attemptId, teamDid }, context) {
|
|
171
|
+
const { webhookAttemptState } = await this.teamManager.getWebhookState(teamDid);
|
|
172
|
+
|
|
173
|
+
const result = await webhookAttemptState.insert({
|
|
174
|
+
eventId,
|
|
175
|
+
webhookId,
|
|
176
|
+
status: STATUS.PENDING,
|
|
177
|
+
retryCount: 1,
|
|
178
|
+
responseStatus: 200,
|
|
179
|
+
responseBody: {},
|
|
180
|
+
triggeredBy: getUserDid(context),
|
|
181
|
+
triggeredFrom: attemptId,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const emitResult = async () => {
|
|
185
|
+
return {
|
|
186
|
+
teamDid,
|
|
187
|
+
...(await webhookAttemptState.findOne({ eventId, webhookId, id: result.id })),
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
this.webhookEndpointQueue.push({
|
|
192
|
+
eventId,
|
|
193
|
+
webhookId,
|
|
194
|
+
appDid: teamDid,
|
|
195
|
+
attemptId: result.id,
|
|
196
|
+
triggeredBy: getUserDid(context),
|
|
197
|
+
triggeredFrom: attemptId,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
this.webhookEndpointQueue.on('finished', async () => {
|
|
201
|
+
this.emit(EVENTS.WEBHOOK_ATTEMPT, { ...(await emitResult()) });
|
|
202
|
+
});
|
|
203
|
+
this.webhookEndpointQueue.on('failed', async () => {
|
|
204
|
+
this.emit(EVENTS.WEBHOOK_ATTEMPT, { ...(await emitResult()) });
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
164
209
|
}
|
|
165
210
|
|
|
166
211
|
module.exports = WebhooksAPI;
|
|
@@ -3,13 +3,19 @@ const axios = require('@abtnode/util/lib/axios');
|
|
|
3
3
|
const { Op } = require('sequelize');
|
|
4
4
|
|
|
5
5
|
const createQueue = require('../../util/queue');
|
|
6
|
-
const { getWebhookJobId } = require('./util');
|
|
6
|
+
const { getWebhookJobId, STATUS } = require('./util');
|
|
7
7
|
|
|
8
8
|
const MAX_RETRY_COUNT = 2; // 重试一次
|
|
9
9
|
const AXIOS_TIMEOUT = 1000 * 60 * 3;
|
|
10
10
|
|
|
11
11
|
const createWebhookEndpointQueue = ({ states, teamManager }) => {
|
|
12
12
|
// https://stripe.com/docs/webhooks
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param {*} job eventId: event.id, webhookId: webhook.id, appDid: job.appDid, attemptId?:string
|
|
16
|
+
*
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
13
19
|
const handleWebhookEndpoint = async (job) => {
|
|
14
20
|
logger.info('handle webhook endpoint', job);
|
|
15
21
|
|
|
@@ -48,14 +54,31 @@ const createWebhookEndpointQueue = ({ states, teamManager }) => {
|
|
|
48
54
|
// verify similar to component call, but supports external urls
|
|
49
55
|
const response = await axios.post(webhook.url, event.request, { timeout: AXIOS_TIMEOUT });
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
if (job.attemptId) {
|
|
58
|
+
await webhookAttemptState.update(
|
|
59
|
+
{ id: job.attemptId },
|
|
60
|
+
{
|
|
61
|
+
status: STATUS.SUCCEEDED,
|
|
62
|
+
responseStatus: response.status,
|
|
63
|
+
responseBody: response.data || {},
|
|
64
|
+
retryCount,
|
|
65
|
+
triggeredBy: job.triggeredBy,
|
|
66
|
+
triggeredFrom: job.triggeredFrom,
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
} else {
|
|
70
|
+
await webhookAttemptState.insert({
|
|
71
|
+
eventId: event.id,
|
|
72
|
+
webhookId: webhook.id,
|
|
73
|
+
status: STATUS.SUCCEEDED,
|
|
74
|
+
responseStatus: response.status,
|
|
75
|
+
responseBody: response.data || {},
|
|
76
|
+
retryCount,
|
|
77
|
+
triggeredBy: job.triggeredBy,
|
|
78
|
+
triggeredFrom: job.triggeredFrom,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
59
82
|
logger.info('WebhookAttempt created successfully', { eventId: event.id, webhookId: webhook.id });
|
|
60
83
|
|
|
61
84
|
const newPendingCount = Math.max(0, event.pendingWebhooks - 1);
|
|
@@ -66,14 +89,31 @@ const createWebhookEndpointQueue = ({ states, teamManager }) => {
|
|
|
66
89
|
} catch (err) {
|
|
67
90
|
logger.warn('webhook attempt error', { ...job, retryCount, message: err.message });
|
|
68
91
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
92
|
+
if (job.attemptId) {
|
|
93
|
+
await webhookAttemptState.update(
|
|
94
|
+
{ id: job.attemptId },
|
|
95
|
+
{
|
|
96
|
+
status: STATUS.FAILED,
|
|
97
|
+
responseStatus: err.response?.status || 500,
|
|
98
|
+
responseBody: err.response?.data || {},
|
|
99
|
+
retryCount,
|
|
100
|
+
triggeredBy: job.triggeredBy,
|
|
101
|
+
triggeredFrom: job.triggeredFrom,
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
} else {
|
|
105
|
+
await webhookAttemptState.insert({
|
|
106
|
+
eventId: event.id,
|
|
107
|
+
webhookId: webhook.id,
|
|
108
|
+
status: STATUS.FAILED,
|
|
109
|
+
responseStatus: err.response?.status || 500,
|
|
110
|
+
responseBody: err.response?.data || {},
|
|
111
|
+
retryCount,
|
|
112
|
+
triggeredBy: job.triggeredBy,
|
|
113
|
+
triggeredFrom: job.triggeredFrom,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
77
117
|
logger.info('Failed WebhookAttempt created', { eventId: event.id, webhookId: webhook.id });
|
|
78
118
|
|
|
79
119
|
// reschedule next attempt
|
|
@@ -6,7 +6,14 @@ const getWebhookJobId = (eventId, webhookId) => {
|
|
|
6
6
|
return md5([eventId, webhookId].join('-'));
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
const STATUS = {
|
|
10
|
+
SUCCEEDED: 'succeeded',
|
|
11
|
+
FAILED: 'failed',
|
|
12
|
+
PENDING: 'pending',
|
|
13
|
+
};
|
|
14
|
+
|
|
9
15
|
module.exports = {
|
|
10
16
|
API_VERSION,
|
|
17
|
+
STATUS,
|
|
11
18
|
getWebhookJobId,
|
|
12
19
|
};
|
package/lib/event/index.js
CHANGED
|
@@ -19,6 +19,7 @@ const {
|
|
|
19
19
|
DEFAULT_DID_DOMAIN,
|
|
20
20
|
WELLKNOWN_BLOCKLET_ADMIN_PATH,
|
|
21
21
|
TEST_STORE_URL,
|
|
22
|
+
WELLKNOWN_SERVICE_PATH_PREFIX,
|
|
22
23
|
} = require('@abtnode/constant');
|
|
23
24
|
const { joinURL } = require('ufo');
|
|
24
25
|
const { encode } = require('@abtnode/util/lib/base32');
|
|
@@ -65,6 +66,7 @@ module.exports = ({
|
|
|
65
66
|
node,
|
|
66
67
|
nodeRuntimeMonitor,
|
|
67
68
|
daemon,
|
|
69
|
+
webhookManager,
|
|
68
70
|
}) => {
|
|
69
71
|
const nodeState = states.node;
|
|
70
72
|
const nodeMonitSender = new NodeMonitSender({ node });
|
|
@@ -561,6 +563,10 @@ module.exports = ({
|
|
|
561
563
|
eventHub.broadcast(name, data);
|
|
562
564
|
});
|
|
563
565
|
|
|
566
|
+
listen(webhookManager, EVENTS.WEBHOOK_ATTEMPT, (name, data) => {
|
|
567
|
+
onEvent(name, data, true);
|
|
568
|
+
});
|
|
569
|
+
|
|
564
570
|
listen(nodeState, BlockletEvents.purchaseChange, onEvent);
|
|
565
571
|
nodeState.on(EVENTS.ROUTING_UPDATED, (nodeInfo) => onEvent(EVENTS.ROUTING_UPDATED, { routing: nodeInfo.routing }));
|
|
566
572
|
nodeState.once(EVENTS.NODE_ADDED_OWNER, () => downloadAddedBlocklet());
|
|
@@ -706,7 +712,7 @@ module.exports = ({
|
|
|
706
712
|
actions: [
|
|
707
713
|
{
|
|
708
714
|
name: translation.viewYourAccount,
|
|
709
|
-
link: joinURL(origin,
|
|
715
|
+
link: joinURL(origin, `${WELLKNOWN_SERVICE_PATH_PREFIX}/user/settings`),
|
|
710
716
|
},
|
|
711
717
|
],
|
|
712
718
|
};
|
package/lib/index.js
CHANGED
|
@@ -753,6 +753,7 @@ function ABTNode(options) {
|
|
|
753
753
|
getWebhookEndpoints: webhookAPI.getWebhookEndpoints.bind(webhookAPI),
|
|
754
754
|
getWebhookEndpoint: webhookAPI.getWebhookEndpoint.bind(webhookAPI),
|
|
755
755
|
getWebhookAttempts: webhookAPI.getWebhookAttempts.bind(webhookAPI),
|
|
756
|
+
retryWebhookAttempt: webhookAPI.retryWebhookAttempt.bind(webhookAPI),
|
|
756
757
|
|
|
757
758
|
// passport
|
|
758
759
|
createPassportLog: passportAPI.createPassportLog.bind(passportAPI),
|
|
@@ -799,6 +800,7 @@ function ABTNode(options) {
|
|
|
799
800
|
nodeRuntimeMonitor: nodeAPI.runtimeMonitor,
|
|
800
801
|
daemon: options.daemon,
|
|
801
802
|
handleBlockletWafChange,
|
|
803
|
+
webhookManager: webhookAPI,
|
|
802
804
|
});
|
|
803
805
|
|
|
804
806
|
const webhook = WebHook({ events, dataDirs, instance, teamManager });
|
package/lib/router/monitor.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { WELLKNOWN_SERVICE_PATH_PREFIX } = require('@abtnode/constant');
|
|
1
2
|
const { createLogWatcher } = require('./watcher');
|
|
2
3
|
|
|
3
4
|
// Function to parse the log entry and extract relevant information
|
|
@@ -36,7 +37,7 @@ function parseLogEntry(line, check = true) {
|
|
|
36
37
|
logEntry.status <= 599 &&
|
|
37
38
|
logEntry.request.includes('/.well-known/did.json') === false &&
|
|
38
39
|
logEntry.request.includes('/websocket') === false &&
|
|
39
|
-
logEntry.request.includes(
|
|
40
|
+
logEntry.request.includes(`${WELLKNOWN_SERVICE_PATH_PREFIX}/health`) === false
|
|
40
41
|
) {
|
|
41
42
|
console.warn(`5xx request detected: ${logEntry.host}`, line);
|
|
42
43
|
return logEntry;
|
package/lib/states/audit-log.js
CHANGED
|
@@ -515,6 +515,8 @@ const getLogContent = async (action, args, context, result, info, node) => {
|
|
|
515
515
|
return `Delete Blocklet Webhook(${result.id})`;
|
|
516
516
|
case 'ensureBlockletRunning':
|
|
517
517
|
return `${result.title}:\n* ${result.description}`;
|
|
518
|
+
case 'retryWebhookAttempt':
|
|
519
|
+
return `Retry Webhook Attempt(${args.attemptId})`;
|
|
518
520
|
|
|
519
521
|
case 'addUploadEndpoint':
|
|
520
522
|
return `Create Upload Endpoint(${args.url})`;
|
|
@@ -657,6 +659,7 @@ const getLogCategory = (action) => {
|
|
|
657
659
|
case 'createWebhookEndpoint':
|
|
658
660
|
case 'updateWebhookEndpoint':
|
|
659
661
|
case 'deleteWebhookEndpoint':
|
|
662
|
+
case 'retryWebhookAttempt':
|
|
660
663
|
return 'integrations';
|
|
661
664
|
|
|
662
665
|
// server
|
package/lib/util/blocklet.js
CHANGED
|
@@ -117,7 +117,14 @@ const FileLock = require('@abtnode/util/lib/lock-with-file');
|
|
|
117
117
|
const { validate: validateEngine, get: getEngine } = require('../blocklet/manager/engine');
|
|
118
118
|
|
|
119
119
|
const isRequirementsSatisfied = require('./requirement');
|
|
120
|
-
const {
|
|
120
|
+
const {
|
|
121
|
+
expandBundle,
|
|
122
|
+
findInterfacePortByName,
|
|
123
|
+
prettyURL,
|
|
124
|
+
templateReplace,
|
|
125
|
+
getServerDidDomain,
|
|
126
|
+
APP_CONFIG_IMAGE_KEYS,
|
|
127
|
+
} = require('./index');
|
|
121
128
|
const { installExternalDependencies } = require('./install-external-dependencies');
|
|
122
129
|
const parseDockerOptionsFromPm2 = require('./docker/parse-docker-options-from-pm2');
|
|
123
130
|
const dockerRemoveByName = require('./docker/docker-remove-by-name');
|
|
@@ -1676,7 +1683,8 @@ const fromProperty2Config = (properties = {}, result) => {
|
|
|
1676
1683
|
name: `${BLOCKLET_PREFERENCE_PREFIX}${key}`,
|
|
1677
1684
|
required: prop.required || false,
|
|
1678
1685
|
secure,
|
|
1679
|
-
|
|
1686
|
+
// eslint-disable-next-line no-nested-ternary
|
|
1687
|
+
shared: secure ? false : typeof prop.shared === 'undefined' ? true : prop.shared,
|
|
1680
1688
|
});
|
|
1681
1689
|
}
|
|
1682
1690
|
});
|
|
@@ -2351,8 +2359,12 @@ const removeAppConfigsFromComponent = async (componentConfigs, app, blockletExtr
|
|
|
2351
2359
|
}
|
|
2352
2360
|
};
|
|
2353
2361
|
|
|
2362
|
+
const getPackComponent = (app) => {
|
|
2363
|
+
return (app?.children || []).find((x) => x.meta.group === BlockletGroup.pack);
|
|
2364
|
+
};
|
|
2365
|
+
|
|
2354
2366
|
const getPackConfig = (app) => {
|
|
2355
|
-
const packComponent = (app
|
|
2367
|
+
const packComponent = getPackComponent(app);
|
|
2356
2368
|
if (!packComponent) {
|
|
2357
2369
|
return null;
|
|
2358
2370
|
}
|
|
@@ -2374,6 +2386,52 @@ const getPackConfig = (app) => {
|
|
|
2374
2386
|
|
|
2375
2387
|
return fs.readJSON(configFile);
|
|
2376
2388
|
};
|
|
2389
|
+
|
|
2390
|
+
/** 复制打包文件中的图片
|
|
2391
|
+
* @param {string} appDataDir
|
|
2392
|
+
* @param {string} packDir
|
|
2393
|
+
* @param {{ navigations: Array<{ section: string | string[], icon: string }>, configObj: Record<string, string> }} packConfig
|
|
2394
|
+
*/
|
|
2395
|
+
const copyPackImages = async ({ appDataDir, packDir, packConfig = {} }) => {
|
|
2396
|
+
const mediaDir = path.join(appDataDir, 'media', 'blocklet-service');
|
|
2397
|
+
const { navigations = [], configObj = {} } = packConfig;
|
|
2398
|
+
await fs.ensureDir(mediaDir);
|
|
2399
|
+
|
|
2400
|
+
// 过滤出 bottomNavigation 的图标
|
|
2401
|
+
const bottomNavItems = navigations.filter((item) => {
|
|
2402
|
+
// 处理 section 字段为数组的情况
|
|
2403
|
+
const sections = Array.isArray(item.section) ? item.section : [item.section];
|
|
2404
|
+
return sections.includes('bottomNavigation') && item.icon;
|
|
2405
|
+
});
|
|
2406
|
+
|
|
2407
|
+
// 复制 tabbar 导航图标
|
|
2408
|
+
if (bottomNavItems.length > 0) {
|
|
2409
|
+
await Promise.all(
|
|
2410
|
+
bottomNavItems.map(async (item) => {
|
|
2411
|
+
const iconFileName = path.basename(item.icon);
|
|
2412
|
+
const iconInImages = path.join(packDir, 'images', iconFileName);
|
|
2413
|
+
|
|
2414
|
+
if (fs.existsSync(iconInImages)) {
|
|
2415
|
+
await fs.copy(iconInImages, path.join(mediaDir, iconFileName));
|
|
2416
|
+
}
|
|
2417
|
+
})
|
|
2418
|
+
);
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
// 复制品牌相关图片
|
|
2422
|
+
await Promise.all(
|
|
2423
|
+
APP_CONFIG_IMAGE_KEYS.map(async (key) => {
|
|
2424
|
+
const value = configObj[key];
|
|
2425
|
+
if (value) {
|
|
2426
|
+
const imgFile = path.join(packDir, 'images', value);
|
|
2427
|
+
if (fs.existsSync(imgFile)) {
|
|
2428
|
+
await fs.copy(imgFile, path.join(appDataDir, value));
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
})
|
|
2432
|
+
);
|
|
2433
|
+
};
|
|
2434
|
+
|
|
2377
2435
|
/**
|
|
2378
2436
|
* @param {import('@abtnode/client').BlockletState} blocklet
|
|
2379
2437
|
* @returns {boolean}
|
|
@@ -2449,7 +2507,9 @@ module.exports = {
|
|
|
2449
2507
|
getAppConfigsFromComponent,
|
|
2450
2508
|
removeAppConfigsFromComponent,
|
|
2451
2509
|
getConfigsFromInput,
|
|
2510
|
+
getPackComponent,
|
|
2452
2511
|
getPackConfig,
|
|
2512
|
+
copyPackImages,
|
|
2453
2513
|
getBlockletConfigObj,
|
|
2454
2514
|
isDevelopmentMode,
|
|
2455
2515
|
resolveMountPointConflict,
|
package/lib/util/index.js
CHANGED
|
@@ -30,8 +30,15 @@ const {
|
|
|
30
30
|
SLOT_FOR_IP_DNS_SITE,
|
|
31
31
|
BLOCKLET_SITE_GROUP_SUFFIX,
|
|
32
32
|
} = require('@abtnode/constant');
|
|
33
|
+
const { BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
|
|
33
34
|
|
|
34
35
|
const DEFAULT_WELLKNOWN_PORT = 8088;
|
|
36
|
+
const APP_CONFIG_IMAGE_KEYS = [
|
|
37
|
+
BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_FAVICON,
|
|
38
|
+
BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SPLASH_PORTRAIT,
|
|
39
|
+
BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SPLASH_LANDSCAPE,
|
|
40
|
+
BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_OG_IMAGE,
|
|
41
|
+
];
|
|
35
42
|
|
|
36
43
|
const logger = require('@abtnode/logger')('@abtnode/core:util');
|
|
37
44
|
const getSafeEnv = require('./get-safe-env');
|
|
@@ -487,6 +494,7 @@ const toCamelCase = (obj) => {
|
|
|
487
494
|
};
|
|
488
495
|
|
|
489
496
|
const lib = {
|
|
497
|
+
APP_CONFIG_IMAGE_KEYS,
|
|
490
498
|
validateOwner,
|
|
491
499
|
getProviderFromNodeInfo,
|
|
492
500
|
toStatus,
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.44-beta-
|
|
6
|
+
"version": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,44 +19,44 @@
|
|
|
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.44-beta-
|
|
23
|
-
"@abtnode/auth": "1.16.44-beta-
|
|
24
|
-
"@abtnode/certificate-manager": "1.16.44-beta-
|
|
25
|
-
"@abtnode/client": "1.16.44-beta-
|
|
26
|
-
"@abtnode/constant": "1.16.44-beta-
|
|
27
|
-
"@abtnode/cron": "1.16.44-beta-
|
|
28
|
-
"@abtnode/docker-utils": "1.16.44-beta-
|
|
29
|
-
"@abtnode/logger": "1.16.44-beta-
|
|
30
|
-
"@abtnode/models": "1.16.44-beta-
|
|
31
|
-
"@abtnode/queue": "1.16.44-beta-
|
|
32
|
-
"@abtnode/rbac": "1.16.44-beta-
|
|
33
|
-
"@abtnode/router-provider": "1.16.44-beta-
|
|
34
|
-
"@abtnode/static-server": "1.16.44-beta-
|
|
35
|
-
"@abtnode/timemachine": "1.16.44-beta-
|
|
36
|
-
"@abtnode/util": "1.16.44-beta-
|
|
37
|
-
"@arcblock/did": "1.20.
|
|
38
|
-
"@arcblock/did-auth": "1.20.
|
|
39
|
-
"@arcblock/did-ext": "1.20.
|
|
22
|
+
"@abtnode/analytics": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
23
|
+
"@abtnode/auth": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
24
|
+
"@abtnode/certificate-manager": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
25
|
+
"@abtnode/client": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
26
|
+
"@abtnode/constant": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
27
|
+
"@abtnode/cron": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
28
|
+
"@abtnode/docker-utils": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
29
|
+
"@abtnode/logger": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
30
|
+
"@abtnode/models": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
31
|
+
"@abtnode/queue": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
32
|
+
"@abtnode/rbac": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
33
|
+
"@abtnode/router-provider": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
34
|
+
"@abtnode/static-server": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
35
|
+
"@abtnode/timemachine": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
36
|
+
"@abtnode/util": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
37
|
+
"@arcblock/did": "1.20.13",
|
|
38
|
+
"@arcblock/did-auth": "1.20.13",
|
|
39
|
+
"@arcblock/did-ext": "1.20.13",
|
|
40
40
|
"@arcblock/did-motif": "^1.1.13",
|
|
41
|
-
"@arcblock/did-util": "1.20.
|
|
42
|
-
"@arcblock/event-hub": "1.20.
|
|
43
|
-
"@arcblock/jwt": "1.20.
|
|
41
|
+
"@arcblock/did-util": "1.20.13",
|
|
42
|
+
"@arcblock/event-hub": "1.20.13",
|
|
43
|
+
"@arcblock/jwt": "1.20.13",
|
|
44
44
|
"@arcblock/pm2-events": "^0.0.5",
|
|
45
|
-
"@arcblock/validator": "1.20.
|
|
46
|
-
"@arcblock/vc": "1.20.
|
|
47
|
-
"@blocklet/constant": "1.16.44-beta-
|
|
48
|
-
"@blocklet/did-space-js": "^1.0.
|
|
49
|
-
"@blocklet/env": "1.16.44-beta-
|
|
45
|
+
"@arcblock/validator": "1.20.13",
|
|
46
|
+
"@arcblock/vc": "1.20.13",
|
|
47
|
+
"@blocklet/constant": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
48
|
+
"@blocklet/did-space-js": "^1.0.57",
|
|
49
|
+
"@blocklet/env": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
50
50
|
"@blocklet/error": "^0.2.5",
|
|
51
|
-
"@blocklet/meta": "1.16.44-beta-
|
|
52
|
-
"@blocklet/resolver": "1.16.44-beta-
|
|
53
|
-
"@blocklet/sdk": "1.16.44-beta-
|
|
54
|
-
"@blocklet/store": "1.16.44-beta-
|
|
55
|
-
"@blocklet/theme": "^2.13.
|
|
51
|
+
"@blocklet/meta": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
52
|
+
"@blocklet/resolver": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
53
|
+
"@blocklet/sdk": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
54
|
+
"@blocklet/store": "1.16.44-beta-20250605-131649-6eaf56d9",
|
|
55
|
+
"@blocklet/theme": "^2.13.61",
|
|
56
56
|
"@fidm/x509": "^1.2.1",
|
|
57
|
-
"@ocap/mcrypto": "1.20.
|
|
58
|
-
"@ocap/util": "1.20.
|
|
59
|
-
"@ocap/wallet": "1.20.
|
|
57
|
+
"@ocap/mcrypto": "1.20.13",
|
|
58
|
+
"@ocap/util": "1.20.13",
|
|
59
|
+
"@ocap/wallet": "1.20.13",
|
|
60
60
|
"@slack/webhook": "^5.0.4",
|
|
61
61
|
"archiver": "^7.0.1",
|
|
62
62
|
"axios": "^1.7.9",
|
|
@@ -116,5 +116,5 @@
|
|
|
116
116
|
"jest": "^29.7.0",
|
|
117
117
|
"unzipper": "^0.10.11"
|
|
118
118
|
},
|
|
119
|
-
"gitHead": "
|
|
119
|
+
"gitHead": "667899e10781e9fcc21c40c2a2f60f3fa2fecc88"
|
|
120
120
|
}
|