datastore-api 1.1.0 → 1.3.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 +22 -0
- package/README.md +3 -2
- package/build/main/lib/dstore-api.d.ts +63 -47
- package/build/main/lib/dstore-api.js +71 -56
- package/build/main/lib/dstore-api.spec.js +65 -99
- package/build/module/lib/dstore-api.d.ts +63 -47
- package/build/module/lib/dstore-api.js +67 -55
- package/build/module/lib/dstore-api.spec.js +64 -99
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
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.3.0](https://github.com/mdornseif/datastore-api/compare/v1.2.0...v1.3.0) (2022-01-03)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* Set excludeLargeProperties by default. ([289cd28](https://github.com/mdornseif/datastore-api/commit/289cd289651b0c34f36098370b3dfbe249790c5a))
|
|
11
|
+
|
|
12
|
+
## [1.2.0](https://github.com/mdornseif/datastore-api/compare/v1.1.3...v1.2.0) (2021-12-30)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* add `query(... selection)` ([e9f8053](https://github.com/mdornseif/datastore-api/commit/e9f8053fa98f496e69ccf83e649e7c1502751f16))
|
|
18
|
+
* add KEYSYM ([d97eff0](https://github.com/mdornseif/datastore-api/commit/d97eff09f0c7dd60caa860eda45975438d369920))
|
|
19
|
+
* debug log; removed readonly from several types ([f1fcdb6](https://github.com/mdornseif/datastore-api/commit/f1fcdb62551c3c624fcfd67f550f40a5bbd38138))
|
|
20
|
+
|
|
21
|
+
### [1.1.3](https://github.com/mdornseif/datastore-api/compare/v1.1.2...v1.1.3) (2021-12-29)
|
|
22
|
+
|
|
23
|
+
### [1.1.2](https://github.com/mdornseif/datastore-api/compare/v1.1.1...v1.1.2) (2021-12-29)
|
|
24
|
+
|
|
25
|
+
### [1.1.1](https://github.com/mdornseif/datastore-api/compare/v1.1.0...v1.1.1) (2021-12-29)
|
|
26
|
+
|
|
5
27
|
## [1.1.0](https://github.com/mdornseif/datastore-api/compare/v1.0.2...v1.1.0) (2021-12-25)
|
|
6
28
|
|
|
7
29
|
|
package/README.md
CHANGED
|
@@ -22,9 +22,9 @@ Main differences:
|
|
|
22
22
|
|
|
23
23
|
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
24
|
|
|
25
|
-
See [the API documentation](http://mdornseif.io/datastore-api/classes/Dstore.html) for Details.
|
|
25
|
+
See [the API documentation](http://mdornseif.io/datastore-api/classes/Dstore.html) for Details, [Github](https://github.com/mdornseif/datastore-api) for source.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
## See also
|
|
28
28
|
|
|
29
29
|
- Google Documentation
|
|
30
30
|
|
|
@@ -33,6 +33,7 @@ See [the API documentation](http://mdornseif.io/datastore-api/classes/Dstore.htm
|
|
|
33
33
|
- 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
34
|
- [SDK Source](https://github.com/googleapis/nodejs-datastore)
|
|
35
35
|
- [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)
|
|
36
37
|
|
|
37
38
|
- API Simplification
|
|
38
39
|
- [google-cloud-datastore-node](https://www.npmjs.com/package/google-cloud-datastore-node)
|
|
@@ -4,57 +4,58 @@ import { Operator, RunQueryResponse } from '@google-cloud/datastore/build/src/qu
|
|
|
4
4
|
import { CommitResponse } from '@google-cloud/datastore/build/src/request';
|
|
5
5
|
/** @ignore */
|
|
6
6
|
export { Datastore, Key, PathType, Query, Transaction, } from '@google-cloud/datastore';
|
|
7
|
+
export declare const KEYSYM: symbol;
|
|
7
8
|
export declare type IGqlFilterTypes = boolean | string | number;
|
|
8
9
|
export declare type IGqlFilterSpec = {
|
|
9
10
|
readonly eq: IGqlFilterTypes;
|
|
10
11
|
};
|
|
11
12
|
export declare type TGqlFilterList = Array<[string, Operator, DstorePropertyValues]>;
|
|
12
13
|
/** Define what can be written into the Datastore */
|
|
13
|
-
export declare type DstorePropertyValues = number | string | Date | boolean | null | undefined | Buffer | Key |
|
|
14
|
-
|
|
14
|
+
export declare type DstorePropertyValues = number | string | Date | boolean | null | undefined | Buffer | Key | DstorePropertyValues[] | {
|
|
15
|
+
[key: string]: DstorePropertyValues;
|
|
15
16
|
};
|
|
16
|
-
export interface
|
|
17
|
+
export interface IDstoreEntryWithoutKey {
|
|
17
18
|
/** All User Data stored in the Datastore */
|
|
18
|
-
|
|
19
|
+
[key: string]: DstorePropertyValues;
|
|
19
20
|
}
|
|
20
21
|
/** Represents what is actually stored inside the Datastore, called "Entity" by Google
|
|
21
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 code. It is automatically used
|
|
22
23
|
to reconstruct `[Datastore.KEY]`, if you use [[Dstore.readKey]].
|
|
23
24
|
*/
|
|
24
|
-
export interface
|
|
25
|
+
export interface IDstoreEntry extends IDstoreEntryWithoutKey {
|
|
25
26
|
readonly [Datastore.KEY]?: Key;
|
|
26
27
|
/** [Datastore.KEY] key */
|
|
27
28
|
_keyStr: string;
|
|
28
29
|
/** All User Data stored in the Datastore */
|
|
29
|
-
|
|
30
|
+
[key: string]: DstorePropertyValues;
|
|
30
31
|
}
|
|
31
32
|
/** Represents the thing you pass to the save method. Also called "Entity" by Google */
|
|
32
33
|
export declare type DstoreSaveEntity = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
key: Key;
|
|
35
|
+
data: Omit<IDstoreEntry, '_keyStr' | Datastore['KEY']>;
|
|
36
|
+
method?: 'insert' | 'update' | 'upsert';
|
|
37
|
+
excludeLargeProperties?: boolean;
|
|
38
|
+
excludeFromIndexes?: readonly string[];
|
|
38
39
|
};
|
|
39
40
|
declare type IDstore = {
|
|
40
41
|
/** Accessible by Users of the library. Keep in mind that you will access outside transactions created by [[runInTransaction]]. */
|
|
41
42
|
readonly datastore: Datastore;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
43
|
+
key: (path: ReadonlyArray<PathType>) => Key;
|
|
44
|
+
keyFromSerialized: (text: string) => Key;
|
|
45
|
+
keySerialize: (key: Key) => string;
|
|
46
|
+
readKey: (entry: IDstoreEntry) => Key;
|
|
47
|
+
get: (key: Key) => Promise<IDstoreEntry | null>;
|
|
48
|
+
getMulti: (keys: ReadonlyArray<Key>) => Promise<ReadonlyArray<IDstoreEntry | undefined>>;
|
|
49
|
+
set: (key: Key, entry: IDstoreEntry) => Promise<Key>;
|
|
50
|
+
save: (entities: readonly DstoreSaveEntity[]) => Promise<CommitResponse | undefined>;
|
|
51
|
+
insert: (entities: readonly DstoreSaveEntity[]) => Promise<CommitResponse | undefined>;
|
|
52
|
+
update: (entities: readonly DstoreSaveEntity[]) => Promise<CommitResponse | undefined>;
|
|
53
|
+
delete: (keys: readonly Key[]) => Promise<CommitResponse | undefined>;
|
|
54
|
+
createQuery: (kind: string) => Query;
|
|
55
|
+
query: (kind: string, filters?: TGqlFilterList, limit?: number, ordering?: readonly string[], selection?: readonly string[], cursor?: string) => Promise<RunQueryResponse>;
|
|
56
|
+
runQuery: (query: Query | Omit<Query, 'run'>) => Promise<RunQueryResponse>;
|
|
57
|
+
allocateOneId: (kindName: string) => Promise<string>;
|
|
58
|
+
runInTransaction: <T>(func: {
|
|
58
59
|
(): Promise<T>;
|
|
59
60
|
(): T;
|
|
60
61
|
}) => Promise<T>;
|
|
@@ -64,18 +65,18 @@ declare type IDstore = {
|
|
|
64
65
|
[@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.
|
|
65
66
|
(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.
|
|
66
67
|
|
|
67
|
-
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` - [[
|
|
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` - [[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.
|
|
68
69
|
|
|
69
70
|
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).
|
|
70
71
|
|
|
71
72
|
Main differences:
|
|
72
73
|
|
|
73
74
|
- Everything asynchronous is Promise-based - no callbacks.
|
|
74
|
-
- [[get]] always returns a single [[
|
|
75
|
-
- [[getMulti]] always returns an Array<[[
|
|
75
|
+
- [[get]] always returns a single [[IDstoreEntry]].
|
|
76
|
+
- [[getMulti]] always returns an Array<[[IDstoreEntry]]> of the same length as the input Array. Items not found are represented by null.
|
|
76
77
|
- [[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.
|
|
77
78
|
- [[key]] handles [[Key]] object instantiation for you.
|
|
78
|
-
- [[readKey]] extracts the key from an [[
|
|
79
|
+
- [[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.
|
|
79
80
|
- [[allocateOneId]] returns a single numeric string encoded unique datastore id without the need of fancy unpacking.
|
|
80
81
|
- [[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).
|
|
81
82
|
- [[keySerialize]] is synchronous.
|
|
@@ -130,24 +131,24 @@ export declare class Dstore implements IDstore {
|
|
|
130
131
|
* @category Datastore Drop-In
|
|
131
132
|
*/
|
|
132
133
|
keyFromSerialized(text: string): Key;
|
|
133
|
-
/** `readKey()` extracts the [[Key]] from an [[
|
|
134
|
+
/** `readKey()` extracts the [[Key]] from an [[IDstoreEntry]].
|
|
134
135
|
*
|
|
135
136
|
* Is is an alternative to `entity[Datastore.KEY]` which tends to fail in various contexts and also confuses older Typescript compilers.
|
|
136
|
-
* It can extract the [[Key]] form a [[
|
|
137
|
+
* It can extract the [[Key]] form a [[IDstoreEntry]] which has been serialized to JSON by leveraging the property `_keyStr`.
|
|
137
138
|
*
|
|
138
139
|
* @category Additional
|
|
139
140
|
*/
|
|
140
|
-
readKey(ent:
|
|
141
|
-
/** `fixKeys()` is called for all [[
|
|
141
|
+
readKey(ent: IDstoreEntry): Key;
|
|
142
|
+
/** `fixKeys()` is called for all [[IDstoreEntry]]sa returned from [[Dstore]].
|
|
142
143
|
*
|
|
143
144
|
* Is ensures that besides `entity[Datastore.KEY]` there is `_keyStr` to be leveraged by [[readKey]].
|
|
144
145
|
*
|
|
145
146
|
* @internal
|
|
146
147
|
*/
|
|
147
148
|
private fixKeys;
|
|
148
|
-
/** `get()` reads a [[
|
|
149
|
+
/** `get()` reads a [[IDstoreEntry]] from the Datastore.
|
|
149
150
|
*
|
|
150
|
-
* It returns [[
|
|
151
|
+
* It returns [[IDstoreEntry]] or `null` if not found.
|
|
151
152
|
|
|
152
153
|
* The underlying Datastore API Call is [lookup](https://cloud.google.com/datastore/docs/reference/data/rest/v1/projects/lookup).
|
|
153
154
|
*
|
|
@@ -156,14 +157,14 @@ export declare class Dstore implements IDstore {
|
|
|
156
157
|
* Differences between [[Dstore.get]] and [[Datastore.get]]:
|
|
157
158
|
*
|
|
158
159
|
* - [Dstore.get]] takes a single [[Key]] as Parameter, no Array. Check [[getMulti]] if you want Arrays.
|
|
159
|
-
* - [Dstore.get]] returns a single [[
|
|
160
|
+
* - [Dstore.get]] returns a single [[IDstoreEntry]], no Array.
|
|
160
161
|
*
|
|
161
162
|
* @category Datastore Drop-In
|
|
162
163
|
*/
|
|
163
|
-
get(key: Key): Promise<
|
|
164
|
-
/** `getMulti()` reads several [[
|
|
164
|
+
get(key: Key): Promise<IDstoreEntry | null>;
|
|
165
|
+
/** `getMulti()` reads several [[IDstoreEntry]]s from the Datastore.
|
|
165
166
|
*
|
|
166
|
-
* It returns a list of [[
|
|
167
|
+
* It returns a list of [[IDstoreEntry]]s or `null` if not found.
|
|
167
168
|
|
|
168
169
|
* The underlying Datastore API Call is [lookup](https://cloud.google.com/datastore/docs/reference/data/rest/v1/projects/lookup).
|
|
169
170
|
*
|
|
@@ -172,12 +173,12 @@ export declare class Dstore implements IDstore {
|
|
|
172
173
|
* Differences between [[Dstore.getMulti]] and [[Datastore.get]]:
|
|
173
174
|
*
|
|
174
175
|
* - [[Dstore.getMulti]] always takes an Array of [[Key]]s as Parameter.
|
|
175
|
-
* - [[Dstore.getMulti]] returns always a Array of [[
|
|
176
|
+
* - [[Dstore.getMulti]] returns always a Array of [[IDstoreEntry]], or null.
|
|
176
177
|
* - [[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.
|
|
177
178
|
*
|
|
178
179
|
* @category Datastore Drop-In
|
|
179
180
|
*/
|
|
180
|
-
getMulti(keys: readonly Key[]): Promise<
|
|
181
|
+
getMulti(keys: readonly Key[]): Promise<Array<IDstoreEntry | undefined>>;
|
|
181
182
|
/** `set()` is addition to [[Datastore]]. It provides a classic Key-value Interface.
|
|
182
183
|
*
|
|
183
184
|
* Instead providing a nested [[DstoreSaveEntity]] to [[save]] you can call set directly as `set( key, value)`.
|
|
@@ -194,7 +195,7 @@ export declare class Dstore implements IDstore {
|
|
|
194
195
|
*
|
|
195
196
|
* @category Additional
|
|
196
197
|
*/
|
|
197
|
-
set(key: Key, data:
|
|
198
|
+
set(key: Key, data: IDstoreEntry): Promise<Key>;
|
|
198
199
|
/** `save()` is compatible to [Datastore.save()](https://cloud.google.com/nodejs/docs/reference/datastore/latest/datastore/datastore#_google_cloud_datastore_Datastore_save_member_1_).
|
|
199
200
|
*
|
|
200
201
|
* The single Parameter is a list of [[DstoreSaveEntity]]s.
|
|
@@ -212,6 +213,20 @@ export declare class Dstore implements IDstore {
|
|
|
212
213
|
* On every subsequent `save()` an string encoded number representation is returned.
|
|
213
214
|
* Dstore normalizes that and always returns an string encoded number representation.
|
|
214
215
|
*
|
|
216
|
+
* Each [[DstoreSaveEntity]] can have an `excludeFromIndexes` property which is somewhat underdocumented.
|
|
217
|
+
* It can use something like JSON-Path notation
|
|
218
|
+
* ([Source](https://github.com/googleapis/nodejs-datastore/blob/2941f2f0f132b41534e303d441d837051ce88fd7/src/index.ts#L948))
|
|
219
|
+
* [.*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1598),
|
|
220
|
+
* [parent[]](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672),
|
|
221
|
+
* [parent.*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672),
|
|
222
|
+
* [parent[].*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672)
|
|
223
|
+
* and [more complex patterns](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1754)
|
|
224
|
+
* seem to be supported patterns.
|
|
225
|
+
*
|
|
226
|
+
* If the caller has not provided an `excludeLargeProperties` in a [[DstoreSaveEntity]] we will default it
|
|
227
|
+
* to `excludeLargeProperties: true`. Without this you can not store strings longer than 1500 bytes easily
|
|
228
|
+
* ([source](https://github.com/googleapis/nodejs-datastore/blob/c7a08a8382c6706ccbfbbf77950babf40bac757c/src/entity.ts#L961)).
|
|
229
|
+
*
|
|
215
230
|
* @category Datastore Drop-In
|
|
216
231
|
*/
|
|
217
232
|
save(entities: readonly DstoreSaveEntity[]): Promise<CommitResponse | undefined>;
|
|
@@ -266,9 +281,10 @@ export declare class Dstore implements IDstore {
|
|
|
266
281
|
* @param kind Name of the [[Datastore]][Kind](https://cloud.google.com/datastore/docs/concepts/entities#kinds_and_identifiers) ("Table") which should be searched.
|
|
267
282
|
*
|
|
268
283
|
* @category Datastore Drop-In
|
|
269
|
-
*/
|
|
284
|
+
*/
|
|
285
|
+
createQuery(kind: string): Query;
|
|
270
286
|
runQuery(query: Query | Omit<Query, 'run'>): Promise<RunQueryResponse>;
|
|
271
|
-
query(kindName: string, filters?: TGqlFilterList, limit?: number,
|
|
287
|
+
query(kindName: string, filters?: TGqlFilterList, limit?: number, ordering?: readonly string[], selection?: string[], cursor?: string): Promise<RunQueryResponse>;
|
|
272
288
|
/** Allocate one ID in the Datastore.
|
|
273
289
|
*
|
|
274
290
|
* Currently (late 2021) there is no documentation provided by Google for the underlying node function.
|
|
@@ -289,7 +305,7 @@ export declare class Dstore implements IDstore {
|
|
|
289
305
|
|
|
290
306
|
[[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).
|
|
291
307
|
|
|
292
|
-
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
|
|
308
|
+
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.
|
|
293
309
|
|
|
294
310
|
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.
|
|
295
311
|
*/
|
|
@@ -7,15 +7,18 @@
|
|
|
7
7
|
* In future https://github.com/graphql/dataloader might be used for batching.
|
|
8
8
|
*
|
|
9
9
|
* Created by Dr. Maximillian Dornseif 2021-12-05 in huwawi3backend 11.10.0
|
|
10
|
-
* Copyright (c) Dr. Maximillian Dornseif
|
|
10
|
+
* Copyright (c) 2021 Dr. Maximillian Dornseif
|
|
11
11
|
*/
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
12
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.DstoreError = exports.Dstore = exports.Transaction = exports.Query = exports.Key = exports.Datastore = void 0;
|
|
16
|
+
exports.DstoreError = exports.Dstore = exports.KEYSYM = exports.Transaction = exports.Query = exports.Key = exports.Datastore = void 0;
|
|
14
17
|
const async_hooks_1 = require("async_hooks");
|
|
15
18
|
const datastore_1 = require("@google-cloud/datastore");
|
|
16
19
|
const entity_1 = require("@google-cloud/datastore/build/src/entity");
|
|
17
20
|
const assertate_1 = require("assertate");
|
|
18
|
-
|
|
21
|
+
const debug_1 = __importDefault(require("debug"));
|
|
19
22
|
/** @ignore */
|
|
20
23
|
var datastore_2 = require("@google-cloud/datastore");
|
|
21
24
|
Object.defineProperty(exports, "Datastore", { enumerable: true, get: function () { return datastore_2.Datastore; } });
|
|
@@ -23,26 +26,31 @@ Object.defineProperty(exports, "Key", { enumerable: true, get: function () { ret
|
|
|
23
26
|
Object.defineProperty(exports, "Query", { enumerable: true, get: function () { return datastore_2.Query; } });
|
|
24
27
|
Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return datastore_2.Transaction; } });
|
|
25
28
|
/** @ignore */
|
|
26
|
-
|
|
29
|
+
const debug = (0, debug_1.default)('ds:api');
|
|
27
30
|
/** @ignore */
|
|
31
|
+
/** Use instead of Datastore.KEY
|
|
32
|
+
*
|
|
33
|
+
* Even better: use `_key` instead.
|
|
34
|
+
*/
|
|
28
35
|
const transactionAsyncLocalStorage = new async_hooks_1.AsyncLocalStorage();
|
|
36
|
+
exports.KEYSYM = datastore_1.Datastore.KEY;
|
|
29
37
|
/** Dstore implements a slightly more accessible version of the [Google Cloud Datastore: Node.js Client](https://cloud.google.com/nodejs/docs/reference/datastore/latest)
|
|
30
38
|
|
|
31
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.
|
|
32
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.
|
|
33
41
|
|
|
34
|
-
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.
|
|
35
43
|
|
|
36
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).
|
|
37
45
|
|
|
38
46
|
Main differences:
|
|
39
47
|
|
|
40
48
|
- Everything asynchronous is Promise-based - no callbacks.
|
|
41
|
-
- [[get]] always returns a single [[
|
|
42
|
-
- [[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.
|
|
43
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.
|
|
44
52
|
- [[key]] handles [[Key]] object instantiation for you.
|
|
45
|
-
- [[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.
|
|
46
54
|
- [[allocateOneId]] returns a single numeric string encoded unique datastore id without the need of fancy unpacking.
|
|
47
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).
|
|
48
56
|
- [[keySerialize]] is synchronous.
|
|
@@ -108,10 +116,10 @@ class Dstore {
|
|
|
108
116
|
keyFromSerialized(text) {
|
|
109
117
|
return this.urlSaveKey.legacyDecode(text);
|
|
110
118
|
}
|
|
111
|
-
/** `readKey()` extracts the [[Key]] from an [[
|
|
119
|
+
/** `readKey()` extracts the [[Key]] from an [[IDstoreEntry]].
|
|
112
120
|
*
|
|
113
121
|
* Is is an alternative to `entity[Datastore.KEY]` which tends to fail in various contexts and also confuses older Typescript compilers.
|
|
114
|
-
* 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`.
|
|
115
123
|
*
|
|
116
124
|
* @category Additional
|
|
117
125
|
*/
|
|
@@ -124,7 +132,7 @@ class Dstore {
|
|
|
124
132
|
(0, assertate_1.assertIsObject)(ret, 'entity[Datastore.KEY]/entity._keyStr', `Entity is missing the datastore Key: ${JSON.stringify(ent)}`);
|
|
125
133
|
return ret;
|
|
126
134
|
}
|
|
127
|
-
/** `fixKeys()` is called for all [[
|
|
135
|
+
/** `fixKeys()` is called for all [[IDstoreEntry]]sa returned from [[Dstore]].
|
|
128
136
|
*
|
|
129
137
|
* Is ensures that besides `entity[Datastore.KEY]` there is `_keyStr` to be leveraged by [[readKey]].
|
|
130
138
|
*
|
|
@@ -135,15 +143,15 @@ class Dstore {
|
|
|
135
143
|
if (!!(x === null || x === void 0 ? void 0 : x[datastore_1.Datastore.KEY]) && x[datastore_1.Datastore.KEY]) {
|
|
136
144
|
(0, assertate_1.assertIsDefined)(x[datastore_1.Datastore.KEY]);
|
|
137
145
|
(0, assertate_1.assertIsObject)(x[datastore_1.Datastore.KEY]);
|
|
138
|
-
//
|
|
146
|
+
// Old TypesScript has problems with symbols as a property
|
|
139
147
|
x._keyStr = this.keySerialize(x[datastore_1.Datastore.KEY]);
|
|
140
148
|
}
|
|
141
149
|
});
|
|
142
150
|
return entities;
|
|
143
151
|
}
|
|
144
|
-
/** `get()` reads a [[
|
|
152
|
+
/** `get()` reads a [[IDstoreEntry]] from the Datastore.
|
|
145
153
|
*
|
|
146
|
-
* It returns [[
|
|
154
|
+
* It returns [[IDstoreEntry]] or `null` if not found.
|
|
147
155
|
|
|
148
156
|
* The underlying Datastore API Call is [lookup](https://cloud.google.com/datastore/docs/reference/data/rest/v1/projects/lookup).
|
|
149
157
|
*
|
|
@@ -152,19 +160,19 @@ class Dstore {
|
|
|
152
160
|
* Differences between [[Dstore.get]] and [[Datastore.get]]:
|
|
153
161
|
*
|
|
154
162
|
* - [Dstore.get]] takes a single [[Key]] as Parameter, no Array. Check [[getMulti]] if you want Arrays.
|
|
155
|
-
* - [Dstore.get]] returns a single [[
|
|
163
|
+
* - [Dstore.get]] returns a single [[IDstoreEntry]], no Array.
|
|
156
164
|
*
|
|
157
165
|
* @category Datastore Drop-In
|
|
158
166
|
*/
|
|
159
167
|
async get(key) {
|
|
160
168
|
(0, assertate_1.assertIsObject)(key);
|
|
161
169
|
(0, assertate_1.assert)(!Array.isArray(key));
|
|
162
|
-
const
|
|
163
|
-
return (
|
|
170
|
+
const result = await this.getMulti([key]);
|
|
171
|
+
return (result === null || result === void 0 ? void 0 : result[0]) || null;
|
|
164
172
|
}
|
|
165
|
-
/** `getMulti()` reads several [[
|
|
173
|
+
/** `getMulti()` reads several [[IDstoreEntry]]s from the Datastore.
|
|
166
174
|
*
|
|
167
|
-
* It returns a list of [[
|
|
175
|
+
* It returns a list of [[IDstoreEntry]]s or `null` if not found.
|
|
168
176
|
|
|
169
177
|
* The underlying Datastore API Call is [lookup](https://cloud.google.com/datastore/docs/reference/data/rest/v1/projects/lookup).
|
|
170
178
|
*
|
|
@@ -173,7 +181,7 @@ class Dstore {
|
|
|
173
181
|
* Differences between [[Dstore.getMulti]] and [[Datastore.get]]:
|
|
174
182
|
*
|
|
175
183
|
* - [[Dstore.getMulti]] always takes an Array of [[Key]]s as Parameter.
|
|
176
|
-
* - [[Dstore.getMulti]] returns always a Array of [[
|
|
184
|
+
* - [[Dstore.getMulti]] returns always a Array of [[IDstoreEntry]], or null.
|
|
177
185
|
* - [[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
186
|
*
|
|
179
187
|
* @category Datastore Drop-In
|
|
@@ -233,17 +241,35 @@ class Dstore {
|
|
|
233
241
|
* On every subsequent `save()` an string encoded number representation is returned.
|
|
234
242
|
* Dstore normalizes that and always returns an string encoded number representation.
|
|
235
243
|
*
|
|
244
|
+
* Each [[DstoreSaveEntity]] can have an `excludeFromIndexes` property which is somewhat underdocumented.
|
|
245
|
+
* It can use something like JSON-Path notation
|
|
246
|
+
* ([Source](https://github.com/googleapis/nodejs-datastore/blob/2941f2f0f132b41534e303d441d837051ce88fd7/src/index.ts#L948))
|
|
247
|
+
* [.*](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1598),
|
|
248
|
+
* [parent[]](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1672),
|
|
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
|
+
* and [more complex patterns](https://github.com/googleapis/nodejs-datastore/blob/406b15d2014087172df617c6e0a397a2c0902c5f/test/index.ts#L1754)
|
|
252
|
+
* seem to be supported patterns.
|
|
253
|
+
*
|
|
254
|
+
* If the caller has not provided an `excludeLargeProperties` in a [[DstoreSaveEntity]] we will default it
|
|
255
|
+
* to `excludeLargeProperties: true`. Without this you can not store strings longer than 1500 bytes easily
|
|
256
|
+
* ([source](https://github.com/googleapis/nodejs-datastore/blob/c7a08a8382c6706ccbfbbf77950babf40bac757c/src/entity.ts#L961)).
|
|
257
|
+
*
|
|
236
258
|
* @category Datastore Drop-In
|
|
237
259
|
*/
|
|
238
260
|
async save(entities) {
|
|
239
261
|
(0, assertate_1.assertIsArray)(entities);
|
|
240
262
|
try {
|
|
241
|
-
//
|
|
263
|
+
// Within Transaction we don't get any answer here!
|
|
242
264
|
// [ { mutationResults: [ [Object], [Object] ], indexUpdates: 51 } ]
|
|
243
265
|
for (const e of entities) {
|
|
244
266
|
(0, assertate_1.assertIsObject)(e.key);
|
|
245
267
|
(0, assertate_1.assertIsObject)(e.data);
|
|
246
268
|
this.fixKeys([e.data]);
|
|
269
|
+
e.excludeLargeProperties =
|
|
270
|
+
e.excludeLargeProperties === undefined
|
|
271
|
+
? true
|
|
272
|
+
: e.excludeLargeProperties;
|
|
247
273
|
}
|
|
248
274
|
return (await this.getDoT().save(entities)) || undefined;
|
|
249
275
|
}
|
|
@@ -338,8 +364,14 @@ class Dstore {
|
|
|
338
364
|
* @param kind Name of the [[Datastore]][Kind](https://cloud.google.com/datastore/docs/concepts/entities#kinds_and_identifiers) ("Table") which should be searched.
|
|
339
365
|
*
|
|
340
366
|
* @category Datastore Drop-In
|
|
341
|
-
*/
|
|
342
|
-
|
|
367
|
+
*/
|
|
368
|
+
createQuery(kind) {
|
|
369
|
+
try {
|
|
370
|
+
return this.getDoT().createQuery(kind);
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
throw new DstoreError('datastore.createQuery error', error);
|
|
374
|
+
}
|
|
343
375
|
}
|
|
344
376
|
async runQuery(query) {
|
|
345
377
|
try {
|
|
@@ -351,32 +383,35 @@ class Dstore {
|
|
|
351
383
|
// throw process.env.NODE_ENV === 'test' ? error : new KvStoreError('datastore.runQuery error', error)
|
|
352
384
|
}
|
|
353
385
|
}
|
|
354
|
-
async query(kindName, filters = [], limit = 2500,
|
|
386
|
+
async query(kindName, filters = [], limit = 2500, ordering = [], selection = [], cursor) {
|
|
355
387
|
(0, assertate_1.assertIsString)(kindName);
|
|
356
388
|
(0, assertate_1.assertIsArray)(filters);
|
|
357
389
|
(0, assertate_1.assertIsNumber)(limit);
|
|
358
390
|
try {
|
|
359
391
|
const q = this.createQuery(kindName);
|
|
360
|
-
for (const
|
|
361
|
-
q.filter(...
|
|
392
|
+
for (const filterSpec of filters) {
|
|
393
|
+
q.filter(...filterSpec);
|
|
362
394
|
}
|
|
363
|
-
for (const orderField of
|
|
395
|
+
for (const orderField of ordering) {
|
|
364
396
|
q.order(orderField);
|
|
365
397
|
}
|
|
366
398
|
if (limit > 0) {
|
|
367
399
|
q.limit(limit);
|
|
368
400
|
}
|
|
401
|
+
if (selection.length > 0) {
|
|
402
|
+
q.select(selection);
|
|
403
|
+
}
|
|
369
404
|
return await this.runQuery(q);
|
|
370
405
|
}
|
|
371
406
|
catch (error) {
|
|
372
|
-
console.error(error, { kindName, filters, limit,
|
|
407
|
+
console.error(error, { kindName, filters, limit, ordering });
|
|
373
408
|
throw process.env.NODE_ENV === 'test'
|
|
374
409
|
? error
|
|
375
410
|
: new DstoreError('datastore.query error', error, {
|
|
376
411
|
kindName,
|
|
377
412
|
filters,
|
|
378
413
|
limit,
|
|
379
|
-
|
|
414
|
+
ordering,
|
|
380
415
|
});
|
|
381
416
|
}
|
|
382
417
|
}
|
|
@@ -405,7 +440,7 @@ class Dstore {
|
|
|
405
440
|
|
|
406
441
|
[[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).
|
|
407
442
|
|
|
408
|
-
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
|
|
443
|
+
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.
|
|
409
444
|
|
|
410
445
|
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.
|
|
411
446
|
*/
|
|
@@ -413,25 +448,15 @@ class Dstore {
|
|
|
413
448
|
let ret;
|
|
414
449
|
const transaction = this.datastore.transaction();
|
|
415
450
|
await transactionAsyncLocalStorage.run(transaction, async () => {
|
|
416
|
-
const [transactionInfo,
|
|
451
|
+
const [transactionInfo, transactionRunApiResponse] = await transaction.run();
|
|
417
452
|
let commitApiResponse;
|
|
418
453
|
try {
|
|
419
454
|
ret = await func();
|
|
420
455
|
}
|
|
421
456
|
catch (error) {
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
// err: error,
|
|
426
|
-
// transactionInfo,
|
|
427
|
-
// transactionRunApiResponse,
|
|
428
|
-
// rollbackInfo,
|
|
429
|
-
// ret,
|
|
430
|
-
// commitApiResponse,
|
|
431
|
-
// },
|
|
432
|
-
// 'Transaction failed'
|
|
433
|
-
// );
|
|
434
|
-
// console.error(error)
|
|
457
|
+
const rollbackInfo = await transaction.rollback();
|
|
458
|
+
debug('Transaction failed, rollback initiated: %O %O %O %O', transactionInfo, transactionRunApiResponse, rollbackInfo, error);
|
|
459
|
+
console.error(error);
|
|
435
460
|
throw process.env.NODE_ENV === 'test'
|
|
436
461
|
? error
|
|
437
462
|
: new DstoreError('datastore.transaction execution error', error);
|
|
@@ -440,17 +465,7 @@ class Dstore {
|
|
|
440
465
|
commitApiResponse = await transaction.commit()[0];
|
|
441
466
|
}
|
|
442
467
|
catch (error) {
|
|
443
|
-
|
|
444
|
-
// {
|
|
445
|
-
// err: error,
|
|
446
|
-
// transactionInfo,
|
|
447
|
-
// transactionRunApiResponse,
|
|
448
|
-
// ret,
|
|
449
|
-
// commitApiResponse,
|
|
450
|
-
// },
|
|
451
|
-
// 'Transaction commit failed'
|
|
452
|
-
// );
|
|
453
|
-
// console.error(error)
|
|
468
|
+
debug('Transaction commit failed: %O %O %O %O ret: %O', transactionInfo, transactionRunApiResponse, commitApiResponse, error, ret);
|
|
454
469
|
throw process.env.NODE_ENV === 'test'
|
|
455
470
|
? error
|
|
456
471
|
: new DstoreError('datastore.transaction execution error', error);
|
|
@@ -477,4 +492,4 @@ class DstoreError extends Error {
|
|
|
477
492
|
}
|
|
478
493
|
}
|
|
479
494
|
exports.DstoreError = DstoreError;
|
|
480
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHN0b3JlLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZHN0b3JlLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7OztHQVNHOzs7QUFFSCw2Q0FBZ0Q7QUFFaEQsdURBTWlDO0FBQ2pDLHFFQUFrRTtBQU1sRSx5Q0FPbUI7QUFHbkIsNkJBQTZCO0FBRTdCLGNBQWM7QUFDZCxxREFNaUM7QUFML0Isc0dBQUEsU0FBUyxPQUFBO0FBQ1QsZ0dBQUEsR0FBRyxPQUFBO0FBRUgsa0dBQUEsS0FBSyxPQUFBO0FBQ0wsd0dBQUEsV0FBVyxPQUFBO0FBR2IsY0FBYztBQUNkLG9DQUFvQztBQUVwQyxjQUFjO0FBQ2QsTUFBTSw0QkFBNEIsR0FBRyxJQUFJLCtCQUFpQixFQUFFLENBQUM7QUF1RjdEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBc0JFO0FBQ0YsTUFBYSxNQUFNO0lBR2pCOzs7Ozs7Ozs7Ozs7OztNQWNFO0lBQ0YsWUFDVyxTQUFvQixFQUNwQixTQUFrQixFQUNsQixNQUFlO1FBRmYsY0FBUyxHQUFULFNBQVMsQ0FBVztRQUNwQixjQUFTLEdBQVQsU0FBUyxDQUFTO1FBQ2xCLFdBQU0sR0FBTixNQUFNLENBQVM7UUFwQlQsZUFBVSxHQUFHLElBQUksZUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBc0JwRCxJQUFBLDBCQUFjLEVBQUMsU0FBUyxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVELHFEQUFxRDtJQUM3QyxNQUFNO1FBQ1osT0FBTyxDQUNKLDRCQUE0QixDQUFDLFFBQVEsRUFBa0IsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUMzRSxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxHQUFHLENBQUMsSUFBeUI7UUFDM0IsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUE2QixDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxZQUFZLENBQUMsR0FBUTs7UUFDbkIsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLE1BQUEsSUFBSSxDQUFDLFNBQVMsbUNBQUksRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDNUUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsaUJBQWlCLENBQUMsSUFBWTtRQUM1QixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxPQUFPLENBQUMsR0FBZ0I7UUFDdEIsSUFBQSwwQkFBYyxFQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLElBQUksR0FBRyxHQUFHLEdBQUcsQ0FBQyxxQkFBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLElBQUksR0FBRyxDQUFDLE9BQU8sSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUN2QixHQUFHLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUMzQztRQUNELElBQUEsMEJBQWMsRUFDWixHQUFHLEVBQ0gsc0NBQXNDLEVBQ3RDLHdDQUF3QyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQzlELENBQUM7UUFDRixPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLE9BQU8sQ0FDYixRQUF5RDtRQUV6RCxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDckIsSUFBSSxDQUFDLENBQUMsQ0FBQSxDQUFDLGFBQUQsQ0FBQyx1QkFBRCxDQUFDLENBQUcscUJBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQSxJQUFJLENBQUMsQ0FBQyxxQkFBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFO2dCQUM1QyxJQUFBLDJCQUFlLEVBQUMsQ0FBQyxDQUFDLHFCQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDbEMsSUFBQSwwQkFBYyxFQUFDLENBQUMsQ0FBQyxxQkFBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pDLDJEQUEyRDtnQkFDM0QsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxxQkFBUyxDQUFDLEdBQUcsQ0FBUSxDQUFDLENBQUM7YUFDeEQ7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sUUFBMEMsQ0FBQztJQUNwRCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDSCxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQVE7UUFDaEIsSUFBQSwwQkFBYyxFQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLElBQUEsa0JBQU0sRUFBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM1QixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzdDLE9BQU8sQ0FBQSxTQUFTLGFBQVQsU0FBUyx1QkFBVCxTQUFTLENBQUcsQ0FBQyxDQUFDLEtBQUksSUFBSSxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7O09BZUc7SUFDSCxLQUFLLENBQUMsUUFBUSxDQUNaLElBQW9COztRQUVwQix1QkFBdUI7UUFDdkIsSUFBSTtZQUNGLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FDakIsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDO2dCQUNiLENBQUMsQ0FBQyxNQUFBLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQTZCLENBQUMsQ0FBQywwQ0FBRyxDQUFDLENBQUM7Z0JBQy9ELENBQUMsQ0FBQyxFQUFFLENBQ1AsQ0FBQztTQUNIO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCx1QkFBdUI7WUFDdkIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxNQUFNO2dCQUNuQyxDQUFDLENBQUMsS0FBSztnQkFDUCxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsMEJBQTBCLEVBQUUsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUNsRTtJQUNILENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7O09BZUc7SUFDSCxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQVEsRUFBRSxJQUFpQjtRQUNuQyxJQUFBLDBCQUFjLEVBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsSUFBQSwwQkFBYyxFQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JCLE1BQU0sVUFBVSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxDQUFDO1FBQ2pDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7UUFDOUIsT0FBTyxVQUFVLENBQUMsR0FBRyxDQUFDO0lBQ3hCLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7O09Ba0JHO0lBQ0gsS0FBSyxDQUFDLElBQUksQ0FDUixRQUFxQztRQUVyQyxJQUFBLHlCQUFhLEVBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEIsSUFBSTtZQUNGLDBEQUEwRDtZQUMxRCxvRUFBb0U7WUFDcEUsS0FBSyxNQUFNLENBQUMsSUFBSSxRQUFRLEVBQUU7Z0JBQ3hCLElBQUEsMEJBQWMsRUFBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3RCLElBQUEsMEJBQWMsRUFBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3ZCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzthQUN4QjtZQUNELE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7U0FDMUQ7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEtBQUssTUFBTTtnQkFDbkMsQ0FBQyxDQUFDLEtBQUs7Z0JBQ1AsQ0FBQyxDQUFDLElBQUksV0FBVyxDQUFDLHNCQUFzQixFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ3BEO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNILEtBQUssQ0FBQyxNQUFNLENBQ1YsUUFBcUM7UUFFckMsSUFBQSx5QkFBYSxFQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3hCLElBQUk7WUFDRixPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksU0FBUyxDQUFDO1NBQzVEO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCx1QkFBdUI7WUFDdkIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxNQUFNO2dCQUNuQyxDQUFDLENBQUMsS0FBSztnQkFDUCxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDdEQ7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDSCxLQUFLLENBQUMsTUFBTSxDQUNWLFFBQXFDO1FBRXJDLElBQUEseUJBQWEsRUFBQyxRQUFRLENBQUMsQ0FBQztRQUN4QixJQUFJO1lBQ0YsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLFNBQVMsQ0FBQztTQUM1RDtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsdUJBQXVCO1lBQ3ZCLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEtBQUssTUFBTTtnQkFDbkMsQ0FBQyxDQUFDLEtBQUs7Z0JBQ1AsQ0FBQyxDQUFDLElBQUksV0FBVyxDQUFDLHdCQUF3QixFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ3REO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNILEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBb0I7UUFDL0IsSUFBQSx5QkFBYSxFQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUEsMEJBQWMsRUFBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzNDLElBQUk7WUFDRixPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksU0FBUyxDQUFDO1NBQ3hEO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCx1QkFBdUI7WUFDdkIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxNQUFNO2dCQUNuQyxDQUFDLENBQUMsS0FBSztnQkFDUCxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDdEQ7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRyxDQUFDLFdBQVcsQ0FBQyxJQUFZO1FBQzFCLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFpQztRQUM5QyxJQUFJO1lBQ0YsT0FBTyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBYyxDQUFDLENBQUM7U0FDckQ7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE1BQU0sSUFBSSxXQUFXLENBQUMsMEJBQTBCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDekQsdUJBQXVCO1lBQ3ZCLHNHQUFzRztTQUN2RztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsS0FBSyxDQUNULFFBQWdCLEVBQ2hCLFVBQTBCLEVBQUUsRUFDNUIsS0FBSyxHQUFHLElBQUksRUFDWixTQUE0QixFQUFFO1FBRTlCLElBQUEsMEJBQWMsRUFBQyxRQUFRLENBQUMsQ0FBQztRQUN6QixJQUFBLHlCQUFhLEVBQUMsT0FBTyxDQUFDLENBQUM7UUFDdkIsSUFBQSwwQkFBYyxFQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RCLElBQUk7WUFDRixNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3JDLEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxFQUFFO2dCQUMzQixDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUM7YUFDcEI7WUFDRCxLQUFLLE1BQU0sVUFBVSxJQUFJLE1BQU0sRUFBRTtnQkFDL0IsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUNyQjtZQUNELElBQUksS0FBSyxHQUFHLENBQUMsRUFBRTtnQkFDYixDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQ2hCO1lBQ0QsT0FBTyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDL0I7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMzRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE1BQU07Z0JBQ25DLENBQUMsQ0FBQyxLQUFLO2dCQUNQLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQyx1QkFBdUIsRUFBRSxLQUFLLEVBQUU7b0JBQzlDLFFBQVE7b0JBQ1IsT0FBTztvQkFDUCxLQUFLO29CQUNMLE1BQU07aUJBQ1AsQ0FBQyxDQUFDO1NBQ1I7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQUMsUUFBUSxHQUFHLFdBQVc7UUFDeEMsSUFBQSwwQkFBYyxFQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pCLE1BQU0sR0FBRyxHQUFHLENBQ1YsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FDMUQsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDWCxJQUFBLDBCQUFjLEVBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7O09BV0c7SUFDSCxLQUFLLENBQUMsZ0JBQWdCLENBQUksSUFBc0I7UUFDOUMsSUFBSSxHQUFHLENBQUM7UUFDUixNQUFNLFdBQVcsR0FBZ0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM5RCxNQUFNLDRCQUE0QixDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDN0QsTUFBTSxDQUFDLGVBQWUsRUFBRSwwQkFBMEIsQ0FBQyxHQUNqRCxNQUFNLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUMxQixJQUFJLGlCQUFpQixDQUFDO1lBQ3RCLElBQUk7Z0JBQ0YsR0FBRyxHQUFHLE1BQU0sSUFBSSxFQUFFLENBQUM7YUFDcEI7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDZCxNQUFNLGFBQWEsR0FBRyxNQUFNLFdBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDbkQsZUFBZTtnQkFDZixNQUFNO2dCQUNOLGtCQUFrQjtnQkFDbEIsdUJBQXVCO2dCQUN2QixpQ0FBaUM7Z0JBQ2pDLG9CQUFvQjtnQkFDcEIsV0FBVztnQkFDWCx5QkFBeUI7Z0JBQ3pCLE9BQU87Z0JBQ1AseUJBQXlCO2dCQUN6QixLQUFLO2dCQUNMLHVCQUF1QjtnQkFDdkIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxNQUFNO29CQUNuQyxDQUFDLENBQUMsS0FBSztvQkFDUCxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxDQUFDLENBQUM7YUFDckU7WUFDRCxJQUFJO2dCQUNGLGlCQUFpQixHQUFHLE1BQU0sV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ25EO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ2QsZUFBZTtnQkFDZixNQUFNO2dCQUNOLGtCQUFrQjtnQkFDbEIsdUJBQXVCO2dCQUN2QixpQ0FBaUM7Z0JBQ2pDLFdBQVc7Z0JBQ1gseUJBQXlCO2dCQUN6QixPQUFPO2dCQUNQLGdDQUFnQztnQkFDaEMsS0FBSztnQkFDTCx1QkFBdUI7Z0JBQ3ZCLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEtBQUssTUFBTTtvQkFDbkMsQ0FBQyxDQUFDLEtBQUs7b0JBQ1AsQ0FBQyxDQUFDLElBQUksV0FBVyxDQUFDLHVDQUF1QyxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3JFO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7Q0FDRjtBQTViRCx3QkE0YkM7QUFFRCxNQUFhLFdBQVksU0FBUSxLQUFLO0lBS3BDLFlBQ0UsT0FBZSxFQUNmLGFBQWdDLEVBQ2hDLFVBQW9DO1FBRXBDLEtBQUssQ0FBQyxHQUFHLE9BQU8sS0FBSyxhQUFhLGFBQWIsYUFBYSx1QkFBYixhQUFhLENBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUUvQyw0RkFBNEY7UUFDNUYsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDZCxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQztTQUMvRDtRQUNELFdBQVc7UUFDWCw2REFBNkQ7UUFDN0QsK0RBQStEO1FBQy9ELGtGQUFrRjtRQUNsRixJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQztRQUNuQyxJQUFJLENBQUMsVUFBVSxxQkFBUSxVQUFVLENBQUUsQ0FBQztRQUNwQyw2REFBNkQ7SUFDL0QsQ0FBQztDQUNGO0FBeEJELGtDQXdCQyJ9
|
|
495
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHN0b3JlLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZHN0b3JlLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7OztHQVNHOzs7Ozs7QUFFSCw2Q0FBZ0Q7QUFFaEQsdURBTWlDO0FBQ2pDLHFFQUFrRTtBQU1sRSx5Q0FPbUI7QUFDbkIsa0RBQTBCO0FBRzFCLGNBQWM7QUFDZCxxREFNaUM7QUFML0Isc0dBQUEsU0FBUyxPQUFBO0FBQ1QsZ0dBQUEsR0FBRyxPQUFBO0FBRUgsa0dBQUEsS0FBSyxPQUFBO0FBQ0wsd0dBQUEsV0FBVyxPQUFBO0FBR2IsY0FBYztBQUNkLE1BQU0sS0FBSyxHQUFHLElBQUEsZUFBSyxFQUFDLFFBQVEsQ0FBQyxDQUFDO0FBRTlCLGNBQWM7QUFFZDs7O0dBR0c7QUFDSCxNQUFNLDRCQUE0QixHQUFHLElBQUksK0JBQWlCLEVBQUUsQ0FBQztBQUVoRCxRQUFBLE1BQU0sR0FBRyxxQkFBUyxDQUFDLEdBQUcsQ0FBQztBQXFGcEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFzQkU7QUFDRixNQUFhLE1BQU07SUFHakI7Ozs7Ozs7Ozs7Ozs7O01BY0U7SUFDRixZQUNXLFNBQW9CLEVBQ3BCLFNBQWtCLEVBQ2xCLE1BQWU7UUFGZixjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3BCLGNBQVMsR0FBVCxTQUFTLENBQVM7UUFDbEIsV0FBTSxHQUFOLE1BQU0sQ0FBUztRQXBCVCxlQUFVLEdBQUcsSUFBSSxlQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7UUFzQnBELElBQUEsMEJBQWMsRUFBQyxTQUFTLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQscURBQXFEO0lBQzdDLE1BQU07UUFDWixPQUFPLENBQ0osNEJBQTRCLENBQUMsUUFBUSxFQUFrQixJQUFJLElBQUksQ0FBQyxTQUFTLENBQzNFLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEdBQUcsQ0FB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
|