@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
package/src/index.ts CHANGED
@@ -5,8 +5,16 @@ import { Command } from './command'
5
5
  import { ServerDateConstructor } from './serverDate/index'
6
6
  import { RegExpConstructor } from './regexp/index'
7
7
  import { startTransaction, runTransaction } from './transaction/index'
8
+ import { LogicCommand } from './commands/logic'
9
+ import { QueryCommand } from './commands/query'
10
+ import { UpdateCommand } from './commands/update'
8
11
  import { ObjectIdConstructor } from './ObjectId/index'
9
12
 
13
+ /**
14
+ * 数据库配置接口(兼容旧名,实际为完整的 CloudBase 配置)
15
+ */
16
+ export type IDbConfig = ICloudBaseConfig
17
+
10
18
  /**
11
19
  * 地理位置类型
12
20
  */
@@ -18,7 +26,7 @@ export { Query } from './query'
18
26
  export { CollectionReference } from './collection'
19
27
  export { DocumentReference } from './document'
20
28
 
21
- interface ICloudBaseConfig {
29
+ export interface ICloudBaseConfig {
22
30
  timeout?: number
23
31
  isHttp?: boolean
24
32
  secretId?: string
@@ -68,12 +76,18 @@ export class Db {
68
76
 
69
77
  runTransaction: any
70
78
 
79
+ logicCommand: any
80
+
81
+ updateCommand: any
82
+
83
+ queryCommand: any
84
+
71
85
  /**
72
86
  * 初始化
73
87
  *
74
88
  * 默认是 `default` 数据库,为今后扩展使用
75
89
  *
76
- * @param config
90
+ * @param config - 数据库配置
77
91
  */
78
92
  config: ICloudBaseConfig
79
93
 
@@ -83,6 +97,8 @@ export class Db {
83
97
 
84
98
  static wsClass: any
85
99
 
100
+ static wsClientClass: any
101
+
86
102
  // 创建签名的工具函数,由jssdk传入
87
103
  static createSign: Function
88
104
 
@@ -94,7 +110,33 @@ export class Db {
94
110
  // 应用签名信息,由jssdk传入
95
111
  static appSecretInfo: any
96
112
 
97
- constructor(config?: any) {
113
+ // 创建请求实例的包装方法,自动添加instance和database参数
114
+ static createRequest(config: ICloudBaseConfig): any {
115
+ const request = new Db.reqClass(config)
116
+ const originalSend = request.send
117
+
118
+ // 包装send方法,自动添加instance和database参数;
119
+ // 剩余参数(如 2.0 引擎的 getReqOpts,含 per-request timeout)原样透传
120
+ request.send = function(action: string, data: any, ...args: any[]): any {
121
+ // data 可能为空(如事务 startTransaction 不带参数),注入前需防护
122
+ if (data) {
123
+ // 如果配置中包含instance或database参数,添加到请求数据中
124
+ if (config.instance) {
125
+ data.instance = config.instance
126
+ }
127
+ if (config.database) {
128
+ data.database = config.database
129
+ }
130
+ }
131
+
132
+ // 调用原始的send方法
133
+ return originalSend.call(this, action, data, ...args)
134
+ }
135
+
136
+ return request
137
+ }
138
+
139
+ constructor(config?: ICloudBaseConfig) {
98
140
  this.config = config
99
141
  this.Geo = Geo
100
142
  this.serverDate = ServerDateConstructor
@@ -103,6 +145,11 @@ export class Db {
103
145
  this.ObjectId = ObjectIdConstructor
104
146
  this.startTransaction = startTransaction
105
147
  this.runTransaction = runTransaction
148
+
149
+ // 暴露command类 给新sdk灰度兼容用
150
+ this.logicCommand = LogicCommand
151
+ this.updateCommand = UpdateCommand
152
+ this.queryCommand = QueryCommand
106
153
  }
107
154
 
108
155
  /**
@@ -121,7 +168,7 @@ export class Db {
121
168
  * 创建集合
122
169
  */
123
170
  createCollection(collName: string) {
124
- let request = new Db.reqClass(this.config)
171
+ let request = Db.createRequest(this.config)
125
172
 
126
173
  const params = {
127
174
  collectionName: collName
package/src/query.ts CHANGED
@@ -9,9 +9,8 @@ import { QuerySerializer } from './serializer/query'
9
9
  import { UpdateSerializer } from './serializer/update'
10
10
  // import { WSClient } from "./websocket/wsclient"
11
11
  import { IWatchOptions, DBRealtimeListener } from './typings/index'
12
- import { RealtimeWebSocketClient } from './realtime/websocket-client'
13
12
  import { ErrorCode } from './constant'
14
- import { getReqOpts, stringifyByEJSON, processReturn } from './utils/utils'
13
+ import { getWsInstance, getReqOpts, stringifyByEJSON, processReturn, withCallback } from './utils/utils'
15
14
  import { ERRORS } from './const/code'
16
15
  import { EJSON } from 'bson'
17
16
 
@@ -156,7 +155,7 @@ export class Query {
156
155
  this._fieldFilters = fieldFilters
157
156
  this._apiOptions = apiOptions || {}
158
157
  /* eslint-disable new-cap */
159
- this._request = new Db.reqClass(this._db.config)
158
+ this._request = Db.createRequest(this._db.config)
160
159
  this._transactionId = transactionId
161
160
  }
162
161
 
@@ -166,7 +165,11 @@ export class Query {
166
165
  * - 默认获取集合下全部文档数据
167
166
  * - 可以把通过 `orderBy`、`where`、`skip`、`limit`设置的数据添加请求参数上
168
167
  */
169
- public async get(): Promise<GetRes> {
168
+ public get(callback?: any): Promise<GetRes> {
169
+ return withCallback(this._get(), callback) as Promise<GetRes>
170
+ }
171
+
172
+ private async _get(): Promise<GetRes> {
170
173
  /* eslint-disable no-param-reassign */
171
174
 
172
175
  const order = (this._apiOptions as QueryOption).order
@@ -176,7 +179,7 @@ export class Query {
176
179
  transactionId?: string
177
180
  query?: Object
178
181
  queryType: QueryType
179
- order?: string[]
182
+ order?: string
180
183
  offset?: number
181
184
  limit?: number
182
185
  projection?: Object
@@ -200,14 +203,8 @@ export class Query {
200
203
  if (offset) {
201
204
  param.offset = offset
202
205
  }
203
-
204
206
  const limit = (this._apiOptions as QueryOption).limit
205
207
 
206
- // if (this._queryOptions.limit) {
207
- // param.limit = this._queryOptions.limit < 1000 ? this._queryOptions.limit : 1000
208
- // } else {
209
- // param.limit = 100
210
- // }
211
208
  if (limit) {
212
209
  param.limit = limit < 1000 ? limit : 1000
213
210
  } else {
@@ -252,7 +249,11 @@ export class Query {
252
249
  /**
253
250
  * 获取总数
254
251
  */
255
- public async count() {
252
+ public count(callback?: any) {
253
+ return withCallback(this._count(), callback)
254
+ }
255
+
256
+ private async _count() {
256
257
  interface Param {
257
258
  collectionName: string
258
259
  query?: Object
@@ -348,7 +349,6 @@ export class Query {
348
349
  const order = (this._apiOptions as QueryOption).order || {}
349
350
 
350
351
  const newApiOption = Object.assign({}, this._apiOptions, {
351
- // order: order.concat(newOrder)
352
352
  order: Object.assign({}, order, newOrder)
353
353
  })
354
354
 
@@ -390,7 +390,11 @@ export class Query {
390
390
  *
391
391
  * @param data 数据
392
392
  */
393
- public async update(data: Object): Promise<any> {
393
+ public update(data: Object, callback?: any): Promise<any> {
394
+ return withCallback(this._update(data), callback)
395
+ }
396
+
397
+ private async _update(data: Object): Promise<any> {
394
398
  if (!data || typeof data !== 'object') {
395
399
  return processReturn(this._db.config.throwOnCode, {
396
400
  ...ERRORS.INVALID_PARAM,
@@ -419,6 +423,10 @@ export class Query {
419
423
  data: UpdateSerializer.encodeEJSON(data, this._apiOptions.raw || false)
420
424
  }
421
425
 
426
+ if (this._transactionId) {
427
+ param.transactionId = this._transactionId
428
+ }
429
+
422
430
  if (this._fieldFilters) {
423
431
  param.query = this._fieldFilters
424
432
  }
@@ -481,7 +489,11 @@ export class Query {
481
489
  /**
482
490
  * 条件删除文档
483
491
  */
484
- public async remove() {
492
+ public remove(callback?: any) {
493
+ return withCallback(this._remove(), callback)
494
+ }
495
+
496
+ private async _remove() {
485
497
  // if (Object.keys(this._queryOptions).length > 0) {
486
498
  // console.warn('`offset`, `limit` and `projection` are not supported in remove() operation')
487
499
  // }
@@ -504,12 +516,15 @@ export class Query {
504
516
  let { multiple } = this._apiOptions as UpdateOption
505
517
  const multi = multiple === undefined ? true : multiple // where remove 不传multi默认为true
506
518
 
507
- const param = {
519
+ const param: any = {
508
520
  collectionName: this._coll,
509
521
  query: this._fieldFilters,
510
522
  queryType: QueryType.WHERE,
511
523
  multi
512
524
  }
525
+ if (this._transactionId) {
526
+ param.transactionId = this._transactionId
527
+ }
513
528
  const res = await this._request.send(
514
529
  'database.removeDocument',
515
530
  param,
@@ -579,22 +594,11 @@ export class Query {
579
594
  * 监听query对应的doc变化
580
595
  */
581
596
  watch = (options: IWatchOptions): DBRealtimeListener => {
582
- if (!Db.ws) {
583
- Db.ws = new RealtimeWebSocketClient({
584
- context: {
585
- appConfig: {
586
- docSizeLimit: 1000,
587
- realtimePingInterval: 10000,
588
- realtimePongWaitTimeout: 5000,
589
- request: this._request
590
- }
591
- }
592
- })
593
- }
597
+ const ws = getWsInstance(this._db)
594
598
 
595
599
  const { limit, order } = this._apiOptions as QueryOption
596
600
 
597
- return (Db.ws as RealtimeWebSocketClient).watch({
601
+ return ws.watch({
598
602
  ...options,
599
603
  envId: this._db.config.env,
600
604
  collectionName: this._coll,
@@ -4,15 +4,27 @@ import {
4
4
  QUERY_COMMANDS_LITERAL,
5
5
  QueryCommand
6
6
  } from '../commands/query'
7
- import { isLogicCommand, LOGIC_COMMANDS_LITERAL, LogicCommand } from '../commands/logic'
7
+ import {
8
+ isLogicCommand,
9
+ LOGIC_COMMANDS_LITERAL,
10
+ LogicCommand
11
+ } from '../commands/logic'
8
12
  import { SYMBOL_UNSET_FIELD_NAME, SYMBOL_GEO_POINT } from '../helper/symbol'
9
13
  import { getType, isObject, isArray, isRegExp, isDate } from '../utils/type'
10
14
  import { operatorToString } from '../operator-map'
11
- import { flattenQueryObject, isConversionRequired, encodeInternalDataType } from './common'
12
- import { IGeoNearOptions, IGeoWithinOptions, IGeoIntersectsOptions } from '../commands/query'
15
+ import {
16
+ flattenQueryObject,
17
+ isConversionRequired,
18
+ encodeInternalDataType
19
+ } from './common'
20
+ import {
21
+ IGeoNearOptions,
22
+ IGeoWithinOptions,
23
+ IGeoIntersectsOptions
24
+ } from '../commands/query'
13
25
  import { stringifyByEJSON } from '../utils/utils'
14
26
  import { Validate } from '../validate'
15
- import { Point } from '../geo'
27
+ import { Point } from '../geo/index'
16
28
 
17
29
  export type IQueryCondition = Record<string, any> | LogicCommand
18
30
 
@@ -39,10 +51,10 @@ class QueryEncoder {
39
51
  } else if (isQueryCommand(query)) {
40
52
  return this.encodeQueryCommand(query)
41
53
  } else if (isRegExp(query)) {
42
- // /xxx/ 形式
54
+ // /xxx/ 形式
43
55
  return { [key]: this.encodeRegExp(query) }
44
56
  } else if (isDate(query)) {
45
- return { [key]: query }
57
+ return { [key]: encodeInternalDataType(query) }
46
58
  } else {
47
59
  return { [key]: this.encodeQueryObject(query) }
48
60
  }
@@ -27,7 +27,7 @@ export class Transaction {
27
27
 
28
28
  public constructor(db: Db) {
29
29
  this._db = db
30
- this._request = new Db.reqClass(this._db.config)
30
+ this._request = Db.createRequest(this._db.config)
31
31
  this.aborted = false
32
32
  this.commited = false
33
33
  this.inited = false
@@ -1,10 +1,6 @@
1
1
  /**
2
2
  * Common interfaces and types
3
3
  */
4
-
5
- /**
6
- * Database Watch
7
- */
8
4
  import { Point } from '../geo/index'
9
5
 
10
6
  export type DataType = 'init' | 'update' | 'add' | 'remove' | 'replace' | 'limit'
@@ -1,9 +1,29 @@
1
+ import { Db } from '../'
1
2
  import { QueryOption, UpdateOption } from '../query'
2
3
  import { EJSON } from 'bson'
3
4
  import { isObject } from './type'
4
5
 
5
6
  export const sleep = (ms: number = 0) => new Promise(r => setTimeout(r, ms))
6
7
 
8
+ /**
9
+ * 兼容旧版 callback 调用风格(对齐 0.12.x 行为):
10
+ * - 传入 callback:成功时 callback(0, result)、失败时 callback(err),方法返回 undefined
11
+ * - 不传 callback:原样返回 promise
12
+ *
13
+ * 注意用 then(f, g) 而非 then(f).catch(g),保证派生 promise 为 resolved,
14
+ * 避免 callback 模式下产生 unhandled rejection。
15
+ */
16
+ export function withCallback<T>(promise: Promise<T>, callback?: any): Promise<T> | undefined {
17
+ if (typeof callback === 'function') {
18
+ promise.then(
19
+ (res: any) => callback(0, res),
20
+ (err: any) => callback(err)
21
+ )
22
+ return undefined
23
+ }
24
+ return promise
25
+ }
26
+
7
27
  const counters: Record<string, number> = {}
8
28
 
9
29
  export const autoCount = (domain: string = 'any'): number => {
@@ -13,6 +33,32 @@ export const autoCount = (domain: string = 'any'): number => {
13
33
  return counters[domain]++
14
34
  }
15
35
 
36
+ /**
37
+ * 工厂模式创建 ws 实例
38
+ */
39
+ const wsList = {}
40
+ export function getWsInstance(db: Db) {
41
+ if(!Db.wsClientClass){
42
+ throw new Error('to use realtime you must import realtime module first')
43
+ }
44
+ const { env } = db.config
45
+
46
+ if (!wsList[env]) {
47
+ wsList[env] = new Db.wsClientClass({
48
+ context: {
49
+ appConfig: {
50
+ docSizeLimit: 1000,
51
+ realtimePingInterval: 10000,
52
+ realtimePongWaitTimeout: 5000,
53
+ request: Db.createRequest(db.config)
54
+ }
55
+ }
56
+ })
57
+ }
58
+
59
+ return wsList[env]
60
+ }
61
+
16
62
  export const getReqOpts = (apiOptions: QueryOption | UpdateOption): any => {
17
63
  // 影响底层request的暂时只有timeout
18
64
  if (apiOptions.timeout !== undefined) {
package/src/validate.ts CHANGED
@@ -11,9 +11,8 @@ import { QueryOption, UpdateOption } from './query'
11
11
  import { ERRORS } from './const/code'
12
12
  import { E } from './utils/utils'
13
13
  import { getType } from './utils/type'
14
- import { Point } from './geo'
14
+ import { Point } from './geo/index'
15
15
  import { CenterSphere } from './typings'
16
-
17
16
  import { SYMBOL_GEO_POINT } from './helper/symbol'
18
17
 
19
18
  const validOptionsKeys = ['limit', 'offset', 'projection', 'order', 'multiple', 'timeout', 'raw']
@@ -243,11 +242,9 @@ export class Validate {
243
242
  }
244
243
 
245
244
  /**
245
+ * 校验 centerSphere 结构
246
246
  *
247
- * @static
248
- * @param {[Point, number]} param
249
- * @returns {Boolean}
250
- * @memberof Validate
247
+ * @param param - [Point, number] 或 [[number, number], number]
251
248
  */
252
249
  static isCentersPhere(param: CenterSphere): Boolean {
253
250
  if (Array.isArray(param) && param.length === 2) {
@@ -0,0 +1,180 @@
1
+ import { EJSON } from 'bson'
2
+ import { Db } from '../src/index'
3
+ import { Transaction } from '../src/transaction/index'
4
+
5
+ /**
6
+ * GATEWAY 模式接口名契约测试
7
+ *
8
+ * js-sdk(packages/cloudbase/database/src/index.ts 的 gateWayFunc)在
9
+ * endPointMode === 'GATEWAY' 时按 action 名查表路由到 RESTful 网关,
10
+ * 表外的 action 会 fallback 到 super.send() 走老通道,导致网关被绕过。
11
+ *
12
+ * 本测试用与 js-sdk gateWayFunc 相同的接口名集合模拟 GATEWAY 分发,
13
+ * 验证 2.0 引擎发出的所有 action 都能命中映射表,
14
+ * 任何一侧改名/新增接口而另一侧未同步时,此测试会失败。
15
+ */
16
+ describe('GATEWAY 模式接口名契约(与 js-sdk gateWayFunc 对齐)', () => {
17
+ // 与 js-sdk gateWayFunc 的 key 保持一致
18
+ const GATEWAY_ACTIONS = [
19
+ // 旧接口名(0.12.x 引擎)
20
+ 'database.queryDocument',
21
+ 'database.addDocument',
22
+ 'database.updateDocument',
23
+ 'database.deleteDocument',
24
+ 'database.countDocument',
25
+ 'database.addCollection',
26
+ 'database.aggregate',
27
+ // 事务(新旧引擎同名)
28
+ 'database.startTransaction',
29
+ 'database.commitTransaction',
30
+ 'database.abortTransaction',
31
+ 'database.getInTransaction',
32
+ 'database.updateDocInTransaction',
33
+ 'database.deleteDocInTransaction',
34
+ 'database.insertDocInTransaction',
35
+ 'database.runCommands',
36
+ // 新接口名(2.0 引擎,js-sdk gateWayFunc 已添加映射)
37
+ 'database.getDocument',
38
+ 'database.insertDocument',
39
+ 'database.modifyDocument',
40
+ 'database.removeDocument',
41
+ 'database.calculateDocument',
42
+ 'database.aggregateDocuments'
43
+ ]
44
+
45
+ let hitActions: string[]
46
+
47
+ class MockGatewayReq {
48
+ async send(action: string) {
49
+ if (GATEWAY_ACTIONS.indexOf(action) < 0) {
50
+ throw new Error(`GATEWAY 模式下无此接口映射: ${action}`)
51
+ }
52
+ hitActions.push(action)
53
+
54
+ // 按接口返回 2.0 引擎期望的最小响应结构
55
+ switch (action) {
56
+ case 'database.getDocument':
57
+ return {
58
+ data: { list: [EJSON.stringify({ _id: 'doc1', name: 'Alice' })] },
59
+ requestId: 'gw-req-get'
60
+ }
61
+ case 'database.insertDocument':
62
+ return {
63
+ data: { insertedIds: ['new-id'] },
64
+ requestId: 'gw-req-insert'
65
+ }
66
+ case 'database.modifyDocument':
67
+ return {
68
+ data: { updated: 1, upsert_id: 'doc1' },
69
+ requestId: 'gw-req-modify'
70
+ }
71
+ case 'database.removeDocument':
72
+ return {
73
+ data: { deleted: 1 },
74
+ requestId: 'gw-req-remove'
75
+ }
76
+ case 'database.calculateDocument':
77
+ return {
78
+ data: { total: 5 },
79
+ requestId: 'gw-req-count'
80
+ }
81
+ case 'database.aggregateDocuments':
82
+ return {
83
+ data: { list: [EJSON.stringify({ total: 1 })] },
84
+ requestId: 'gw-req-agg'
85
+ }
86
+ case 'database.startTransaction':
87
+ return { transactionId: 'gw-tx-001' }
88
+ case 'database.commitTransaction':
89
+ case 'database.abortTransaction':
90
+ return { requestId: 'gw-req-tx' }
91
+ default:
92
+ return { data: { ok: 1 }, requestId: 'gw-req-default' }
93
+ }
94
+ }
95
+ }
96
+
97
+ beforeEach(() => {
98
+ hitActions = []
99
+ Db.reqClass = MockGatewayReq as any
100
+ })
101
+
102
+ function createDb() {
103
+ return new Db({ env: 'test-env' })
104
+ }
105
+
106
+ async function createInitedTransaction(db: Db) {
107
+ const tx = new Transaction(db)
108
+ await tx.init()
109
+ return tx
110
+ }
111
+
112
+ it('collection CRUD 应全部命中网关映射表', async () => {
113
+ const db = createDb()
114
+ const coll = db.collection('users')
115
+
116
+ await coll.where({ age: 18 }).get()
117
+ await coll.where({ age: 18 }).count()
118
+ await coll.where({ age: 18 }).update({ age: 19 })
119
+ await coll.where({ age: 18 }).remove()
120
+ await coll.add({ name: 'New' })
121
+ await coll
122
+ .aggregate()
123
+ .match({ age: { $gt: 10 } })
124
+ .end()
125
+
126
+ expect(hitActions).toEqual([
127
+ 'database.getDocument',
128
+ 'database.calculateDocument',
129
+ 'database.modifyDocument',
130
+ 'database.removeDocument',
131
+ 'database.insertDocument',
132
+ 'database.aggregateDocuments'
133
+ ])
134
+ })
135
+
136
+ it('document CRUD 应全部命中网关映射表', async () => {
137
+ const db = createDb()
138
+ const doc = db.collection('users').doc('doc1')
139
+
140
+ await doc.get()
141
+ await doc.create({ name: 'Alice' })
142
+ await doc.set({ name: 'Alice2' })
143
+ await doc.update({ name: 'Alice3' })
144
+ await doc.remove()
145
+
146
+ expect(hitActions).toEqual([
147
+ 'database.getDocument',
148
+ 'database.insertDocument',
149
+ 'database.modifyDocument',
150
+ 'database.modifyDocument',
151
+ 'database.removeDocument'
152
+ ])
153
+ })
154
+
155
+ it('事务操作应全部命中网关映射表', async () => {
156
+ const db = createDb()
157
+ const tx = await createInitedTransaction(db)
158
+
159
+ await tx.collection('users').where({ age: 18 }).get()
160
+ await tx.collection('users').where({ age: 18 }).update({ age: 19 })
161
+ await tx.collection('users').add({ name: 'TxNew' })
162
+ await tx.collection('users').doc('doc1').set({ name: 'TxSet' })
163
+ await tx.commit()
164
+
165
+ expect(hitActions).toEqual([
166
+ 'database.startTransaction',
167
+ 'database.getDocument',
168
+ 'database.modifyDocument',
169
+ 'database.insertDocument',
170
+ 'database.modifyDocument',
171
+ 'database.commitTransaction'
172
+ ])
173
+ })
174
+
175
+ it('createCollection 应命中网关映射表', async () => {
176
+ const db = createDb()
177
+ await db.createCollection('new-coll')
178
+ expect(hitActions).toEqual(['database.addCollection'])
179
+ })
180
+ })