datastore-api 2.2.0 → 4.0.3

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.
@@ -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
+ };