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 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
- # See also
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 | readonly DstorePropertyValues[] | {
14
- readonly [key: string]: DstorePropertyValues;
14
+ export declare type DstorePropertyValues = number | string | Date | boolean | null | undefined | Buffer | Key | DstorePropertyValues[] | {
15
+ [key: string]: DstorePropertyValues;
15
16
  };
16
- export interface DstoreEntryWithoutKey {
17
+ export interface IDstoreEntryWithoutKey {
17
18
  /** All User Data stored in the Datastore */
18
- readonly [key: string]: DstorePropertyValues;
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 DstoreEntry extends DstoreEntryWithoutKey {
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
- readonly [key: string]: DstorePropertyValues;
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
- readonly key: Key;
34
- readonly data: Omit<DstoreEntry, '_keyStr' | Datastore['KEY']>;
35
- readonly method?: 'insert' | 'update' | 'upsert';
36
- readonly excludeLargeProperties?: boolean;
37
- readonly excludeFromIndexes?: readonly string[];
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
- readonly key: (path: ReadonlyArray<PathType>) => Key;
43
- readonly keyFromSerialized: (text: string) => Key;
44
- readonly keySerialize: (key: Key) => string;
45
- readonly readKey: (entry: DstoreEntry) => Key;
46
- readonly get: (key: Key) => Promise<DstoreEntry | null>;
47
- readonly getMulti: (keys: ReadonlyArray<Key>) => Promise<ReadonlyArray<DstoreEntry | undefined>>;
48
- readonly set: (key: Key, entry: DstoreEntry) => Promise<Key>;
49
- readonly save: (entities: readonly DstoreSaveEntity[]) => Promise<CommitResponse | undefined>;
50
- readonly insert: (entities: readonly DstoreSaveEntity[]) => Promise<CommitResponse | undefined>;
51
- readonly update: (entities: readonly DstoreSaveEntity[]) => Promise<CommitResponse | undefined>;
52
- readonly delete: (keys: readonly Key[]) => Promise<CommitResponse | undefined>;
53
- readonly createQuery: (kind: string) => Query;
54
- readonly query: (kind: string, filters?: TGqlFilterList, limit?: number, orders?: readonly string[]) => Promise<RunQueryResponse>;
55
- readonly runQuery: (query: Query | Omit<Query, 'run'>) => Promise<RunQueryResponse>;
56
- readonly allocateOneId: (kindname: string) => Promise<string>;
57
- readonly runInTransaction: <T>(func: {
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` - [[DstoreEntry]]), 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
+ 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 [[DstoreEntry]].
75
- - [[getMulti]] always returns an Array<[[DstoreEntry]]> of the same length as the input Array. Items not found are represented by null.
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 [[DstoreEntry]] 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 [[DstoreEntry]] from a serializing cache.
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 [[DstoreEntry]].
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 [[DstoreEntry]] which has been serialized to JSON by leveraging the property `_keyStr`.
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: DstoreEntry): Key;
141
- /** `fixKeys()` is called for all [[DstoreEntry]]sa returned from [[Dstore]].
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 [[DstoreEntry]] from the Datastore.
149
+ /** `get()` reads a [[IDstoreEntry]] from the Datastore.
149
150
  *
150
- * It returns [[DstoreEntry]] or `null` if not found.
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 [[DstoreEntry]], no Array.
160
+ * - [Dstore.get]] returns a single [[IDstoreEntry]], no Array.
160
161
  *
161
162
  * @category Datastore Drop-In
162
163
  */
163
- get(key: Key): Promise<DstoreEntry | null>;
164
- /** `getMulti()` reads several [[DstoreEntry]]s from the Datastore.
164
+ get(key: Key): Promise<IDstoreEntry | null>;
165
+ /** `getMulti()` reads several [[IDstoreEntry]]s from the Datastore.
165
166
  *
166
- * It returns a list of [[DstoreEntry]]s or `null` if not found.
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 [[DstoreEntry]], or null.
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<ReadonlyArray<DstoreEntry | undefined>>;
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: DstoreEntry): Promise<Key>;
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
- */ createQuery(kind: string): Query;
284
+ */
285
+ createQuery(kind: string): Query;
270
286
  runQuery(query: Query | Omit<Query, 'run'>): Promise<RunQueryResponse>;
271
- query(kindName: string, filters?: TGqlFilterList, limit?: number, orders?: readonly string[]): Promise<RunQueryResponse>;
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 seralize 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.
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
- // import Debug from 'debug';
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
- // const debug = Debug('h3:dstore');
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` - [[DstoreEntry]]), 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.
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 [[DstoreEntry]].
42
- - [[getMulti]] always returns an Array<[[DstoreEntry]]> of the same length as the input Array. Items not found are represented by null.
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 [[DstoreEntry]] 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 [[DstoreEntry]] from a serializing cache.
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 [[DstoreEntry]].
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 [[DstoreEntry]] which has been serialized to JSON by leveraging the property `_keyStr`.
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 [[DstoreEntry]]sa returned from [[Dstore]].
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
- // Scheinbar stolpert TypesScript über Symbole als Attribut
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 [[DstoreEntry]] from the Datastore.
152
+ /** `get()` reads a [[IDstoreEntry]] from the Datastore.
145
153
  *
146
- * It returns [[DstoreEntry]] or `null` if not found.
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 [[DstoreEntry]], no Array.
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 getresult = await this.getMulti([key]);
163
- return (getresult === null || getresult === void 0 ? void 0 : getresult[0]) || null;
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 [[DstoreEntry]]s from the Datastore.
173
+ /** `getMulti()` reads several [[IDstoreEntry]]s from the Datastore.
166
174
  *
167
- * It returns a list of [[DstoreEntry]]s or `null` if not found.
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 [[DstoreEntry]], or null.
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
- // Innerhalb von Transaktionen bekommen wir keine Antwort!
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
- */ createQuery(kind) {
342
- return this.getDoT().createQuery(kind);
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, orders = []) {
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 fspec of filters) {
361
- q.filter(...fspec);
392
+ for (const filterSpec of filters) {
393
+ q.filter(...filterSpec);
362
394
  }
363
- for (const orderField of orders) {
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, orders });
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
- orders,
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 seralize 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.
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, _transactionRunApiResponse] = await transaction.run();
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 _rollbackInfo = await transaction.rollback();
423
- // logger.info(
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
- // logger.info(
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHN0b3JlLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZHN0b3JlLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7OztHQVNHOzs7QUFFSCw2Q0FBZ0Q7QUFFaEQsdURBTWlDO0FBQ2pDLHFFQUFrRTtBQU1sRSx5Q0FPbUI7QUFHbkIsNkJBQTZCO0FBRTdCLGNBQWM7QUFDZCxxREFNaUM7QUFML0Isc0dBQUEsU0FBUyxPQUFBO0FBQ1QsZ0dBQUEsR0FBRyxPQUFBO0FBRUgsa0dBQUEsS0FBSyxPQUFBO0FBQ0wsd0dBQUEsV0FBVyxPQUFBO0FBR2IsY0FBYztBQUNkLG9DQUFvQztBQUVwQyxjQUFjO0FBQ2QsTUFBTSw0QkFBNEIsR0FBRyxJQUFJLCtCQUFpQixFQUFFLENBQUM7QUF1RjdEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBc0JFO0FBQ0YsTUFBYSxNQUFNO0lBR2pCOzs7Ozs7Ozs7Ozs7OztNQWNFO0lBQ0YsWUFDVyxTQUFvQixFQUNwQixTQUFrQixFQUNsQixNQUFlO1FBRmYsY0FBUyxHQUFULFNBQVMsQ0FBVztRQUNwQixjQUFTLEdBQVQsU0FBUyxDQUFTO1FBQ2xCLFdBQU0sR0FBTixNQUFNLENBQVM7UUFwQlQsZUFBVSxHQUFHLElBQUksZUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBc0JwRCxJQUFBLDBCQUFjLEVBQUMsU0FBUyxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVELHFEQUFxRDtJQUM3QyxNQUFNO1FBQ1osT0FBTyxDQUNKLDRCQUE0QixDQUFDLFFBQVEsRUFBa0IsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUMzRSxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxHQUFHLENBQUMsSUFBeUI7UUFDM0IsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUE2QixDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFD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
495
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHN0b3JlLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZHN0b3JlLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7OztHQVNHOzs7Ozs7QUFFSCw2Q0FBZ0Q7QUFFaEQsdURBTWlDO0FBQ2pDLHFFQUFrRTtBQU1sRSx5Q0FPbUI7QUFDbkIsa0RBQTBCO0FBRzFCLGNBQWM7QUFDZCxxREFNaUM7QUFML0Isc0dBQUEsU0FBUyxPQUFBO0FBQ1QsZ0dBQUEsR0FBRyxPQUFBO0FBRUgsa0dBQUEsS0FBSyxPQUFBO0FBQ0wsd0dBQUEsV0FBVyxPQUFBO0FBR2IsY0FBYztBQUNkLE1BQU0sS0FBSyxHQUFHLElBQUEsZUFBSyxFQUFDLFFBQVEsQ0FBQyxDQUFDO0FBRTlCLGNBQWM7QUFFZDs7O0dBR0c7QUFDSCxNQUFNLDRCQUE0QixHQUFHLElBQUksK0JBQWlCLEVBQUUsQ0FBQztBQUVoRCxRQUFBLE1BQU0sR0FBRyxxQkFBUyxDQUFDLEdBQUcsQ0FBQztBQXFGcEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFzQkU7QUFDRixNQUFhLE1BQU07SUFHakI7Ozs7Ozs7Ozs7Ozs7O01BY0U7SUFDRixZQUNXLFNBQW9CLEVBQ3BCLFNBQWtCLEVBQ2xCLE1BQWU7UUFGZixjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3BCLGNBQVMsR0FBVCxTQUFTLENBQVM7UUFDbEIsV0FBTSxHQUFOLE1BQU0sQ0FBUztRQXBCVCxlQUFVLEdBQUcsSUFBSSxlQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7UUFzQnBELElBQUEsMEJBQWMsRUFBQyxTQUFTLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQscURBQXFEO0lBQzdDLE1BQU07UUFDWixPQUFPLENBQ0osNEJBQTRCLENBQUMsUUFBUSxFQUFrQixJQUFJLElBQUksQ0FBQyxTQUFTLENBQzNFLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEdBQUcsQ0FBQyxJQUF5QjtRQUMzQixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQTZCLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILFlBQVksQ0FBQyxHQUFROztRQUNuQixPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsTUFBQSxJQUFJLENBQUMsU0FBUyxtQ0FBSSxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM1RSxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxpQkFBaUIsQ0FBQyxJQUFZO1FBQzVCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE9BQU8sQ0FBQyxHQUFpQjtRQUN2QixJQUFBLDBCQUFjLEVBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsSUFBSSxHQUFHLEdBQUcsR0FBRyxDQUFDLHFCQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDN0IsSUFBSSxHQUFHLENBQUMsT0FBTyxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ3ZCLEdBQUcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQzNDO1FBQ0QsSUFBQSwwQkFBYyxFQUNaLEdBQUcsRUFDSCxzQ0FBc0MsRUFDdEMsd0NBQXdDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FDOUQsQ0FBQztRQUNGLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssT0FBTyxDQUNiLFFBQTBEO1FBRTFELFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNyQixJQUFJLENBQUMsQ0FBQyxDQUFBLENBQUMsYUFBRCxDQUFDLHVCQUFELENBQUMsQ0FBRyxxQkFBUyxDQUFDLEdBQUcsQ0FBQyxDQUFBLElBQUksQ0FBQyxDQUFDLHFCQUFTLENBQUMsR0FBRyxDQUFDLEVBQUU7Z0JBQzVDLElBQUEsMkJBQWUsRUFBQyxDQUFDLENBQUMscUJBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNsQyxJQUFBLDBCQUFjLEVBQUMsQ0FBQyxDQUFDLHFCQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDakMsMERBQTBEO2dCQUMxRCxDQUFDLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLHFCQUFTLENBQUMsR0FBRyxDQUFRLENBQUMsQ0FBQzthQUN4RDtRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxRQUEyQyxDQUFDO0lBQ3JELENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNILEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBUTtRQUNoQixJQUFBLDBCQUFjLEVBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsSUFBQSxrQkFBTSxFQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzVCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDMUMsT0FBTyxDQUFBLE1BQU0sYUFBTixNQUFNLHVCQUFOLE1BQU0sQ0FBRyxDQUFDLENBQUMsS0FBSSxJQUFJLENBQUM7SUFDN0IsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7T0FlRztJQUNILEtBQUssQ0FBQyxRQUFRLENBQ1osSUFBb0I7O1FBRXBCLHVCQUF1QjtRQUN2QixJQUFJO1lBQ0YsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLENBQUM7Z0JBQ2IsQ0FBQyxDQUFDLE1BQUEsQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBNkIsQ0FBQyxDQUFDLDBDQUFHLENBQUMsQ0FBQztnQkFDL0QsQ0FBQyxDQUFDLEVBQUUsQ0FDUCxDQUFDO1NBQ0g7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLHVCQUF1QjtZQUN2QixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE1BQU07Z0JBQ25DLENBQUMsQ0FBQyxLQUFLO2dCQUNQLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQywwQkFBMEIsRUFBRSxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1NBQ2xFO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7T0FlRztJQUNILEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBUSxFQUFFLElBQWtCO1FBQ3BDLElBQUEsMEJBQWMsRUFBQyxHQUFHLENBQUMsQ0FBQztRQUNwQixJQUFBLDBCQUFjLEVBQUMsSUFBSSxDQUFDLENBQUM7UUFDckIsTUFBTSxVQUFVLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFDakMsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUM5QixPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQWdDRztJQUNILEtBQUssQ0FBQyxJQUFJLENBQ1IsUUFBcUM7UUFFckMsSUFBQSx5QkFBYSxFQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3hCLElBQUk7WUFDRixtREFBbUQ7WUFDbkQsb0VBQW9FO1lBQ3BFLEtBQUssTUFBTSxDQUFDLElBQUksUUFBUSxFQUFFO2dCQUN4QixJQUFBLDBCQUFjLEVBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN0QixJQUFBLDBCQUFjLEVBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZCLENBQUMsQ0FBQyxzQkFBc0I7b0JBQ3RCLENBQUMsQ0FBQyxzQkFBc0IsS0FBSyxTQUFTO3dCQUNwQyxDQUFDLENBQUMsSUFBSTt3QkFDTixDQUFDLENBQUMsQ0FBQyxDQUFDLHNCQUFzQixDQUFDO2FBQ2hDO1lBQ0QsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLFNBQVMsQ0FBQztTQUMxRDtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxNQUFNO2dCQUNuQyxDQUFDLENBQUMsS0FBSztnQkFDUCxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsc0JBQXNCLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDcEQ7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0gsS0FBSyxDQUFDLE1BQU0sQ0FDVixRQUFxQztRQUVyQyxJQUFBLHlCQUFhLEVBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEIsSUFBSTtZQUNGLE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7U0FDNUQ7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLHVCQUF1QjtZQUN2QixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE1BQU07Z0JBQ25DLENBQUMsQ0FBQyxLQUFLO2dCQUNQLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQyx3QkFBd0IsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUN0RDtJQUNILENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNILEtBQUssQ0FBQyxNQUFNLENBQ1YsUUFBcUM7UUFFckMsSUFBQSx5QkFBYSxFQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3hCLElBQUk7WUFDRixPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksU0FBUyxDQUFDO1NBQzVEO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCx1QkFBdUI7WUFDdkIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxNQUFNO2dCQUNuQyxDQUFDLENBQUMsS0FBSztnQkFDUCxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDdEQ7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0gsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFvQjtRQUMvQixJQUFBLHlCQUFhLEVBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBQSwwQkFBYyxFQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDM0MsSUFBSTtZQUNGLE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7U0FDeEQ7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLHVCQUF1QjtZQUN2QixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE1BQU07Z0JBQ25DLENBQUMsQ0FBQyxLQUFLO2dCQUNQLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQyx3QkFBd0IsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUN0RDtJQUNILENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsV0FBVyxDQUFDLElBQVk7UUFDdEIsSUFBSTtZQUNGLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN4QztRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsTUFBTSxJQUFJLFdBQVcsQ0FBQyw2QkFBNkIsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUM3RDtJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQWlDO1FBQzlDLElBQUk7WUFDRixPQUFPLE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxLQUFjLENBQUMsQ0FBQztTQUNyRDtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsTUFBTSxJQUFJLFdBQVcsQ0FBQywwQkFBMEIsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN6RCx1QkFBdUI7WUFDdkIsc0dBQXNHO1NBQ3ZHO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxLQUFLLENBQ1QsUUFBZ0IsRUFDaEIsVUFBMEIsRUFBRSxFQUM1QixLQUFLLEdBQUcsSUFBSSxFQUNaLFdBQThCLEVBQUUsRUFDaEMsWUFBc0IsRUFBRSxFQUN4QixNQUFlO1FBRWYsSUFBQSwwQkFBYyxFQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pCLElBQUEseUJBQWEsRUFBQyxPQUFPLENBQUMsQ0FBQztRQUN2QixJQUFBLDBCQUFjLEVBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEIsSUFBSTtZQUNGLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDckMsS0FBSyxNQUFNLFVBQVUsSUFBSSxPQUFPLEVBQUU7Z0JBQ2hDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQzthQUN6QjtZQUNELEtBQUssTUFBTSxVQUFVLElBQUksUUFBUSxFQUFFO2dCQUNqQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ3JCO1lBQ0QsSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFO2dCQUNiLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDaEI7WUFDRCxJQUFJLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUN4QixDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQ3JCO1lBQ0QsT0FBTyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDL0I7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUM3RCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE1BQU07Z0JBQ25DLENBQUMsQ0FBQyxLQUFLO2dCQUNQLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQyx1QkFBdUIsRUFBRSxLQUFLLEVBQUU7b0JBQzlDLFFBQVE7b0JBQ1IsT0FBTztvQkFDUCxLQUFLO29CQUNMLFFBQVE7aUJBQ1QsQ0FBQyxDQUFDO1NBQ1I7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQUMsUUFBUSxHQUFHLFdBQVc7UUFDeEMsSUFBQSwwQkFBYyxFQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pCLE1BQU0sR0FBRyxHQUFHLENBQ1YsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FDMUQsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDWCxJQUFBLDBCQUFjLEVBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7O09BV0c7SUFDSCxLQUFLLENBQUMsZ0JBQWdCLENBQUksSUFBc0I7UUFDOUMsSUFBSSxHQUFHLENBQUM7UUFDUixNQUFNLFdBQVcsR0FBZ0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM5RCxNQUFNLDRCQUE0QixDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDN0QsTUFBTSxDQUFDLGVBQWUsRUFBRSx5QkFBeUIsQ0FBQyxHQUNoRCxNQUFNLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUMxQixJQUFJLGlCQUFpQixDQUFDO1lBQ3RCLElBQUk7Z0JBQ0YsR0FBRyxHQUFHLE1BQU0sSUFBSSxFQUFFLENBQUM7YUFDcEI7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDZCxNQUFNLFlBQVksR0FBRyxNQUFNLFdBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDbEQsS0FBSyxDQUNILHNEQUFzRCxFQUN0RCxlQUFlLEVBQ2YseUJBQXlCLEVBQ3pCLFlBQVksRUFDWixLQUFLLENBQ04sQ0FBQztnQkFDRixPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNyQixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE1BQU07b0JBQ25DLENBQUMsQ0FBQyxLQUFLO29CQUNQLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQyx1Q0FBdUMsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUNyRTtZQUNELElBQUk7Z0JBQ0YsaUJBQWlCLEdBQUcsTUFBTSxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDbkQ7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDZCxLQUFLLENBQ0gsZ0RBQWdELEVBQ2hELGVBQWUsRUFDZix5QkFBeUIsRUFDekIsaUJBQWlCLEVBQ2pCLEtBQUssRUFDTCxHQUFHLENBQ0osQ0FBQztnQkFDRixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE1BQU07b0JBQ25DLENBQUMsQ0FBQyxLQUFLO29CQUNQLENBQUMsQ0FBQyxJQUFJLFdBQVcsQ0FBQyx1Q0FBdUMsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUNyRTtRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0NBQ0Y7QUFqZEQsd0JBaWRDO0FBRUQsTUFBYSxXQUFZLFNBQVEsS0FBSztJQUtwQyxZQUNFLE9BQWUsRUFDZixhQUFnQyxFQUNoQyxVQUFvQztRQUVwQyxLQUFLLENBQUMsR0FBRyxPQUFPLEtBQUssYUFBYSxhQUFiLGFBQWEsdUJBQWIsYUFBYSxDQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFFL0MsNEZBQTRGO1FBQzVGLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ2QsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQUM7U0FDL0Q7UUFDRCxXQUFXO1FBQ1gsNkRBQTZEO1FBQzdELCtEQUErRDtRQUMvRCxrRkFBa0Y7UUFDbEYsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFDbkMsSUFBSSxDQUFDLFVBQVUscUJBQVEsVUFBVSxDQUFFLENBQUM7UUFDcEMsNkRBQTZEO0lBQy9ELENBQUM7Q0FDRjtBQXhCRCxrQ0F3QkMifQ==