@blocklet/sdk 1.7.27 → 1.8.2

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/README.md CHANGED
@@ -303,20 +303,6 @@ For Blocklet to write business logs, provides a consistent write format.
303
303
 
304
304
  ### Usage
305
305
 
306
- ```javascript
307
- const { logger } = require('@blocklet/sdk');
308
-
309
- // log
310
- log = logger('demo');
311
- log.info('this is demo', { id: 'test-id' });
312
- log.warn('this is demo', { id: 'test-id' });
313
- log.error('this is demo', { id: 'test-id' });
314
- log.debug('this is demo', { id: 'test-id' });
315
-
316
- // access log
317
- app.use(morgan('combined', { stream: logger.getAccessLogStream() }));
318
- ```
319
-
320
306
  ## getWallet
321
307
 
322
308
  ### Usage
package/lib/index.js CHANGED
@@ -6,7 +6,6 @@ const Database = require('./database');
6
6
  const env = require('./env');
7
7
  const middlewares = require('./middlewares');
8
8
  const getWallet = require('./wallet');
9
- const logger = require('./logger');
10
9
 
11
10
  module.exports = {
12
11
  AuthService,
@@ -17,5 +16,4 @@ module.exports = {
17
16
  getWallet,
18
17
  env,
19
18
  middlewares,
20
- logger,
21
19
  };
@@ -123,6 +123,7 @@ class AuthService extends Client {
123
123
  this[api] = apiFnMap[api] ? apiFnMap[api](fn) : apiFallback(fn);
124
124
  });
125
125
 
126
+ // eslint-disable-next-line no-constructor-return
126
127
  return new Proxy(this, {
127
128
  get(target, propKey) {
128
129
  if (!apiList.includes(propKey)) {
@@ -2,25 +2,62 @@ const Jwt = require('@arcblock/jwt');
2
2
  const EventEmitter = require('events');
3
3
 
4
4
  const { WsClient } = require('@arcblock/ws');
5
+ const { getAppPublicChannel } = require('@blocklet/meta/lib/channel');
5
6
 
6
7
  const checkBlockletEnv = require('../util/check-blocklet-env');
7
- const sendNotification = require('../util/send-notification');
8
+ const { sendToUser, sendToAppChannel } = require('../util/send-notification');
8
9
  const { SERVICE_PREFIX } = require('../util/constants');
9
10
  const getWallet = require('../wallet');
11
+ const { NOTIFICATION_TYPES } = require('../validators/notification');
10
12
 
11
- const sendToUser = async (receiver, notification, options) => {
13
+ const getSender = () => ({
14
+ appDid: process.env.BLOCKLET_APP_ID,
15
+ appSk: process.env.BLOCKLET_APP_SK,
16
+ });
17
+
18
+ /**
19
+ *
20
+ * @param {Notification} notification
21
+ * @param {{
22
+ * keepForOfflineUser: Boolean
23
+ * }} options
24
+ * @returns
25
+ */
26
+ const doSendToUser = async (receiver, notification, options) => {
27
+ checkBlockletEnv();
28
+
29
+ return sendToUser(receiver, notification, getSender(), process.env.ABT_NODE_SERVICE_PORT, options);
30
+ };
31
+
32
+ /**
33
+ *
34
+ * @param {Notification} notification
35
+ * @param {{
36
+ * channel: String
37
+ * event: String
38
+ * socketId: String
39
+ * socketDid: String
40
+ * }} options
41
+ * @returns
42
+ */
43
+ const broadcast = async (notification, options = {}) => {
12
44
  checkBlockletEnv();
13
45
 
14
- const sender = {
15
- appId: process.env.BLOCKLET_APP_ID,
16
- appSk: process.env.BLOCKLET_APP_SK,
17
- did: process.env.BLOCKLET_DID,
18
- };
46
+ const sender = getSender();
19
47
 
20
- return sendNotification(receiver, notification, sender, process.env.ABT_NODE_SERVICE_PORT, options);
48
+ const { channel = getAppPublicChannel(sender.appDid) } = options;
49
+ const { event = 'message' } = options;
50
+
51
+ return sendToAppChannel(channel, event, notification, sender, process.env.ABT_NODE_SERVICE_PORT, options);
21
52
  };
22
53
 
23
54
  const emitter = new EventEmitter();
55
+ const messageEmitter = new EventEmitter();
56
+
57
+ const emitError = (error) => {
58
+ messageEmitter.emit('error', error);
59
+ emitter.emit('error', error);
60
+ };
24
61
 
25
62
  let client = null;
26
63
 
@@ -41,9 +78,38 @@ const initClient = () => {
41
78
 
42
79
  client.connect();
43
80
 
44
- const channel = client.channel(wallet.address, () => ({ token: token(), pk }));
81
+ const messageChannel = client.channel(did, () => ({ token: token(), pk }));
82
+ const appPublicChannel = client.channel(getAppPublicChannel(did), () => ({ token: token(), pk }));
45
83
 
46
- channel
84
+ messageChannel
85
+ .join()
86
+ .receive('error', (err) => {
87
+ const msg = `join channel error: ${err.message}`;
88
+ console.error(msg);
89
+ emitError({ message: msg });
90
+ })
91
+ .receive('timeout', () => {
92
+ const msg = 'join channel timeout';
93
+ console.error(msg);
94
+ emitError({ message: msg });
95
+ });
96
+
97
+ messageChannel.on('message', ({ status, response } = {}) => {
98
+ if (status === 'ok') {
99
+ messageEmitter.emit(response.type, response);
100
+ if (response.type === NOTIFICATION_TYPES.HI) {
101
+ emitter.emit(response.type, response);
102
+ }
103
+ } else {
104
+ emitError(response);
105
+ console.error({
106
+ status,
107
+ response,
108
+ });
109
+ }
110
+ });
111
+
112
+ appPublicChannel
47
113
  .join()
48
114
  .receive('error', (err) => {
49
115
  const msg = `join channel error: ${err.message}`;
@@ -56,9 +122,9 @@ const initClient = () => {
56
122
  emitter.emit('error', { message: msg });
57
123
  });
58
124
 
59
- channel.on('message', ({ status, response } = {}) => {
125
+ appPublicChannel.on(NOTIFICATION_TYPES.HI, ({ status, response } = {}) => {
60
126
  if (status === 'ok') {
61
- emitter.emit(response.type, response);
127
+ emitter.emit(NOTIFICATION_TYPES.HI, response);
62
128
  } else {
63
129
  emitter.emit('error', response);
64
130
  console.error({
@@ -70,14 +136,30 @@ const initClient = () => {
70
136
  }
71
137
  };
72
138
 
139
+ const ensureClient = () => {
140
+ if (!client) {
141
+ initClient();
142
+ }
143
+ };
144
+
73
145
  module.exports = {
74
- sendToUser,
75
- on: (event, cb) => {
76
- if (!client) {
77
- initClient();
78
- }
146
+ sendToUser: doSendToUser,
147
+ broadcast,
79
148
 
149
+ // System notification
150
+ on: (event, cb) => {
151
+ ensureClient();
80
152
  return emitter.on(event, cb);
81
153
  },
82
154
  off: emitter.off.bind(emitter),
155
+
156
+ // Just for DID Wallet developing
157
+ // Any message received from any account
158
+ _message: {
159
+ on: (event, cb) => {
160
+ ensureClient();
161
+ return messageEmitter.on(event, cb);
162
+ },
163
+ off: messageEmitter.off.bind(messageEmitter),
164
+ },
83
165
  };
@@ -10,26 +10,32 @@ const { SERVICE_PREFIX } = require('./constants');
10
10
 
11
11
  const VERSION = require('../../package.json').version; // version of notification sdk
12
12
 
13
- const { validateNotification, validateReceiver, validateOption } = validators;
13
+ const { validateNotification, validateReceiver, validateOption, validateChannelEvent } = validators;
14
14
 
15
15
  const SERVER_MODE = process.env.ABT_NODE_MODE;
16
16
 
17
+ const getRequestHeaders = () => ({ 'User-Agent': `BlockletSDK/${VERSION}` });
18
+
17
19
  /**
18
20
  * @param {String|Array} receiver
19
21
  * @param {Object} notification
20
- * @param {Object} sender
22
+ * @param {{
23
+ * appDid: String
24
+ * appSk: String
25
+ * }} sender
21
26
  * @param {String|Number} port port of abtnode service endpoint
22
27
  * @param {Object} options
23
28
  * @returns
24
29
  */
25
- module.exports = async (
30
+ const sendToUser = async (
26
31
  receiver,
27
32
  notification,
28
- { appId, appSk, did } = {},
33
+ { appDid, appSk } = {},
29
34
  port = process.env.ABT_NODE_SERVICE_PORT,
30
35
  options = {}
31
36
  ) => {
32
37
  await validateReceiver(receiver);
38
+
33
39
  const opt = pick(options, ['keepForOfflineUser']);
34
40
  await validateOption(opt);
35
41
 
@@ -37,27 +43,87 @@ module.exports = async (
37
43
  await validateNotification(notification);
38
44
  }
39
45
 
40
- const token = JWT.sign(appId, appSk);
41
-
42
46
  try {
43
47
  const { data: res } = await axios.post(
44
- `http://127.0.0.1:${port}${SERVICE_PREFIX}/api/sendToUser`,
48
+ `http://127.0.0.1:${port}${SERVICE_PREFIX}/api/send-to-user`,
45
49
  {
46
50
  apiVersion: VERSION,
47
51
  data: {
48
- sender: { did, token, appDid: appId },
52
+ sender: { appDid, token: JWT.sign(appDid, appSk) },
49
53
  receiver,
50
54
  notification,
51
55
  options: opt,
52
56
  },
53
57
  },
54
58
  {
55
- headers: { 'User-Agent': `BlockletSDK/${VERSION}` },
59
+ timeout: 60 * 1000,
60
+ headers: getRequestHeaders(),
61
+ }
62
+ );
63
+
64
+ return res;
65
+ } catch (error) {
66
+ console.error(error);
67
+ throw new Error(error.response ? error.response.statusText : error.message);
68
+ }
69
+ };
70
+
71
+ const sendToAppChannel = async (
72
+ channel,
73
+ event,
74
+ notification,
75
+ { appDid, appSk } = {},
76
+ port = process.env.ABT_NODE_SERVICE_PORT,
77
+ options = {}
78
+ ) => {
79
+ if (!channel) {
80
+ throw new Error('channel is required');
81
+ }
82
+
83
+ if (!event) {
84
+ throw new Error('event is required');
85
+ }
86
+
87
+ await validateChannelEvent(event);
88
+
89
+ const opt = pick(options, ['socketId', 'userDid']);
90
+
91
+ if (opt.userDid) {
92
+ opt.socketDid = opt.userDid;
93
+ delete opt.userDid;
94
+ }
95
+
96
+ if (SERVER_MODE !== NODE_MODES.DEBUG) {
97
+ await validateNotification(notification);
98
+ }
99
+
100
+ try {
101
+ const { data: res } = await axios.post(
102
+ `http://127.0.0.1:${port}${SERVICE_PREFIX}/api/send-to-app-channel`,
103
+ {
104
+ apiVersion: VERSION,
105
+ data: {
106
+ sender: { appDid, token: JWT.sign(appDid, appSk) },
107
+ channel,
108
+ event,
109
+ notification,
110
+ options: opt,
111
+ },
112
+ },
113
+ {
114
+ timeout: 60 * 1000,
115
+ headers: getRequestHeaders(),
56
116
  }
57
117
  );
58
118
 
59
119
  return res;
60
120
  } catch (error) {
121
+ console.error(error);
61
122
  throw new Error(error.response ? error.response.statusText : error.message);
62
123
  }
63
124
  };
125
+
126
+ module.exports = {
127
+ sendToUser,
128
+ sendToAppChannel,
129
+ };
@@ -1,7 +1,8 @@
1
- const { validateNotification, validateReceiver, validateOption } = require('./notification');
1
+ const { validateNotification, validateReceiver, validateOption, validateChannelEvent } = require('./notification');
2
2
 
3
3
  module.exports = {
4
4
  validateNotification,
5
5
  validateReceiver,
6
6
  validateOption,
7
+ validateChannelEvent,
7
8
  };
@@ -89,12 +89,15 @@ const inputReceiverSchema = Joi.alternatives().try(Joi.array().items(receiverSch
89
89
 
90
90
  const optionSchema = Joi.object({
91
91
  keepForOfflineUser: Joi.boolean(),
92
- });
92
+ }).unknown();
93
+
94
+ const channelEventSchema = Joi.string().required();
93
95
 
94
96
  module.exports = {
95
97
  validateReceiver: inputReceiverSchema.validateAsync.bind(inputReceiverSchema),
96
98
  validateNotification: inputNotificationSchema.validateAsync.bind(inputNotificationSchema),
97
99
  validateMessage: messageSchema.validateAsync.bind(messageSchema),
100
+ validateChannelEvent: channelEventSchema.validateAsync.bind(channelEventSchema),
98
101
  validateOption: optionSchema.validateAsync.bind(optionSchema),
99
102
  tokenSchema,
100
103
  actionSchema,
@@ -104,4 +107,6 @@ module.exports = {
104
107
  notificationSchema,
105
108
  messageSchema,
106
109
  optionSchema,
110
+ channelEventSchema,
111
+ NOTIFICATION_TYPES: TYPES,
107
112
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.7.27",
6
+ "version": "1.8.2",
7
7
  "description": "graphql client to read/write data on abt node",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,16 +19,15 @@
19
19
  "author": "linchen1987 <linchen.1987@foxmail.com> (http://github.com/linchen1987)",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@abtnode/client": "1.7.27",
23
- "@abtnode/constant": "1.7.27",
24
- "@abtnode/logger": "1.7.27",
25
- "@arcblock/did-auth": "1.17.0",
26
- "@arcblock/jwt": "1.17.0",
27
- "@arcblock/ws": "1.17.0",
28
- "@blocklet/meta": "1.7.27",
29
- "@nedb/core": "^1.2.2",
30
- "@ocap/mcrypto": "1.17.0",
31
- "@ocap/wallet": "1.17.0",
22
+ "@abtnode/client": "1.8.2",
23
+ "@abtnode/constant": "1.8.2",
24
+ "@arcblock/did-auth": "1.17.2",
25
+ "@arcblock/jwt": "1.17.2",
26
+ "@arcblock/ws": "1.17.2",
27
+ "@blocklet/meta": "1.8.2",
28
+ "@nedb/core": "^1.3.1",
29
+ "@ocap/mcrypto": "1.17.2",
30
+ "@ocap/wallet": "1.17.2",
32
31
  "axios": "^0.27.2",
33
32
  "fs-extra": "^10.0.1",
34
33
  "joi": "^17.6.0",
@@ -40,5 +39,5 @@
40
39
  "detect-port": "^1.3.0",
41
40
  "jest": "^27.4.5"
42
41
  },
43
- "gitHead": "81a5492df66389b0aede13f033d1e493450833bc"
42
+ "gitHead": "fcbe3c97f3825c507ee16714f49bbf8f58c5b59f"
44
43
  }
package/lib/logger.js DELETED
@@ -1,8 +0,0 @@
1
- const logger = require('@abtnode/logger');
2
-
3
- if (!process.env.BLOCKLET_LOG_DIR) {
4
- throw new Error('valid BLOCKLET_LOG_DIR env is required by logger');
5
- }
6
-
7
- module.exports = (label) => logger(label, { logDir: process.env.BLOCKLET_LOG_DIR, filename: 'info' });
8
- module.exports.getAccessLogStream = () => logger.getAccessLogStream(process.env.BLOCKLET_LOG_DIR);