@abtnode/core 1.16.18-beta-aa01bd8e → 1.16.18-beta-bb4ebacc

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.
@@ -1,7 +1,7 @@
1
1
  const get = require('lodash/get');
2
2
  const cloneDeep = require('lodash/cloneDeep');
3
3
  const { EventEmitter } = require('events');
4
- const { wipeSensitiveData } = require('@blocklet/meta/lib/util');
4
+ const { wipeSensitiveData, getDisplayName } = require('@blocklet/meta/lib/util');
5
5
  const logger = require('@abtnode/logger')('@abtnode/core:event');
6
6
  const {
7
7
  BLOCKLET_MODES,
@@ -308,20 +308,32 @@ module.exports = ({
308
308
  } else if (BlockletEvents.backupProgress === eventName && payload?.completed) {
309
309
  try {
310
310
  const backupEndpoint = getBackupEndpoint(blocklet?.environments);
311
+ const args = {
312
+ did: blocklet.meta.did,
313
+ url: getDIDSpacesUrlFromEndpoint(backupEndpoint),
314
+ backupUrl: getBackupFilesUrlFromEndpoint(backupEndpoint),
315
+ success: payload?.progress === 100,
316
+ errorMessage: payload?.message,
317
+ strategy: payload.backup.strategy,
318
+ };
311
319
 
312
320
  await node.createAuditLog({
313
321
  action: 'backupToSpaces',
314
- args: {
315
- did: blocklet.meta.did,
316
- url: getDIDSpacesUrlFromEndpoint(backupEndpoint),
317
- backupUrl: getBackupFilesUrlFromEndpoint(backupEndpoint),
318
- success: payload?.progress === 100,
319
- errorMessage: payload?.message,
320
- strategy: payload.backup.strategy,
321
- },
322
+ args,
322
323
  context: payload?.context ?? {},
323
324
  result: cloneDeep(blocklet),
324
325
  });
326
+
327
+ if (payload?.progress !== 100) {
328
+ await node.createNotification({
329
+ title: 'App Backup Failed',
330
+ description: `Failed to backup ${getDisplayName(blocklet)} to ${args.url}, due to: ${args.errorMessage}`,
331
+ entityType: 'blocklet',
332
+ entityId: args.did,
333
+ severity: 'error',
334
+ sticky: true,
335
+ });
336
+ }
325
337
  } catch (error) {
326
338
  logger.error('Failed to createAuditLog for backupToSpaces failed', { error });
327
339
  }
package/lib/index.js CHANGED
@@ -436,6 +436,7 @@ function ABTNode(options) {
436
436
  deleteBlockletStore: teamAPI.deleteStore.bind(teamAPI),
437
437
 
438
438
  // Notifications
439
+ createNotification: states.notification.create.bind(states.notification),
439
440
  getNotifications: states.notification.findPaginated.bind(states.notification),
440
441
  readNotifications: states.notification.read.bind(states.notification),
441
442
  unreadNotifications: states.notification.unread.bind(states.notification),
@@ -635,6 +636,7 @@ function ABTNode(options) {
635
636
  createWebHook: webhook.create.bind(webhook),
636
637
  deleteWebHook: webhook.delete.bind(webhook),
637
638
  getWebhookSenders: webhook.listSenders.bind(webhook),
639
+ getMessageSender: webhook.getMessageSender.bind(webhook),
638
640
  sendTestMessage: webhook.sendTestMessage.bind(webhook),
639
641
  });
640
642
  }
@@ -4,6 +4,7 @@ const axon = require('axon');
4
4
  const path = require('path');
5
5
  const shell = require('shelljs');
6
6
  const semver = require('semver');
7
+ const { getInstaller, getInstallCommands } = require('@abtnode/util/lib/get-installer');
7
8
 
8
9
  const VERBOSE = '';
9
10
  // const VERBOSE = '--verbose';
@@ -26,30 +27,8 @@ const runAsync = (command, options) =>
26
27
  });
27
28
  });
28
29
 
29
- const getInstaller = () => {
30
- const { stdout: pnpmPath } = shell.which('pnpm') || {};
31
- if (pnpmPath) {
32
- const { stdout: expectedDir } = shell.exec('pnpm bin -g', { silent: true });
33
- const { stdout: binPath } = shell.which(BINARY_NAME);
34
- if (expectedDir && binPath && expectedDir.trim() === path.dirname(binPath)) {
35
- return 'pnpm';
36
- }
37
- }
38
-
39
- const { stdout: yarnPath } = shell.which('yarn') || {};
40
- if (yarnPath) {
41
- const { stdout: binaryDir } = shell.exec(`yarn global bin ${BINARY_NAME}`, { silent: true });
42
- const binaryPath = path.join(binaryDir, BINARY_NAME);
43
- if (fs.existsSync(binaryPath)) {
44
- return 'yarn';
45
- }
46
- }
47
-
48
- return 'npm';
49
- };
50
-
51
30
  const getBinaryDir = () => {
52
- const installer = getInstaller();
31
+ const installer = getInstaller(BINARY_NAME);
53
32
  if (installer === 'pnpm') {
54
33
  const { stdout: binaryDir, code } = shell.exec('pnpm bin -g', { silent: true });
55
34
  if (code === 0) {
@@ -77,12 +56,8 @@ const installBlockletServer = async (version) => {
77
56
  return { code: 1, stderr: 'Abort because you are not using a standard @blocklet/cli setup' };
78
57
  }
79
58
 
80
- const installer = getInstaller();
81
- const commands = {
82
- pnpm: `pnpm add -g ${PACKAGE_NAME}@${version} ${VERBOSE}`,
83
- npm: `npm install -g ${PACKAGE_NAME}@${version} ${VERBOSE}`,
84
- yarn: `yarn global add ${PACKAGE_NAME}@${version} ${VERBOSE}`,
85
- };
59
+ const installer = getInstaller(BINARY_NAME);
60
+ const commands = getInstallCommands({ packageName: PACKAGE_NAME, version, params: VERBOSE });
86
61
  const command = commands[installer];
87
62
  console.info('Installing blocklet server', { version, installer, command });
88
63
  const result = await runAsync(command, {
@@ -145,7 +145,7 @@ const getLogContent = async (action, args, context, result, info, node) => {
145
145
  }
146
146
  return `Automatic backup application to ${args.url} successfully:\n- Backup files have been stored [here](${args.backupUrl})`;
147
147
  }
148
- return `Backup application to ${args.url} failed:\n- The reason for the error is: <span style='color:red'>${args.errorMessage}</span>`;
148
+ return `Backup application to ${args.url} failed:\n- Reason: <span style='color:red'>${args.errorMessage}</span>`;
149
149
  case 'configPublicToStore':
150
150
  return `set publicToStore to ${args.publicToStore ? 'true' : 'false'}`;
151
151
  case 'configNavigations':
@@ -4,7 +4,13 @@ const omit = require('lodash/omit');
4
4
  const isEmpty = require('lodash/isEmpty');
5
5
  const security = require('@abtnode/util/lib/security');
6
6
  const { isFromPublicKey } = require('@arcblock/did');
7
- const { NODE_MODES, DISK_ALERT_THRESHOLD_PERCENT, EVENTS, SERVER_STATUS } = require('@abtnode/constant');
7
+ const {
8
+ NODE_MODES,
9
+ DISK_ALERT_THRESHOLD_PERCENT,
10
+ EVENTS,
11
+ SERVER_STATUS,
12
+ PROXY_MAX_MEM_LIMIT_IN_MB,
13
+ } = require('@abtnode/constant');
8
14
  // const logger = require('@abtnode/logger')('@abtnode/core:states:node');
9
15
 
10
16
  const BaseState = require('./base');
@@ -132,6 +138,10 @@ class NodeState extends BaseState {
132
138
  doc.sk = security.decrypt(doc.sk, doc.did, dek);
133
139
  }
134
140
 
141
+ if (doc.runtimeConfig && !doc.runtimeConfig.proxyMaxMemoryLimit) {
142
+ doc.runtimeConfig.proxyMaxMemoryLimit = PROXY_MAX_MEM_LIMIT_IN_MB;
143
+ }
144
+
135
145
  return doc;
136
146
  }
137
147
 
package/lib/util/log.js CHANGED
@@ -117,6 +117,7 @@ const getLogFiles = async ({ name, node }) => {
117
117
  const access = path.join(logDir, 'access.log');
118
118
  const stdout = path.join(logDir, 'daemon.stdout.log');
119
119
  const stderr = path.join(logDir, 'daemon.stderr.log');
120
+ const pm2 = path.join(process.env.PM2_HOME, 'pm2.log');
120
121
 
121
122
  createFile({
122
123
  info,
@@ -124,6 +125,7 @@ const getLogFiles = async ({ name, node }) => {
124
125
  access,
125
126
  stdout,
126
127
  stderr,
128
+ pm2,
127
129
  });
128
130
 
129
131
  return {
@@ -132,6 +134,7 @@ const getLogFiles = async ({ name, node }) => {
132
134
  access,
133
135
  stdout,
134
136
  stderr,
137
+ pm2,
135
138
  };
136
139
  }
137
140
 
@@ -30,7 +30,7 @@ const nodeInfoSchema = Joi.object({
30
30
  }),
31
31
  nftDomainUrl: Joi.string()
32
32
  .uri({ scheme: [/https?/] })
33
- .label('web wallet url')
33
+ .label('nft domain url')
34
34
  .allow('')
35
35
  .optional()
36
36
  .messages({
@@ -173,7 +173,7 @@ module.exports = ({ events, dataDirs, instance }) => {
173
173
  const sendTestMessage = async (msg) => {
174
174
  const { webhookId, message } = msg;
175
175
  try {
176
- const webhook = await webhookState.findOne(webhookId);
176
+ const webhook = webhookId ? await webhookState.findOne(webhookId) : msg.webhook;
177
177
  await sentTextMessage(webhook, message);
178
178
 
179
179
  notification.create({
@@ -195,6 +195,7 @@ module.exports = ({ events, dataDirs, instance }) => {
195
195
 
196
196
  return {
197
197
  listSenders: WebHookSender.listSenders,
198
+ getMessageSender: WebHookSender.getMessageSender,
198
199
  create: createWebhook,
199
200
  delete: deleteWebhook,
200
201
  sendTestMessage,
@@ -9,12 +9,16 @@ class APISender extends BaseSender {
9
9
  const { status, name, title, description } = message;
10
10
 
11
11
  try {
12
- await axios.post(url, {
13
- status,
14
- name,
15
- title,
16
- description,
17
- });
12
+ await axios.post(
13
+ url,
14
+ {
15
+ status,
16
+ name,
17
+ title,
18
+ description,
19
+ },
20
+ { timeout: 10000 }
21
+ );
18
22
  } catch (error) {
19
23
  logger.error('failed to push notification to api', { url, message: JSON.stringify(message), error });
20
24
  }
@@ -28,6 +32,14 @@ class APISender extends BaseSender {
28
32
  title: 'Test Message',
29
33
  });
30
34
  }
35
+
36
+ async sendNotification(url, notification) {
37
+ try {
38
+ await axios.post(url, notification, { timeout: 10000 });
39
+ } catch (error) {
40
+ logger.error('failed to push notification to api', { url, error });
41
+ }
42
+ }
31
43
  }
32
44
 
33
45
  APISender.type = 'api';
@@ -59,8 +59,9 @@ class SlackSender extends BaseSender {
59
59
  username: 'Blocklet Server',
60
60
  icon_url: 'https://releases.arcblockio.cn/arcblock.png',
61
61
  });
62
- } catch (error) {
63
- logger.error('failed to push notification to slack', { api: url, message: JSON.stringify(message), error });
62
+ } catch (err) {
63
+ console.error(err);
64
+ logger.error('failed to push notification to slack', { api: url, message: JSON.stringify(message), error: err });
64
65
  }
65
66
  }
66
67
 
@@ -73,6 +74,66 @@ class SlackSender extends BaseSender {
73
74
  'text'
74
75
  );
75
76
  }
77
+
78
+ async sendNotification(url, message) {
79
+ const { title, body, sender, attachments, actions = [] } = message;
80
+ try {
81
+ const blocks = [];
82
+ if (title) {
83
+ blocks.push({
84
+ type: 'header',
85
+ text: {
86
+ type: 'plain_text',
87
+ text: title,
88
+ },
89
+ });
90
+ }
91
+ if (body) {
92
+ blocks.push({
93
+ type: 'section',
94
+ text: {
95
+ type: 'plain_text',
96
+ text: body,
97
+ },
98
+ });
99
+ }
100
+
101
+ // FIXME: support more attachment types: nft, image, token, vc
102
+ (attachments || [])
103
+ .filter((x) => x.type === 'section')
104
+ .forEach((x) => {
105
+ blocks.push({
106
+ type: x.type,
107
+ fields: x.fields.map((f) => ({ type: 'plain_text', text: f.data.text })),
108
+ });
109
+ });
110
+ if (actions.length) {
111
+ blocks.push({
112
+ type: 'actions',
113
+ elements: actions.map((x) => ({
114
+ type: 'button',
115
+ text: {
116
+ type: 'plain_text',
117
+ text: x.name,
118
+ },
119
+ style: 'primary',
120
+ value: x.name,
121
+ url: x.link,
122
+ })),
123
+ });
124
+ }
125
+
126
+ const webhook = new IncomingWebhook(url);
127
+ await webhook.send({
128
+ blocks,
129
+ username: sender.name,
130
+ icon_url: sender.logo,
131
+ });
132
+ } catch (err) {
133
+ console.error(err);
134
+ logger.error('failed to push notification to slack', { api: url, error: err });
135
+ }
136
+ }
76
137
  }
77
138
 
78
139
  SlackSender.type = 'slack';
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.18-beta-aa01bd8e",
6
+ "version": "1.16.18-beta-bb4ebacc",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,19 +19,19 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "Apache-2.0",
21
21
  "dependencies": {
22
- "@abtnode/analytics": "1.16.18-beta-aa01bd8e",
23
- "@abtnode/auth": "1.16.18-beta-aa01bd8e",
24
- "@abtnode/certificate-manager": "1.16.18-beta-aa01bd8e",
25
- "@abtnode/constant": "1.16.18-beta-aa01bd8e",
26
- "@abtnode/cron": "1.16.18-beta-aa01bd8e",
27
- "@abtnode/logger": "1.16.18-beta-aa01bd8e",
28
- "@abtnode/models": "1.16.18-beta-aa01bd8e",
29
- "@abtnode/queue": "1.16.18-beta-aa01bd8e",
30
- "@abtnode/rbac": "1.16.18-beta-aa01bd8e",
31
- "@abtnode/router-provider": "1.16.18-beta-aa01bd8e",
32
- "@abtnode/static-server": "1.16.18-beta-aa01bd8e",
33
- "@abtnode/timemachine": "1.16.18-beta-aa01bd8e",
34
- "@abtnode/util": "1.16.18-beta-aa01bd8e",
22
+ "@abtnode/analytics": "1.16.18-beta-bb4ebacc",
23
+ "@abtnode/auth": "1.16.18-beta-bb4ebacc",
24
+ "@abtnode/certificate-manager": "1.16.18-beta-bb4ebacc",
25
+ "@abtnode/constant": "1.16.18-beta-bb4ebacc",
26
+ "@abtnode/cron": "1.16.18-beta-bb4ebacc",
27
+ "@abtnode/logger": "1.16.18-beta-bb4ebacc",
28
+ "@abtnode/models": "1.16.18-beta-bb4ebacc",
29
+ "@abtnode/queue": "1.16.18-beta-bb4ebacc",
30
+ "@abtnode/rbac": "1.16.18-beta-bb4ebacc",
31
+ "@abtnode/router-provider": "1.16.18-beta-bb4ebacc",
32
+ "@abtnode/static-server": "1.16.18-beta-bb4ebacc",
33
+ "@abtnode/timemachine": "1.16.18-beta-bb4ebacc",
34
+ "@abtnode/util": "1.16.18-beta-bb4ebacc",
35
35
  "@arcblock/did": "1.18.95",
36
36
  "@arcblock/did-auth": "1.18.95",
37
37
  "@arcblock/did-ext": "^1.18.95",
@@ -42,12 +42,12 @@
42
42
  "@arcblock/pm2-events": "^0.0.5",
43
43
  "@arcblock/validator": "^1.18.95",
44
44
  "@arcblock/vc": "1.18.95",
45
- "@blocklet/constant": "1.16.18-beta-aa01bd8e",
46
- "@blocklet/env": "1.16.18-beta-aa01bd8e",
47
- "@blocklet/meta": "1.16.18-beta-aa01bd8e",
48
- "@blocklet/resolver": "1.16.18-beta-aa01bd8e",
49
- "@blocklet/sdk": "1.16.18-beta-aa01bd8e",
50
- "@did-space/client": "^0.3.20",
45
+ "@blocklet/constant": "1.16.18-beta-bb4ebacc",
46
+ "@blocklet/env": "1.16.18-beta-bb4ebacc",
47
+ "@blocklet/meta": "1.16.18-beta-bb4ebacc",
48
+ "@blocklet/resolver": "1.16.18-beta-bb4ebacc",
49
+ "@blocklet/sdk": "1.16.18-beta-bb4ebacc",
50
+ "@did-space/client": "^0.3.22",
51
51
  "@fidm/x509": "^1.2.1",
52
52
  "@ocap/mcrypto": "1.18.95",
53
53
  "@ocap/util": "1.18.95",
@@ -69,7 +69,7 @@
69
69
  "hasha": "^5.2.2",
70
70
  "is-base64": "^1.1.0",
71
71
  "is-url": "^1.2.4",
72
- "joi": "17.7.0",
72
+ "joi": "17.11.0",
73
73
  "joi-extension-semver": "^5.0.0",
74
74
  "js-yaml": "^4.1.0",
75
75
  "kill-port": "^2.0.1",
@@ -101,5 +101,5 @@
101
101
  "jest": "^27.5.1",
102
102
  "unzipper": "^0.10.11"
103
103
  },
104
- "gitHead": "2bfa63d05ad290f13eee359661e4175b857d9f9d"
104
+ "gitHead": "aca7ff8eb508ecf586108b99a9e07ceab2a62430"
105
105
  }