datastore-api 2.2.0 → 4.0.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.
- package/README.md +17 -0
- package/dist/datastore-api.cjs.development.js +1432 -0
- package/dist/datastore-api.cjs.development.js.map +1 -0
- package/dist/datastore-api.cjs.production.min.js +2 -0
- package/dist/datastore-api.cjs.production.min.js.map +1 -0
- package/dist/datastore-api.esm.js +1411 -0
- package/dist/datastore-api.esm.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +8 -0
- package/dist/lib/dstore-api.d.ts +350 -0
- package/dist/mock/index.d.ts +107 -0
- package/dist/mock/operators.d.ts +8 -0
- package/package.json +17 -23
- package/src/index.ts +1 -0
- package/src/lib/dstore-api-cloud.spec.ts +435 -0
- package/src/lib/dstore-api-emulator.spec.ts +440 -0
- package/src/lib/dstore-api-simulator.spec.ts +461 -0
- package/src/lib/dstore-api.ts +706 -0
- package/src/mock/index.ts +649 -0
- package/src/mock/operators.ts +20 -0
- package/CHANGELOG.md +0 -124
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* datastore-simulator.ts
|
|
3
|
+
*
|
|
4
|
+
* Created by Dr. Maximillian Dornseif 2023-05-11 in huwawi3backend 18.16.3
|
|
5
|
+
* Copyright (c) 2023 HUDORA GmbH
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
9
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
10
|
+
/*
|
|
11
|
+
* index.ts
|
|
12
|
+
*
|
|
13
|
+
* Created by Dr. Maximillian Dornseif 2023-04-20 in huwawi3backend 18.13.0
|
|
14
|
+
* based on https://github.com/KoryNunn/datastore-mock 1.1.0 by korynunn
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
DatastoreOptions,
|
|
19
|
+
DatastoreRequest,
|
|
20
|
+
Entity,
|
|
21
|
+
InsertCallback,
|
|
22
|
+
InsertResponse,
|
|
23
|
+
Key,
|
|
24
|
+
KeyToLegacyUrlSafeCallback,
|
|
25
|
+
Datastore as OrigDatastore,
|
|
26
|
+
TransactionOptions,
|
|
27
|
+
UpdateCallback,
|
|
28
|
+
UpdateResponse,
|
|
29
|
+
UpsertCallback,
|
|
30
|
+
UpsertResponse,
|
|
31
|
+
Query,
|
|
32
|
+
PathType,
|
|
33
|
+
} from '@google-cloud/datastore'
|
|
34
|
+
import { google } from '@google-cloud/datastore/build/protos/protos'
|
|
35
|
+
import { AggregateQuery } from '@google-cloud/datastore/build/src/aggregate'
|
|
36
|
+
import { Entities, entity } from '@google-cloud/datastore/build/src/entity'
|
|
37
|
+
import { RunQueryOptions, RunQueryResponse, RunQueryCallback } from '@google-cloud/datastore/build/src/query'
|
|
38
|
+
import {
|
|
39
|
+
AllocateIdsCallback,
|
|
40
|
+
AllocateIdsOptions,
|
|
41
|
+
AllocateIdsResponse,
|
|
42
|
+
CommitCallback,
|
|
43
|
+
CommitResponse,
|
|
44
|
+
CreateReadStreamOptions,
|
|
45
|
+
DeleteCallback,
|
|
46
|
+
DeleteResponse,
|
|
47
|
+
GetCallback,
|
|
48
|
+
GetResponse,
|
|
49
|
+
PrepareEntityObjectResponse,
|
|
50
|
+
RequestOptions,
|
|
51
|
+
SaveCallback,
|
|
52
|
+
SaveResponse,
|
|
53
|
+
} from '@google-cloud/datastore/build/src/request'
|
|
54
|
+
import { promisifyAll } from '@google-cloud/promisify'
|
|
55
|
+
import { assert } from 'assertate-debug'
|
|
56
|
+
import { CallOptions } from 'google-gax'
|
|
57
|
+
import * as is from 'is'
|
|
58
|
+
|
|
59
|
+
const urlSafeKey = new entity.URLSafeKey()
|
|
60
|
+
|
|
61
|
+
const KEY_SELECT = '__key__'
|
|
62
|
+
|
|
63
|
+
function filter(query: { filters: any[][] }, field: any, operator: any, value: any): any {
|
|
64
|
+
query.filters.push([field, operator, value])
|
|
65
|
+
return createQuery(query)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function limit(query: { limit: any }, limit: any): any {
|
|
69
|
+
query.limit = limit
|
|
70
|
+
return createQuery(query)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function select(query: { select: string | string[] }, fields: ConcatArray<never>) {
|
|
74
|
+
query.select = [].concat(fields)
|
|
75
|
+
|
|
76
|
+
if (query.select.length > 1 && query.select.includes(KEY_SELECT)) {
|
|
77
|
+
throw new Error('Cannot mix __key__ select with other fields')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return createQuery(query)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function createQuery(query: any): any {
|
|
84
|
+
return {
|
|
85
|
+
filter: filter.bind(null, query),
|
|
86
|
+
limit: limit.bind(null, query),
|
|
87
|
+
select: select.bind(null, query),
|
|
88
|
+
query,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export class Datastore extends OrigDatastore {
|
|
93
|
+
db: Map<string, any>
|
|
94
|
+
rnd = 0
|
|
95
|
+
engine = 'datastore-simulator'
|
|
96
|
+
|
|
97
|
+
constructor(options?: DatastoreOptions) {
|
|
98
|
+
super()
|
|
99
|
+
options = options || {}
|
|
100
|
+
this.clients_ = new Map()
|
|
101
|
+
// this.datastore = this as unknown as Datastore;
|
|
102
|
+
this.namespace = options.namespace
|
|
103
|
+
this.db = new Map()
|
|
104
|
+
|
|
105
|
+
options.projectId = options.projectId || process.env.DATASTORE_PROJECT_ID
|
|
106
|
+
}
|
|
107
|
+
_keySerializer(key: entity.Key) {
|
|
108
|
+
const newKey =
|
|
109
|
+
key.id === undefined
|
|
110
|
+
? this.key(key.path)
|
|
111
|
+
: this.key([...key.path.slice(0, -1), this.int(key.path.slice(-1)[0])])
|
|
112
|
+
return JSON.stringify(newKey)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// export
|
|
116
|
+
// getIndexes getIndexes
|
|
117
|
+
// getProjectId
|
|
118
|
+
// index(id: string): Index {
|
|
119
|
+
// return new Index(this, id);
|
|
120
|
+
// }
|
|
121
|
+
|
|
122
|
+
allocateIds(key: entity.Key, options: AllocateIdsOptions | number): Promise<AllocateIdsResponse>
|
|
123
|
+
allocateIds(key: entity.Key, options: AllocateIdsOptions | number, callback: AllocateIdsCallback): void
|
|
124
|
+
allocateIds(
|
|
125
|
+
key: entity.Key,
|
|
126
|
+
options: AllocateIdsOptions | number,
|
|
127
|
+
callback?: AllocateIdsCallback
|
|
128
|
+
): void | Promise<AllocateIdsResponse> {
|
|
129
|
+
options = typeof options === 'number' ? { allocations: options } : options
|
|
130
|
+
const allocations = options.allocations || 1
|
|
131
|
+
const result: entity.Key[] = []
|
|
132
|
+
const info = { keys: [] as any[] }
|
|
133
|
+
|
|
134
|
+
do {
|
|
135
|
+
const id = 5000000000000000 + this.rnd++
|
|
136
|
+
const newKey = this.key([...key.path.slice(0, -1), this.int(id)])
|
|
137
|
+
result.push(newKey)
|
|
138
|
+
info.keys.push({
|
|
139
|
+
partitionId: {
|
|
140
|
+
databaseId: '',
|
|
141
|
+
namespaceId: 'test',
|
|
142
|
+
projectId: 'huwawi3',
|
|
143
|
+
},
|
|
144
|
+
path: [
|
|
145
|
+
{
|
|
146
|
+
id: newKey.id,
|
|
147
|
+
idType: 'id',
|
|
148
|
+
kind: newKey.kind,
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
})
|
|
152
|
+
} while (result.length < allocations)
|
|
153
|
+
callback!(null, result, info)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
delete(keys: Entities, gaxOptions?: CallOptions): Promise<DeleteResponse>
|
|
157
|
+
delete(keys: Entities, callback: DeleteCallback): void
|
|
158
|
+
delete(keys: Entities, gaxOptions: CallOptions, callback: DeleteCallback): void
|
|
159
|
+
delete(
|
|
160
|
+
keys: entity.Key | entity.Key[],
|
|
161
|
+
gaxOptionsOrCallback?: CallOptions | DeleteCallback,
|
|
162
|
+
cb?: DeleteCallback
|
|
163
|
+
): void | Promise<DeleteResponse> {
|
|
164
|
+
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {}
|
|
165
|
+
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!
|
|
166
|
+
|
|
167
|
+
const result: CommitResponse[] = []
|
|
168
|
+
|
|
169
|
+
for (const key of [keys].flat()) {
|
|
170
|
+
this.db.delete(this._keySerializer(key))
|
|
171
|
+
result.push({
|
|
172
|
+
mutationResults: [
|
|
173
|
+
{
|
|
174
|
+
key: null,
|
|
175
|
+
version: 1,
|
|
176
|
+
conflictDetected: false, // (boolean|null);
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
indexUpdates: 1, // number|null);
|
|
180
|
+
} as unknown as CommitResponse)
|
|
181
|
+
}
|
|
182
|
+
setImmediate(() => callback(null, result.length === 1 ? result[0] : (result as any)))
|
|
183
|
+
}
|
|
184
|
+
get(keys: entity.Key | entity.Key[], options?: CreateReadStreamOptions): Promise<GetResponse>
|
|
185
|
+
get(keys: entity.Key | entity.Key[], callback: GetCallback): void
|
|
186
|
+
get(keys: entity.Key | entity.Key[], options: CreateReadStreamOptions, callback: GetCallback): void
|
|
187
|
+
get(
|
|
188
|
+
keys: entity.Key | entity.Key[],
|
|
189
|
+
optionsOrCallback?: CreateReadStreamOptions | GetCallback,
|
|
190
|
+
cb?: GetCallback
|
|
191
|
+
): void | Promise<GetResponse> {
|
|
192
|
+
const options = typeof optionsOrCallback === 'object' && optionsOrCallback ? optionsOrCallback : {}
|
|
193
|
+
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!
|
|
194
|
+
|
|
195
|
+
if ([keys].flat().length === 0) {
|
|
196
|
+
throw Error('At least one Key object is required.')
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const result: any[] = []
|
|
200
|
+
let lastK
|
|
201
|
+
for (let key of [keys].flat()) {
|
|
202
|
+
// dedupe
|
|
203
|
+
const k = this._keySerializer(key)
|
|
204
|
+
if (k !== lastK && this.db.has(k)) {
|
|
205
|
+
result.push(this.db.get(k))
|
|
206
|
+
}
|
|
207
|
+
lastK = k
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
setImmediate(() => callback(null, Array.isArray(keys) ? result : (result[0] as any)))
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
runQuery(query: Query, options?: RunQueryOptions): Promise<RunQueryResponse>
|
|
214
|
+
runQuery(query: Query, options: RunQueryOptions, callback: RunQueryCallback): void
|
|
215
|
+
runQuery(query: Query, callback: RunQueryCallback): void
|
|
216
|
+
runQuery(
|
|
217
|
+
query: Query,
|
|
218
|
+
optionsOrCallback?: RunQueryOptions | RunQueryCallback,
|
|
219
|
+
cb?: RunQueryCallback
|
|
220
|
+
): void | Promise<RunQueryResponse> {
|
|
221
|
+
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}
|
|
222
|
+
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!
|
|
223
|
+
assert(query.kinds.length === 1)
|
|
224
|
+
const kind = query.kinds[0]
|
|
225
|
+
|
|
226
|
+
const reply: any[] = []
|
|
227
|
+
const filtered = Array.from(this.db.entries()).filter(([ks, v]) => {
|
|
228
|
+
const k = JSON.parse(ks)
|
|
229
|
+
return k.kind === kind && k.namespace === query.namespace
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
if (query.filters.length === 0) {
|
|
233
|
+
for (let [ks, entity] of filtered) {
|
|
234
|
+
reply.push(entity)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
for (let filter of query.filters) {
|
|
239
|
+
if (filter.name === '__key__' && filter.op === 'HAS_ANCESTOR') {
|
|
240
|
+
const parent = filter.val.path.join('⭕️')
|
|
241
|
+
for (let [ks, entity] of filtered) {
|
|
242
|
+
const k = JSON.parse(ks)
|
|
243
|
+
if (k.path.join('⭕️').startsWith(parent)) {
|
|
244
|
+
reply.push(entity)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
} else if (filter.op === '=') {
|
|
248
|
+
for (let [ks, entity] of filtered) {
|
|
249
|
+
if (entity[filter.name] == filter.val) {
|
|
250
|
+
reply.push(entity)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
} else if (filter.op === '>=') {
|
|
254
|
+
for (let [ks, entity] of filtered) {
|
|
255
|
+
if (entity[filter.name] >= filter.val) {
|
|
256
|
+
reply.push(entity)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} else if (filter.op === '<') {
|
|
260
|
+
for (let [ks, entity] of filtered) {
|
|
261
|
+
if (entity[filter.name] >= filter.val) {
|
|
262
|
+
reply.push(entity)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} else {
|
|
266
|
+
console.log('unknown filter', filter)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// TODO: handle query.limit
|
|
271
|
+
|
|
272
|
+
setImmediate(() => callback(null, reply, { moreResults: 'MORE_RESULTS_AFTER_LIMIT' }))
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
merge(entities: Entities): Promise<CommitResponse>
|
|
276
|
+
merge(entities: Entities, callback: SaveCallback): void
|
|
277
|
+
merge(entities: Entities, callback?: SaveCallback): void | Promise<CommitResponse> {
|
|
278
|
+
throw Error('not implemented')
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
insert(entities: Entities): Promise<InsertResponse>
|
|
282
|
+
insert(entities: Entities, callback: InsertCallback): void
|
|
283
|
+
insert(entities: Entities, callback?: InsertCallback): void | Promise<InsertResponse> {
|
|
284
|
+
entities = [entities]
|
|
285
|
+
.flat()
|
|
286
|
+
.map(DatastoreRequest.prepareEntityObject_)
|
|
287
|
+
.map((x: PrepareEntityObjectResponse) => {
|
|
288
|
+
x.method = 'insert'
|
|
289
|
+
return x
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
this.save(entities, callback!)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
update(entities: Entities): Promise<UpdateResponse>
|
|
296
|
+
update(entities: Entities, callback: UpdateCallback): void
|
|
297
|
+
update(entities: Entities, callback?: UpdateCallback): void | Promise<UpdateResponse> {
|
|
298
|
+
entities = [entities]
|
|
299
|
+
.flat()
|
|
300
|
+
.map(DatastoreRequest.prepareEntityObject_)
|
|
301
|
+
.map((x: PrepareEntityObjectResponse) => {
|
|
302
|
+
x.method = 'update'
|
|
303
|
+
return x
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
this.save(entities, callback!)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
upsert(entities: Entities): Promise<UpsertResponse>
|
|
310
|
+
upsert(entities: Entities, callback: UpsertCallback): void
|
|
311
|
+
upsert(entities: Entities, callback?: UpsertCallback): void | Promise<UpsertResponse> {
|
|
312
|
+
entities = [entities]
|
|
313
|
+
.flat()
|
|
314
|
+
.map(DatastoreRequest.prepareEntityObject_)
|
|
315
|
+
.map((x: PrepareEntityObjectResponse) => {
|
|
316
|
+
x.method = 'upsert'
|
|
317
|
+
return x
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
this.save(entities, callback!)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
save(entities: Entities, gaxOptions?: CallOptions): Promise<SaveResponse>
|
|
324
|
+
save(entities: Entities, gaxOptions: CallOptions, callback: SaveCallback): void
|
|
325
|
+
save(entities: Entities, callback: SaveCallback): void
|
|
326
|
+
save(
|
|
327
|
+
entities: Entities,
|
|
328
|
+
gaxOptionsOrCallback?: CallOptions | SaveCallback,
|
|
329
|
+
cb?: SaveCallback
|
|
330
|
+
): void | Promise<SaveResponse> {
|
|
331
|
+
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {}
|
|
332
|
+
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!
|
|
333
|
+
|
|
334
|
+
const methods: Record<string, boolean> = {
|
|
335
|
+
insert: true,
|
|
336
|
+
update: true,
|
|
337
|
+
upsert: true,
|
|
338
|
+
}
|
|
339
|
+
entities = [entities].flat()
|
|
340
|
+
// Iterate over the entity objects, build a proto from all keys and values,
|
|
341
|
+
// then place in the correct mutation array (insert, update, etc).
|
|
342
|
+
const result: CommitResponse[] = []
|
|
343
|
+
;[entities]
|
|
344
|
+
.flat()
|
|
345
|
+
.map(DatastoreRequest.prepareEntityObject_)
|
|
346
|
+
.forEach((entityObject: Entity, index: number) => {
|
|
347
|
+
let method = 'upsert'
|
|
348
|
+
if (entityObject.method) {
|
|
349
|
+
if (methods[entityObject.method]) {
|
|
350
|
+
method = entityObject.method
|
|
351
|
+
} else {
|
|
352
|
+
throw new Error('Method ' + entityObject.method + ' not recognized.')
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
// TODO: generate key
|
|
356
|
+
|
|
357
|
+
// Numerical IDs are always encoded as string in the datastore
|
|
358
|
+
const newKey =
|
|
359
|
+
entityObject.key.id === undefined
|
|
360
|
+
? this.key(entityObject.key.path)
|
|
361
|
+
: this.key([...entityObject.key.path.slice(0, -1), this.int(entityObject.key.path.slice(-1)[0])])
|
|
362
|
+
|
|
363
|
+
this.db.set(this._keySerializer(newKey), {
|
|
364
|
+
[Datastore.KEY]: newKey,
|
|
365
|
+
...entityObject.data,
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
result.push({
|
|
369
|
+
mutationResults: [
|
|
370
|
+
{
|
|
371
|
+
key: null,
|
|
372
|
+
version: 1,
|
|
373
|
+
conflictDetected: false, // (boolean|null);
|
|
374
|
+
createTime: { nanos: 1, seconds: 2 },
|
|
375
|
+
updateTime: { nanos: 3, seconds: 4 },
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
indexUpdates: 1, // number|null);
|
|
379
|
+
} as unknown as CommitResponse)
|
|
380
|
+
})
|
|
381
|
+
setImmediate(() => callback(null, result[0] as any))
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
static KEY: typeof entity.KEY_SYMBOL = entity.KEY_SYMBOL
|
|
385
|
+
KEY: typeof entity.KEY_SYMBOL = Datastore.KEY
|
|
386
|
+
static MORE_RESULTS_AFTER_CURSOR = 'MORE_RESULTS_AFTER_CURSOR'
|
|
387
|
+
MORE_RESULTS_AFTER_CURSOR = Datastore.MORE_RESULTS_AFTER_CURSOR
|
|
388
|
+
static MORE_RESULTS_AFTER_LIMIT = 'MORE_RESULTS_AFTER_LIMIT'
|
|
389
|
+
MORE_RESULTS_AFTER_LIMIT = Datastore.MORE_RESULTS_AFTER_LIMIT
|
|
390
|
+
static NO_MORE_RESULTS = 'NO_MORE_RESULTS'
|
|
391
|
+
NO_MORE_RESULTS = Datastore.NO_MORE_RESULTS
|
|
392
|
+
|
|
393
|
+
createQuery(kind?: string): Query
|
|
394
|
+
createQuery(kind?: string[]): Query
|
|
395
|
+
createQuery(namespace: string, kind: string): Query
|
|
396
|
+
createQuery(namespace: string, kind: string[]): Query
|
|
397
|
+
createQuery(namespaceOrKind?: string | string[], kind?: string | string[]): Query {
|
|
398
|
+
let namespace = namespaceOrKind as string
|
|
399
|
+
if (!kind) {
|
|
400
|
+
kind = namespaceOrKind
|
|
401
|
+
namespace = this.namespace!
|
|
402
|
+
}
|
|
403
|
+
return new Query(this as any, namespace, [kind].flat() as string[])
|
|
404
|
+
}
|
|
405
|
+
key(options: entity.KeyOptions): entity.Key
|
|
406
|
+
key(path: PathType[]): entity.Key
|
|
407
|
+
key(path: string): entity.Key
|
|
408
|
+
key(options: string | entity.KeyOptions | PathType[]): entity.Key {
|
|
409
|
+
const keyOptions = is.object(options)
|
|
410
|
+
? (options as entity.KeyOptions)
|
|
411
|
+
: {
|
|
412
|
+
namespace: this.namespace,
|
|
413
|
+
path: [options].flat() as PathType[],
|
|
414
|
+
}
|
|
415
|
+
return new entity.Key(keyOptions)
|
|
416
|
+
}
|
|
417
|
+
static isKey(value?: unknown) {
|
|
418
|
+
return entity.isDsKey(value as any)
|
|
419
|
+
}
|
|
420
|
+
isKey(value?: unknown) {
|
|
421
|
+
return Datastore.isKey(value)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
keyToLegacyUrlSafe(key: entity.Key, locationPrefix?: string): Promise<string>
|
|
425
|
+
keyToLegacyUrlSafe(key: entity.Key, callback: KeyToLegacyUrlSafeCallback): void
|
|
426
|
+
keyToLegacyUrlSafe(key: entity.Key, locationPrefix: string, callback: KeyToLegacyUrlSafeCallback): void
|
|
427
|
+
keyToLegacyUrlSafe(
|
|
428
|
+
key: entity.Key,
|
|
429
|
+
locationPrefixOrCallback?: string | KeyToLegacyUrlSafeCallback,
|
|
430
|
+
callback?: KeyToLegacyUrlSafeCallback
|
|
431
|
+
): Promise<string> | void {
|
|
432
|
+
const locationPrefix = typeof locationPrefixOrCallback === 'string' ? locationPrefixOrCallback : ''
|
|
433
|
+
callback = typeof locationPrefixOrCallback === 'function' ? locationPrefixOrCallback : callback
|
|
434
|
+
this.auth.getProjectId((err: any, projectId: any) => {
|
|
435
|
+
if (err) {
|
|
436
|
+
setImmediate(() => callback!(err))
|
|
437
|
+
return
|
|
438
|
+
}
|
|
439
|
+
setImmediate(() => callback!(null, urlSafeKey.legacyEncode(projectId!, key, locationPrefix)))
|
|
440
|
+
})
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
keyFromLegacyUrlsafe(key: string): entity.Key {
|
|
444
|
+
return urlSafeKey.legacyDecode(key)
|
|
445
|
+
}
|
|
446
|
+
transaction(options?: TransactionOptions) {
|
|
447
|
+
return new Transaction(this as any, options)
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
promisifyAll(Datastore, {
|
|
452
|
+
exclude: [
|
|
453
|
+
'createAggregationQuery',
|
|
454
|
+
'double',
|
|
455
|
+
'isDouble',
|
|
456
|
+
'geoPoint',
|
|
457
|
+
'getProjectId',
|
|
458
|
+
'getSharedQueryOptions',
|
|
459
|
+
'isGeoPoint',
|
|
460
|
+
'index',
|
|
461
|
+
'int',
|
|
462
|
+
'isInt',
|
|
463
|
+
'createQuery',
|
|
464
|
+
'key',
|
|
465
|
+
'isKey',
|
|
466
|
+
'keyFromLegacyUrlsafe',
|
|
467
|
+
'transaction',
|
|
468
|
+
],
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
export default Datastore
|
|
472
|
+
|
|
473
|
+
class Transaction extends DatastoreRequest {
|
|
474
|
+
namespace?: string
|
|
475
|
+
readOnly: boolean
|
|
476
|
+
request: any // Function
|
|
477
|
+
modifiedEntities_: ModifiedEntities
|
|
478
|
+
skipCommit?: boolean
|
|
479
|
+
constructor(datastore: Datastore, options?: TransactionOptions) {
|
|
480
|
+
super()
|
|
481
|
+
/**
|
|
482
|
+
* @name Transaction#datastore
|
|
483
|
+
* @type {Datastore}
|
|
484
|
+
*/
|
|
485
|
+
this.datastore = datastore
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* @name Transaction#namespace
|
|
489
|
+
* @type {string}
|
|
490
|
+
*/
|
|
491
|
+
this.namespace = datastore.namespace
|
|
492
|
+
|
|
493
|
+
options = options || {}
|
|
494
|
+
|
|
495
|
+
this.id = options.id
|
|
496
|
+
this.readOnly = options.readOnly === true
|
|
497
|
+
|
|
498
|
+
// A queue for entity modifications made during the transaction.
|
|
499
|
+
this.modifiedEntities_ = []
|
|
500
|
+
|
|
501
|
+
// Queue the callbacks that process the API responses.
|
|
502
|
+
this.requestCallbacks_ = []
|
|
503
|
+
|
|
504
|
+
// Queue the requests to make when we send the transactional commit.
|
|
505
|
+
this.requests_ = []
|
|
506
|
+
}
|
|
507
|
+
commit(gaxOptions?: CallOptions): Promise<CommitResponse>
|
|
508
|
+
commit(callback: CommitCallback): void
|
|
509
|
+
commit(gaxOptions: CallOptions, callback: CommitCallback): void
|
|
510
|
+
commit(
|
|
511
|
+
gaxOptionsOrCallback?: CallOptions | CommitCallback,
|
|
512
|
+
cb?: CommitCallback
|
|
513
|
+
): void | Promise<CommitResponse> {
|
|
514
|
+
const callback =
|
|
515
|
+
typeof gaxOptionsOrCallback === 'function'
|
|
516
|
+
? gaxOptionsOrCallback
|
|
517
|
+
: typeof cb === 'function'
|
|
518
|
+
? cb
|
|
519
|
+
: () => {}
|
|
520
|
+
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {}
|
|
521
|
+
|
|
522
|
+
if (this.skipCommit) {
|
|
523
|
+
setImmediate(callback)
|
|
524
|
+
return
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const keys: Entities = {}
|
|
528
|
+
|
|
529
|
+
callback(null, undefined)
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
createQuery(kind?: string): Query
|
|
533
|
+
createQuery(kind?: string[]): Query
|
|
534
|
+
createQuery(namespace: string, kind: string): Query
|
|
535
|
+
createQuery(namespace: string, kind: string[]): Query
|
|
536
|
+
createQuery(namespaceOrKind?: string | string[], kind?: string | string[]): Query {
|
|
537
|
+
return this.datastore.createQuery.call(this, namespaceOrKind as string, kind as string[])
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
createAggregationQuery(query: Query): AggregateQuery {
|
|
541
|
+
return this.datastore.createAggregationQuery.call(this, query)
|
|
542
|
+
}
|
|
543
|
+
delete(entities?: Entities): any {
|
|
544
|
+
this.datastore.delete(entities)
|
|
545
|
+
}
|
|
546
|
+
insert(entities: Entities): void {
|
|
547
|
+
this.save(entities)
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
rollback(callback: RollbackCallback): void
|
|
551
|
+
rollback(gaxOptions?: CallOptions): Promise<RollbackResponse>
|
|
552
|
+
rollback(gaxOptions: CallOptions, callback: RollbackCallback): void
|
|
553
|
+
rollback(
|
|
554
|
+
gaxOptionsOrCallback?: CallOptions | RollbackCallback,
|
|
555
|
+
cb?: RollbackCallback
|
|
556
|
+
): void | Promise<RollbackResponse> {
|
|
557
|
+
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {}
|
|
558
|
+
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!
|
|
559
|
+
|
|
560
|
+
callback(null, undefined)
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
run(options?: RunOptions): Promise<RunResponse>
|
|
564
|
+
run(callback: RunCallback): void
|
|
565
|
+
run(options: RunOptions, callback: RunCallback): void
|
|
566
|
+
run(optionsOrCallback?: RunOptions | RunCallback, cb?: RunCallback): void | Promise<RunResponse> {
|
|
567
|
+
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}
|
|
568
|
+
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!
|
|
569
|
+
|
|
570
|
+
const reqOpts = {
|
|
571
|
+
transactionOptions: {},
|
|
572
|
+
} as RequestOptions
|
|
573
|
+
|
|
574
|
+
if (options.readOnly || this.readOnly) {
|
|
575
|
+
reqOpts.transactionOptions!.readOnly = {}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (options.transactionId || this.id) {
|
|
579
|
+
reqOpts.transactionOptions!.readWrite = {
|
|
580
|
+
previousTransaction: options.transactionId || this.id,
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (options.transactionOptions) {
|
|
585
|
+
reqOpts.transactionOptions = options.transactionOptions
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
callback(null, this, undefined)
|
|
589
|
+
}
|
|
590
|
+
save(entities: Entities): void {
|
|
591
|
+
this.datastore.save(entities)
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
update(entities: Entities): void {
|
|
595
|
+
entities = [entities]
|
|
596
|
+
.flat()
|
|
597
|
+
.map(DatastoreRequest.prepareEntityObject_)
|
|
598
|
+
.map((x: PrepareEntityObjectResponse) => {
|
|
599
|
+
x.method = 'update'
|
|
600
|
+
return x
|
|
601
|
+
})
|
|
602
|
+
|
|
603
|
+
this.save(entities)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
upsert(entities: Entities): void {
|
|
607
|
+
entities = [entities]
|
|
608
|
+
.flat()
|
|
609
|
+
.map(DatastoreRequest.prepareEntityObject_)
|
|
610
|
+
.map((x: PrepareEntityObjectResponse) => {
|
|
611
|
+
x.method = 'upsert'
|
|
612
|
+
return x
|
|
613
|
+
})
|
|
614
|
+
|
|
615
|
+
this.save(entities)
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
export type ModifiedEntities = Array<{
|
|
620
|
+
entity: { key: Entity }
|
|
621
|
+
method: string
|
|
622
|
+
args: Entity[]
|
|
623
|
+
}>
|
|
624
|
+
export type RunResponse = [Transaction, google.datastore.v1.IBeginTransactionResponse]
|
|
625
|
+
export interface RunCallback {
|
|
626
|
+
(
|
|
627
|
+
error: Error | null,
|
|
628
|
+
transaction: Transaction | null,
|
|
629
|
+
response?: google.datastore.v1.IBeginTransactionResponse
|
|
630
|
+
): void
|
|
631
|
+
}
|
|
632
|
+
export interface RollbackCallback {
|
|
633
|
+
(error: Error | null, response?: google.datastore.v1.IRollbackResponse): void
|
|
634
|
+
}
|
|
635
|
+
export type RollbackResponse = [google.datastore.v1.IRollbackResponse]
|
|
636
|
+
export interface RunOptions {
|
|
637
|
+
readOnly?: boolean
|
|
638
|
+
transactionId?: string
|
|
639
|
+
transactionOptions?: TransactionOptions
|
|
640
|
+
gaxOptions?: CallOptions
|
|
641
|
+
}
|
|
642
|
+
/*! Developer Documentation
|
|
643
|
+
*
|
|
644
|
+
* All async methods (except for streams) will return a Promise in the event
|
|
645
|
+
* that a callback is omitted.
|
|
646
|
+
*/
|
|
647
|
+
promisifyAll(Transaction, {
|
|
648
|
+
exclude: ['createAggregationQuery', 'createQuery', 'delete', 'insert', 'save', 'update', 'upsert'],
|
|
649
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* operators.ts
|
|
3
|
+
*
|
|
4
|
+
* Created by Dr. Maximillian Dornseif 2023-04-20 in huwawi3backend 18.13.0
|
|
5
|
+
* based on https://github.com/KoryNunn/datastore-mock 1.1.0 by korynunn
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
|
|
11
|
+
'>': (a, b) => a > b,
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
'<': (a, b) => a < b,
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
'>=': (a, b) => a <= b,
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
'<=': (a, b) => a >= b,
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
'=': (a, b) => a === b,
|
|
20
|
+
}
|