datastore-api 1.2.0 → 1.6.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/CHANGELOG.md +28 -0
- package/README.md +6 -2
- package/build/main/lib/dstore-api.d.ts +45 -23
- package/build/main/lib/dstore-api.js +61 -24
- package/build/main/lib/dstore-api.spec.js +51 -129
- package/build/module/lib/dstore-api.d.ts +45 -23
- package/build/module/lib/dstore-api.js +61 -24
- package/build/module/lib/dstore-api.spec.js +48 -128
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [1.6.0](https://github.com/mdornseif/datastore-api/compare/v1.5.0...v1.6.0) (2022-01-10)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* catch incomplete keys before trying to update the datastore ([1132e3b](https://github.com/mdornseif/datastore-api/commit/1132e3b52913d83b189c7bf94101c6df162f87df))
|
|
11
|
+
|
|
12
|
+
## [1.5.0](https://github.com/mdornseif/datastore-api/compare/v1.4.0...v1.5.0) (2022-01-06)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* provide _keyStr also in queries ([fe7e90b](https://github.com/mdornseif/datastore-api/commit/fe7e90b3011e08de552e1b4e35b1ad110efa6b1b))
|
|
18
|
+
|
|
19
|
+
## [1.4.0](https://github.com/mdornseif/datastore-api/compare/v1.3.0...v1.4.0) (2022-01-04)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* save() adds _keyStr the same way get() does ([f4f6452](https://github.com/mdornseif/datastore-api/commit/f4f6452c77046c0ee8d0b6ddfe2ec6744a4968bd))
|
|
25
|
+
|
|
26
|
+
## [1.3.0](https://github.com/mdornseif/datastore-api/compare/v1.2.0...v1.3.0) (2022-01-03)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
* Set excludeLargeProperties by default. ([289cd28](https://github.com/mdornseif/datastore-api/commit/289cd289651b0c34f36098370b3dfbe249790c5a))
|
|
32
|
+
|
|
5
33
|
## [1.2.0](https://github.com/mdornseif/datastore-api/compare/v1.1.3...v1.2.0) (2021-12-30)
|
|
6
34
|
|
|
7
35
|
|
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
[](https://npmjs.org/datastore-api)
|
|
2
|
+
[](https://github.com/mdornseif/datastore-api/blob/master/LICENSE)
|
|
3
|
+
[](https://npmcharts.com/compare/datastore-api)
|
|
4
|
+
|
|
1
5
|
# datastore-api
|
|
2
6
|
|
|
3
7
|
Simplified, more consistent API for Google Cloud Datastore.
|
|
@@ -22,7 +26,7 @@ Main differences:
|
|
|
22
26
|
|
|
23
27
|
Find the full documentation [here](http://mdornseif.io/datastore-api/classes/Dstore.html). In there also some of the idiosyncrasies of using the Datastore are explained.
|
|
24
28
|
|
|
25
|
-
See [the API documentation](http://mdornseif.io/datastore-api/classes/Dstore.html) for Details.
|
|
29
|
+
See [the API documentation](http://mdornseif.io/datastore-api/classes/Dstore.html) for Details, [Github](https://github.com/mdornseif/datastore-api) for source.
|
|
26
30
|
|
|
27
31
|
## See also
|
|
28
32
|
|
|
@@ -33,7 +37,7 @@ See [the API documentation](http://mdornseif.io/datastore-api/classes/Dstore.htm
|
|
|
33
37
|
- Other [Hidden Auto-Generated Datastore API Documentation](https://googleapis.dev/nodejs/datastore/latest/) with better navigation. Seems to contain more on the lower level access.
|
|
34
38
|
- [SDK Source](https://github.com/googleapis/nodejs-datastore)
|
|
35
39
|
- [API reference](https://cloud.google.com/datastore/docs/reference/data/rpc) helps to understand under-documented SDK.
|
|
36
|
-
- [grpc-js environment variables](https://github.com/grpc/grpc-node/blob/master/doc/environment_variables.md) - try[GRPC_VERBOSITY=DEBUG GRPC_TRACE=all yarn test](https://github.com/grpc/grpc-node/blob/master/TROUBLESHOOTING.md)
|
|
40
|
+
- [grpc-js environment variables](https://github.com/grpc/grpc-node/blob/master/doc/environment_variables.md) - try [GRPC_VERBOSITY=DEBUG GRPC_TRACE=all yarn test](https://github.com/grpc/grpc-node/blob/master/TROUBLESHOOTING.md)
|
|
37
41
|
|
|
38
42
|
- API Simplification
|
|
39
43
|
- [google-cloud-datastore-node](https://www.npmjs.com/package/google-cloud-datastore-node)
|
|
@@ -19,8 +19,7 @@ export interface IDstoreEntryWithoutKey {
|
|
|
19
19
|
[key: string]: DstorePropertyValues;
|
|
20
20
|
}
|
|
21
21
|
/** Represents what is actually stored inside the Datastore, called "Entity" by Google
|
|
22
|
-
[@google-cloud/datastore](https://github.com/googleapis/nodejs-datastore#readme) adds `[Datastore.KEY]`. Using ES6 Symbols presents all kinds of hurdles, especially when you try to serialize into a cache. So we add the property _keyStr which contains the encoded
|
|
23
|
-
to reconstruct `[Datastore.KEY]`, if you use [[Dstore.readKey]].
|
|
22
|
+
[@google-cloud/datastore](https://github.com/googleapis/nodejs-datastore#readme) adds `[Datastore.KEY]`. Using ES6 Symbols presents all kinds of hurdles, especially when you try to serialize into a cache. So we add the property _keyStr which contains the encoded key. It is automatically used to reconstruct `[Datastore.KEY]`, if you use [[Dstore.readKey]].
|
|
24
23
|
*/
|
|
25
24
|
export interface IDstoreEntry extends IDstoreEntryWithoutKey {
|
|
26
25
|
readonly [Datastore.KEY]?: Key;
|
|
@@ -32,7 +31,10 @@ export interface IDstoreEntry extends IDstoreEntryWithoutKey {
|
|
|
32
31
|
/** Represents the thing you pass to the save method. Also called "Entity" by Google */
|
|
33
32
|
export declare type DstoreSaveEntity = {
|
|
34
33
|
key: Key;
|
|
35
|
-
data: Omit<IDstoreEntry, '_keyStr' | Datastore['KEY']
|
|
34
|
+
data: Omit<IDstoreEntry, '_keyStr' | Datastore['KEY']> & Partial<{
|
|
35
|
+
_keyStr: string;
|
|
36
|
+
[Datastore.KEY]: Key;
|
|
37
|
+
}>;
|
|
36
38
|
method?: 'insert' | 'update' | 'upsert';
|
|
37
39
|
excludeLargeProperties?: boolean;
|
|
38
40
|
excludeFromIndexes?: readonly string[];
|
|
@@ -65,18 +67,18 @@ declare type IDstore = {
|
|
|
65
67
|
[@google-cloud/datastore](https://github.com/googleapis/nodejs-datastore#readme) is a strange beast: [The documentation is auto generated](https://cloud.google.com/nodejs/docs/reference/datastore/latest) and completely shy of documenting any advanced concepts.
|
|
66
68
|
(Example: If you ask the datastore to auto-generate keys during save: how do you retrieve the generated key?) Generally I suggest to look at the Python 2.x [db](https://cloud.google.com/appengine/docs/standard/python/datastore/api-overview) and [ndb](https://cloud.google.com/appengine/docs/standard/python/ndb) documentation to get a better explanation of the workings of the datastore.
|
|
67
69
|
|
|
68
|
-
Also the typings are strange. The Google provided type `Entities` can be the on disk representation, the same but including a key reference (`Datastore.KEY` - [[
|
|
70
|
+
Also the typings are strange. The Google provided type `Entities` can be the on disk representation, the same but including a key reference (`Datastore.KEY` - [[IDstoreEntry]]), a list of these or a structured object containing the on disk representation under the `data` property and a `key` property and maybe some configuration like `excludeFromIndexes` ([[DstoreSaveEntity]]) or a list of these.
|
|
69
71
|
|
|
70
72
|
KvStore tries to abstract away most surprises the datastore provides to you but als tries to stay as API compatible as possible to [@google-cloud/datastore](https://github.com/googleapis/nodejs-datastore).
|
|
71
73
|
|
|
72
74
|
Main differences:
|
|
73
75
|
|
|
74
76
|
- Everything asynchronous is Promise-based - no callbacks.
|
|
75
|
-
- [[get]] always returns a single [[
|
|
76
|
-
- [[getMulti]] always returns an Array<[[
|
|
77
|
+
- [[get]] always returns a single [[IDstoreEntry]].
|
|
78
|
+
- [[getMulti]] always returns an Array<[[IDstoreEntry]]> of the same length as the input Array. Items not found are represented by null.
|
|
77
79
|
- [[set]] is called with `(key, value)` and always returns the complete [[Key]] of the entity being written. Keys are normalized, numeric IDs are always encoded as strings.
|
|
78
80
|
- [[key]] handles [[Key]] object instantiation for you.
|
|
79
|
-
- [[readKey]] extracts the key from an [[
|
|
81
|
+
- [[readKey]] extracts the key from an [[IDstoreEntry]] you have read without the need of fancy `Symbol`-based access to `entity[Datastore.KEY]`. If needed, it tries to deserialize `_keyStr` to create `entity[Datastore.KEY]`. This ist important when rehydrating an [[IDstoreEntry]] from a serializing cache.
|
|
80
82
|
- [[allocateOneId]] returns a single numeric string encoded unique datastore id without the need of fancy unpacking.
|
|
81
83
|
- [[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).
|
|
82
84
|
- [[keySerialize]] is synchronous.
|
|
@@ -131,24 +133,24 @@ export declare class Dstore implements IDstore {
|
|
|
131
133
|
* @category Datastore Drop-In
|
|
132
134
|
*/
|
|
133
135
|
keyFromSerialized(text: string): Key;
|
|
134
|
-
/** `readKey()` extracts the [[Key]] from an [[
|
|
136
|
+
/** `readKey()` extracts the [[Key]] from an [[IDstoreEntry]].
|
|
135
137
|
*
|
|
136
138
|
* Is is an alternative to `entity[Datastore.KEY]` which tends to fail in various contexts and also confuses older Typescript compilers.
|
|
137
|
-
* It can extract the [[Key]] form a [[
|
|
139
|
+
* It can extract the [[Key]] form a [[IDstoreEntry]] which has been serialized to JSON by leveraging the property `_keyStr`.
|
|
138
140
|
*
|
|
139
141
|
* @category Additional
|
|
140
142
|
*/
|
|
141
143
|
readKey(ent: IDstoreEntry): Key;
|
|
142
|
-
/** `fixKeys()` is called for all [[
|
|
144
|
+
/** `fixKeys()` is called for all [[IDstoreEntry]]sa returned from [[Dstore]].
|
|
143
145
|
*
|
|
144
146
|
* Is ensures that besides `entity[Datastore.KEY]` there is `_keyStr` to be leveraged by [[readKey]].
|
|
145
147
|
*
|
|
146
148
|
* @internal
|
|
147
149
|
*/
|
|
148
150
|
private fixKeys;
|
|
149
|
-
/** `get()` reads a [[
|
|
151
|
+
/** `get()` reads a [[IDstoreEntry]] from the Datastore.
|
|
150
152
|
*
|
|
151
|
-
* It returns [[
|
|
153
|
+
* It returns [[IDstoreEntry]] or `null` if not found.
|
|
152
154
|
|
|
153
155
|
* The underlying Datastore API Call is [lookup](https://cloud.google.com/datastore/docs/reference/data/rest/v1/projects/lookup).
|
|
154
156
|
*
|
|
@@ -157,14 +159,14 @@ export declare class Dstore implements IDstore {
|
|
|
157
159
|
* Differences between [[Dstore.get]] and [[Datastore.get]]:
|
|
158
160
|
*
|
|
159
161
|
* - [Dstore.get]] takes a single [[Key]] as Parameter, no Array. Check [[getMulti]] if you want Arrays.
|
|
160
|
-
* - [Dstore.get]] returns a single [[
|
|
162
|
+
* - [Dstore.get]] returns a single [[IDstoreEntry]], no Array.
|
|
161
163
|
*
|
|
162
164
|
* @category Datastore Drop-In
|
|
163
165
|
*/
|
|
164
166
|
get(key: Key): Promise<IDstoreEntry | null>;
|
|
165
|
-
/** `getMulti()` reads several [[
|
|
167
|
+
/** `getMulti()` reads several [[IDstoreEntry]]s from the Datastore.
|
|
166
168
|
*
|
|
167
|
-
* It returns a list of [[
|
|
169
|
+
* It returns a list of [[IDstoreEntry]]s or `null` if not found.
|
|
168
170
|
|
|
169
171
|
* The underlying Datastore API Call is [lookup](https://cloud.google.com/datastore/docs/reference/data/rest/v1/projects/lookup).
|
|
170
172
|
*
|
|
@@ -173,7 +175,7 @@ export declare class Dstore implements IDstore {
|
|
|
173
175
|
* Differences between [[Dstore.getMulti]] and [[Datastore.get]]:
|
|
174
176
|
*
|
|
175
177
|
* - [[Dstore.getMulti]] always takes an Array of [[Key]]s as Parameter.
|
|
176
|
-
* - [[Dstore.getMulti]] returns always a Array of [[
|
|
178
|
+
* - [[Dstore.getMulti]] returns always a Array of [[IDstoreEntry]], or null.
|
|
177
179
|
* - [[Datastore.get]] has many edge cases - e.g. when not being able to find any of the provided keys - which return surprising results. [[Dstore.getMulti]] always returns an Array. TODO: return a Array with the same length as the Input.
|
|
178
180
|
*
|
|
179
181
|
* @category Datastore Drop-In
|
|
@@ -211,7 +213,21 @@ export declare class Dstore implements IDstore {
|
|
|
211
213
|
*
|
|
212
214
|
* If the Datastore generates a new ID because of an incomplete [[Key]] *on first save* it will return an large integer as [[Key.id]].
|
|
213
215
|
* On every subsequent `save()` an string encoded number representation is returned.
|
|
214
|
-
* Dstore normalizes that and always
|
|
216
|
+
* @todo Dstore should normalizes that and always return an string encoded number representation.
|
|
217
|
+
*
|
|
218
|
+
* Each [[DstoreSaveEntity]] can have an `excludeFromIndexes` property which is somewhat underdocumented.
|
|
219
|
+
* It can use something like JSON-Path notation
|
|
220
|
+
* ([Source](https://github.com/googleapis/nodejs-datastore/blob/2941f2f0f132b41534e303d441d837051ce88fd7/src/index.ts#L948))
|
|
221
|
+
* [.*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1598),
|
|
222
|
+
* [parent[]](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672),
|
|
223
|
+
* [parent.*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672),
|
|
224
|
+
* [parent[].*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672)
|
|
225
|
+
* and [more complex patterns](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1754)
|
|
226
|
+
* seem to be supported patterns.
|
|
227
|
+
*
|
|
228
|
+
* If the caller has not provided an `excludeLargeProperties` in a [[DstoreSaveEntity]] we will default it
|
|
229
|
+
* to `excludeLargeProperties: true`. Without this you can not store strings longer than 1500 bytes easily
|
|
230
|
+
* ([source](https://github.com/googleapis/nodejs-datastore/blob/c7a08a8382c6706ccbfbbf77950babf40bac757c/src/entity.ts#L961)).
|
|
215
231
|
*
|
|
216
232
|
* @category Datastore Drop-In
|
|
217
233
|
*/
|
|
@@ -226,6 +242,8 @@ export declare class Dstore implements IDstore {
|
|
|
226
242
|
*
|
|
227
243
|
* For handling of incomplete [[Key]]s see [[save]].
|
|
228
244
|
*
|
|
245
|
+
* This function can be completely emulated by using [[save]] with `method: 'insert'` inside each [[DstoreSaveEntity]].
|
|
246
|
+
*
|
|
229
247
|
* @throws [[DstoreError]]
|
|
230
248
|
* @category Datastore Drop-In
|
|
231
249
|
*/
|
|
@@ -240,15 +258,17 @@ export declare class Dstore implements IDstore {
|
|
|
240
258
|
* It throws an [[DstoreError]] if there is no Entity with the same [[Key]] in the Datastore. `update()` *overwrites all existing data* for that [[Key]].
|
|
241
259
|
* There was an alpha functionality called `merge()` in the Datastore which read an Entity, merged it with the new data and wrote it back, but this was never documented.
|
|
242
260
|
*
|
|
243
|
-
* `update()` is idempotent.
|
|
261
|
+
* `update()` is idempotent. Updating the same [[Key]] twice is no error.
|
|
262
|
+
*
|
|
263
|
+
* This function can be completely emulated by using [[save]] with `method: 'update'` inside each [[DstoreSaveEntity]].
|
|
244
264
|
*
|
|
245
265
|
* @throws [[DstoreError]]
|
|
246
266
|
* @category Datastore Drop-In
|
|
247
267
|
*/
|
|
248
268
|
update(entities: readonly DstoreSaveEntity[]): Promise<CommitResponse | undefined>;
|
|
249
|
-
/** `delete()` is compatible to [Datastore.
|
|
269
|
+
/** `delete()` is compatible to [Datastore.delete()].
|
|
250
270
|
*
|
|
251
|
-
* Unfortunately currently (late 2021) there is no formal documentation from Google on [Datastore.
|
|
271
|
+
* Unfortunately currently (late 2021) there is no formal documentation from Google on [Datastore.delete()].
|
|
252
272
|
*
|
|
253
273
|
* The single Parameter is a list of [[Key]]s.
|
|
254
274
|
* If called within a transaction it returns `undefined`.
|
|
@@ -285,8 +305,6 @@ export declare class Dstore implements IDstore {
|
|
|
285
305
|
allocateOneId(kindName?: string): Promise<string>;
|
|
286
306
|
/** This tries to give high level access to transactions.
|
|
287
307
|
|
|
288
|
-
Be aware that Transactions differ considerable between Master-Slave Datastore (very old), High Replication Datastore (old, later called [Google Cloud Datastore](https://cloud.google.com/datastore/docs/concepts/cloud-datastore-transactions)) and [Firestore in Datastore Mode](https://cloud.google.com/datastore/docs/firestore-or-datastore#in_datastore_mode) (current).
|
|
289
|
-
|
|
290
308
|
So called "Gross Group Transactions" are always enabled. Transactions are never Cross Project. `runInTransaction()` works only if you use the same [[KvStore] instance for all access within the Transaction.
|
|
291
309
|
|
|
292
310
|
[[runInTransaction]] is modelled after Python 2.7 [ndb's `@ndb.transactional` feature](https://cloud.google.com/appengine/docs/standard/python/ndb/transactions). This is based on node's [AsyncLocalStorage](https://nodejs.org/docs/latest-v14.x/api/async_hooks.html).
|
|
@@ -294,7 +312,11 @@ export declare class Dstore implements IDstore {
|
|
|
294
312
|
Transactions frequently fail if you try to access the same data via in a transaction. See the [Documentation on Locking](https://cloud.google.com/datastore/docs/concepts/transactions#transaction_locks) for further reference. You are advised to use [p-limit](https://github.com/sindresorhus/p-limit)(1) to serialize transactions touching the same resource. This should work nicely with node's single process model. It is a much bigger problem on shared-nothing approaches, like Python on App Engine.
|
|
295
313
|
|
|
296
314
|
Transactions might be wrapped in [p-retry](https://github.com/sindresorhus/p-retry) to implement automatically retrying them with exponential back-off should they fail due to contention.
|
|
297
|
-
|
|
315
|
+
|
|
316
|
+
Be aware that Transactions differ considerable between Master-Slave Datastore (very old), High Replication Datastore (old, later called [Google Cloud Datastore](https://cloud.google.com/datastore/docs/concepts/cloud-datastore-transactions)) and [Firestore in Datastore Mode](https://cloud.google.com/datastore/docs/firestore-or-datastore#in_datastore_mode) (current).
|
|
317
|
+
|
|
318
|
+
Most Applications today are running on "Firestore in Datastore Mode". Beware that the Datastore-Emulator fails with `error: 3 INVALID_ARGUMENT: Only ancestor queries are allowed inside transactions.` during [[runQuery]] while the Datastore on Google Infrastructure does not have such an restriction anymore as of 2022.
|
|
319
|
+
*/
|
|
298
320
|
runInTransaction<T>(func: () => Promise<T>): Promise<T>;
|
|
299
321
|
}
|
|
300
322
|
export declare class DstoreError extends Error {
|
|
@@ -39,18 +39,18 @@ exports.KEYSYM = datastore_1.Datastore.KEY;
|
|
|
39
39
|
[@google-cloud/datastore](https://github.com/googleapis/nodejs-datastore#readme) is a strange beast: [The documentation is auto generated](https://cloud.google.com/nodejs/docs/reference/datastore/latest) and completely shy of documenting any advanced concepts.
|
|
40
40
|
(Example: If you ask the datastore to auto-generate keys during save: how do you retrieve the generated key?) Generally I suggest to look at the Python 2.x [db](https://cloud.google.com/appengine/docs/standard/python/datastore/api-overview) and [ndb](https://cloud.google.com/appengine/docs/standard/python/ndb) documentation to get a better explanation of the workings of the datastore.
|
|
41
41
|
|
|
42
|
-
Also the typings are strange. The Google provided type `Entities` can be the on disk representation, the same but including a key reference (`Datastore.KEY` - [[
|
|
42
|
+
Also the typings are strange. The Google provided type `Entities` can be the on disk representation, the same but including a key reference (`Datastore.KEY` - [[IDstoreEntry]]), a list of these or a structured object containing the on disk representation under the `data` property and a `key` property and maybe some configuration like `excludeFromIndexes` ([[DstoreSaveEntity]]) or a list of these.
|
|
43
43
|
|
|
44
44
|
KvStore tries to abstract away most surprises the datastore provides to you but als tries to stay as API compatible as possible to [@google-cloud/datastore](https://github.com/googleapis/nodejs-datastore).
|
|
45
45
|
|
|
46
46
|
Main differences:
|
|
47
47
|
|
|
48
48
|
- Everything asynchronous is Promise-based - no callbacks.
|
|
49
|
-
- [[get]] always returns a single [[
|
|
50
|
-
- [[getMulti]] always returns an Array<[[
|
|
49
|
+
- [[get]] always returns a single [[IDstoreEntry]].
|
|
50
|
+
- [[getMulti]] always returns an Array<[[IDstoreEntry]]> of the same length as the input Array. Items not found are represented by null.
|
|
51
51
|
- [[set]] is called with `(key, value)` and always returns the complete [[Key]] of the entity being written. Keys are normalized, numeric IDs are always encoded as strings.
|
|
52
52
|
- [[key]] handles [[Key]] object instantiation for you.
|
|
53
|
-
- [[readKey]] extracts the key from an [[
|
|
53
|
+
- [[readKey]] extracts the key from an [[IDstoreEntry]] you have read without the need of fancy `Symbol`-based access to `entity[Datastore.KEY]`. If needed, it tries to deserialize `_keyStr` to create `entity[Datastore.KEY]`. This ist important when rehydrating an [[IDstoreEntry]] from a serializing cache.
|
|
54
54
|
- [[allocateOneId]] returns a single numeric string encoded unique datastore id without the need of fancy unpacking.
|
|
55
55
|
- [[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).
|
|
56
56
|
- [[keySerialize]] is synchronous.
|
|
@@ -116,10 +116,10 @@ class Dstore {
|
|
|
116
116
|
keyFromSerialized(text) {
|
|
117
117
|
return this.urlSaveKey.legacyDecode(text);
|
|
118
118
|
}
|
|
119
|
-
/** `readKey()` extracts the [[Key]] from an [[
|
|
119
|
+
/** `readKey()` extracts the [[Key]] from an [[IDstoreEntry]].
|
|
120
120
|
*
|
|
121
121
|
* Is is an alternative to `entity[Datastore.KEY]` which tends to fail in various contexts and also confuses older Typescript compilers.
|
|
122
|
-
* It can extract the [[Key]] form a [[
|
|
122
|
+
* It can extract the [[Key]] form a [[IDstoreEntry]] which has been serialized to JSON by leveraging the property `_keyStr`.
|
|
123
123
|
*
|
|
124
124
|
* @category Additional
|
|
125
125
|
*/
|
|
@@ -132,7 +132,7 @@ class Dstore {
|
|
|
132
132
|
(0, assertate_1.assertIsObject)(ret, 'entity[Datastore.KEY]/entity._keyStr', `Entity is missing the datastore Key: ${JSON.stringify(ent)}`);
|
|
133
133
|
return ret;
|
|
134
134
|
}
|
|
135
|
-
/** `fixKeys()` is called for all [[
|
|
135
|
+
/** `fixKeys()` is called for all [[IDstoreEntry]]sa returned from [[Dstore]].
|
|
136
136
|
*
|
|
137
137
|
* Is ensures that besides `entity[Datastore.KEY]` there is `_keyStr` to be leveraged by [[readKey]].
|
|
138
138
|
*
|
|
@@ -149,9 +149,9 @@ class Dstore {
|
|
|
149
149
|
});
|
|
150
150
|
return entities;
|
|
151
151
|
}
|
|
152
|
-
/** `get()` reads a [[
|
|
152
|
+
/** `get()` reads a [[IDstoreEntry]] from the Datastore.
|
|
153
153
|
*
|
|
154
|
-
* It returns [[
|
|
154
|
+
* It returns [[IDstoreEntry]] or `null` if not found.
|
|
155
155
|
|
|
156
156
|
* The underlying Datastore API Call is [lookup](https://cloud.google.com/datastore/docs/reference/data/rest/v1/projects/lookup).
|
|
157
157
|
*
|
|
@@ -160,19 +160,20 @@ class Dstore {
|
|
|
160
160
|
* Differences between [[Dstore.get]] and [[Datastore.get]]:
|
|
161
161
|
*
|
|
162
162
|
* - [Dstore.get]] takes a single [[Key]] as Parameter, no Array. Check [[getMulti]] if you want Arrays.
|
|
163
|
-
* - [Dstore.get]] returns a single [[
|
|
163
|
+
* - [Dstore.get]] returns a single [[IDstoreEntry]], no Array.
|
|
164
164
|
*
|
|
165
165
|
* @category Datastore Drop-In
|
|
166
166
|
*/
|
|
167
167
|
async get(key) {
|
|
168
168
|
(0, assertate_1.assertIsObject)(key);
|
|
169
169
|
(0, assertate_1.assert)(!Array.isArray(key));
|
|
170
|
+
(0, assertate_1.assert)(key.path.length % 2 == 0, `key.path must be complete: ${JSON.stringify(key.path)}`);
|
|
170
171
|
const result = await this.getMulti([key]);
|
|
171
172
|
return (result === null || result === void 0 ? void 0 : result[0]) || null;
|
|
172
173
|
}
|
|
173
|
-
/** `getMulti()` reads several [[
|
|
174
|
+
/** `getMulti()` reads several [[IDstoreEntry]]s from the Datastore.
|
|
174
175
|
*
|
|
175
|
-
* It returns a list of [[
|
|
176
|
+
* It returns a list of [[IDstoreEntry]]s or `null` if not found.
|
|
176
177
|
|
|
177
178
|
* The underlying Datastore API Call is [lookup](https://cloud.google.com/datastore/docs/reference/data/rest/v1/projects/lookup).
|
|
178
179
|
*
|
|
@@ -181,7 +182,7 @@ class Dstore {
|
|
|
181
182
|
* Differences between [[Dstore.getMulti]] and [[Datastore.get]]:
|
|
182
183
|
*
|
|
183
184
|
* - [[Dstore.getMulti]] always takes an Array of [[Key]]s as Parameter.
|
|
184
|
-
* - [[Dstore.getMulti]] returns always a Array of [[
|
|
185
|
+
* - [[Dstore.getMulti]] returns always a Array of [[IDstoreEntry]], or null.
|
|
185
186
|
* - [[Datastore.get]] has many edge cases - e.g. when not being able to find any of the provided keys - which return surprising results. [[Dstore.getMulti]] always returns an Array. TODO: return a Array with the same length as the Input.
|
|
186
187
|
*
|
|
187
188
|
* @category Datastore Drop-In
|
|
@@ -239,21 +240,44 @@ class Dstore {
|
|
|
239
240
|
*
|
|
240
241
|
* If the Datastore generates a new ID because of an incomplete [[Key]] *on first save* it will return an large integer as [[Key.id]].
|
|
241
242
|
* On every subsequent `save()` an string encoded number representation is returned.
|
|
242
|
-
* Dstore normalizes that and always
|
|
243
|
+
* @todo Dstore should normalizes that and always return an string encoded number representation.
|
|
244
|
+
*
|
|
245
|
+
* Each [[DstoreSaveEntity]] can have an `excludeFromIndexes` property which is somewhat underdocumented.
|
|
246
|
+
* It can use something like JSON-Path notation
|
|
247
|
+
* ([Source](https://github.com/googleapis/nodejs-datastore/blob/2941f2f0f132b41534e303d441d837051ce88fd7/src/index.ts#L948))
|
|
248
|
+
* [.*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1598),
|
|
249
|
+
* [parent[]](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672),
|
|
250
|
+
* [parent.*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672),
|
|
251
|
+
* [parent[].*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672)
|
|
252
|
+
* and [more complex patterns](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1754)
|
|
253
|
+
* seem to be supported patterns.
|
|
254
|
+
*
|
|
255
|
+
* If the caller has not provided an `excludeLargeProperties` in a [[DstoreSaveEntity]] we will default it
|
|
256
|
+
* to `excludeLargeProperties: true`. Without this you can not store strings longer than 1500 bytes easily
|
|
257
|
+
* ([source](https://github.com/googleapis/nodejs-datastore/blob/c7a08a8382c6706ccbfbbf77950babf40bac757c/src/entity.ts#L961)).
|
|
243
258
|
*
|
|
244
259
|
* @category Datastore Drop-In
|
|
245
260
|
*/
|
|
246
261
|
async save(entities) {
|
|
247
262
|
(0, assertate_1.assertIsArray)(entities);
|
|
248
263
|
try {
|
|
249
|
-
// Within Transaction we
|
|
264
|
+
// Within Transaction we don't get any answer here!
|
|
250
265
|
// [ { mutationResults: [ [Object], [Object] ], indexUpdates: 51 } ]
|
|
251
266
|
for (const e of entities) {
|
|
252
267
|
(0, assertate_1.assertIsObject)(e.key);
|
|
253
268
|
(0, assertate_1.assertIsObject)(e.data);
|
|
254
269
|
this.fixKeys([e.data]);
|
|
270
|
+
e.excludeLargeProperties =
|
|
271
|
+
e.excludeLargeProperties === undefined
|
|
272
|
+
? true
|
|
273
|
+
: e.excludeLargeProperties;
|
|
255
274
|
}
|
|
256
|
-
|
|
275
|
+
const ret = (await this.getDoT().save(entities)) || undefined;
|
|
276
|
+
for (const e of entities) {
|
|
277
|
+
e.data[datastore_1.Datastore.KEY] = e.key;
|
|
278
|
+
this.fixKeys([e.data]);
|
|
279
|
+
}
|
|
280
|
+
return ret;
|
|
257
281
|
}
|
|
258
282
|
catch (error) {
|
|
259
283
|
throw process.env.NODE_ENV === 'test'
|
|
@@ -271,6 +295,8 @@ class Dstore {
|
|
|
271
295
|
*
|
|
272
296
|
* For handling of incomplete [[Key]]s see [[save]].
|
|
273
297
|
*
|
|
298
|
+
* This function can be completely emulated by using [[save]] with `method: 'insert'` inside each [[DstoreSaveEntity]].
|
|
299
|
+
*
|
|
274
300
|
* @throws [[DstoreError]]
|
|
275
301
|
* @category Datastore Drop-In
|
|
276
302
|
*/
|
|
@@ -296,13 +322,20 @@ class Dstore {
|
|
|
296
322
|
* It throws an [[DstoreError]] if there is no Entity with the same [[Key]] in the Datastore. `update()` *overwrites all existing data* for that [[Key]].
|
|
297
323
|
* There was an alpha functionality called `merge()` in the Datastore which read an Entity, merged it with the new data and wrote it back, but this was never documented.
|
|
298
324
|
*
|
|
299
|
-
* `update()` is idempotent.
|
|
325
|
+
* `update()` is idempotent. Updating the same [[Key]] twice is no error.
|
|
326
|
+
*
|
|
327
|
+
* This function can be completely emulated by using [[save]] with `method: 'update'` inside each [[DstoreSaveEntity]].
|
|
300
328
|
*
|
|
301
329
|
* @throws [[DstoreError]]
|
|
302
330
|
* @category Datastore Drop-In
|
|
303
331
|
*/
|
|
304
332
|
async update(entities) {
|
|
305
333
|
(0, assertate_1.assertIsArray)(entities);
|
|
334
|
+
entities.forEach((entity) => (0, assertate_1.assertIsObject)(entity.key));
|
|
335
|
+
entities.forEach((entity) => (0, assertate_1.assert)(entity.key.path.length % 2 == 0, `entity.key.path must be complete: ${JSON.stringify([
|
|
336
|
+
entity.key.path,
|
|
337
|
+
entity,
|
|
338
|
+
])}`));
|
|
306
339
|
try {
|
|
307
340
|
return (await this.getDoT().update(entities)) || undefined;
|
|
308
341
|
}
|
|
@@ -313,9 +346,9 @@ class Dstore {
|
|
|
313
346
|
: new DstoreError('datastore.update error', error);
|
|
314
347
|
}
|
|
315
348
|
}
|
|
316
|
-
/** `delete()` is compatible to [Datastore.
|
|
349
|
+
/** `delete()` is compatible to [Datastore.delete()].
|
|
317
350
|
*
|
|
318
|
-
* Unfortunately currently (late 2021) there is no formal documentation from Google on [Datastore.
|
|
351
|
+
* Unfortunately currently (late 2021) there is no formal documentation from Google on [Datastore.delete()].
|
|
319
352
|
*
|
|
320
353
|
* The single Parameter is a list of [[Key]]s.
|
|
321
354
|
* If called within a transaction it returns `undefined`.
|
|
@@ -329,6 +362,7 @@ class Dstore {
|
|
|
329
362
|
async delete(keys) {
|
|
330
363
|
(0, assertate_1.assertIsArray)(keys);
|
|
331
364
|
keys.forEach((key) => (0, assertate_1.assertIsObject)(key));
|
|
365
|
+
keys.forEach((key) => (0, assertate_1.assert)(key.path.length % 2 == 0, `key.path must be complete: ${JSON.stringify(key.path)}`));
|
|
332
366
|
try {
|
|
333
367
|
return (await this.getDoT().delete(keys)) || undefined;
|
|
334
368
|
}
|
|
@@ -357,7 +391,8 @@ class Dstore {
|
|
|
357
391
|
}
|
|
358
392
|
async runQuery(query) {
|
|
359
393
|
try {
|
|
360
|
-
|
|
394
|
+
const [entities, info] = await this.getDoT().runQuery(query);
|
|
395
|
+
return [this.fixKeys(entities), info];
|
|
361
396
|
}
|
|
362
397
|
catch (error) {
|
|
363
398
|
throw new DstoreError('datastore.runQuery error', error);
|
|
@@ -416,8 +451,6 @@ class Dstore {
|
|
|
416
451
|
}
|
|
417
452
|
/** This tries to give high level access to transactions.
|
|
418
453
|
|
|
419
|
-
Be aware that Transactions differ considerable between Master-Slave Datastore (very old), High Replication Datastore (old, later called [Google Cloud Datastore](https://cloud.google.com/datastore/docs/concepts/cloud-datastore-transactions)) and [Firestore in Datastore Mode](https://cloud.google.com/datastore/docs/firestore-or-datastore#in_datastore_mode) (current).
|
|
420
|
-
|
|
421
454
|
So called "Gross Group Transactions" are always enabled. Transactions are never Cross Project. `runInTransaction()` works only if you use the same [[KvStore] instance for all access within the Transaction.
|
|
422
455
|
|
|
423
456
|
[[runInTransaction]] is modelled after Python 2.7 [ndb's `@ndb.transactional` feature](https://cloud.google.com/appengine/docs/standard/python/ndb/transactions). This is based on node's [AsyncLocalStorage](https://nodejs.org/docs/latest-v14.x/api/async_hooks.html).
|
|
@@ -425,7 +458,11 @@ class Dstore {
|
|
|
425
458
|
Transactions frequently fail if you try to access the same data via in a transaction. See the [Documentation on Locking](https://cloud.google.com/datastore/docs/concepts/transactions#transaction_locks) for further reference. You are advised to use [p-limit](https://github.com/sindresorhus/p-limit)(1) to serialize transactions touching the same resource. This should work nicely with node's single process model. It is a much bigger problem on shared-nothing approaches, like Python on App Engine.
|
|
426
459
|
|
|
427
460
|
Transactions might be wrapped in [p-retry](https://github.com/sindresorhus/p-retry) to implement automatically retrying them with exponential back-off should they fail due to contention.
|
|
428
|
-
|
|
461
|
+
|
|
462
|
+
Be aware that Transactions differ considerable between Master-Slave Datastore (very old), High Replication Datastore (old, later called [Google Cloud Datastore](https://cloud.google.com/datastore/docs/concepts/cloud-datastore-transactions)) and [Firestore in Datastore Mode](https://cloud.google.com/datastore/docs/firestore-or-datastore#in_datastore_mode) (current).
|
|
463
|
+
|
|
464
|
+
Most Applications today are running on "Firestore in Datastore Mode". Beware that the Datastore-Emulator fails with `error: 3 INVALID_ARGUMENT: Only ancestor queries are allowed inside transactions.` during [[runQuery]] while the Datastore on Google Infrastructure does not have such an restriction anymore as of 2022.
|
|
465
|
+
*/
|
|
429
466
|
async runInTransaction(func) {
|
|
430
467
|
let ret;
|
|
431
468
|
const transaction = this.datastore.transaction();
|
|
@@ -474,4 +511,4 @@ class DstoreError extends Error {
|
|
|
474
511
|
}
|
|
475
512
|
}
|
|
476
513
|
exports.DstoreError = DstoreError;
|
|
477
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHN0b3JlLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZHN0b3JlLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7OztHQVNHOzs7Ozs7QUFFSCw2Q0FBZ0Q7QUFFaEQsdURBTWlDO0FBQ2pDLHFFQUFrRTtBQU1sRSx5Q0FPbUI7QUFDbkIsa0RBQTBCO0FBRzFCLGNBQWM7QUFDZCxxREFNaUM7QUFML0Isc0dBQUEsU0FBUyxPQUFBO0FBQ1QsZ0dBQUEsR0FBRyxPQUFBO0FBRUgsa0dBQUEsS0FBSyxPQUFBO0FBQ0wsd0dBQUEsV0FBVyxPQUFBO0FBR2IsY0FBYztBQUNkLE1BQU0sS0FBSyxHQUFHLElBQUEsZUFBSyxFQUFDLFFBQVEsQ0FBQyxDQUFDO0FBRTlCLGNBQWM7QUFFZDs7O0dBR0c7QUFDSCxNQUFNLDRCQUE0QixHQUFHLElBQUksK0JBQWlCLEVBQUUsQ0FBQztBQUVoRCxRQUFBLE1BQU0sR0FBRyxxQkFBUyxDQUFDLEdBQUcsQ0FBQztBQXFGcEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFzQkU7QUFDRixNQUFhLE1BQU07SUFHakI7Ozs7Ozs7Ozs7Ozs7O01BY0U7SUFDRixZQUNXLFNBQW9CLEVBQ3BCLFNBQWtCLEVBQ2xCLE1BQWU7UUFGZixjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3BCLGNBQVMsR0FBVCxTQUFTLENBQVM7UUFDbEIsV0FBTSxHQUFOLE1BQU0sQ0FBUztRQXBCVCxlQUFVLEdBQUcsSUFBSSxlQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7UUFzQnBELElBQUEsMEJBQWMsRUFBQyxTQUFTLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQscURBQXFEO0lBQzdDLE1BQU07UUFDWixPQUFPLENBQ0osNEJBQTRCLENBQUMsUUFBUSxFQUFrQixJQUFJLElBQUksQ0FBQyxTQUFTLENBQzNFLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEdBQUcsQ0FB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
|
|
514
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHN0b3JlLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZHN0b3JlLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7OztHQVNHOzs7Ozs7QUFFSCw2Q0FBZ0Q7QUFFaEQsdURBTWlDO0FBQ2pDLHFFQUEwRTtBQU8xRSx5Q0FPbUI7QUFDbkIsa0RBQTBCO0FBRzFCLGNBQWM7QUFDZCxxREFNaUM7QUFML0Isc0dBQUEsU0FBUyxPQUFBO0FBQ1QsZ0dBQUEsR0FBRyxPQUFBO0FBRUgsa0dBQUEsS0FBSyxPQUFBO0FBQ0wsd0dBQUEsV0FBVyxPQUFBO0FBR2IsY0FBYztBQUNkLE1BQU0sS0FBSyxHQUFHLElBQUEsZUFBSyxFQUFDLFFBQVEsQ0FBQyxDQUFDO0FBRTlCLGNBQWM7QUFFZDs7O0dBR0c7QUFDSCxNQUFNLDRCQUE0QixHQUFHLElBQUksK0JBQWlCLEVBQUUsQ0FBQztBQUVoRCxRQUFBLE1BQU0sR0FBRyxxQkFBUyxDQUFDLEdBQUcsQ0FBQztBQXdGcEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFzQkU7QUFDRixNQUFhLE1BQU07SUFHakI7Ozs7Ozs7Ozs7Ozs7O01BY0U7SUFDRixZQUNXLFNBQW9CLEVBQ3BCLFNBQWtCLEVBQ2xCLE1BQWU7UUFGZixjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3BCLGNBQVMsR0FBVCxTQUFTLENBQVM7UUFDbEIsV0FBTSxHQUFOLE1BQU0sQ0FBUztRQXBCVCxlQUFVLEdBQUcsSUFBSSxlQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7UUFzQnBELElBQUEsMEJBQWMsRUFBQyxTQUFTLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQscURBQXFEO0lBQzdDLE1BQU07UUFDWixPQUFPLENBQ0osNEJBQTRCLENBQUMsUUFBUSxFQUFrQixJQUFJLElBQUksQ0FBQyxTQUFTLENBQzNFLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEdBQUcsQ0FB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
|