@cloudbase/database 1.4.3 → 1.5.0

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.
Files changed (196) hide show
  1. package/dist/commonjs/ObjectId/index.d.ts +1 -1
  2. package/dist/commonjs/ObjectId/index.js +16 -9
  3. package/dist/commonjs/aggregate.js +126 -75
  4. package/dist/commonjs/collection.d.ts +3 -2
  5. package/dist/commonjs/collection.js +131 -58
  6. package/dist/commonjs/command.d.ts +5 -5
  7. package/dist/commonjs/command.js +181 -154
  8. package/dist/commonjs/commands/logic.js +30 -20
  9. package/dist/commonjs/commands/query.d.ts +1 -1
  10. package/dist/commonjs/commands/query.js +85 -65
  11. package/dist/commonjs/commands/update.js +9 -7
  12. package/dist/commonjs/config/error.config.js +1 -0
  13. package/dist/commonjs/const/code.js +1 -0
  14. package/dist/commonjs/constant.d.ts +7 -7
  15. package/dist/commonjs/constant.js +13 -11
  16. package/dist/commonjs/document.d.ts +10 -6
  17. package/dist/commonjs/document.js +305 -193
  18. package/dist/commonjs/geo/index.js +20 -9
  19. package/dist/commonjs/geo/lineString.d.ts +1 -1
  20. package/dist/commonjs/geo/lineString.js +62 -33
  21. package/dist/commonjs/geo/multiLineString.d.ts +1 -1
  22. package/dist/commonjs/geo/multiLineString.js +71 -32
  23. package/dist/commonjs/geo/multiPoint.d.ts +1 -1
  24. package/dist/commonjs/geo/multiPoint.js +58 -29
  25. package/dist/commonjs/geo/multiPolygon.d.ts +1 -1
  26. package/dist/commonjs/geo/multiPolygon.js +96 -36
  27. package/dist/commonjs/geo/point.d.ts +1 -1
  28. package/dist/commonjs/geo/point.js +30 -23
  29. package/dist/commonjs/geo/polygon.d.ts +1 -1
  30. package/dist/commonjs/geo/polygon.js +78 -39
  31. package/dist/commonjs/helper/symbol.js +17 -5
  32. package/dist/commonjs/index.d.ts +8 -2
  33. package/dist/commonjs/index.js +73 -20
  34. package/dist/commonjs/lib/util.d.ts +1 -0
  35. package/dist/commonjs/lib/util.js +26 -0
  36. package/dist/commonjs/operator-map.js +7 -6
  37. package/dist/commonjs/query.d.ts +8 -4
  38. package/dist/commonjs/query.js +308 -201
  39. package/dist/commonjs/regexp/index.d.ts +1 -1
  40. package/dist/commonjs/regexp/index.js +16 -9
  41. package/dist/commonjs/serializer/common.d.ts +2 -2
  42. package/dist/commonjs/serializer/common.js +59 -22
  43. package/dist/commonjs/serializer/datatype.d.ts +2 -2
  44. package/dist/commonjs/serializer/datatype.js +58 -21
  45. package/dist/commonjs/serializer/query.d.ts +1 -1
  46. package/dist/commonjs/serializer/query.js +137 -127
  47. package/dist/commonjs/serializer/update.d.ts +1 -1
  48. package/dist/commonjs/serializer/update.js +83 -78
  49. package/dist/commonjs/serverDate/index.d.ts +1 -1
  50. package/dist/commonjs/serverDate/index.js +16 -9
  51. package/dist/commonjs/transaction/collection.d.ts +7 -0
  52. package/dist/commonjs/transaction/collection.js +49 -0
  53. package/dist/commonjs/transaction/document.d.ts +27 -0
  54. package/dist/commonjs/transaction/document.js +205 -0
  55. package/dist/commonjs/transaction/index.js +196 -86
  56. package/dist/commonjs/transaction/query.d.ts +43 -0
  57. package/dist/commonjs/transaction/query.js +261 -0
  58. package/dist/commonjs/typings/index.d.ts +4 -4
  59. package/dist/commonjs/typings/realtime.d.ts +16 -16
  60. package/dist/commonjs/util.js +123 -92
  61. package/dist/commonjs/utils/error.d.ts +2 -1
  62. package/dist/commonjs/utils/error.js +74 -38
  63. package/dist/commonjs/utils/symbol.js +33 -14
  64. package/dist/commonjs/utils/type.d.ts +1 -1
  65. package/dist/commonjs/utils/type.js +25 -13
  66. package/dist/commonjs/utils/utils.d.ts +4 -1
  67. package/dist/commonjs/utils/utils.js +93 -22
  68. package/dist/commonjs/validate.js +79 -63
  69. package/dist/esm/ObjectId/index.d.ts +1 -1
  70. package/dist/esm/ObjectId/index.js +15 -8
  71. package/dist/esm/aggregate.js +118 -66
  72. package/dist/esm/collection.d.ts +3 -2
  73. package/dist/esm/collection.js +125 -52
  74. package/dist/esm/command.d.ts +5 -5
  75. package/dist/esm/command.js +175 -147
  76. package/dist/esm/commands/logic.js +30 -20
  77. package/dist/esm/commands/query.d.ts +1 -1
  78. package/dist/esm/commands/query.js +91 -71
  79. package/dist/esm/commands/update.js +8 -6
  80. package/dist/esm/config/error.config.js +1 -1
  81. package/dist/esm/const/code.js +1 -1
  82. package/dist/esm/constant.d.ts +7 -7
  83. package/dist/esm/constant.js +12 -11
  84. package/dist/esm/document.d.ts +10 -6
  85. package/dist/esm/document.js +297 -185
  86. package/dist/esm/geo/interface.js +1 -0
  87. package/dist/esm/geo/lineString.d.ts +1 -1
  88. package/dist/esm/geo/lineString.js +57 -28
  89. package/dist/esm/geo/multiLineString.d.ts +1 -1
  90. package/dist/esm/geo/multiLineString.js +66 -27
  91. package/dist/esm/geo/multiPoint.d.ts +1 -1
  92. package/dist/esm/geo/multiPoint.js +53 -24
  93. package/dist/esm/geo/multiPolygon.d.ts +1 -1
  94. package/dist/esm/geo/multiPolygon.js +91 -31
  95. package/dist/esm/geo/point.d.ts +1 -1
  96. package/dist/esm/geo/point.js +26 -19
  97. package/dist/esm/geo/polygon.d.ts +1 -1
  98. package/dist/esm/geo/polygon.js +73 -34
  99. package/dist/esm/helper/symbol.js +13 -13
  100. package/dist/esm/index.d.ts +8 -2
  101. package/dist/esm/index.js +62 -9
  102. package/dist/esm/lib/util.d.ts +1 -0
  103. package/dist/esm/lib/util.js +22 -0
  104. package/dist/esm/operator-map.js +4 -4
  105. package/dist/esm/query.d.ts +8 -4
  106. package/dist/esm/query.js +299 -192
  107. package/dist/esm/regexp/index.d.ts +1 -1
  108. package/dist/esm/regexp/index.js +15 -8
  109. package/dist/esm/serializer/common.d.ts +2 -2
  110. package/dist/esm/serializer/common.js +49 -13
  111. package/dist/esm/serializer/datatype.d.ts +2 -2
  112. package/dist/esm/serializer/datatype.js +44 -8
  113. package/dist/esm/serializer/query.d.ts +1 -1
  114. package/dist/esm/serializer/query.js +112 -102
  115. package/dist/esm/serializer/update.d.ts +1 -1
  116. package/dist/esm/serializer/update.js +69 -64
  117. package/dist/esm/serverDate/index.d.ts +1 -1
  118. package/dist/esm/serverDate/index.js +15 -8
  119. package/dist/esm/transaction/collection.d.ts +7 -0
  120. package/dist/esm/transaction/collection.js +46 -0
  121. package/dist/esm/transaction/document.d.ts +27 -0
  122. package/dist/esm/transaction/document.js +202 -0
  123. package/dist/esm/transaction/index.js +191 -81
  124. package/dist/esm/transaction/query.d.ts +43 -0
  125. package/dist/esm/transaction/query.js +258 -0
  126. package/dist/esm/typings/index.d.ts +4 -4
  127. package/dist/esm/typings/index.js +1 -0
  128. package/dist/esm/typings/realtime.d.ts +16 -16
  129. package/dist/esm/typings/realtime.js +1 -0
  130. package/dist/esm/util.js +121 -90
  131. package/dist/esm/utils/error.d.ts +2 -1
  132. package/dist/esm/utils/error.js +70 -35
  133. package/dist/esm/utils/symbol.js +33 -14
  134. package/dist/esm/utils/type.d.ts +1 -1
  135. package/dist/esm/utils/type.js +12 -12
  136. package/dist/esm/utils/utils.d.ts +4 -1
  137. package/dist/esm/utils/utils.js +78 -16
  138. package/dist/esm/validate.js +65 -49
  139. package/jest.config.js +14 -0
  140. package/package.json +14 -10
  141. package/src/aggregate.ts +1 -5
  142. package/src/collection.ts +15 -2
  143. package/src/document.ts +45 -34
  144. package/src/index.ts +51 -4
  145. package/src/query.ts +33 -29
  146. package/src/serializer/query.ts +18 -6
  147. package/src/transaction/index.ts +1 -1
  148. package/src/typings/index.ts +0 -4
  149. package/src/utils/utils.ts +46 -0
  150. package/src/validate.ts +3 -6
  151. package/tests/gateway-contract.test.ts +180 -0
  152. package/tests/index.test.ts +283 -0
  153. package/tests/transaction-query.test.ts +207 -0
  154. package/tsconfig.esm.json +4 -2
  155. package/tsconfig.json +16 -6
  156. package/tsconfig.test.json +15 -0
  157. package/dist/commonjs/realtime/error.d.ts +0 -7
  158. package/dist/commonjs/realtime/error.js +0 -11
  159. package/dist/commonjs/realtime/listener.d.ts +0 -14
  160. package/dist/commonjs/realtime/listener.js +0 -17
  161. package/dist/commonjs/realtime/message.d.ts +0 -3
  162. package/dist/commonjs/realtime/message.js +0 -10
  163. package/dist/commonjs/realtime/snapshot.d.ts +0 -16
  164. package/dist/commonjs/realtime/snapshot.js +0 -42
  165. package/dist/commonjs/realtime/virtual-websocket-client.d.ts +0 -63
  166. package/dist/commonjs/realtime/virtual-websocket-client.js +0 -736
  167. package/dist/commonjs/realtime/websocket-client.d.ts +0 -78
  168. package/dist/commonjs/realtime/websocket-client.js +0 -567
  169. package/dist/commonjs/realtime/ws-event.d.ts +0 -126
  170. package/dist/commonjs/realtime/ws-event.js +0 -139
  171. package/dist/commonjs/transaction.d.ts +0 -42
  172. package/dist/commonjs/transaction.js +0 -126
  173. package/dist/esm/realtime/error.d.ts +0 -7
  174. package/dist/esm/realtime/error.js +0 -8
  175. package/dist/esm/realtime/listener.d.ts +0 -14
  176. package/dist/esm/realtime/listener.js +0 -14
  177. package/dist/esm/realtime/message.d.ts +0 -3
  178. package/dist/esm/realtime/message.js +0 -6
  179. package/dist/esm/realtime/snapshot.d.ts +0 -16
  180. package/dist/esm/realtime/snapshot.js +0 -39
  181. package/dist/esm/realtime/virtual-websocket-client.d.ts +0 -63
  182. package/dist/esm/realtime/virtual-websocket-client.js +0 -733
  183. package/dist/esm/realtime/websocket-client.d.ts +0 -78
  184. package/dist/esm/realtime/websocket-client.js +0 -564
  185. package/dist/esm/realtime/ws-event.d.ts +0 -126
  186. package/dist/esm/realtime/ws-event.js +0 -137
  187. package/dist/esm/transaction.d.ts +0 -42
  188. package/dist/esm/transaction.js +0 -121
  189. package/src/realtime/error.ts +0 -19
  190. package/src/realtime/listener.ts +0 -35
  191. package/src/realtime/message.ts +0 -14
  192. package/src/realtime/snapshot.ts +0 -60
  193. package/src/realtime/virtual-websocket-client.ts +0 -1195
  194. package/src/realtime/websocket-client.ts +0 -995
  195. package/src/realtime/ws-event.ts +0 -163
  196. package/src/transaction.ts +0 -190
@@ -0,0 +1,283 @@
1
+ import { EJSON } from 'bson'
2
+ import { Db } from '../src/index'
3
+
4
+ describe('数据库请求参数测试', function() {
5
+ // 模拟请求类,用于捕获和验证请求参数
6
+ class MockRequest {
7
+ private config: any;
8
+
9
+ constructor(config: any) {
10
+ this.config = config;
11
+ }
12
+
13
+ async send(action: string, data: any) {
14
+ // 验证 instance 和 database 参数是否正确传递
15
+ if (this.config.instance) {
16
+ expect(data).toHaveProperty('instance', this.config.instance);
17
+ }
18
+ if (this.config.database) {
19
+ expect(data).toHaveProperty('database', this.config.database);
20
+ }
21
+
22
+ // 返回符合各操作期望的数据结构
23
+ switch (action) {
24
+ case 'database.getDocument':
25
+ return {
26
+ data: {
27
+ list: [
28
+ EJSON.stringify({ _id: 'doc1', name: '测试文档1', value: 100 }),
29
+ EJSON.stringify({ _id: 'doc2', name: '测试文档2', value: 200 })
30
+ ]
31
+ },
32
+ requestId: 'mock-request-id-123456',
33
+ total: 2,
34
+ limit: 100,
35
+ offset: 5
36
+ };
37
+ case 'database.insertDocument':
38
+ return {
39
+ data: { insertedIds: ['doc-new'] },
40
+ requestId: 'mock-request-id-insert'
41
+ };
42
+ case 'database.modifyDocument':
43
+ return {
44
+ data: { updated: 1, upsert_id: 'doc1' },
45
+ requestId: 'mock-request-id-modify'
46
+ };
47
+ case 'database.aggregateDocuments':
48
+ return {
49
+ data: { list: [] },
50
+ requestId: 'mock-request-id-aggregate'
51
+ };
52
+ default:
53
+ return { data: { ok: 1 } };
54
+ }
55
+ }
56
+ }
57
+
58
+ // 测试配置
59
+ const testConfig = {
60
+ env: 'test-env',
61
+ instance: 'test-instance',
62
+ database: 'test-database'
63
+ };
64
+
65
+ // 在每个测试前配置
66
+ beforeEach(function() {
67
+ Db.reqClass = MockRequest;
68
+ });
69
+
70
+ it('集合查询操作应包含 instance 和 database 参数', async function() {
71
+ const db = new Db(testConfig);
72
+ const coll = db.collection('test-collection');
73
+ await coll.where({}).get();
74
+ });
75
+
76
+ it('集合添加操作应包含 instance 和 database 参数', async function() {
77
+ const db = new Db(testConfig);
78
+ const coll = db.collection('test-collection');
79
+ await coll.add({ name: '新文档', value: 300 });
80
+ });
81
+
82
+ it('文档更新操作应包含 instance 和 database 参数', async function() {
83
+ const db = new Db(testConfig);
84
+ const coll = db.collection('test-collection');
85
+ const doc = coll.doc('doc1');
86
+ await doc.update({ value: 150 });
87
+ });
88
+
89
+ it('聚合操作应包含 instance 和 database 参数', async function() {
90
+ const db = new Db(testConfig);
91
+ const coll = db.collection('test-collection');
92
+ const aggregate = coll
93
+ .aggregate()
94
+ .match({ value: { $gt: 50 } })
95
+ .group({ _id: null, total: { $sum: '$value' } });
96
+ await aggregate.end();
97
+ });
98
+
99
+ it('创建集合操作应包含 instance 和 database 参数', async function() {
100
+ const db = new Db(testConfig);
101
+ await db.createCollection('new-collection');
102
+ });
103
+
104
+ it('应支持 const res = await db.collection(\'xxx\').get() 方式调用', async function() {
105
+ const db = new Db(testConfig);
106
+ const coll = db.collection('test-collection');
107
+
108
+ // 测试直接调用 get() 而不传递 where 条件
109
+ const res = await coll.get();
110
+
111
+ // 验证返回结果的结构
112
+ expect(res).toHaveProperty('data');
113
+ expect(res).toHaveProperty('requestId');
114
+ expect(res).toHaveProperty('total');
115
+ expect(res).toHaveProperty('limit');
116
+ expect(res).toHaveProperty('offset');
117
+
118
+ // 验证返回的数据
119
+ expect(Array.isArray(res.data)).toBe(true);
120
+ expect(res.data.length).toBe(2);
121
+ expect(res.data[0]).toHaveProperty('_id', 'doc1');
122
+ expect(res.data[0]).toHaveProperty('name', '测试文档1');
123
+ expect(res.data[1]).toHaveProperty('_id', 'doc2');
124
+ expect(res.data[1]).toHaveProperty('name', '测试文档2');
125
+ });
126
+
127
+ // ---------- timeout 透传(per-request,经 createRequest 第三参数) ----------
128
+ describe('timeout 透传', function() {
129
+ it('options({timeout}) 应把 timeout 作为 send 第三参透传', async function() {
130
+ let capturedArgs: any[] = [];
131
+ class TimeoutReq {
132
+ constructor(_config: any) {}
133
+ async send(...args: any[]) {
134
+ capturedArgs = args;
135
+ return { data: { list: [] }, requestId: 'req-timeout' };
136
+ }
137
+ }
138
+ Db.reqClass = TimeoutReq as any;
139
+
140
+ const db = new Db({ env: 'test-env' });
141
+ await db.collection('users').options({ timeout: 500 }).get();
142
+
143
+ expect(capturedArgs[0]).toBe('database.getDocument');
144
+ expect(capturedArgs[2]).toEqual({ timeout: 500 });
145
+ });
146
+
147
+ it('未设置 timeout 时第三参应为空对象', async function() {
148
+ let capturedArgs: any[] = [];
149
+ class TimeoutReq {
150
+ constructor(_config: any) {}
151
+ async send(...args: any[]) {
152
+ capturedArgs = args;
153
+ return { data: { list: [] }, requestId: 'req-no-timeout' };
154
+ }
155
+ }
156
+ Db.reqClass = TimeoutReq as any;
157
+
158
+ const db = new Db({ env: 'test-env' });
159
+ await db.collection('users').get();
160
+
161
+ expect(capturedArgs[2]).toEqual({});
162
+ });
163
+
164
+ it('timeout 与 instance/database 注入应共存', async function() {
165
+ let capturedArgs: any[] = [];
166
+ class TimeoutReq {
167
+ constructor(_config: any) {}
168
+ async send(...args: any[]) {
169
+ capturedArgs = args;
170
+ return { data: { list: [] }, requestId: 'req-mix' };
171
+ }
172
+ }
173
+ Db.reqClass = TimeoutReq as any;
174
+
175
+ const db = new Db({ env: 'test-env', instance: 'inst-1', database: 'db-1' });
176
+ await db.collection('users').options({ timeout: 1000 }).get();
177
+
178
+ expect(capturedArgs[1]).toMatchObject({ instance: 'inst-1', database: 'db-1' });
179
+ expect(capturedArgs[2]).toEqual({ timeout: 1000 });
180
+ });
181
+ });
182
+
183
+ // ---------- callback 兼容(对齐 0.12.x 旧调用风格) ----------
184
+ describe('callback 兼容', function() {
185
+ it('collection().get(callback) 应调用 callback(0, result) 且返回 undefined', async function() {
186
+ const db = new Db(testConfig);
187
+ const coll = db.collection('test-collection');
188
+
189
+ const callback = jest.fn();
190
+ const retVal = coll.get(callback);
191
+
192
+ // 对齐 master 行为:传 callback 时返回 undefined
193
+ expect(retVal).toBeUndefined();
194
+
195
+ // 等 callback 被调用
196
+ await new Promise<void>(resolve => {
197
+ const timer = setInterval(() => {
198
+ if (callback.mock.calls.length > 0) {
199
+ clearInterval(timer);
200
+ resolve();
201
+ }
202
+ }, 10);
203
+ });
204
+
205
+ expect(callback).toHaveBeenCalledTimes(1);
206
+ const [err, result] = callback.mock.calls[0];
207
+ expect(err).toBe(0);
208
+ expect(result).toHaveProperty('data');
209
+ expect(result.data.length).toBe(2);
210
+ expect(result).toHaveProperty('requestId');
211
+ });
212
+
213
+ it('collection().add(data, callback) 应调用 callback(0, result)', async function() {
214
+ const db = new Db(testConfig);
215
+ const coll = db.collection('test-collection');
216
+
217
+ const callback = jest.fn();
218
+ coll.add({ name: 'cb-doc' }, callback);
219
+
220
+ await new Promise<void>(resolve => {
221
+ const timer = setInterval(() => {
222
+ if (callback.mock.calls.length > 0) {
223
+ clearInterval(timer);
224
+ resolve();
225
+ }
226
+ }, 10);
227
+ });
228
+
229
+ const [err, result] = callback.mock.calls[0];
230
+ expect(err).toBe(0);
231
+ expect(result).toHaveProperty('id', 'doc-new');
232
+ expect(result).toHaveProperty('requestId');
233
+ });
234
+
235
+ it('doc().get(callback) 应调用 callback(0, result)', async function() {
236
+ const db = new Db(testConfig);
237
+ const doc = db.collection('test-collection').doc('doc1');
238
+
239
+ const callback = jest.fn();
240
+ doc.get(callback);
241
+
242
+ await new Promise<void>(resolve => {
243
+ const timer = setInterval(() => {
244
+ if (callback.mock.calls.length > 0) {
245
+ clearInterval(timer);
246
+ resolve();
247
+ }
248
+ }, 10);
249
+ });
250
+
251
+ const [err, result] = callback.mock.calls[0];
252
+ expect(err).toBe(0);
253
+ expect(result).toHaveProperty('data');
254
+ expect(result).toHaveProperty('requestId');
255
+ });
256
+
257
+ it('请求异常时应调用 callback(err)', async function() {
258
+ class FailRequest {
259
+ async send() {
260
+ throw new Error('network down');
261
+ }
262
+ }
263
+ Db.reqClass = FailRequest as any;
264
+
265
+ const db = new Db(testConfig);
266
+ const callback = jest.fn();
267
+ db.collection('test-collection').get(callback);
268
+
269
+ await new Promise<void>(resolve => {
270
+ const timer = setInterval(() => {
271
+ if (callback.mock.calls.length > 0) {
272
+ clearInterval(timer);
273
+ resolve();
274
+ }
275
+ }, 10);
276
+ });
277
+
278
+ const [err] = callback.mock.calls[0];
279
+ expect(err).toBeInstanceOf(Error);
280
+ expect(err.message).toBe('network down');
281
+ });
282
+ });
283
+ });
@@ -0,0 +1,207 @@
1
+ import { EJSON } from 'bson'
2
+ import { Db } from '../src/index'
3
+ import { Transaction } from '../src/transaction/index'
4
+
5
+ describe('Transaction(新事务 API)', () => {
6
+ let sendFn: jest.Mock
7
+
8
+ class MockRequest {
9
+ send(action: string, data: any) {
10
+ return sendFn(action, data)
11
+ }
12
+ }
13
+
14
+ beforeEach(() => {
15
+ sendFn = jest.fn()
16
+ Db.reqClass = MockRequest as any
17
+ })
18
+
19
+ function createDb() {
20
+ return new Db({ env: 'test-env' })
21
+ }
22
+
23
+ async function createInitedTransaction(db: Db, txId = 'tx-001') {
24
+ const tx = new Transaction(db)
25
+ sendFn.mockResolvedValueOnce({ transactionId: txId })
26
+ await tx.init()
27
+ return tx
28
+ }
29
+
30
+ function findCall(action: string) {
31
+ return sendFn.mock.calls.find(c => c[0] === action)
32
+ }
33
+
34
+ // ---------- 初始化 ----------
35
+ describe('init()', () => {
36
+ it('应调用 database.startTransaction 并记录 transactionId', async () => {
37
+ const db = createDb()
38
+ const tx = await createInitedTransaction(db, 'tx-init')
39
+
40
+ expect(findCall('database.startTransaction')).toBeDefined()
41
+ expect(tx.getTransactionId()).toBe('tx-init')
42
+ })
43
+
44
+ it('init 不带 data 参数时(send(START) 单参)在配置 instance/database 下不应崩溃', async () => {
45
+ class NoDataReq {
46
+ async send(...args: any[]) {
47
+ if (args[0] === 'database.startTransaction') {
48
+ return { transactionId: 'tx-nodata' }
49
+ }
50
+ return { data: { list: [] }, requestId: 'r' }
51
+ }
52
+ }
53
+ Db.reqClass = NoDataReq as any
54
+
55
+ const db = new Db({ env: 'test-env', instance: 'inst-1', database: 'db-1' })
56
+ const tx = new Transaction(db)
57
+ await tx.init() // 不应抛 TypeError
58
+
59
+ expect(tx.getTransactionId()).toBe('tx-nodata')
60
+ })
61
+ })
62
+
63
+ // ---------- 事务内查询 ----------
64
+ describe('collection() + where().get()', () => {
65
+ it('应把 transactionId 传给 database.getDocument', async () => {
66
+ const db = createDb()
67
+ const tx = await createInitedTransaction(db)
68
+
69
+ sendFn.mockResolvedValueOnce({ data: { list: [] }, requestId: 'req-1' })
70
+
71
+ await tx.collection('users').where({ age: 18 }).get()
72
+
73
+ const call = findCall('database.getDocument')
74
+ expect(call).toBeDefined()
75
+ expect(call![1]).toMatchObject({
76
+ collectionName: 'users',
77
+ transactionId: 'tx-001'
78
+ })
79
+ })
80
+
81
+ it('get() 应解析 EJSON list 并返回文档数组', async () => {
82
+ const db = createDb()
83
+ const tx = await createInitedTransaction(db)
84
+
85
+ const list = [
86
+ EJSON.stringify({ _id: 'doc1', name: 'Alice' }),
87
+ EJSON.stringify({ _id: 'doc2', name: 'Bob' })
88
+ ]
89
+ sendFn.mockResolvedValueOnce({ data: { list }, requestId: 'req-2', total: 2 })
90
+
91
+ const result = await tx.collection('users').where({}).get()
92
+
93
+ expect(result.data.length).toBe(2)
94
+ expect(result.data[0]).toMatchObject({ _id: 'doc1', name: 'Alice' })
95
+ expect(result.total).toBe(2)
96
+ expect(result.requestId).toBe('req-2')
97
+ })
98
+ })
99
+
100
+ // ---------- 事务内更新 ----------
101
+ describe('collection() + where().update()', () => {
102
+ it('应把 transactionId 传给 database.modifyDocument', async () => {
103
+ const db = createDb()
104
+ const tx = await createInitedTransaction(db)
105
+
106
+ sendFn.mockResolvedValueOnce({ data: { updated: 1 }, requestId: 'req-3' })
107
+
108
+ const result = await tx.collection('users').where({ name: 'Alice' }).update({ age: 25 })
109
+
110
+ const call = findCall('database.modifyDocument')
111
+ expect(call).toBeDefined()
112
+ expect(call![1]).toMatchObject({
113
+ collectionName: 'users',
114
+ transactionId: 'tx-001'
115
+ })
116
+ expect(result.updated).toBe(1)
117
+ })
118
+ })
119
+
120
+ // ---------- 事务内删除 ----------
121
+ describe('collection() + where().remove()', () => {
122
+ it('应把 transactionId 传给 database.removeDocument', async () => {
123
+ const db = createDb()
124
+ const tx = await createInitedTransaction(db)
125
+
126
+ sendFn.mockResolvedValueOnce({ data: { deleted: 3 }, requestId: 'req-4' })
127
+
128
+ const result = await tx.collection('users').where({ status: 'inactive' }).remove()
129
+
130
+ const call = findCall('database.removeDocument')
131
+ expect(call).toBeDefined()
132
+ expect(call![1]).toMatchObject({
133
+ collectionName: 'users',
134
+ transactionId: 'tx-001'
135
+ })
136
+ expect(result.deleted).toBe(3)
137
+ })
138
+ })
139
+
140
+ // ---------- 事务内计数 ----------
141
+ describe('collection() + where().count()', () => {
142
+ it('应调用 database.calculateDocument 并返回 total', async () => {
143
+ const db = createDb()
144
+ const tx = await createInitedTransaction(db)
145
+
146
+ sendFn.mockResolvedValueOnce({ data: { total: 5 }, requestId: 'req-5' })
147
+
148
+ const result = await tx.collection('users').where({ age: { $gt: 18 } }).count()
149
+
150
+ expect(findCall('database.calculateDocument')).toBeDefined()
151
+ expect(result.total).toBe(5)
152
+ })
153
+ })
154
+
155
+ // ---------- 事务内插入 ----------
156
+ describe('collection().add()', () => {
157
+ it('应把 transactionId 传给 database.insertDocument,并返回事务兼容结果', async () => {
158
+ const db = createDb()
159
+ const tx = await createInitedTransaction(db)
160
+
161
+ sendFn.mockResolvedValueOnce({ data: { insertedIds: ['new-id'] }, requestId: 'req-6' })
162
+
163
+ const result = await tx.collection('users').add({ name: 'New' })
164
+
165
+ const call = findCall('database.insertDocument')
166
+ expect(call).toBeDefined()
167
+ expect(call![1]).toMatchObject({
168
+ collectionName: 'users',
169
+ transactionId: 'tx-001'
170
+ })
171
+ expect(result).toMatchObject({ inserted: 1, ok: 1, id: 'new-id' })
172
+ })
173
+ })
174
+
175
+ // ---------- 事务内文档操作 ----------
176
+ describe('collection().doc().set()', () => {
177
+ it('应把 transactionId 传给 database.modifyDocument', async () => {
178
+ const db = createDb()
179
+ const tx = await createInitedTransaction(db)
180
+
181
+ sendFn.mockResolvedValueOnce({ data: { updated: 1, upsert_id: 'doc1' }, requestId: 'req-7' })
182
+
183
+ await tx.collection('users').doc('doc1').set({ name: 'Set' })
184
+
185
+ const call = findCall('database.modifyDocument')
186
+ expect(call).toBeDefined()
187
+ expect(call![1]).toMatchObject({
188
+ collectionName: 'users',
189
+ transactionId: 'tx-001'
190
+ })
191
+ })
192
+ })
193
+
194
+ // ---------- 提交 ----------
195
+ describe('commit()', () => {
196
+ it('应调用 database.commitTransaction 并携带 transactionId', async () => {
197
+ const db = createDb()
198
+ const tx = await createInitedTransaction(db, 'tx-cmt')
199
+
200
+ sendFn.mockResolvedValueOnce({ requestId: 'req-cmt' })
201
+ await tx.commit()
202
+
203
+ const call = findCall('database.commitTransaction')
204
+ expect(call![1]).toEqual({ transactionId: 'tx-cmt' })
205
+ })
206
+ })
207
+ })
package/tsconfig.esm.json CHANGED
@@ -20,10 +20,11 @@
20
20
  "pretty": true,
21
21
  "removeComments": true,
22
22
  "stripInternal": true,
23
+ "downlevelIteration": true,
23
24
  "skipDefaultLibCheck": true,
24
25
  "skipLibCheck": true,
25
26
  "moduleResolution": "node",
26
- "target": "es2017",
27
+ "target": "es5",
27
28
  "lib": [
28
29
  "es2015",
29
30
  "es6",
@@ -35,6 +36,7 @@
35
36
  ],
36
37
  "exclude": [
37
38
  // "node_modules",
38
- "test"
39
+ "test",
40
+ "tests"
39
41
  ]
40
42
  }
package/tsconfig.json CHANGED
@@ -4,7 +4,6 @@
4
4
  "allowJs": false,
5
5
  "allowUnreachableCode": false,
6
6
  "allowUnusedLabels": false,
7
- "charset": "utf8",
8
7
  "declaration": true,
9
8
  "experimentalDecorators": true,
10
9
  "emitDecoratorMetadata": true,
@@ -21,10 +20,21 @@
21
20
  "removeComments": true,
22
21
  "stripInternal": true,
23
22
  "skipDefaultLibCheck": true,
23
+ "downlevelIteration": true,
24
24
  "skipLibCheck": true,
25
- "target": "es2017",
26
- "lib": ["es2015", "es6", "dom"]
25
+ "target": "es5",
26
+ "lib": [
27
+ "es2015",
28
+ "es6",
29
+ "dom"
30
+ ]
27
31
  },
28
- "include": ["src/**/*"],
29
- "exclude": ["node_modules", "test"]
30
- }
32
+ "include": [
33
+ "src/**/*"
34
+ ],
35
+ "exclude": [
36
+ "node_modules",
37
+ "test",
38
+ "tests"
39
+ ]
40
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "target": "es6",
5
+ "module": "commonjs",
6
+ "isolatedModules": true,
7
+ "skipLibCheck": true,
8
+ "strict": false,
9
+ "esModuleInterop": true,
10
+ "moduleResolution": "node",
11
+ "allowJs": true
12
+ },
13
+ "include": ["tests/**/*.ts", "src/**/*.ts"],
14
+ "exclude": ["node_modules"]
15
+ }
@@ -1,7 +0,0 @@
1
- import { IResponseMessageErrorMsg } from '../typings/realtime';
2
- export declare class RealtimeErrorMessageError extends Error {
3
- isRealtimeErrorMessageError: boolean;
4
- payload: IResponseMessageErrorMsg;
5
- constructor(serverErrorMsg: IResponseMessageErrorMsg);
6
- }
7
- export declare const isRealtimeErrorMessageError: (e: any) => e is RealtimeErrorMessageError;
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- class RealtimeErrorMessageError extends Error {
4
- constructor(serverErrorMsg) {
5
- super(`Watch Error ${JSON.stringify(serverErrorMsg.msgData)} (requestid: ${serverErrorMsg.requestId})`);
6
- this.isRealtimeErrorMessageError = true;
7
- this.payload = serverErrorMsg;
8
- }
9
- }
10
- exports.RealtimeErrorMessageError = RealtimeErrorMessageError;
11
- exports.isRealtimeErrorMessageError = (e) => e && e.isRealtimeErrorMessageError;
@@ -1,14 +0,0 @@
1
- import { VirtualWebSocketClient } from './virtual-websocket-client';
2
- import { IRealtimeListenerConstructorOptions, DBRealtimeListener } from '../typings/index';
3
- interface IRealtimeListenerOptions extends IRealtimeListenerConstructorOptions {
4
- close: () => void;
5
- debug?: boolean;
6
- virtualClient?: VirtualWebSocketClient;
7
- }
8
- export declare class RealtimeListener implements DBRealtimeListener {
9
- close: () => void;
10
- onChange: (res: any) => void;
11
- onError: (error: any) => void;
12
- constructor(options: IRealtimeListenerOptions);
13
- }
14
- export {};
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- class RealtimeListener {
4
- constructor(options) {
5
- this.close = options.close;
6
- this.onChange = options.onChange;
7
- this.onError = options.onError;
8
- if (options.debug) {
9
- Object.defineProperty(this, 'virtualClient', {
10
- get: () => {
11
- return options.virtualClient;
12
- }
13
- });
14
- }
15
- }
16
- }
17
- exports.RealtimeListener = RealtimeListener;
@@ -1,3 +0,0 @@
1
- import { IResponseMessage, IResponseMessageInitEventMsg } from '../typings/realtime';
2
- export declare function genRequestId(prefix?: string): string;
3
- export declare function isInitEventMessage(msg: IResponseMessage): msg is IResponseMessageInitEventMsg;
@@ -1,10 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- function genRequestId(prefix = '') {
4
- return `${prefix ? `${prefix}_` : ''}${+new Date()}_${Math.random()}`;
5
- }
6
- exports.genRequestId = genRequestId;
7
- function isInitEventMessage(msg) {
8
- return msg.msgType === 'INIT_EVENT';
9
- }
10
- exports.isInitEventMessage = isInitEventMessage;
@@ -1,16 +0,0 @@
1
- import { ISingleDBEvent, SnapshotType, ISnapshot } from '../typings/index';
2
- interface ISnapshotConstructorOptions {
3
- id: number;
4
- docChanges: ISingleDBEvent[];
5
- docs: Record<string, any>[];
6
- type?: SnapshotType;
7
- msgType?: String;
8
- }
9
- export declare class Snapshot implements ISnapshot {
10
- id: number;
11
- docChanges: ISingleDBEvent[];
12
- docs: Record<string, any>[];
13
- type?: 'init';
14
- constructor(options: ISnapshotConstructorOptions);
15
- }
16
- export {};