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
|
@@ -6,30 +6,43 @@
|
|
|
6
6
|
*/
|
|
7
7
|
// @ts-nocheck
|
|
8
8
|
// import { Datastore, Key } from '@google-cloud/datastore';
|
|
9
|
-
import { afterAll, assert, beforeAll, describe, expect, test } from 'vitest'
|
|
9
|
+
import { afterAll, assert, beforeAll, describe, expect, test } from 'vitest'
|
|
10
10
|
|
|
11
|
-
import { Datastore } from '../mock'
|
|
11
|
+
import { Datastore } from '../mock'
|
|
12
12
|
|
|
13
|
-
import { Dstore } from './dstore-api'
|
|
13
|
+
import { Dstore } from './dstore-api'
|
|
14
14
|
|
|
15
|
-
process.env.GCLOUD_PROJECT = 'project-id'
|
|
16
|
-
let emulator
|
|
15
|
+
process.env.GCLOUD_PROJECT = 'project-id' // Set the datastore project Id globally
|
|
16
|
+
let emulator, entity, saveResult
|
|
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
|
+
})
|
|
17
30
|
|
|
18
31
|
function getDstore() {
|
|
19
|
-
return new Dstore(new Datastore({ namespace: 'test', projectId: process.env.GCLOUD_PROJECT }))
|
|
32
|
+
return new Dstore(new Datastore({ namespace: 'test', projectId: process.env.GCLOUD_PROJECT }))
|
|
20
33
|
}
|
|
21
34
|
|
|
22
35
|
test('keySerialize', async () => {
|
|
23
|
-
const kvStore = getDstore()
|
|
24
|
-
assert.deepEqual(kvStore.key(['testYodel', 123]).path, ['testYodel', 123])
|
|
36
|
+
const kvStore = getDstore()
|
|
37
|
+
assert.deepEqual(kvStore.key(['testYodel', 123]).path, ['testYodel', 123])
|
|
25
38
|
assert.deepEqual(JSON.parse(JSON.stringify(kvStore.key(['testYodel', 123]))), {
|
|
26
39
|
id: 123 as any, // typing in inconclusive here
|
|
27
40
|
kind: 'testYodel',
|
|
28
41
|
namespace: 'test',
|
|
29
42
|
path: ['testYodel', 123],
|
|
30
|
-
} as any)
|
|
31
|
-
const ser = kvStore.keySerialize(kvStore.key(['testYodel', 123]))
|
|
32
|
-
expect(ser).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBh7DKIBBHRlc3Q"')
|
|
43
|
+
} as any)
|
|
44
|
+
const ser = kvStore.keySerialize(kvStore.key(['testYodel', 123]))
|
|
45
|
+
expect(ser).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBh7DKIBBHRlc3Q"')
|
|
33
46
|
expect(JSON.parse(JSON.stringify(kvStore.keyFromSerialized(ser)))).toMatchInlineSnapshot(`
|
|
34
47
|
{
|
|
35
48
|
"id": "123",
|
|
@@ -40,18 +53,18 @@ test('keySerialize', async () => {
|
|
|
40
53
|
"123",
|
|
41
54
|
],
|
|
42
55
|
}
|
|
43
|
-
`)
|
|
44
|
-
})
|
|
56
|
+
`)
|
|
57
|
+
})
|
|
45
58
|
test('keyFromLegacyUrlsafe', async () => {
|
|
46
|
-
const kvStore = getDstore()
|
|
47
|
-
const ser = await kvStore.datastore.keyToLegacyUrlSafe(kvStore.key(['testYodel', 123]))
|
|
59
|
+
const kvStore = getDstore()
|
|
60
|
+
const ser = await kvStore.datastore.keyToLegacyUrlSafe(kvStore.key(['testYodel', 123]))
|
|
48
61
|
expect(ser).toMatchInlineSnapshot(`
|
|
49
62
|
[
|
|
50
63
|
"agpwcm9qZWN0LWlkcg8LEgl0ZXN0WW9kZWwYewyiAQR0ZXN0",
|
|
51
64
|
]
|
|
52
|
-
`)
|
|
65
|
+
`)
|
|
53
66
|
|
|
54
|
-
const key = kvStore.datastore.keyFromLegacyUrlsafe(ser[0])
|
|
67
|
+
const key = kvStore.datastore.keyFromLegacyUrlsafe(ser[0])
|
|
55
68
|
expect(key).toMatchInlineSnapshot(`
|
|
56
69
|
Key {
|
|
57
70
|
"id": "123",
|
|
@@ -62,40 +75,40 @@ test('keyFromLegacyUrlsafe', async () => {
|
|
|
62
75
|
"123",
|
|
63
76
|
],
|
|
64
77
|
}
|
|
65
|
-
`)
|
|
66
|
-
expect(kvStore.datastore.isKey(key)).toBeTruthy()
|
|
67
|
-
})
|
|
78
|
+
`)
|
|
79
|
+
expect(kvStore.datastore.isKey(key)).toBeTruthy()
|
|
80
|
+
})
|
|
68
81
|
|
|
69
82
|
describe('Allocation', () => {
|
|
70
83
|
test('allocateIds', async () => {
|
|
71
|
-
const kvStore = getDstore()
|
|
72
|
-
const keys = await kvStore.datastore.allocateIds(kvStore.datastore.key(['testYodel']), 2)
|
|
73
|
-
expect(Array.isArray(keys)).toBeTruthy()
|
|
74
|
-
expect(keys[0].length).toBe(2)
|
|
75
|
-
expect(keys[0][0].kind).toBe('testYodel')
|
|
76
|
-
expect(keys[0][0].id).toMatch(/\d+/)
|
|
77
|
-
expect(keys?.[1]?.keys?.length).toBe(2)
|
|
78
|
-
expect(keys[1].keys[0].partitionId.namespaceId).toMatchInlineSnapshot('"test"')
|
|
79
|
-
expect(keys[1].keys[0].path[0].idType).toMatchInlineSnapshot('"id"')
|
|
80
|
-
expect(keys[1].keys[0].path[0].kind).toMatchInlineSnapshot('"testYodel"')
|
|
81
|
-
})
|
|
84
|
+
const kvStore = getDstore()
|
|
85
|
+
const keys = await kvStore.datastore.allocateIds(kvStore.datastore.key(['testYodel']), 2)
|
|
86
|
+
expect(Array.isArray(keys)).toBeTruthy()
|
|
87
|
+
expect(keys[0].length).toBe(2)
|
|
88
|
+
expect(keys[0][0].kind).toBe('testYodel')
|
|
89
|
+
expect(keys[0][0].id).toMatch(/\d+/)
|
|
90
|
+
expect(keys?.[1]?.keys?.length).toBe(2)
|
|
91
|
+
expect(keys[1].keys[0].partitionId.namespaceId).toMatchInlineSnapshot('"test"')
|
|
92
|
+
expect(keys[1].keys[0].path[0].idType).toMatchInlineSnapshot('"id"')
|
|
93
|
+
expect(keys[1].keys[0].path[0].kind).toMatchInlineSnapshot('"testYodel"')
|
|
94
|
+
})
|
|
82
95
|
|
|
83
96
|
test('allocateOneId', async () => {
|
|
84
|
-
const kvStore = getDstore()
|
|
85
|
-
const id = await kvStore.allocateOneId()
|
|
86
|
-
expect(id).toMatch(/\d+/)
|
|
87
|
-
})
|
|
88
|
-
})
|
|
97
|
+
const kvStore = getDstore()
|
|
98
|
+
const id = await kvStore.allocateOneId()
|
|
99
|
+
expect(id).toMatch(/\d+/)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
89
102
|
|
|
90
103
|
describe('Read', () => {
|
|
91
104
|
test('get num_id', async () => {
|
|
92
|
-
const kvStore = getDstore()
|
|
93
|
-
const entity = { key: kvStore.key(['testYodel', 2]), data: { foo: 'bar' } }
|
|
105
|
+
const kvStore = getDstore()
|
|
106
|
+
const entity = { key: kvStore.key(['testYodel', 2]), data: { foo: 'bar' } }
|
|
94
107
|
const entity2 = {
|
|
95
108
|
key: kvStore.key(['testYodel', 3]),
|
|
96
109
|
data: { foo: 'bar' },
|
|
97
|
-
}
|
|
98
|
-
const commitResponse = await kvStore.save([entity, entity2])
|
|
110
|
+
}
|
|
111
|
+
const commitResponse = await kvStore.save([entity, entity2])
|
|
99
112
|
// expect(isNumber(commitResponse?.[0]?.indexUpdates)).toBeTruthy();
|
|
100
113
|
// expect(commitResponse).toMatchInlineSnapshot(`
|
|
101
114
|
// Array [
|
|
@@ -137,22 +150,22 @@ describe('Read', () => {
|
|
|
137
150
|
],
|
|
138
151
|
},
|
|
139
152
|
}
|
|
140
|
-
`)
|
|
153
|
+
`)
|
|
141
154
|
|
|
142
|
-
const result = await kvStore.get(entity.key)
|
|
155
|
+
const result = await kvStore.get(entity.key)
|
|
143
156
|
// get returns a single Entity
|
|
144
|
-
expect(Array.isArray(result)).toBeFalsy()
|
|
145
|
-
expect(result).toMatchInlineSnapshot('null')
|
|
157
|
+
expect(Array.isArray(result)).toBeFalsy()
|
|
158
|
+
expect(result).toMatchInlineSnapshot('null')
|
|
146
159
|
// expect(kvStore.readKey(result)).toBeInstanceOf(Key);
|
|
147
160
|
|
|
148
|
-
const result2 = await kvStore.getMulti([entity.key])
|
|
161
|
+
const result2 = await kvStore.getMulti([entity.key])
|
|
149
162
|
// getMulti returns a Array even for single keys
|
|
150
163
|
expect(result2).toMatchInlineSnapshot(`
|
|
151
164
|
[
|
|
152
165
|
null,
|
|
153
166
|
]
|
|
154
|
-
`)
|
|
155
|
-
const result3 = await kvStore.getMulti([entity.key, kvStore.key(['testYodel', 3])])
|
|
167
|
+
`)
|
|
168
|
+
const result3 = await kvStore.getMulti([entity.key, kvStore.key(['testYodel', 3])])
|
|
156
169
|
// getMulti returns a Array with multiple keys
|
|
157
170
|
// expect(Array.isArray(result)).toBeTruthy();
|
|
158
171
|
expect(result3).toMatchInlineSnapshot(`
|
|
@@ -160,8 +173,8 @@ describe('Read', () => {
|
|
|
160
173
|
null,
|
|
161
174
|
null,
|
|
162
175
|
]
|
|
163
|
-
`)
|
|
164
|
-
const result4 = await kvStore.getMulti([entity.key, entity.key])
|
|
176
|
+
`)
|
|
177
|
+
const result4 = await kvStore.getMulti([entity.key, entity.key])
|
|
165
178
|
// getMulti returns a Array but collapses duplicate keys
|
|
166
179
|
// expect(Array.isArray(result)).toBeTruthy();
|
|
167
180
|
// Firestore in Datastore returns the entity once
|
|
@@ -172,9 +185,9 @@ describe('Read', () => {
|
|
|
172
185
|
null,
|
|
173
186
|
null,
|
|
174
187
|
]
|
|
175
|
-
`)
|
|
188
|
+
`)
|
|
176
189
|
|
|
177
|
-
const result5 = await kvStore.getMulti([entity.key, kvStore.key(['YodelNotThere', 3])])
|
|
190
|
+
const result5 = await kvStore.getMulti([entity.key, kvStore.key(['YodelNotThere', 3])])
|
|
178
191
|
// getMulti returns a Array but omits unknown keys
|
|
179
192
|
// expect(Array.isArray(result)).toBeTruthy();
|
|
180
193
|
expect(result5).toMatchInlineSnapshot(`
|
|
@@ -182,233 +195,195 @@ describe('Read', () => {
|
|
|
182
195
|
null,
|
|
183
196
|
null,
|
|
184
197
|
]
|
|
185
|
-
`)
|
|
186
|
-
const result6 = await kvStore.getMulti([])
|
|
198
|
+
`)
|
|
199
|
+
const result6 = await kvStore.getMulti([])
|
|
187
200
|
// getMulti returns a empty Array for an empty array
|
|
188
201
|
// expect(Array.isArray(result)).toBeTruthy();
|
|
189
|
-
expect(result6).toMatchInlineSnapshot('[]')
|
|
190
|
-
})
|
|
202
|
+
expect(result6).toMatchInlineSnapshot('[]')
|
|
203
|
+
})
|
|
191
204
|
|
|
192
205
|
test('get name', async (t) => {
|
|
193
|
-
const kvStore = getDstore()
|
|
206
|
+
const kvStore = getDstore()
|
|
194
207
|
const entity = {
|
|
195
208
|
key: kvStore.key(['testYodel', 'two']),
|
|
196
209
|
data: { foo: 'bar' },
|
|
197
|
-
}
|
|
198
|
-
await kvStore.save([entity])
|
|
199
|
-
const result = await kvStore.get(entity.key)
|
|
200
|
-
expect(result?._keyStr).toMatchInlineSnapshot('"agByEgsSCXRlc3RZb2RlbCIDdHdvDKIBBHRlc3Q"')
|
|
201
|
-
expect(result?.foo).toBe('bar')
|
|
202
|
-
})
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
key: kvStore.key(['testYodel', '3']),
|
|
209
|
-
data: { foo: 'bar', baz: 'baz' },
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
await kvStore.save([entity]);
|
|
213
|
-
const query = kvStore.datastore.createQuery('testYodel');
|
|
214
|
-
query.limit(1);
|
|
215
|
-
const [entities, runQueryInfo] = await kvStore.datastore.runQuery(query);
|
|
216
|
-
expect(entities.length).toBe(1);
|
|
217
|
-
expect(entities).toMatchInlineSnapshot(`
|
|
218
|
-
[
|
|
219
|
-
{
|
|
220
|
-
"foo": "bar",
|
|
221
|
-
Symbol(KEY): Key {
|
|
222
|
-
"id": "2",
|
|
223
|
-
"kind": "testYodel",
|
|
224
|
-
"namespace": "test",
|
|
225
|
-
"path": [
|
|
226
|
-
"testYodel",
|
|
227
|
-
"2",
|
|
228
|
-
],
|
|
229
|
-
},
|
|
230
|
-
},
|
|
231
|
-
]
|
|
232
|
-
`);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
test('query', async () => {
|
|
236
|
-
const kvStore = getDstore();
|
|
237
|
-
const entity = {
|
|
238
|
-
key: kvStore.key(['testYodel', '3']),
|
|
239
|
-
data: { foo: 'bar', baz: 'baz' },
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const saveResult = await kvStore.save([entity]);
|
|
210
|
+
}
|
|
211
|
+
await kvStore.save([entity])
|
|
212
|
+
const result = await kvStore.get(entity.key)
|
|
213
|
+
expect(result?._keyStr).toMatchInlineSnapshot('"agByEgsSCXRlc3RZb2RlbCIDdHdvDKIBBHRlc3Q"')
|
|
214
|
+
expect(result?.foo).toBe('bar')
|
|
215
|
+
})
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
describe('queryies', async () => {
|
|
219
|
+
test('sanity check', async () => {
|
|
220
|
+
const kvStore = getDstore()
|
|
243
221
|
expect(saveResult).toMatchInlineSnapshot(`
|
|
244
|
-
|
|
245
|
-
{
|
|
246
|
-
"indexUpdates": 1,
|
|
247
|
-
"mutationResults": [
|
|
248
|
-
{
|
|
249
|
-
"conflictDetected": false,
|
|
250
|
-
"createTime": {
|
|
251
|
-
"nanos": 1,
|
|
252
|
-
"seconds": 2,
|
|
253
|
-
},
|
|
254
|
-
"key": null,
|
|
255
|
-
"updateTime": {
|
|
256
|
-
"nanos": 3,
|
|
257
|
-
"seconds": 4,
|
|
258
|
-
},
|
|
259
|
-
"version": 1,
|
|
260
|
-
},
|
|
261
|
-
],
|
|
262
|
-
},
|
|
263
|
-
]
|
|
264
|
-
`);
|
|
265
|
-
expect(await kvStore.get(entity.key)).toMatchInlineSnapshot(`
|
|
222
|
+
[
|
|
266
223
|
{
|
|
267
|
-
"
|
|
268
|
-
"
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
"
|
|
276
|
-
"
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
224
|
+
"indexUpdates": 1,
|
|
225
|
+
"mutationResults": [
|
|
226
|
+
{
|
|
227
|
+
"conflictDetected": false,
|
|
228
|
+
"createTime": {
|
|
229
|
+
"nanos": 1,
|
|
230
|
+
"seconds": 2,
|
|
231
|
+
},
|
|
232
|
+
"key": null,
|
|
233
|
+
"updateTime": {
|
|
234
|
+
"nanos": 3,
|
|
235
|
+
"seconds": 4,
|
|
236
|
+
},
|
|
237
|
+
"version": 1,
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
},
|
|
241
|
+
]
|
|
242
|
+
`)
|
|
281
243
|
|
|
282
|
-
|
|
283
|
-
|
|
244
|
+
expect(await kvStore.get(entity.key)).toMatchInlineSnapshot(`null`)
|
|
245
|
+
})
|
|
284
246
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const
|
|
247
|
+
test('raw', async () => {
|
|
248
|
+
const kvStore = getDstore()
|
|
249
|
+
const query = kvStore.datastore.createQuery('testYodel')
|
|
250
|
+
query.limit(1)
|
|
251
|
+
const [entities, runQueryInfo] = await kvStore.datastore.runQuery(query)
|
|
288
252
|
// expect(entities.length).toBe(1)
|
|
289
|
-
expect(entities).toMatchInlineSnapshot(`
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
"path": [
|
|
300
|
-
"testYodel",
|
|
301
|
-
"3",
|
|
302
|
-
],
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
|
-
]
|
|
306
|
-
`);
|
|
253
|
+
expect(entities).toMatchInlineSnapshot(`[]`)
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
test('runQuery', async () => {
|
|
257
|
+
const kvStore = getDstore()
|
|
258
|
+
const query = kvStore.createQuery('testYodel')
|
|
259
|
+
query.limit(1)
|
|
260
|
+
const [entities, runQueryInfo] = await kvStore.runQuery(query)
|
|
261
|
+
// expect(entities.length).toBe(1)
|
|
262
|
+
expect(entities).toMatchInlineSnapshot(`[]`)
|
|
307
263
|
expect(runQueryInfo).toMatchInlineSnapshot(`
|
|
308
264
|
{
|
|
309
265
|
"moreResults": "MORE_RESULTS_AFTER_LIMIT",
|
|
310
266
|
}
|
|
311
|
-
`)
|
|
312
|
-
expect(entities?.[0]?.foo).toBe('bar')
|
|
313
|
-
expect(entities?.[0]?.[Datastore.KEY]?.kind).toBe('testYodel')
|
|
314
|
-
expect(runQueryInfo?.moreResults).toBe('MORE_RESULTS_AFTER_LIMIT')
|
|
267
|
+
`)
|
|
268
|
+
// expect(entities?.[0]?.foo).toBe('bar')
|
|
269
|
+
// expect(entities?.[0]?.[Datastore.KEY]?.kind).toBe('testYodel')
|
|
270
|
+
expect(runQueryInfo?.moreResults).toBe('MORE_RESULTS_AFTER_LIMIT')
|
|
271
|
+
})
|
|
315
272
|
|
|
273
|
+
test('query', async () => {
|
|
316
274
|
// modern interface
|
|
317
|
-
const
|
|
318
|
-
|
|
275
|
+
const kvStore = getDstore()
|
|
276
|
+
const [result1] = await kvStore.query('testYodel')
|
|
277
|
+
expect(result1?.[0]).toMatchInlineSnapshot(`undefined`)
|
|
278
|
+
const [result2] = await kvStore.query('testYodel', [])
|
|
279
|
+
expect(result2?.[0]).toMatchInlineSnapshot(`undefined`)
|
|
280
|
+
const [result3] = await kvStore.query('testYodel', [], 1)
|
|
281
|
+
expect(result3?.[0]).toMatchInlineSnapshot(`undefined`)
|
|
282
|
+
const [result4] = await kvStore.query('testYodel', [], 1, [])
|
|
283
|
+
expect(result4?.[0]).toMatchInlineSnapshot(`undefined`)
|
|
284
|
+
// expect(result2.length).toBe(1)
|
|
319
285
|
// foo is removed by selection
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
286
|
+
const [result5] = await kvStore.query('testYodel', [], 1, [], ['baz'])
|
|
287
|
+
expect(result5?.[0]).toMatchInlineSnapshot(`undefined`)
|
|
288
|
+
|
|
289
|
+
// const key = kvStore.readKey(result2?.[0])
|
|
290
|
+
// expect(key.id).toBe(entity.key.id)
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
test.skip('iterate', async () => {
|
|
294
|
+
const kvStore = getDstore()
|
|
295
|
+
const result = await kvStore.iterate({ kindName: 'testYodel', limit: 1 })
|
|
296
|
+
for await (const entity of result) {
|
|
297
|
+
expect(entity).toMatchInlineSnapshot()
|
|
298
|
+
}
|
|
299
|
+
})
|
|
327
300
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
301
|
+
test.skip('list', async () => {
|
|
302
|
+
const kvStore = getDstore()
|
|
303
|
+
const result = await kvStore.list({ kindName: 'testYodel', limit: 1 })
|
|
304
|
+
expect(result).toMatchInlineSnapshot()
|
|
305
|
+
})
|
|
306
|
+
})
|
|
332
307
|
|
|
333
308
|
test('set', async () => {
|
|
334
309
|
// expect.assertions(2);
|
|
335
|
-
const kvStore = getDstore()
|
|
310
|
+
const kvStore = getDstore()
|
|
336
311
|
const result = await kvStore.set(kvStore.key(['testYodel', '5e7']), {
|
|
337
312
|
foo: 'bar',
|
|
338
|
-
})
|
|
339
|
-
expect(result.name).toBe('5e7')
|
|
340
|
-
expect(result.kind).toBe('testYodel')
|
|
313
|
+
})
|
|
314
|
+
expect(result.name).toBe('5e7')
|
|
315
|
+
expect(result.kind).toBe('testYodel')
|
|
341
316
|
|
|
342
317
|
// autogenerate key
|
|
343
|
-
const result2 = await kvStore.set(kvStore.key(['testYodel']), { foo: 'bar' })
|
|
344
|
-
expect(result2.kind).toBe('testYodel')
|
|
345
|
-
})
|
|
318
|
+
const result2 = await kvStore.set(kvStore.key(['testYodel']), { foo: 'bar' })
|
|
319
|
+
expect(result2.kind).toBe('testYodel')
|
|
320
|
+
})
|
|
346
321
|
|
|
347
322
|
test('save / upsert', async () => {
|
|
348
323
|
// expect.assertions(2);
|
|
349
|
-
const kvStore = getDstore()
|
|
324
|
+
const kvStore = getDstore()
|
|
350
325
|
const entity = {
|
|
351
326
|
key: kvStore.key(['testYodel', 3]),
|
|
352
327
|
data: { foo: 'bar' } as any,
|
|
353
|
-
}
|
|
354
|
-
const result = await kvStore.save([entity])
|
|
328
|
+
}
|
|
329
|
+
const result = await kvStore.save([entity])
|
|
355
330
|
// const result2 = await kvStore.upsert([entity]);
|
|
356
|
-
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
357
|
-
expect(entity.data._keyStr).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBgDDKIBBHRlc3Q"')
|
|
358
|
-
expect(entity.data.foo).toBe('bar')
|
|
359
|
-
expect(entity.data[Datastore.KEY].kind).toBe('testYodel')
|
|
360
|
-
})
|
|
331
|
+
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
332
|
+
expect(entity.data._keyStr).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBgDDKIBBHRlc3Q"')
|
|
333
|
+
expect(entity.data.foo).toBe('bar')
|
|
334
|
+
expect(entity.data[Datastore.KEY].kind).toBe('testYodel')
|
|
335
|
+
})
|
|
361
336
|
|
|
362
337
|
test('update', async (t) => {
|
|
363
338
|
// expect.assertions(3);
|
|
364
|
-
const kvStore = getDstore()
|
|
365
|
-
const keyName = `4insert${Math.random()}
|
|
339
|
+
const kvStore = getDstore()
|
|
340
|
+
const keyName = `4insert${Math.random()}`
|
|
366
341
|
const entity = {
|
|
367
342
|
key: kvStore.key(['testYodel', keyName]),
|
|
368
343
|
data: { foo: 'bar' },
|
|
369
|
-
}
|
|
344
|
+
}
|
|
370
345
|
// const request = kvStore.update([entity]);
|
|
371
346
|
// await expect(request).rejects.toThrowError(Error);
|
|
372
347
|
|
|
373
|
-
await kvStore.save([entity])
|
|
374
|
-
const result = await kvStore.update([entity])
|
|
375
|
-
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
376
|
-
expect(result?.[0]?.mutationResults?.[0]?.key).toBe(null)
|
|
348
|
+
await kvStore.save([entity])
|
|
349
|
+
const result = await kvStore.update([entity])
|
|
350
|
+
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
351
|
+
expect(result?.[0]?.mutationResults?.[0]?.key).toBe(null)
|
|
377
352
|
// expect(result?.[0]?.indexUpdates).toBe(2);
|
|
378
|
-
})
|
|
353
|
+
})
|
|
379
354
|
|
|
380
355
|
test('insert / delete', async (t) => {
|
|
381
356
|
// expect.assertions(2);
|
|
382
|
-
const kvStore = getDstore()
|
|
383
|
-
const testkey = kvStore.key(['testYodel', 4])
|
|
384
|
-
await kvStore.delete([testkey])
|
|
357
|
+
const kvStore = getDstore()
|
|
358
|
+
const testkey = kvStore.key(['testYodel', 4])
|
|
359
|
+
await kvStore.delete([testkey])
|
|
385
360
|
const entity = {
|
|
386
361
|
key: testkey,
|
|
387
362
|
data: { foo: 'bar' } as any,
|
|
388
|
-
}
|
|
389
|
-
const result = await kvStore.insert([entity])
|
|
363
|
+
}
|
|
364
|
+
const result = await kvStore.insert([entity])
|
|
390
365
|
|
|
391
|
-
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
392
|
-
expect(result?.[0]?.mutationResults?.[0]?.version).toMatch(/\d+/)
|
|
393
|
-
expect(entity.data.foo).toBe('bar')
|
|
394
|
-
expect(entity.key.path[0]).toBe('testYodel')
|
|
366
|
+
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
367
|
+
expect(result?.[0]?.mutationResults?.[0]?.version).toMatch(/\d+/)
|
|
368
|
+
expect(entity.data.foo).toBe('bar')
|
|
369
|
+
expect(entity.key.path[0]).toBe('testYodel')
|
|
395
370
|
// expect(result?.[0]?.indexUpdates).toBe(3);
|
|
396
371
|
|
|
397
|
-
const result2 = await kvStore.delete([entity.key])
|
|
398
|
-
expect(result2?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
399
|
-
})
|
|
372
|
+
const result2 = await kvStore.delete([entity.key])
|
|
373
|
+
expect(result2?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
374
|
+
})
|
|
400
375
|
|
|
401
376
|
test('exception', async () => {
|
|
402
377
|
// expect.assertions(2);
|
|
403
|
-
const kvStore = getDstore()
|
|
378
|
+
const kvStore = getDstore()
|
|
404
379
|
try {
|
|
405
380
|
const result = await kvStore.set(kvStore.key(['testYodel', NaN]), {
|
|
406
381
|
foo: 'bar',
|
|
407
|
-
})
|
|
382
|
+
})
|
|
408
383
|
} catch (e) {
|
|
409
|
-
expect(e.stack).toMatch(/Dstore\.set/)
|
|
384
|
+
expect(e.stack).toMatch(/Dstore\.set/)
|
|
410
385
|
}
|
|
411
|
-
})
|
|
386
|
+
})
|
|
412
387
|
// describe("Transactions", () => {
|
|
413
388
|
// it("simple", async () => {
|
|
414
389
|
// expect.assertions(2);
|
package/src/lib/dstore-api.ts
CHANGED
|
@@ -149,6 +149,7 @@ type IDstore = {
|
|
|
149
149
|
cursor?: string
|
|
150
150
|
) => Promise<RunQueryResponse>
|
|
151
151
|
iterate: <T = IDstoreEntryWithKey>(options: IIterateParams) => AsyncIterable<T>
|
|
152
|
+
list: <T = IDstoreEntryWithKey>(options: IIterateParams) => Promise<Array<T>>
|
|
152
153
|
allocateOneId: (kindName: string) => Promise<string>
|
|
153
154
|
runInTransaction: <T>(func: { (): Promise<T>; (): T }) => Promise<T>
|
|
154
155
|
}
|
|
@@ -248,7 +249,7 @@ export class Dstore implements IDstore {
|
|
|
248
249
|
* @category Additional
|
|
249
250
|
*/
|
|
250
251
|
readKey(ent: IDstoreEntry): Key {
|
|
251
|
-
assertIsObject(ent)
|
|
252
|
+
assertIsObject(ent, 'entity', 'readKey() wants to be provided an entity object')
|
|
252
253
|
let ret = ent[Datastore.KEY]
|
|
253
254
|
if (ent._keyStr && !ret) {
|
|
254
255
|
ret = this.keyFromSerialized(ent._keyStr)
|
|
@@ -715,6 +716,33 @@ export class Dstore implements IDstore {
|
|
|
715
716
|
}
|
|
716
717
|
}
|
|
717
718
|
|
|
719
|
+
/** `list()` is a non iteratingversion of `iterate()`.
|
|
720
|
+
*
|
|
721
|
+
* @param kindName Name of the [[Datastore]][Kind](https://cloud.google.com/datastore/docs/concepts/entities#kinds_and_identifiers) ("Table") which should be searched.
|
|
722
|
+
* @param filters List of [[Query]] filter() calls.
|
|
723
|
+
* @param limit Maximum Number of Results to return.
|
|
724
|
+
* @param ordering List of [[Query]] order() calls.
|
|
725
|
+
* @param selection selectionList of [[Query]] select() calls.
|
|
726
|
+
*
|
|
727
|
+
* @throws [[DstoreError]]
|
|
728
|
+
* @category Additional
|
|
729
|
+
*/
|
|
730
|
+
async list<T = IDstoreEntryWithKey>({
|
|
731
|
+
kindName,
|
|
732
|
+
filters = [],
|
|
733
|
+
limit = 0,
|
|
734
|
+
ordering = [],
|
|
735
|
+
selection = [],
|
|
736
|
+
}: IIterateParams): Array<T> {
|
|
737
|
+
const iterator = this.iterate<T>({ kindName, filters, limit, ordering, selection })
|
|
738
|
+
const entities: T[] = []
|
|
739
|
+
for await (const entity of iterator) {
|
|
740
|
+
entities.push(entity as T)
|
|
741
|
+
}
|
|
742
|
+
return entities
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
|
|
718
746
|
/** Allocate one ID in the Datastore.
|
|
719
747
|
*
|
|
720
748
|
* Currently (late 2021) there is no documentation provided by Google for the underlying node function.
|