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 +1 -1
- package/package.json +1 -15
- package/src/lib/dstore-api-cloud.spec.ts +147 -68
- package/src/lib/dstore-api-emulator.spec.ts +324 -173
- package/src/lib/dstore-api-simulator.spec.ts +192 -217
- package/src/lib/dstore-api.ts +29 -1
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 (
|
|
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.
|
|
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
|
-
|
|
214
|
+
describe('queryies', async () => {
|
|
166
215
|
const kvStore = getDstore()
|
|
167
216
|
const entity = {
|
|
168
|
-
key: kvStore.key(['testYodel', '
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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('
|
|
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 () => {
|