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
|
@@ -5,39 +5,50 @@
|
|
|
5
5
|
* Copyright (c) 2021, 2023 Dr. Maximilian Dornseif
|
|
6
6
|
*/
|
|
7
7
|
// @ts-nocheck
|
|
8
|
-
import { Datastore, Key } from '@google-cloud/datastore'
|
|
9
|
-
import Emulator from 'google-datastore-emulator'
|
|
10
|
-
import { afterAll, assert, beforeAll, describe, expect, test } from 'vitest'
|
|
8
|
+
import { Datastore, Key } from '@google-cloud/datastore'
|
|
9
|
+
import Emulator from 'google-datastore-emulator'
|
|
10
|
+
import { afterAll, assert, beforeAll, describe, expect, test } from 'vitest'
|
|
11
11
|
|
|
12
|
-
import { Dstore } from './dstore-api'
|
|
12
|
+
import { Dstore } from './dstore-api'
|
|
13
13
|
|
|
14
|
-
process.env.GCLOUD_PROJECT = 'project-id'
|
|
15
|
-
let emulator
|
|
14
|
+
process.env.GCLOUD_PROJECT = 'project-id' // Set the datastore project Id globally
|
|
15
|
+
let emulator, entity, saveResult
|
|
16
16
|
|
|
17
17
|
beforeAll(async () => {
|
|
18
|
-
emulator = new Emulator({ debug: false })
|
|
19
|
-
await emulator.start()
|
|
20
|
-
|
|
18
|
+
emulator = new Emulator({ debug: false })
|
|
19
|
+
await emulator.start()
|
|
20
|
+
|
|
21
|
+
// Data for the query tests
|
|
22
|
+
const kvStore = getDstore()
|
|
23
|
+
entity = {
|
|
24
|
+
key: kvStore.key(['testYodel', '3']),
|
|
25
|
+
data: { foo: 'bar', baz: 'baz' },
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
saveResult = await kvStore.save([entity])
|
|
29
|
+
// Give Datastore time to become consistent
|
|
30
|
+
do { } while ((await kvStore.get(entity.key)) === null)
|
|
31
|
+
})
|
|
21
32
|
|
|
22
33
|
afterAll(async () => {
|
|
23
|
-
await emulator.stop()
|
|
24
|
-
})
|
|
34
|
+
await emulator.stop()
|
|
35
|
+
})
|
|
25
36
|
|
|
26
37
|
function getDstore() {
|
|
27
|
-
return new Dstore(new Datastore({ namespace: 'test', projectId: process.env.GCLOUD_PROJECT }))
|
|
38
|
+
return new Dstore(new Datastore({ namespace: 'test', projectId: process.env.GCLOUD_PROJECT }))
|
|
28
39
|
}
|
|
29
40
|
|
|
30
41
|
test('keySerialize', async () => {
|
|
31
|
-
const kvStore = getDstore()
|
|
32
|
-
assert.deepEqual(kvStore.key(['testYodel', 123]).path, ['testYodel', 123])
|
|
42
|
+
const kvStore = getDstore()
|
|
43
|
+
assert.deepEqual(kvStore.key(['testYodel', 123]).path, ['testYodel', 123])
|
|
33
44
|
assert.deepEqual(JSON.parse(JSON.stringify(kvStore.key(['testYodel', 123]))), {
|
|
34
45
|
id: 123 as any, // typing in inconclusive here
|
|
35
46
|
kind: 'testYodel',
|
|
36
47
|
namespace: 'test',
|
|
37
48
|
path: ['testYodel', 123],
|
|
38
|
-
} as any)
|
|
39
|
-
const ser = kvStore.keySerialize(kvStore.key(['testYodel', 123]))
|
|
40
|
-
expect(ser).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBh7DKIBBHRlc3Q"')
|
|
49
|
+
} as any)
|
|
50
|
+
const ser = kvStore.keySerialize(kvStore.key(['testYodel', 123]))
|
|
51
|
+
expect(ser).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBh7DKIBBHRlc3Q"')
|
|
41
52
|
expect(JSON.parse(JSON.stringify(kvStore.keyFromSerialized(ser)))).toMatchInlineSnapshot(`
|
|
42
53
|
{
|
|
43
54
|
"id": "123",
|
|
@@ -48,39 +59,62 @@ test('keySerialize', async () => {
|
|
|
48
59
|
"123",
|
|
49
60
|
],
|
|
50
61
|
}
|
|
51
|
-
`)
|
|
52
|
-
})
|
|
62
|
+
`)
|
|
63
|
+
})
|
|
64
|
+
test('keyFromLegacyUrlsafe', async () => {
|
|
65
|
+
const kvStore = getDstore()
|
|
66
|
+
const ser = await kvStore.datastore.keyToLegacyUrlSafe(kvStore.key(['testYodel', 123]))
|
|
67
|
+
expect(ser).toMatchInlineSnapshot(`
|
|
68
|
+
[
|
|
69
|
+
"agpwcm9qZWN0LWlkcg8LEgl0ZXN0WW9kZWwYewyiAQR0ZXN0",
|
|
70
|
+
]
|
|
71
|
+
`)
|
|
72
|
+
|
|
73
|
+
const key = kvStore.datastore.keyFromLegacyUrlsafe(ser[0])
|
|
74
|
+
expect(key).toMatchInlineSnapshot(`
|
|
75
|
+
Key {
|
|
76
|
+
"id": "123",
|
|
77
|
+
"kind": "testYodel",
|
|
78
|
+
"namespace": "test",
|
|
79
|
+
"path": [
|
|
80
|
+
"testYodel",
|
|
81
|
+
"123",
|
|
82
|
+
],
|
|
83
|
+
}
|
|
84
|
+
`)
|
|
85
|
+
expect(kvStore.datastore.isKey(key)).toBeTruthy()
|
|
86
|
+
})
|
|
53
87
|
|
|
54
88
|
describe('Allocation', () => {
|
|
55
89
|
test('allocateIds', async () => {
|
|
56
|
-
const kvStore = getDstore()
|
|
57
|
-
const keys = await kvStore.datastore.allocateIds(kvStore.datastore.key(['testYodel']), 2)
|
|
58
|
-
expect(Array.isArray(keys)).toBeTruthy()
|
|
59
|
-
expect(keys[0].length).toBe(2)
|
|
60
|
-
expect(keys[0][0].kind).toBe('testYodel')
|
|
61
|
-
expect(keys[0][0].id).toMatch(/\d+/)
|
|
62
|
-
expect(keys?.[1]?.keys?.length).toBe(2)
|
|
63
|
-
expect(keys[1].keys[0].partitionId.namespaceId).toMatchInlineSnapshot('"test"')
|
|
64
|
-
expect(keys[1].keys[0].path[0].idType).toMatchInlineSnapshot('"id"')
|
|
65
|
-
expect(keys[1].keys[0].path[0].kind).toMatchInlineSnapshot('"testYodel"')
|
|
66
|
-
})
|
|
90
|
+
const kvStore = getDstore()
|
|
91
|
+
const keys = await kvStore.datastore.allocateIds(kvStore.datastore.key(['testYodel']), 2)
|
|
92
|
+
expect(Array.isArray(keys)).toBeTruthy()
|
|
93
|
+
expect(keys[0].length).toBe(2)
|
|
94
|
+
expect(keys[0][0].kind).toBe('testYodel')
|
|
95
|
+
expect(keys[0][0].id).toMatch(/\d+/)
|
|
96
|
+
expect(keys?.[1]?.keys?.length).toBe(2)
|
|
97
|
+
expect(keys[1].keys[0].partitionId.namespaceId).toMatchInlineSnapshot('"test"')
|
|
98
|
+
expect(keys[1].keys[0].path[0].idType).toMatchInlineSnapshot('"id"')
|
|
99
|
+
expect(keys[1].keys[0].path[0].kind).toMatchInlineSnapshot('"testYodel"')
|
|
100
|
+
})
|
|
67
101
|
|
|
68
102
|
test('allocateOneId', async () => {
|
|
69
|
-
const kvStore = getDstore()
|
|
70
|
-
const id = await kvStore.allocateOneId()
|
|
71
|
-
expect(id).toMatch(/\d+/)
|
|
72
|
-
})
|
|
73
|
-
})
|
|
103
|
+
const kvStore = getDstore()
|
|
104
|
+
const id = await kvStore.allocateOneId()
|
|
105
|
+
expect(id).toMatch(/\d+/)
|
|
106
|
+
})
|
|
107
|
+
})
|
|
74
108
|
|
|
75
109
|
describe('Read', () => {
|
|
76
110
|
test('get num_id', async () => {
|
|
77
|
-
const kvStore = getDstore()
|
|
78
|
-
const entity = { key: kvStore.key(['testYodel', 2]), data: { foo: 'bar' } }
|
|
111
|
+
const kvStore = getDstore()
|
|
112
|
+
const entity = { key: kvStore.key(['testYodel', 2]), data: { foo: 'bar' } }
|
|
79
113
|
const entity2 = {
|
|
80
114
|
key: kvStore.key(['testYodel', 3]),
|
|
81
115
|
data: { foo: 'bar' },
|
|
82
|
-
}
|
|
83
|
-
const commitResponse = await kvStore.save([entity, entity2])
|
|
116
|
+
}
|
|
117
|
+
const commitResponse = await kvStore.save([entity, entity2])
|
|
84
118
|
// expect(isNumber(commitResponse?.[0]?.indexUpdates)).toBeTruthy();
|
|
85
119
|
// expect(commitResponse).toMatchInlineSnapshot(`
|
|
86
120
|
// Array [
|
|
@@ -122,22 +156,22 @@ describe('Read', () => {
|
|
|
122
156
|
],
|
|
123
157
|
},
|
|
124
158
|
}
|
|
125
|
-
`)
|
|
159
|
+
`)
|
|
126
160
|
|
|
127
|
-
const result = await kvStore.get(entity.key)
|
|
161
|
+
const result = await kvStore.get(entity.key)
|
|
128
162
|
// get returns a single Entity
|
|
129
|
-
expect(Array.isArray(result)).toBeFalsy()
|
|
130
|
-
expect(result).toMatchInlineSnapshot('null')
|
|
163
|
+
expect(Array.isArray(result)).toBeFalsy()
|
|
164
|
+
expect(result).toMatchInlineSnapshot('null')
|
|
131
165
|
// expect(kvStore.readKey(result)).toBeInstanceOf(Key);
|
|
132
166
|
|
|
133
|
-
const result2 = await kvStore.getMulti([entity.key])
|
|
167
|
+
const result2 = await kvStore.getMulti([entity.key])
|
|
134
168
|
// getMulti returns a Array even for single keys
|
|
135
169
|
expect(result2).toMatchInlineSnapshot(`
|
|
136
170
|
[
|
|
137
171
|
null,
|
|
138
172
|
]
|
|
139
|
-
`)
|
|
140
|
-
const result3 = await kvStore.getMulti([entity.key, kvStore.key(['testYodel', 3])])
|
|
173
|
+
`)
|
|
174
|
+
const result3 = await kvStore.getMulti([entity.key, kvStore.key(['testYodel', 3])])
|
|
141
175
|
// getMulti returns a Array with multiple keys
|
|
142
176
|
// expect(Array.isArray(result)).toBeTruthy();
|
|
143
177
|
expect(result3).toMatchInlineSnapshot(`
|
|
@@ -145,8 +179,8 @@ describe('Read', () => {
|
|
|
145
179
|
null,
|
|
146
180
|
null,
|
|
147
181
|
]
|
|
148
|
-
`)
|
|
149
|
-
const result4 = await kvStore.getMulti([entity.key, entity.key])
|
|
182
|
+
`)
|
|
183
|
+
const result4 = await kvStore.getMulti([entity.key, entity.key])
|
|
150
184
|
// getMulti returns a Array but collapses duplicate keys
|
|
151
185
|
// expect(Array.isArray(result)).toBeTruthy();
|
|
152
186
|
// Firestore in Datastore returns the entity once
|
|
@@ -157,9 +191,9 @@ describe('Read', () => {
|
|
|
157
191
|
null,
|
|
158
192
|
null,
|
|
159
193
|
]
|
|
160
|
-
`)
|
|
194
|
+
`)
|
|
161
195
|
|
|
162
|
-
const result5 = await kvStore.getMulti([entity.key, kvStore.key(['YodelNotThere', 3])])
|
|
196
|
+
const result5 = await kvStore.getMulti([entity.key, kvStore.key(['YodelNotThere', 3])])
|
|
163
197
|
// getMulti returns a Array but omits unknown keys
|
|
164
198
|
// expect(Array.isArray(result)).toBeTruthy();
|
|
165
199
|
expect(result5).toMatchInlineSnapshot(`
|
|
@@ -167,39 +201,77 @@ describe('Read', () => {
|
|
|
167
201
|
null,
|
|
168
202
|
null,
|
|
169
203
|
]
|
|
170
|
-
`)
|
|
171
|
-
const result6 = await kvStore.getMulti([])
|
|
204
|
+
`)
|
|
205
|
+
const result6 = await kvStore.getMulti([])
|
|
172
206
|
// getMulti returns a empty Array for an empty array
|
|
173
207
|
// expect(Array.isArray(result)).toBeTruthy();
|
|
174
|
-
expect(result6).toMatchInlineSnapshot('[]')
|
|
175
|
-
})
|
|
176
|
-
|
|
208
|
+
expect(result6).toMatchInlineSnapshot('[]')
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
test('get name', async (t) => {
|
|
212
|
+
const kvStore = getDstore()
|
|
213
|
+
const entity = {
|
|
214
|
+
key: kvStore.key(['testYodel', 'two']),
|
|
215
|
+
data: { foo: 'bar' },
|
|
216
|
+
}
|
|
217
|
+
await kvStore.save([entity])
|
|
218
|
+
const result = await kvStore.get(entity.key)
|
|
219
|
+
expect(result?._keyStr).toMatchInlineSnapshot('"agByEgsSCXRlc3RZb2RlbCIDdHdvDKIBBHRlc3Q"')
|
|
220
|
+
expect(result?.foo).toBe('bar')
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
describe('queryies', async () => {
|
|
225
|
+
test('sanity check', async () => {
|
|
226
|
+
const kvStore = getDstore()
|
|
227
|
+
expect(saveResult).toMatchInlineSnapshot(`
|
|
228
|
+
[
|
|
229
|
+
{
|
|
230
|
+
"commitTime": null,
|
|
231
|
+
"indexUpdates": 5,
|
|
232
|
+
"mutationResults": [
|
|
233
|
+
{
|
|
234
|
+
"conflictDetected": false,
|
|
235
|
+
"createTime": null,
|
|
236
|
+
"key": null,
|
|
237
|
+
"updateTime": null,
|
|
238
|
+
"version": "2",
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
},
|
|
242
|
+
]
|
|
243
|
+
`)
|
|
244
|
+
|
|
245
|
+
expect(await kvStore.get(entity.key)).toMatchInlineSnapshot(`
|
|
246
|
+
{
|
|
247
|
+
"_keyStr": "agByEAsSCXRlc3RZb2RlbCIBMwyiAQR0ZXN0",
|
|
248
|
+
"baz": "baz",
|
|
249
|
+
"foo": "bar",
|
|
250
|
+
Symbol(KEY): Key {
|
|
251
|
+
"kind": "testYodel",
|
|
252
|
+
"name": "3",
|
|
253
|
+
"namespace": "test",
|
|
254
|
+
"path": [
|
|
255
|
+
"testYodel",
|
|
256
|
+
"3",
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
}
|
|
260
|
+
`)
|
|
261
|
+
})
|
|
177
262
|
|
|
178
|
-
test('get name', async (t) => {
|
|
179
|
-
const kvStore = getDstore();
|
|
180
|
-
const entity = {
|
|
181
|
-
key: kvStore.key(['testYodel', 'two']),
|
|
182
|
-
data: { foo: 'bar' },
|
|
183
|
-
};
|
|
184
|
-
await kvStore.save([entity]);
|
|
185
|
-
const result = await kvStore.get(entity.key);
|
|
186
|
-
expect(result?._keyStr).toMatchInlineSnapshot('"agByEgsSCXRlc3RZb2RlbCIDdHdvDKIBBHRlc3Q"');
|
|
187
|
-
expect(result?.foo).toBe('bar');
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
describe('query', async () => {
|
|
191
263
|
test('raw', async () => {
|
|
192
|
-
const kvStore = getDstore()
|
|
264
|
+
const kvStore = getDstore()
|
|
193
265
|
const entity = {
|
|
194
266
|
key: kvStore.key(['testYodel', '3']),
|
|
195
267
|
data: { foo: 'bar', baz: 'baz' },
|
|
196
|
-
}
|
|
268
|
+
}
|
|
197
269
|
|
|
198
|
-
await kvStore.save([entity])
|
|
199
|
-
const query = kvStore.datastore.createQuery('testYodel')
|
|
200
|
-
query.limit(1)
|
|
201
|
-
const [entities, runQueryInfo] = await kvStore.datastore.runQuery(query)
|
|
202
|
-
expect(entities.length).toBe(1)
|
|
270
|
+
await kvStore.save([entity])
|
|
271
|
+
const query = kvStore.datastore.createQuery('testYodel')
|
|
272
|
+
query.limit(1)
|
|
273
|
+
const [entities, runQueryInfo] = await kvStore.datastore.runQuery(query)
|
|
274
|
+
expect(entities.length).toBe(1)
|
|
203
275
|
expect(entities).toMatchInlineSnapshot(`
|
|
204
276
|
[
|
|
205
277
|
{
|
|
@@ -215,39 +287,117 @@ describe('query', async () => {
|
|
|
215
287
|
},
|
|
216
288
|
},
|
|
217
289
|
]
|
|
218
|
-
`)
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
test('
|
|
222
|
-
const kvStore = getDstore()
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const saveResult = await kvStore.save([entity]);
|
|
229
|
-
expect(saveResult).toMatchInlineSnapshot(`
|
|
290
|
+
`)
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
test('runQuery', async () => {
|
|
294
|
+
const kvStore = getDstore()
|
|
295
|
+
const query = kvStore.createQuery('testYodel')
|
|
296
|
+
query.limit(1)
|
|
297
|
+
const [entities, runQueryInfo] = await kvStore.runQuery(query)
|
|
298
|
+
// expect(entities.length).toBe(1)
|
|
299
|
+
expect(entities).toMatchInlineSnapshot(`
|
|
230
300
|
[
|
|
231
301
|
{
|
|
232
|
-
"
|
|
233
|
-
"
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
"
|
|
240
|
-
"
|
|
241
|
-
|
|
242
|
-
|
|
302
|
+
"_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
|
|
303
|
+
"foo": "bar",
|
|
304
|
+
Symbol(KEY): Key {
|
|
305
|
+
"id": "2",
|
|
306
|
+
"kind": "testYodel",
|
|
307
|
+
"namespace": "test",
|
|
308
|
+
"path": [
|
|
309
|
+
"testYodel",
|
|
310
|
+
"2",
|
|
311
|
+
],
|
|
312
|
+
},
|
|
243
313
|
},
|
|
244
314
|
]
|
|
245
|
-
`)
|
|
246
|
-
expect(
|
|
315
|
+
`)
|
|
316
|
+
expect(runQueryInfo).toMatchInlineSnapshot(`
|
|
317
|
+
{
|
|
318
|
+
"endCursor": "CioSJGoKcHJvamVjdC1pZHIPCxIJdGVzdFlvZGVsGAIMogEEdGVzdBgAIAA=",
|
|
319
|
+
"moreResults": "MORE_RESULTS_AFTER_LIMIT",
|
|
320
|
+
}
|
|
321
|
+
`)
|
|
322
|
+
expect(entities?.[0]?.foo).toBe('bar')
|
|
323
|
+
expect(entities?.[0]?.[Datastore.KEY]?.kind).toBe('testYodel')
|
|
324
|
+
expect(runQueryInfo?.moreResults).toBe('MORE_RESULTS_AFTER_LIMIT')
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
test('query', async () => {
|
|
328
|
+
// modern interface
|
|
329
|
+
const kvStore = getDstore()
|
|
330
|
+
const [result1] = await kvStore.query('testYodel')
|
|
331
|
+
expect(result1?.[0]).toMatchInlineSnapshot(`
|
|
332
|
+
{
|
|
333
|
+
"_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
|
|
334
|
+
"foo": "bar",
|
|
335
|
+
Symbol(KEY): Key {
|
|
336
|
+
"id": "2",
|
|
337
|
+
"kind": "testYodel",
|
|
338
|
+
"namespace": "test",
|
|
339
|
+
"path": [
|
|
340
|
+
"testYodel",
|
|
341
|
+
"2",
|
|
342
|
+
],
|
|
343
|
+
},
|
|
344
|
+
}
|
|
345
|
+
`)
|
|
346
|
+
const [result2] = await kvStore.query('testYodel', [])
|
|
347
|
+
expect(result2?.[0]).toMatchInlineSnapshot(`
|
|
348
|
+
{
|
|
349
|
+
"_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
|
|
350
|
+
"foo": "bar",
|
|
351
|
+
Symbol(KEY): Key {
|
|
352
|
+
"id": "2",
|
|
353
|
+
"kind": "testYodel",
|
|
354
|
+
"namespace": "test",
|
|
355
|
+
"path": [
|
|
356
|
+
"testYodel",
|
|
357
|
+
"2",
|
|
358
|
+
],
|
|
359
|
+
},
|
|
360
|
+
}
|
|
361
|
+
`)
|
|
362
|
+
const [result3] = await kvStore.query('testYodel', [], 1)
|
|
363
|
+
expect(result3?.[0]).toMatchInlineSnapshot(`
|
|
364
|
+
{
|
|
365
|
+
"_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
|
|
366
|
+
"foo": "bar",
|
|
367
|
+
Symbol(KEY): Key {
|
|
368
|
+
"id": "2",
|
|
369
|
+
"kind": "testYodel",
|
|
370
|
+
"namespace": "test",
|
|
371
|
+
"path": [
|
|
372
|
+
"testYodel",
|
|
373
|
+
"2",
|
|
374
|
+
],
|
|
375
|
+
},
|
|
376
|
+
}
|
|
377
|
+
`)
|
|
378
|
+
const [result4] = await kvStore.query('testYodel', [], 1, [])
|
|
379
|
+
expect(result4?.[0]).toMatchInlineSnapshot(`
|
|
380
|
+
{
|
|
381
|
+
"_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
|
|
382
|
+
"foo": "bar",
|
|
383
|
+
Symbol(KEY): Key {
|
|
384
|
+
"id": "2",
|
|
385
|
+
"kind": "testYodel",
|
|
386
|
+
"namespace": "test",
|
|
387
|
+
"path": [
|
|
388
|
+
"testYodel",
|
|
389
|
+
"2",
|
|
390
|
+
],
|
|
391
|
+
},
|
|
392
|
+
}
|
|
393
|
+
`)
|
|
394
|
+
// expect(result2.length).toBe(1)
|
|
395
|
+
// foo is removed by selection
|
|
396
|
+
const [result5] = await kvStore.query('testYodel', [], 1, [], ['baz'])
|
|
397
|
+
expect(result5?.[0]).toMatchInlineSnapshot(`
|
|
247
398
|
{
|
|
248
399
|
"_keyStr": "agByEAsSCXRlc3RZb2RlbCIBMwyiAQR0ZXN0",
|
|
249
400
|
"baz": "baz",
|
|
250
|
-
"foo": "bar",
|
|
251
401
|
Symbol(KEY): Key {
|
|
252
402
|
"kind": "testYodel",
|
|
253
403
|
"name": "3",
|
|
@@ -258,15 +408,38 @@ describe('query', async () => {
|
|
|
258
408
|
],
|
|
259
409
|
},
|
|
260
410
|
}
|
|
261
|
-
`)
|
|
262
|
-
// Give Datastore time to become consistent
|
|
263
|
-
do {} while ((await kvStore.get(entity.key)) === null);
|
|
411
|
+
`)
|
|
264
412
|
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
413
|
+
const key = kvStore.readKey(result2?.[0])
|
|
414
|
+
// expect(key.id).toBe(entity.key.id)
|
|
415
|
+
})
|
|
416
|
+
|
|
417
|
+
test('iterate', async () => {
|
|
418
|
+
const kvStore = getDstore()
|
|
419
|
+
const result = await kvStore.iterate({ kindName: 'testYodel', limit: 1 })
|
|
420
|
+
for await (const entity of result) {
|
|
421
|
+
expect(entity).toMatchInlineSnapshot(`
|
|
422
|
+
{
|
|
423
|
+
"_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
|
|
424
|
+
"foo": "bar",
|
|
425
|
+
Symbol(KEY): Key {
|
|
426
|
+
"id": "2",
|
|
427
|
+
"kind": "testYodel",
|
|
428
|
+
"namespace": "test",
|
|
429
|
+
"path": [
|
|
430
|
+
"testYodel",
|
|
431
|
+
"2",
|
|
432
|
+
],
|
|
433
|
+
},
|
|
434
|
+
}
|
|
435
|
+
`)
|
|
436
|
+
}
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
test('list', async () => {
|
|
440
|
+
const kvStore = getDstore()
|
|
441
|
+
const result = await kvStore.list({ kindName: 'testYodel', limit: 1 })
|
|
442
|
+
expect(result).toMatchInlineSnapshot(`
|
|
270
443
|
[
|
|
271
444
|
{
|
|
272
445
|
"_keyStr": "agByDwsSCXRlc3RZb2RlbBgCDKIBBHRlc3Q",
|
|
@@ -282,112 +455,90 @@ describe('query', async () => {
|
|
|
282
455
|
},
|
|
283
456
|
},
|
|
284
457
|
]
|
|
285
|
-
`)
|
|
286
|
-
|
|
287
|
-
{
|
|
288
|
-
"endCursor": "CioSJGoKcHJvamVjdC1pZHIPCxIJdGVzdFlvZGVsGAIMogEEdGVzdBgAIAA=",
|
|
289
|
-
"moreResults": "MORE_RESULTS_AFTER_LIMIT",
|
|
290
|
-
}
|
|
291
|
-
`);
|
|
292
|
-
expect(entities?.[0]?.foo).toBe('bar');
|
|
293
|
-
expect(entities?.[0]?.[Datastore.KEY]?.kind).toBe('testYodel');
|
|
294
|
-
expect(runQueryInfo?.moreResults).toBe('MORE_RESULTS_AFTER_LIMIT');
|
|
295
|
-
|
|
296
|
-
// modern interface
|
|
297
|
-
const [result2] = await kvStore.query('testYodel', [], 1, [], ['baz']);
|
|
298
|
-
expect(result2.length).toBe(1);
|
|
299
|
-
// foo is removed by selection
|
|
300
|
-
expect(JSON.parse(JSON.stringify(result2?.[0]))).toMatchInlineSnapshot(`
|
|
301
|
-
{
|
|
302
|
-
"_keyStr": "agByEAsSCXRlc3RZb2RlbCIBMwyiAQR0ZXN0",
|
|
303
|
-
"baz": "baz",
|
|
304
|
-
}
|
|
305
|
-
`);
|
|
458
|
+
`)
|
|
459
|
+
})
|
|
306
460
|
|
|
307
|
-
|
|
308
|
-
expect(key.id).toBe(entity.key.id);
|
|
309
|
-
});
|
|
310
|
-
});
|
|
461
|
+
})
|
|
311
462
|
|
|
312
463
|
test('set', async () => {
|
|
313
464
|
// expect.assertions(2);
|
|
314
|
-
const kvStore = getDstore()
|
|
465
|
+
const kvStore = getDstore()
|
|
315
466
|
const result = await kvStore.set(kvStore.key(['testYodel', '5e7']), {
|
|
316
467
|
foo: 'bar',
|
|
317
|
-
})
|
|
318
|
-
expect(result.name).toBe('5e7')
|
|
319
|
-
expect(result.kind).toBe('testYodel')
|
|
468
|
+
})
|
|
469
|
+
expect(result.name).toBe('5e7')
|
|
470
|
+
expect(result.kind).toBe('testYodel')
|
|
320
471
|
|
|
321
472
|
// autogenerate key
|
|
322
|
-
const result2 = await kvStore.set(kvStore.key(['testYodel']), { foo: 'bar' })
|
|
323
|
-
expect(result2.kind).toBe('testYodel')
|
|
324
|
-
})
|
|
473
|
+
const result2 = await kvStore.set(kvStore.key(['testYodel']), { foo: 'bar' })
|
|
474
|
+
expect(result2.kind).toBe('testYodel')
|
|
475
|
+
})
|
|
325
476
|
|
|
326
477
|
test('save / upsert', async () => {
|
|
327
478
|
// expect.assertions(2);
|
|
328
|
-
const kvStore = getDstore()
|
|
479
|
+
const kvStore = getDstore()
|
|
329
480
|
const entity = {
|
|
330
481
|
key: kvStore.key(['testYodel', 3]),
|
|
331
482
|
data: { foo: 'bar' } as any,
|
|
332
|
-
}
|
|
333
|
-
const result = await kvStore.save([entity])
|
|
483
|
+
}
|
|
484
|
+
const result = await kvStore.save([entity])
|
|
334
485
|
// const result2 = await kvStore.upsert([entity]);
|
|
335
|
-
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
336
|
-
expect(entity.data._keyStr).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBgDDKIBBHRlc3Q"')
|
|
337
|
-
expect(entity.data.foo).toBe('bar')
|
|
338
|
-
expect(entity.data[Datastore.KEY].kind).toBe('testYodel')
|
|
339
|
-
})
|
|
486
|
+
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
487
|
+
expect(entity.data._keyStr).toMatchInlineSnapshot('"agByDwsSCXRlc3RZb2RlbBgDDKIBBHRlc3Q"')
|
|
488
|
+
expect(entity.data.foo).toBe('bar')
|
|
489
|
+
expect(entity.data[Datastore.KEY].kind).toBe('testYodel')
|
|
490
|
+
})
|
|
340
491
|
|
|
341
492
|
test('update', async (t) => {
|
|
342
493
|
// expect.assertions(3);
|
|
343
|
-
const kvStore = getDstore()
|
|
344
|
-
const keyName = `4insert${Math.random()}
|
|
494
|
+
const kvStore = getDstore()
|
|
495
|
+
const keyName = `4insert${Math.random()}`
|
|
345
496
|
const entity = {
|
|
346
497
|
key: kvStore.key(['testYodel', keyName]),
|
|
347
498
|
data: { foo: 'bar' },
|
|
348
|
-
}
|
|
499
|
+
}
|
|
349
500
|
// const request = kvStore.update([entity]);
|
|
350
501
|
// await expect(request).rejects.toThrowError(Error);
|
|
351
502
|
|
|
352
|
-
await kvStore.save([entity])
|
|
353
|
-
const result = await kvStore.update([entity])
|
|
354
|
-
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
355
|
-
expect(result?.[0]?.mutationResults?.[0]?.key).toBe(null)
|
|
503
|
+
await kvStore.save([entity])
|
|
504
|
+
const result = await kvStore.update([entity])
|
|
505
|
+
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
506
|
+
expect(result?.[0]?.mutationResults?.[0]?.key).toBe(null)
|
|
356
507
|
// expect(result?.[0]?.indexUpdates).toBe(2);
|
|
357
|
-
})
|
|
508
|
+
})
|
|
358
509
|
|
|
359
510
|
test('insert / delete', async (t) => {
|
|
360
511
|
// expect.assertions(2);
|
|
361
|
-
const kvStore = getDstore()
|
|
362
|
-
const testkey = kvStore.key(['testYodel', 4])
|
|
363
|
-
await kvStore.delete([testkey])
|
|
512
|
+
const kvStore = getDstore()
|
|
513
|
+
const testkey = kvStore.key(['testYodel', 4])
|
|
514
|
+
await kvStore.delete([testkey])
|
|
364
515
|
const entity = {
|
|
365
516
|
key: testkey,
|
|
366
517
|
data: { foo: 'bar' } as any,
|
|
367
|
-
}
|
|
368
|
-
const result = await kvStore.insert([entity])
|
|
518
|
+
}
|
|
519
|
+
const result = await kvStore.insert([entity])
|
|
369
520
|
|
|
370
|
-
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
371
|
-
expect(result?.[0]?.mutationResults?.[0]?.version).toMatch(/\d+/)
|
|
372
|
-
expect(entity.data.foo).toBe('bar')
|
|
373
|
-
expect(entity.key.path[0]).toBe('testYodel')
|
|
521
|
+
expect(result?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
522
|
+
expect(result?.[0]?.mutationResults?.[0]?.version).toMatch(/\d+/)
|
|
523
|
+
expect(entity.data.foo).toBe('bar')
|
|
524
|
+
expect(entity.key.path[0]).toBe('testYodel')
|
|
374
525
|
// expect(result?.[0]?.indexUpdates).toBe(3);
|
|
375
526
|
|
|
376
|
-
const result2 = await kvStore.delete([entity.key])
|
|
377
|
-
expect(result2?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
378
|
-
})
|
|
527
|
+
const result2 = await kvStore.delete([entity.key])
|
|
528
|
+
expect(result2?.[0]?.mutationResults?.[0]?.conflictDetected).toBe(false)
|
|
529
|
+
})
|
|
379
530
|
|
|
380
531
|
test('exception', async () => {
|
|
381
532
|
// expect.assertions(2);
|
|
382
|
-
const kvStore = getDstore()
|
|
533
|
+
const kvStore = getDstore()
|
|
383
534
|
try {
|
|
384
535
|
const result = await kvStore.set(kvStore.key(['testYodel', NaN]), {
|
|
385
536
|
foo: 'bar',
|
|
386
|
-
})
|
|
537
|
+
})
|
|
387
538
|
} catch (e) {
|
|
388
|
-
expect(e.stack).toMatch(/Dstore\.set/)
|
|
539
|
+
expect(e.stack).toMatch(/Dstore\.set/)
|
|
389
540
|
}
|
|
390
|
-
})
|
|
541
|
+
})
|
|
391
542
|
// describe("Transactions", () => {
|
|
392
543
|
// it("simple", async () => {
|
|
393
544
|
// expect.assertions(2);
|