datastore-api 6.3.0 → 6.4.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 CHANGED
@@ -23,7 +23,7 @@ Main differences:
23
23
  - [allocateOneId](http://mdornseif.io/datastore-api/classes/Dstore.html#allocateOneId) returns a single numeric string encoded unique datastore id without the need of fancy unpacking.
24
24
  - [runInTransaction](http://mdornseif.io/datastore-api/classes/Dstore.html#runInTransaction) allows you to provide a function to be executed inside an transaction without the need of passing around the transaction object. This is modelled after Python 2.7 [ndb's `@ndb.transactional` feature](https://cloud.google.com/appengine/docs/standard/python/ndb/transactions). This is implemented via node's [AsyncLocalStorage](https://nodejs.org/docs/latest-v14.x/api/async_hooks.html).
25
25
  - [keySerialize](http://mdornseif.io/datastore-api/classes/Dstore.html#keySerialize) is synchronous. 🦄
26
- - [iterate] allows for async iteration of (larege) queries.
26
+ - [iterate] allows for async iteration of (large) queries. [list] has the same API but generates an array.
27
27
  - Starting your code with the environment variable `DEBUG='ds:api'` allows you to trace API calls.
28
28
 
29
29
  Find the full documentation [here](https://mdornseif.github.io/datastore-api/classes/Dstore.html). In there also some of the idiosyncrasies of using the Datastore are explained.
package/package.json CHANGED
@@ -54,7 +54,6 @@
54
54
  "nyc": "^15.1.0",
55
55
  "open-cli": "8.0.0",
56
56
  "prettier": "^3.2.5",
57
- "sort-package-json": "^2.8.0",
58
57
  "standard-version": "^9.5.0",
59
58
  "ts-essentials": "9.4.1",
60
59
  "ts-node": "^10.9.2",
@@ -71,24 +70,11 @@
71
70
  "src"
72
71
  ],
73
72
  "homepage": "https://forge.23.nu/md/datastore-api",
74
- "husky": {
75
- "hooks": {
76
- "pre-commit": "lint-staged"
77
- }
78
- },
79
73
  "keywords": [
80
74
  "datastore",
81
75
  "google cloud"
82
76
  ],
83
77
  "license": "MIT",
84
- "lint-staged": {
85
- "*{css,scss,md,markdown,json,yaml,yml,graphql,html}": "npx prettier -w",
86
- "*{js,jsx,ts,tsx}": [
87
- "npx prettier -w",
88
- "npm run lint --fix"
89
- ],
90
- "package.json": "sort-package-json"
91
- },
92
78
  "main": "dist/index.js",
93
79
  "module": "dist/datastore-api2.esm.js",
94
80
  "name": "datastore-api",
@@ -122,5 +108,5 @@
122
108
  "update": "npx npm-check-updates --interactive"
123
109
  },
124
110
  "typings": "dist/index.d.ts",
125
- "version": "6.3.0"
111
+ "version": "6.4.0"
126
112
  }
@@ -6,14 +6,28 @@
6
6
  */
7
7
  // @ts-nocheck
8
8
  import { Datastore, Key } from '@google-cloud/datastore'
9
- import { assert, describe, expect, test } from 'vitest'
9
+ import { beforeAll, assert, describe, expect, test } from 'vitest'
10
10
 
11
11
  import { Dstore } from './dstore-api'
12
+ let entity, saveResult
12
13
 
13
14
  function getDstore() {
14
15
  return new Dstore(new Datastore({ namespace: 'test', projectId: 'hdmashup-hrd' }))
15
16
  }
16
17
 
18
+ beforeAll(async () => {
19
+ // Data for the query tests
20
+ const kvStore = getDstore()
21
+ entity = {
22
+ key: kvStore.key(['testYodel', '3']),
23
+ data: { foo: 'bar', baz: 'baz' },
24
+ }
25
+
26
+ saveResult = await kvStore.save([entity])
27
+ // Give Datastore time to become consistent
28
+ do { } while ((await kvStore.get(entity.key)) === null)
29
+ })
30
+
17
31
  test('keySerialize', async () => {
18
32
  const kvStore = getDstore()
19
33
  assert.deepEqual(kvStore.key(['testYodel', 123]).path, ['testYodel', 123])
@@ -37,6 +51,29 @@ test('keySerialize', async () => {
37
51
  }
38
52
  `)
39
53
  })
54
+ test('keyFromLegacyUrlsafe', async () => {
55
+ const kvStore = getDstore()
56
+ const ser = await kvStore.datastore.keyToLegacyUrlSafe(kvStore.key(['testYodel', 123]))
57
+ expect(ser).toMatchInlineSnapshot(`
58
+ [
59
+ "agxoZG1hc2h1cC1ocmRyDwsSCXRlc3RZb2RlbBh7DKIBBHRlc3Q",
60
+ ]
61
+ `)
62
+
63
+ const key = kvStore.datastore.keyFromLegacyUrlsafe(ser[0])
64
+ expect(key).toMatchInlineSnapshot(`
65
+ Key {
66
+ "id": "123",
67
+ "kind": "testYodel",
68
+ "namespace": "test",
69
+ "path": [
70
+ "testYodel",
71
+ "123",
72
+ ],
73
+ }
74
+ `)
75
+ expect(kvStore.datastore.isKey(key)).toBeTruthy()
76
+ })
40
77
 
41
78
  describe('Allocation', () => {
42
79
  test('allocateIds', async () => {
@@ -160,29 +197,77 @@ describe('Read', () => {
160
197
  // expect(Array.isArray(result)).toBeTruthy();
161
198
  expect(result6).toMatchInlineSnapshot('[]')
162
199
  })
200
+
201
+ test('get name', async (t) => {
202
+ const kvStore = getDstore()
203
+ const entity = {
204
+ key: kvStore.key(['testYodel', 'two']),
205
+ data: { foo: 'bar' },
206
+ }
207
+ await kvStore.save([entity])
208
+ const result = await kvStore.get(entity.key)
209
+ expect(result?._keyStr).toMatchInlineSnapshot('"agByEgsSCXRlc3RZb2RlbCIDdHdvDKIBBHRlc3Q"')
210
+ expect(result?.foo).toBe('bar')
211
+ })
163
212
  })
164
213
 
165
- test('get name', async (t) => {
214
+ describe('queryies', async () => {
166
215
  const kvStore = getDstore()
167
216
  const entity = {
168
- key: kvStore.key(['testYodel', 'two']),
169
- data: { foo: 'bar' },
217
+ key: kvStore.key(['testYodel', '3']),
218
+ data: { foo: 'bar', baz: 'baz' },
170
219
  }
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
220
 
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' },
221
+ const saveResult = await kvStore.save([entity])
222
+ // Give Datastore time to become consistent
223
+ do { } while ((await kvStore.get(entity.key)) === null)
224
+
225
+ test('sanity check', async () => {
226
+ expect(saveResult).toMatchInlineSnapshot(`
227
+ [
228
+ {
229
+ "commitTime": null,
230
+ "indexUpdates": 0,
231
+ "mutationResults": [
232
+ {
233
+ "conflictDetected": false,
234
+ "createTime": {
235
+ "nanos": 706047000,
236
+ "seconds": "1688123436",
237
+ },
238
+ "key": null,
239
+ "updateTime": {
240
+ "nanos": 706047000,
241
+ "seconds": "1688123436",
242
+ },
243
+ "version": "1688123436706047",
244
+ },
245
+ ],
246
+ },
247
+ ]
248
+ `)
249
+
250
+ expect(await kvStore.get(entity.key)).toMatchInlineSnapshot(`
251
+ {
252
+ "_keyStr": "agByEAsSCXRlc3RZb2RlbCIBMwyiAQR0ZXN0",
253
+ "baz": "baz",
254
+ "foo": "bar",
255
+ Symbol(KEY): Key {
256
+ "kind": "testYodel",
257
+ "name": "3",
258
+ "namespace": "test",
259
+ "path": [
260
+ "testYodel",
261
+ "3",
262
+ ],
263
+ },
183
264
  }
265
+ `)
266
+ })
184
267
 
185
- await kvStore.save([entity])
268
+
269
+ test('raw', async () => {
270
+ const kvStore = getDstore()
186
271
  const query = kvStore.datastore.createQuery('testYodel')
187
272
  query.limit(1)
188
273
  const [entities, runQueryInfo] = await kvStore.datastore.runQuery(query)
@@ -205,58 +290,7 @@ describe('query', async () => {
205
290
  `)
206
291
  })
207
292
 
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
-
293
+ test('runQuery', async () => {
260
294
  const query = kvStore.createQuery('testYodel')
261
295
  query.limit(1)
262
296
  const [entities, runQueryInfo] = await kvStore.runQuery(query)
@@ -287,7 +321,9 @@ describe('query', async () => {
287
321
  expect(entities?.[0]?.foo).toBe('bar')
288
322
  expect(entities?.[0]?.[Datastore.KEY]?.kind).toBe('testYodel')
289
323
  expect(runQueryInfo?.moreResults).toBe('MORE_RESULTS_AFTER_LIMIT')
324
+ })
290
325
 
326
+ test('query', async () => {
291
327
  // modern interface
292
328
  const [result2] = await kvStore.query('testYodel', [], 1, [], ['baz'])
293
329
  expect(result2.length).toBe(1)
@@ -302,6 +338,49 @@ describe('query', async () => {
302
338
  const key = kvStore.readKey(result2?.[0])
303
339
  expect(key.id).toBe(entity.key.id)
304
340
  })
341
+
342
+ test('iterate', async () => {
343
+ const result = await kvStore.iterate({ kindName: 'testYodel', limit: 1 })
344
+ for await (const entity of result) {
345
+ expect(entity).toMatchInlineSnapshot(`
346
+ {
347
+ "_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
348
+ "foo": "bar",
349
+ Symbol(KEY): Key {
350
+ "id": "2",
351
+ "kind": "testYodel",
352
+ "namespace": "test",
353
+ "path": [
354
+ "testYodel",
355
+ "2",
356
+ ],
357
+ },
358
+ }
359
+ `)
360
+ }
361
+ })
362
+
363
+ test('list', async () => {
364
+ const kvStore = getDstore()
365
+ const result = await kvStore.list({ kindName: 'testYodel', limit: 1 })
366
+ expect(result).toMatchInlineSnapshot(`
367
+ [
368
+ {
369
+ "_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
370
+ "foo": "bar",
371
+ Symbol(KEY): Key {
372
+ "id": "2",
373
+ "kind": "testYodel",
374
+ "namespace": "test",
375
+ "path": [
376
+ "testYodel",
377
+ "2",
378
+ ],
379
+ },
380
+ },
381
+ ]
382
+ `)
383
+ })
305
384
  })
306
385
 
307
386
  test('set', async () => {