tmc.js 0.3.6 → 0.3.8

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
@@ -30,14 +30,14 @@ new Tmc('your_app_key', 'your_app_secret')
30
30
 
31
31
  ## API
32
32
 
33
- **`new Tmc(appKey: string, appSecret: BinaryLike, groupName?: string | object, options?: object)`**
33
+ **`new Tmc(appKey: string, appSecret: BinaryLike, groupName?: string | ConsumerOptions, options?: ConsumerOptions)`**
34
34
 
35
35
  | 参数 | 类型 | 说明 |
36
36
  | --- | --- | --- |
37
37
  | appKey | `string` | 应用ID |
38
38
  | appSecret | `BinaryLike` | 应用密钥 |
39
- | groupName | `string` | 消息分组(可选,默认`default`) |
40
- | options | `object` | 消费端配置参数(可选) |
39
+ | groupName | `string \| ConsumerOptions` | 消息分组(可选,默认`default`) |
40
+ | options | `ConsumerOptions` | 消费端配置参数(可选) |
41
41
  | options.pullRequestInterval | `number` | 定时发送`pullRequest`请求时间间隔(默认`5000`毫秒) |
42
42
  | options.onErrorReconnection | `number` | 当消费端出现错误,重试连接间隔(默认`15000`毫秒) |
43
43
  | options.onCloseReconnection | `number` | 当消费端断开连接,重试连接间隔(默认`3000`毫秒) |
@@ -75,11 +75,11 @@ new Tmc('your_app_key', 'your_app_secret')
75
75
 
76
76
  **`tmc.send(msg: Message, options?: { mask?: true, binary?: true }, cb?: (err: Error) => void) => void`**
77
77
 
78
- 实例化后,当自动应答确认消息无法满足需求的时候,比如消息处理失败,需要`Publisher`再次重推消息,在实例初始化时置`options.autoReplyConfirmation=false`,则在消息处理函数内,可以通过 `this.send()` 函数回复`确认`或者`失败`消息。例如:
78
+ 自`v0.3.4`起,当自动应答确认消息无法满足需求的时候,比如消息处理失败,需要`Publisher`再次重推消息,在实例初始化时置`options.autoReplyConfirmation=false`,则在消息处理函数内,可以通过 `this.send()` 函数回复`确认`或者`失败`消息。例如:
79
79
 
80
80
  ```js
81
81
  new Tmc('your_app_key', 'your_app_secret', { autoReplyConfirmation: false })
82
- .taobao_trade_TradeDelayConfirmPay(function needDoubleReriesThenConfirm(msg) {
82
+ .taobao_trade_TradeDelayConfirmPay(function needDoubleRetriesThenConfirm(msg) {
83
83
  if (msg instanceof Message && msg.content?.retried === 0) {
84
84
  this.send(
85
85
  new Message(MessageType.SENDACK, MessageKind.Failed)
@@ -91,6 +91,29 @@ new Tmc('your_app_key', 'your_app_secret', { autoReplyConfirmation: false })
91
91
  .connect();
92
92
  ```
93
93
 
94
+ 也可以使用此方法发送`To淘宝`消息。在`>=v0.3.4 && <v0.3.7`版本期间,需要自主对`$.content.content`数据做`JSON`字符串化(**特别注意:** 原生`JSON`对`BigInt`类型无法处理)。自`v0.3.7`起,可直接对`$.content.content`以原生`object`类型描述,`SDK`会将此对象转化成`JSON`字符串。例如:
95
+
96
+ ```js
97
+ /** @see https://open.taobao.com/tmc.htm?docId=732&docType=9 */
98
+ .send(
99
+ new Message(MessageType.SEND, MessageKind.Data)
100
+ .with(MessageFields.TOPIC, 'taobao_fuwu_ElectronicInvoice')
101
+ .with(MessageFields.CONTENT, {
102
+ id: 12345678901234567n, // 支持 BigInt 类型
103
+ tid: 12345678901234567n,
104
+ oid: 12345678901234567n,
105
+ invoice_file: 12345678901234567n,
106
+ e_invoice_no: '12342243435466',
107
+ invoice_time: '2015-04-10 10:33:49', // 时区 +08:00
108
+ invoice_no: '123456',
109
+ invoice_code: '123456',
110
+ amount: '100.00',
111
+ })
112
+ // >=v0.3.4 && <v0.3.7 写法
113
+ // .with(MessageFields.CONTENT, '{"tid":12345678901234567,"amount":"100.00"}')
114
+ )
115
+ ```
116
+
94
117
  <details><summary>可选设置的 NODE_DEBUG=< label > 环境变量</summary>
95
118
 
96
119
  | label | 说明 |
package/lib/consumer.js CHANGED
@@ -99,10 +99,16 @@ class TaoMessageConsumer extends EventEmitter {
99
99
  * @param {object|Function} [options] - The options
100
100
  * @param {Function} [cb] - The Callback
101
101
  * @returns {void}
102
- * @since v0.3.4
102
+ * @since v0.3.4 Exposed for `send(new Message(SENDACK, Failed))` scene
103
+ * @since v0.3.7 The `data.content.content` can be a plain `object` now
103
104
  */
104
105
  send(data, options = { mask: true, binary: true }, cb = undefined) {
105
- if (data instanceof Message) { this[kWebSocket]?.send(data.with(TOKEN, this[kToken]).buffer, options, cb); }
106
+ if (data instanceof Message) {
107
+ if (typeof data[CONTENT][CONTENT] === 'object' && data[CONTENT][CONTENT] !== null) {
108
+ Reflect.set(data[CONTENT], CONTENT, stringify(data[CONTENT][CONTENT]));
109
+ }
110
+ this[kWebSocket]?.send(data.with(TOKEN, this[kToken]).buffer, options, cb);
111
+ }
106
112
  }
107
113
 
108
114
  onopen() {
package/lib/message.js CHANGED
@@ -56,29 +56,16 @@ class Message {
56
56
 
57
57
  const utf8 = 'utf8';
58
58
 
59
- const write = 'write';
60
-
61
- const writeInt8 = 'writeInt8';
62
-
63
- const writeInt16LE = 'writeInt16LE';
64
-
65
- const writeInt32LE = 'writeInt32LE';
66
-
67
- const writeBigInt64LE = 'writeBigInt64LE';
59
+ const kOffset = Symbol('kOffset');
68
60
 
69
61
  const {
70
62
  Void, Byte, Int16, Int32, Int64, ByteArray, CountedString,
71
63
  } = ValueFormat;
72
64
 
73
- function pick(size, method, ...value) {
74
- const buf = Buffer.alloc(size);
75
- buf[method](...value);
76
-
77
- return Buffer.from(buf.buffer);
78
- }
79
-
80
65
  class Encoder {
81
- [kBuffer] = [];
66
+ [kOffset] = 0;
67
+
68
+ [kBuffer] = [/* method, value, offset, length, charset */];
82
69
 
83
70
  [kData];
84
71
 
@@ -102,25 +89,25 @@ class Encoder {
102
89
  }
103
90
 
104
91
  put(value) {
105
- this[kBuffer].push(pick(1, writeInt8, Number(value)));
92
+ this[kBuffer].push(['writeInt8', Number(value), (this[kOffset] += 1) - 1, 1]);
106
93
 
107
94
  return this;
108
95
  }
109
96
 
110
97
  putShort(value) {
111
- this[kBuffer].push(pick(2, writeInt16LE, Number(value)));
98
+ this[kBuffer].push(['writeInt16LE', Number(value), (this[kOffset] += 2) - 2, 2]);
112
99
 
113
100
  return this;
114
101
  }
115
102
 
116
103
  putInt(value) {
117
- this[kBuffer].push(pick(4, writeInt32LE, Number(value)));
104
+ this[kBuffer].push(['writeInt32LE', Number(value), (this[kOffset] += 4) - 4, 4]);
118
105
 
119
106
  return this;
120
107
  }
121
108
 
122
109
  putLong(value) {
123
- this[kBuffer].push(pick(8, writeBigInt64LE, BigInt(value)));
110
+ this[kBuffer].push(['writeBigInt64LE', BigInt(value), (this[kOffset] += 8) - 8, 8]);
124
111
 
125
112
  return this;
126
113
  }
@@ -128,7 +115,7 @@ class Encoder {
128
115
  writeCountedString(value) {
129
116
  const len = value ? Buffer.byteLength(value) : 0;
130
117
  this.putInt(len);
131
- if (len) { this[kBuffer].push(pick(len, write, value, utf8)); }
118
+ if (len) { this[kBuffer].push(['write', value, (this[kOffset] += len) - len, len, utf8]); }
132
119
 
133
120
  return this;
134
121
  }
@@ -168,17 +155,24 @@ class Encoder {
168
155
  }
169
156
 
170
157
  if (Buffer.isBuffer(value)) {
171
- this.put(ByteArray).putInt(value.length);
172
- this[kBuffer].push(value);
158
+ const len = value.length;
159
+ this.put(ByteArray).putInt(len);
160
+ this[kBuffer].push(['fill', value, (this[kOffset] += len) - len, len]);
173
161
  }
174
162
 
175
163
  return this;
176
164
  }
177
165
 
178
- get buffer() { return Buffer.concat(this.compress()[kBuffer]); }
179
- }
166
+ get buffer() {
167
+ this[kOffset] = 0;
168
+ this[kBuffer] = [];
169
+ this.compress();
170
+ const buf = Buffer.alloc(this[kOffset]);
171
+ this[kBuffer].forEach(([method, value, offset, length, charset]) => buf[method](value, offset, length, charset));
180
172
 
181
- const kOffset = Symbol('kOffset');
173
+ return buf;
174
+ }
175
+ }
182
176
 
183
177
  class Decoder {
184
178
  [kOffset] = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmc.js",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Events driven and chained Taobao Message Channel(TMC) for NodeJS",
5
5
  "author": "James ZHANG",
6
6
  "license": "MIT",