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,8 @@
1
+ declare const _default: {
2
+ '>': (a: any, b: any) => boolean;
3
+ '<': (a: any, b: any) => boolean;
4
+ '>=': (a: any, b: any) => boolean;
5
+ '<=': (a: any, b: any) => boolean;
6
+ '=': (a: any, b: any) => boolean;
7
+ };
8
+ export default _default;
package/package.json CHANGED
@@ -18,24 +18,21 @@
18
18
  }
19
19
  },
20
20
  "dependencies": {
21
+ "@google-cloud/datastore": "^8.0.0",
21
22
  "assertate-debug": "^2.4.2",
22
- "google-datastore-emulator": "^5.1.0",
23
23
  "prom-client": "^14.0.1"
24
24
  },
25
25
  "description": "Simplified, more consitent API for Google Cloud Datastore",
26
26
  "devDependencies": {
27
- "@ava/typescript": "^4.0.0",
28
- "@google-cloud/datastore": "7.3",
29
27
  "@google-cloud/promisify": "^3.0.1",
30
28
  "@istanbuljs/nyc-config-typescript": "^1.0.1",
31
29
  "@size-limit/preset-small-lib": "^8.2.6",
32
30
  "@tsconfig/recommended": "^1.0.2",
33
31
  "@types/debug": "^4.1.8",
34
32
  "@types/is": "^0.0.22",
35
- "@types/node": "^17.0.0",
33
+ "@types/node": "^20.3.3",
36
34
  "@typescript-eslint/eslint-plugin": "^4.0.1",
37
35
  "@typescript-eslint/parser": "^4.0.1",
38
- "ava": "^5.2.0",
39
36
  "codecov": "^3.5.0",
40
37
  "cspell": "5.14.0",
41
38
  "cz-conventional-changelog": "^3.3.0",
@@ -50,34 +47,30 @@
50
47
  "eslint-plugin-prettier": "^4.2.1",
51
48
  "eslint-plugin-react": "^7.32.2",
52
49
  "eslint-plugin-react-hooks": "^4.6.0",
53
- "gh-pages": "^3.1.0",
50
+ "gh-pages": "^5.0.0",
51
+ "google-datastore-emulator": "^7.0.0",
54
52
  "husky": "^8.0.3",
55
- "lint-staged": "^13.2.2",
53
+ "lint-staged": "^13.2.3",
56
54
  "npm-run-all": "^4.1.5",
57
55
  "nyc": "^15.1.0",
58
- "open-cli": "7.0.1",
56
+ "open-cli": "7.2.0",
59
57
  "prettier": "^2.1.1",
60
58
  "size-limit": "^8.2.6",
61
- "sort-package-json": "^2.4.1",
59
+ "sort-package-json": "^2.5.0",
62
60
  "standard-version": "^9.0.0",
63
- "ts-essentials": "9.1.2",
61
+ "ts-essentials": "9.3.2",
64
62
  "ts-node": "^10.4.0",
65
63
  "tslib": "^2.6.0",
66
- "typedoc": "0.22.11",
64
+ "typedoc": "0.24.8",
67
65
  "typescript": "^4.0.2",
68
- "vitest": "^0.30.1"
66
+ "vitest": "^0.32.2"
69
67
  },
70
68
  "engines": {
71
69
  "node": ">=16"
72
70
  },
73
71
  "files": [
74
- "build/main",
75
- "build/module",
76
- "!**/*.spec.*",
77
- "!**/*.json",
78
- "CHANGELOG.md",
79
- "LICENSE",
80
- "README.md"
72
+ "dist",
73
+ "src"
81
74
  ],
82
75
  "homepage": "http://github.com/mdornseif/datastore-api/",
83
76
  "husky": {
@@ -94,12 +87,12 @@
94
87
  "*{css,scss,md,markdown,json,yaml,yml,graphql,html}": "prettier -w",
95
88
  "*{js,jsx,ts,tsx}": [
96
89
  "prettier -w",
97
- "eslint --cache --fix"
90
+ "yarn lint --fix"
98
91
  ],
99
- "package*json": "sort-package-json"
92
+ "package.json": "sort-package-json"
100
93
  },
101
- "main": "build/main/index.js",
102
- "module": "build/module/index.js",
94
+ "main": "dist/index.js",
95
+ "module": "dist/datastore-api2.esm.js",
103
96
  "name": "datastore-api",
104
97
  "nyc": {
105
98
  "exclude": [
@@ -108,12 +101,11 @@
108
101
  "extends": "@istanbuljs/nyc-config-typescript"
109
102
  },
110
103
  "peerDependencies": {
111
- "@google-cloud/datastore": "^6.6.2",
112
104
  "debug": "^4.3.3"
113
105
  },
114
106
  "prettier": {
115
107
  "printWidth": 110,
116
- "semi": false,
108
+ "semi": true,
117
109
  "singleQuote": true,
118
110
  "trailingComma": "es5"
119
111
  },
@@ -128,6 +120,7 @@
128
120
  "scripts": {
129
121
  "analyze": "size-limit --why",
130
122
  "build": "dts build",
123
+ "doc": "typedoc src/ --exclude **/*.spec.ts --out build/docs",
131
124
  "lint": "dts lint",
132
125
  "size": "size-limit",
133
126
  "start": "dts watch",
@@ -135,6 +128,7 @@
135
128
  "unimported": "npx unimported; npx findead src",
136
129
  "version": "standard-version"
137
130
  },
138
- "typings": "build/main/index.d.ts",
139
- "version": "2.2.0"
131
+ "typings": "dist/index.d.ts",
132
+ "version": "4.0.3",
133
+ "packageManager": "yarn@3.6.4+sha256.7f7d51b38db0d94adf25c512e3f3d3b47d23c97922eecc540f7440f116bdb99a"
140
134
  }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './lib/dstore-api';
@@ -0,0 +1,435 @@
1
+ /*
2
+ * dstore-api-cloud.test.ts - Test again the real Datastore.
3
+ *
4
+ * Created by Dr. Maximilian Dornseif 2021-12-10 in huwawi3backend 11.10.0
5
+ * Copyright (c) 2021, 2023 Dr. Maximilian Dornseif
6
+ */
7
+ // @ts-nocheck
8
+ import { Datastore, Key } from '@google-cloud/datastore';
9
+ import { assert, describe, expect, test } from 'vitest';
10
+
11
+ import { Dstore } from './dstore-api';
12
+
13
+ function getDstore() {
14
+ return new Dstore(new Datastore({ namespace: 'test', projectId: 'hdmashup-hrd' }));
15
+ }
16
+
17
+ test('keySerialize', async () => {
18
+ const kvStore = getDstore();
19
+ assert.deepEqual(kvStore.key(['testYodel', 123]).path, ['testYodel', 123]);
20
+ assert.deepEqual(JSON.parse(JSON.stringify(kvStore.key(['testYodel', 123]))), {
21
+ id: 123 as any, // typing in inconclusive here
22
+ kind: 'testYodel',
23
+ namespace: 'test',
24
+ path: ['testYodel', 123],
25
+ } as any);
26
+ const ser = kvStore.keySerialize(kvStore.key(['testYodel', 123]));
27
+ expect(ser).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBh7DKIBBHRlc3Q"');
28
+ expect(JSON.parse(JSON.stringify(kvStore.keyFromSerialized(ser)))).toMatchInlineSnapshot(`
29
+ {
30
+ "id": "123",
31
+ "kind": "testYodel",
32
+ "namespace": "test",
33
+ "path": [
34
+ "testYodel",
35
+ "123",
36
+ ],
37
+ }
38
+ `);
39
+ });
40
+
41
+ describe('Allocation', () => {
42
+ test('allocateIds', async () => {
43
+ const kvStore = getDstore();
44
+ const keys = await kvStore.datastore.allocateIds(kvStore.datastore.key(['testYodel']), 2);
45
+ expect(Array.isArray(keys)).toBeTruthy();
46
+ expect(keys[0].length).toBe(2);
47
+ expect(keys[0][0].kind).toBe('testYodel');
48
+ expect(keys[0][0].id).toMatch(/\d+/);
49
+ expect(keys?.[1]?.keys?.length).toBe(2);
50
+ expect(keys[1].keys[0].partitionId.namespaceId).toMatchInlineSnapshot('"test"');
51
+ expect(keys[1].keys[0].path[0].idType).toMatchInlineSnapshot('"id"');
52
+ expect(keys[1].keys[0].path[0].kind).toMatchInlineSnapshot('"testYodel"');
53
+ });
54
+
55
+ test('allocateOneId', async () => {
56
+ const kvStore = getDstore();
57
+ const id = await kvStore.allocateOneId();
58
+ expect(id).toMatch(/\d+/);
59
+ });
60
+ });
61
+
62
+ describe('Read', () => {
63
+ test('get num_id', async () => {
64
+ const kvStore = getDstore();
65
+ const entity = { key: kvStore.key(['testYodel', 2]), data: { foo: 'bar' } };
66
+ const entity2 = {
67
+ key: kvStore.key(['testYodel', 3]),
68
+ data: { foo: 'bar' },
69
+ };
70
+ const commitResponse = await kvStore.save([entity, entity2]);
71
+ // expect(isNumber(commitResponse?.[0]?.indexUpdates)).toBeTruthy();
72
+ // expect(commitResponse).toMatchInlineSnapshot(`
73
+ // Array [
74
+ // Object {
75
+ // "indexUpdates": 0,
76
+ // "mutationResults": Array [
77
+ // Object {
78
+ // "conflictDetected": false,
79
+ // "key": null,
80
+ // "version": "1234567890123456",
81
+ // },
82
+ // ],
83
+ // },
84
+ // ]
85
+ // `);
86
+ expect(entity).toMatchInlineSnapshot(`
87
+ {
88
+ "data": {
89
+ "_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
90
+ "foo": "bar",
91
+ Symbol(KEY): Key {
92
+ "id": 2,
93
+ "kind": "testYodel",
94
+ "namespace": "test",
95
+ "path": [
96
+ "testYodel",
97
+ 2,
98
+ ],
99
+ },
100
+ },
101
+ "excludeLargeProperties": true,
102
+ "key": Key {
103
+ "id": 2,
104
+ "kind": "testYodel",
105
+ "namespace": "test",
106
+ "path": [
107
+ "testYodel",
108
+ 2,
109
+ ],
110
+ },
111
+ }
112
+ `);
113
+
114
+ const result = await kvStore.get(entity.key);
115
+ // get returns a single Entity
116
+ expect(Array.isArray(result)).toBeFalsy();
117
+ expect(result).toMatchInlineSnapshot('null');
118
+ // expect(kvStore.readKey(result)).toBeInstanceOf(Key);
119
+
120
+ const result2 = await kvStore.getMulti([entity.key]);
121
+ // getMulti returns a Array even for single keys
122
+ expect(result2).toMatchInlineSnapshot(`
123
+ [
124
+ null,
125
+ ]
126
+ `);
127
+ const result3 = await kvStore.getMulti([entity.key, kvStore.key(['testYodel', 3])]);
128
+ // getMulti returns a Array with multiple keys
129
+ // expect(Array.isArray(result)).toBeTruthy();
130
+ expect(result3).toMatchInlineSnapshot(`
131
+ [
132
+ null,
133
+ null,
134
+ ]
135
+ `);
136
+ const result4 = await kvStore.getMulti([entity.key, entity.key]);
137
+ // getMulti returns a Array but collapses duplicate keys
138
+ // expect(Array.isArray(result)).toBeTruthy();
139
+ // Firestore in Datastore returns the entity once
140
+ // Datastore Emulator returns the Entity twice
141
+ // kvStore should normalize that.
142
+ expect(result4).toMatchInlineSnapshot(`
143
+ [
144
+ null,
145
+ null,
146
+ ]
147
+ `);
148
+
149
+ const result5 = await kvStore.getMulti([entity.key, kvStore.key(['YodelNotThere', 3])]);
150
+ // getMulti returns a Array but omits unknown keys
151
+ // expect(Array.isArray(result)).toBeTruthy();
152
+ expect(result5).toMatchInlineSnapshot(`
153
+ [
154
+ null,
155
+ null,
156
+ ]
157
+ `);
158
+ const result6 = await kvStore.getMulti([]);
159
+ // getMulti returns a empty Array for an empty array
160
+ // expect(Array.isArray(result)).toBeTruthy();
161
+ expect(result6).toMatchInlineSnapshot('[]');
162
+ });
163
+ });
164
+
165
+ test('get name', async (t) => {
166
+ const kvStore = getDstore();
167
+ const entity = {
168
+ key: kvStore.key(['testYodel', 'two']),
169
+ data: { foo: 'bar' },
170
+ };
171
+ await kvStore.save([entity]);
172
+ const result = await kvStore.get(entity.key);
173
+ expect(result?._keyStr).toMatchInlineSnapshot('"agByEgsSCXRlc3RZb2RlbCIDdHdvDKIBBHRlc3Q"');
174
+ expect(result?.foo).toBe('bar');
175
+ });
176
+
177
+ describe('query', async () => {
178
+ test('raw', async () => {
179
+ const kvStore = getDstore();
180
+ const entity = {
181
+ key: kvStore.key(['testYodel', '3']),
182
+ data: { foo: 'bar', baz: 'baz' },
183
+ };
184
+
185
+ await kvStore.save([entity]);
186
+ const query = kvStore.datastore.createQuery('testYodel');
187
+ query.limit(1);
188
+ const [entities, runQueryInfo] = await kvStore.datastore.runQuery(query);
189
+ expect(entities.length).toBe(1);
190
+ expect(entities).toMatchInlineSnapshot(`
191
+ [
192
+ {
193
+ "foo": "bar",
194
+ Symbol(KEY): Key {
195
+ "id": "2",
196
+ "kind": "testYodel",
197
+ "namespace": "test",
198
+ "path": [
199
+ "testYodel",
200
+ "2",
201
+ ],
202
+ },
203
+ },
204
+ ]
205
+ `);
206
+ });
207
+
208
+ test('query', async () => {
209
+ const kvStore = getDstore();
210
+ const entity = {
211
+ key: kvStore.key(['testYodel', '3']),
212
+ data: { foo: 'bar', baz: 'baz' },
213
+ };
214
+
215
+ const saveResult = await kvStore.save([entity]);
216
+ expect(saveResult?.[0]?.mutationResults?.key).toMatchInlineSnapshot('undefined');
217
+
218
+ // expect(saveResult).toMatchInlineSnapshot(`
219
+ // [
220
+ // {
221
+ // "commitTime": null,
222
+ // "indexUpdates": 0,
223
+ // "mutationResults": [
224
+ // {
225
+ // "conflictDetected": false,
226
+ // "createTime": {
227
+ // "nanos": 706047000,
228
+ // "seconds": "1688123436",
229
+ // },
230
+ // "key": null,
231
+ // "updateTime": {
232
+ // "nanos": 706047000,
233
+ // "seconds": "1688123436",
234
+ // },
235
+ // "version": "1688123436706047",
236
+ // },
237
+ // ],
238
+ // },
239
+ // ]
240
+ // `)
241
+ expect(await kvStore.get(entity.key)).toMatchInlineSnapshot(`
242
+ {
243
+ "_keyStr": "agByEAsSCXRlc3RZb2RlbCIBMwyiAQR0ZXN0",
244
+ "baz": "baz",
245
+ "foo": "bar",
246
+ Symbol(KEY): Key {
247
+ "kind": "testYodel",
248
+ "name": "3",
249
+ "namespace": "test",
250
+ "path": [
251
+ "testYodel",
252
+ "3",
253
+ ],
254
+ },
255
+ }
256
+ `);
257
+ // Give Datastore time to become consistent
258
+ do {} while ((await kvStore.get(entity.key)) === null);
259
+
260
+ const query = kvStore.createQuery('testYodel');
261
+ query.limit(1);
262
+ const [entities, runQueryInfo] = await kvStore.runQuery(query);
263
+ // expect(entities.length).toBe(1)
264
+ expect(entities).toMatchInlineSnapshot(`
265
+ [
266
+ {
267
+ "_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
268
+ "foo": "bar",
269
+ Symbol(KEY): Key {
270
+ "id": "2",
271
+ "kind": "testYodel",
272
+ "namespace": "test",
273
+ "path": [
274
+ "testYodel",
275
+ "2",
276
+ ],
277
+ },
278
+ },
279
+ ]
280
+ `);
281
+ expect(runQueryInfo).toMatchInlineSnapshot(`
282
+ {
283
+ "endCursor": "Ci4SKGoOc35oZG1hc2h1cC1ocmRyDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3QYACAA",
284
+ "moreResults": "MORE_RESULTS_AFTER_LIMIT",
285
+ }
286
+ `);
287
+ expect(entities?.[0]?.foo).toBe('bar');
288
+ expect(entities?.[0]?.[Datastore.KEY]?.kind).toBe('testYodel');
289
+ expect(runQueryInfo?.moreResults).toBe('MORE_RESULTS_AFTER_LIMIT');
290
+
291
+ // modern interface
292
+ const [result2] = await kvStore.query('testYodel', [], 1, [], ['baz']);
293
+ expect(result2.length).toBe(1);
294
+ // foo is removed by selection
295
+ expect(JSON.parse(JSON.stringify(result2?.[0]))).toMatchInlineSnapshot(`
296
+ {
297
+ "_keyStr": "agByEAsSCXRlc3RZb2RlbCIBMwyiAQR0ZXN0",
298
+ "baz": "baz",
299
+ }
300
+ `);
301
+
302
+ const key = kvStore.readKey(result2?.[0]);
303
+ expect(key.id).toBe(entity.key.id);
304
+ });
305
+ });
306
+
307
+ test('set', async () => {
308
+ // expect.assertions(2);
309
+ const kvStore = getDstore();
310
+ const result = await kvStore.set(kvStore.key(['testYodel', '5e7']), {
311
+ foo: 'bar',
312
+ });
313
+ expect(result.name).toBe('5e7');
314
+ expect(result.kind).toBe('testYodel');
315
+
316
+ // autogenerate key
317
+ const result2 = await kvStore.set(kvStore.key(['testYodel']), { foo: 'bar' });
318
+ expect(result2.kind).toBe('testYodel');
319
+ });
320
+
321
+ test('save / upsert', async () => {
322
+ // expect.assertions(2);
323
+ const kvStore = getDstore();
324
+ const entity = {
325
+ key: kvStore.key(['testYodel', 3]),
326
+ data: { foo: 'bar' } as any,
327
+ };
328
+ const result = await kvStore.save([entity]);
329
+ // const result2 = await kvStore.upsert([entity]);
330
+ expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false);
331
+ expect(entity.data._keyStr).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBgDDKIBBHRlc3Q"');
332
+ expect(entity.data.foo).toBe('bar');
333
+ expect(entity.data[Datastore.KEY].kind).toBe('testYodel');
334
+ });
335
+
336
+ test('update', async (t) => {
337
+ // expect.assertions(3);
338
+ const kvStore = getDstore();
339
+ const keyName = `4insert${Math.random()}`;
340
+ const entity = {
341
+ key: kvStore.key(['testYodel', keyName]),
342
+ data: { foo: 'bar' },
343
+ };
344
+ // const request = kvStore.update([entity]);
345
+ // await expect(request).rejects.toThrowError(Error);
346
+
347
+ await kvStore.save([entity]);
348
+ const result = await kvStore.update([entity]);
349
+ expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false);
350
+ expect(result?.[0]?.mutationResults?.[0]?.key).toBe(null);
351
+ // expect(result?.[0]?.indexUpdates).toBe(2);
352
+ });
353
+
354
+ test('insert / delete', async (t) => {
355
+ // expect.assertions(2);
356
+ const kvStore = getDstore();
357
+ const testkey = kvStore.key(['testYodel', 4]);
358
+ await kvStore.delete([testkey]);
359
+ const entity = {
360
+ key: testkey,
361
+ data: { foo: 'bar' } as any,
362
+ };
363
+ const result = await kvStore.insert([entity]);
364
+
365
+ expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false);
366
+ expect(result?.[0]?.mutationResults?.[0]?.version).toMatch(/\d+/);
367
+ expect(entity.data.foo).toBe('bar');
368
+ expect(entity.key.path[0]).toBe('testYodel');
369
+ // expect(result?.[0]?.indexUpdates).toBe(3);
370
+
371
+ const result2 = await kvStore.delete([entity.key]);
372
+ expect(result2?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false);
373
+ });
374
+
375
+ test('exception', async () => {
376
+ // expect.assertions(2);
377
+ const kvStore = getDstore();
378
+ try {
379
+ const result = await kvStore.set(kvStore.key(['testYodel', NaN]), {
380
+ foo: 'bar',
381
+ });
382
+ } catch (e) {
383
+ expect(e.stack).toMatch(/Dstore\.set/);
384
+ }
385
+ });
386
+ // describe("Transactions", () => {
387
+ // it("simple", async () => {
388
+ // expect.assertions(2);
389
+ // const kvStore = getDstore("huwawi3Datastore");
390
+ // const outerResult = await kvStore.runInTransaction<any>(async () => {
391
+ // // write inside the transaction
392
+ // const entity = { key: kvStore.key(["testYodel", 6]), data: { foo: "foobar" } };
393
+ // const innerResult = await kvStore.save([entity]);
394
+ // // save does not return anything within transactions
395
+ // expect(innerResult).toMatchInlineSnapshot(`undefined`);
396
+ // return 123;
397
+ // });
398
+ // expect(outerResult).toMatchInlineSnapshot(`123`);
399
+
400
+ // // this fails in the Datastore Emulator
401
+ // const entitiey = await kvStore.get(kvStore.key(["testYodel", 6]));
402
+ // // expect(entitiey).toMatchInlineSnapshot(`
403
+ // // Object {
404
+ // // "foo": "foobar",
405
+ // // Symbol(KEY): Key {
406
+ // // "id": "6",
407
+ // // "kind": "testYodel",
408
+ // // "namespace": "test",
409
+ // // "path": Array [
410
+ // // "testYodel",
411
+ // // "6",
412
+ // // ],
413
+ // // },
414
+ // // }
415
+ // // `);
416
+ // });
417
+
418
+ // it("throws", async () => {
419
+ // expect.assertions(1);
420
+ // const kvStore = getDstore("huwawi3Datastore");
421
+ // const request = kvStore.runInTransaction<any>(async () => {
422
+ // throw new DstoreError("TestError", undefined);
423
+ // });
424
+ // await expect(request).rejects.toThrowError(DstoreError);
425
+ // });
426
+ // });
427
+
428
+ // describe('Exceptions', () => {
429
+ // it('simple', async () => {
430
+ // const t = () => {
431
+ // throw new DstoreError('bla', undefined);
432
+ // };
433
+ // expect(t).toThrow(DstoreError);
434
+ // });
435
+ // });