datastore-api 4.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/datastore-api.cjs.development.js +1 -1
- package/dist/datastore-api.cjs.development.js.map +1 -1
- package/dist/datastore-api.cjs.production.min.js +1 -1
- package/dist/datastore-api.cjs.production.min.js.map +1 -1
- package/dist/datastore-api.esm.js +2 -2
- package/dist/datastore-api.esm.js.map +1 -1
- package/dist/lib/dstore-api.d.ts +1 -3
- package/package.json +21 -22
- package/src/index.ts +1 -1
- package/src/lib/dstore-api-cloud.spec.ts +123 -123
- package/src/lib/dstore-api-emulator.spec.ts +131 -131
- package/src/lib/dstore-api-simulator.spec.ts +132 -132
- package/src/lib/dstore-api.ts +189 -190
- package/src/mock/index.ts +228 -228
- package/src/mock/operators.ts +1 -1
package/src/mock/index.ts
CHANGED
|
@@ -30,11 +30,11 @@ import {
|
|
|
30
30
|
UpsertResponse,
|
|
31
31
|
Query,
|
|
32
32
|
PathType,
|
|
33
|
-
} from '@google-cloud/datastore'
|
|
34
|
-
import { google } from '@google-cloud/datastore/build/protos/protos'
|
|
35
|
-
import { AggregateQuery } from '@google-cloud/datastore/build/src/aggregate'
|
|
36
|
-
import { Entities, entity } from '@google-cloud/datastore/build/src/entity'
|
|
37
|
-
import { RunQueryOptions, RunQueryResponse, RunQueryCallback } from '@google-cloud/datastore/build/src/query'
|
|
33
|
+
} from '@google-cloud/datastore';
|
|
34
|
+
import { google } from '@google-cloud/datastore/build/protos/protos';
|
|
35
|
+
import { AggregateQuery } from '@google-cloud/datastore/build/src/aggregate';
|
|
36
|
+
import { Entities, entity } from '@google-cloud/datastore/build/src/entity';
|
|
37
|
+
import { RunQueryOptions, RunQueryResponse, RunQueryCallback } from '@google-cloud/datastore/build/src/query';
|
|
38
38
|
import {
|
|
39
39
|
AllocateIdsCallback,
|
|
40
40
|
AllocateIdsOptions,
|
|
@@ -50,34 +50,34 @@ import {
|
|
|
50
50
|
RequestOptions,
|
|
51
51
|
SaveCallback,
|
|
52
52
|
SaveResponse,
|
|
53
|
-
} from '@google-cloud/datastore/build/src/request'
|
|
54
|
-
import { promisifyAll } from '@google-cloud/promisify'
|
|
55
|
-
import { assert } from 'assertate-debug'
|
|
56
|
-
import { CallOptions } from 'google-gax'
|
|
57
|
-
import * as is from 'is'
|
|
53
|
+
} from '@google-cloud/datastore/build/src/request';
|
|
54
|
+
import { promisifyAll } from '@google-cloud/promisify';
|
|
55
|
+
import { assert } from 'assertate-debug';
|
|
56
|
+
import { CallOptions } from 'google-gax';
|
|
57
|
+
import * as is from 'is';
|
|
58
58
|
|
|
59
|
-
const urlSafeKey = new entity.URLSafeKey()
|
|
59
|
+
const urlSafeKey = new entity.URLSafeKey();
|
|
60
60
|
|
|
61
|
-
const KEY_SELECT = '__key__'
|
|
61
|
+
const KEY_SELECT = '__key__';
|
|
62
62
|
|
|
63
63
|
function filter(query: { filters: any[][] }, field: any, operator: any, value: any): any {
|
|
64
|
-
query.filters.push([field, operator, value])
|
|
65
|
-
return createQuery(query)
|
|
64
|
+
query.filters.push([field, operator, value]);
|
|
65
|
+
return createQuery(query);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function limit(query: { limit: any }, limit: any): any {
|
|
69
|
-
query.limit = limit
|
|
70
|
-
return createQuery(query)
|
|
69
|
+
query.limit = limit;
|
|
70
|
+
return createQuery(query);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
function select(query: { select: string | string[] }, fields: ConcatArray<never>) {
|
|
74
|
-
query.select = [].concat(fields)
|
|
74
|
+
query.select = [].concat(fields);
|
|
75
75
|
|
|
76
76
|
if (query.select.length > 1 && query.select.includes(KEY_SELECT)) {
|
|
77
|
-
throw new Error('Cannot mix __key__ select with other fields')
|
|
77
|
+
throw new Error('Cannot mix __key__ select with other fields');
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
return createQuery(query)
|
|
80
|
+
return createQuery(query);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
function createQuery(query: any): any {
|
|
@@ -86,30 +86,30 @@ function createQuery(query: any): any {
|
|
|
86
86
|
limit: limit.bind(null, query),
|
|
87
87
|
select: select.bind(null, query),
|
|
88
88
|
query,
|
|
89
|
-
}
|
|
89
|
+
};
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
export class Datastore extends OrigDatastore {
|
|
93
|
-
db: Map<string, any
|
|
94
|
-
rnd = 0
|
|
95
|
-
engine = 'datastore-simulator'
|
|
93
|
+
db: Map<string, any>;
|
|
94
|
+
rnd = 0;
|
|
95
|
+
engine = 'datastore-simulator';
|
|
96
96
|
|
|
97
97
|
constructor(options?: DatastoreOptions) {
|
|
98
|
-
super()
|
|
99
|
-
options = options || {}
|
|
100
|
-
this.clients_ = new Map()
|
|
98
|
+
super();
|
|
99
|
+
options = options || {};
|
|
100
|
+
this.clients_ = new Map();
|
|
101
101
|
// this.datastore = this as unknown as Datastore;
|
|
102
|
-
this.namespace = options.namespace
|
|
103
|
-
this.db = new Map()
|
|
102
|
+
this.namespace = options.namespace;
|
|
103
|
+
this.db = new Map();
|
|
104
104
|
|
|
105
|
-
options.projectId = options.projectId || process.env.DATASTORE_PROJECT_ID
|
|
105
|
+
options.projectId = options.projectId || process.env.DATASTORE_PROJECT_ID;
|
|
106
106
|
}
|
|
107
107
|
_keySerializer(key: entity.Key) {
|
|
108
108
|
const newKey =
|
|
109
109
|
key.id === undefined
|
|
110
110
|
? this.key(key.path)
|
|
111
|
-
: this.key([...key.path.slice(0, -1), this.int(key.path.slice(-1)[0])])
|
|
112
|
-
return JSON.stringify(newKey)
|
|
111
|
+
: this.key([...key.path.slice(0, -1), this.int(key.path.slice(-1)[0])]);
|
|
112
|
+
return JSON.stringify(newKey);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
// export
|
|
@@ -119,22 +119,22 @@ export class Datastore extends OrigDatastore {
|
|
|
119
119
|
// return new Index(this, id);
|
|
120
120
|
// }
|
|
121
121
|
|
|
122
|
-
allocateIds(key: entity.Key, options: AllocateIdsOptions | number): Promise<AllocateIdsResponse
|
|
123
|
-
allocateIds(key: entity.Key, options: AllocateIdsOptions | number, callback: AllocateIdsCallback): void
|
|
122
|
+
allocateIds(key: entity.Key, options: AllocateIdsOptions | number): Promise<AllocateIdsResponse>;
|
|
123
|
+
allocateIds(key: entity.Key, options: AllocateIdsOptions | number, callback: AllocateIdsCallback): void;
|
|
124
124
|
allocateIds(
|
|
125
125
|
key: entity.Key,
|
|
126
126
|
options: AllocateIdsOptions | number,
|
|
127
127
|
callback?: AllocateIdsCallback
|
|
128
128
|
): void | Promise<AllocateIdsResponse> {
|
|
129
|
-
options = typeof options === 'number' ? { allocations: options } : options
|
|
130
|
-
const allocations = options.allocations || 1
|
|
131
|
-
const result: entity.Key[] = []
|
|
132
|
-
const info = { keys: [] as any[] }
|
|
129
|
+
options = typeof options === 'number' ? { allocations: options } : options;
|
|
130
|
+
const allocations = options.allocations || 1;
|
|
131
|
+
const result: entity.Key[] = [];
|
|
132
|
+
const info = { keys: [] as any[] };
|
|
133
133
|
|
|
134
134
|
do {
|
|
135
|
-
const id = 5000000000000000 + this.rnd
|
|
136
|
-
const newKey = this.key([...key.path.slice(0, -1), this.int(id)])
|
|
137
|
-
result.push(newKey)
|
|
135
|
+
const id = 5000000000000000 + this.rnd++;
|
|
136
|
+
const newKey = this.key([...key.path.slice(0, -1), this.int(id)]);
|
|
137
|
+
result.push(newKey);
|
|
138
138
|
info.keys.push({
|
|
139
139
|
partitionId: {
|
|
140
140
|
databaseId: '',
|
|
@@ -148,26 +148,26 @@ export class Datastore extends OrigDatastore {
|
|
|
148
148
|
kind: newKey.kind,
|
|
149
149
|
},
|
|
150
150
|
],
|
|
151
|
-
})
|
|
152
|
-
} while (result.length < allocations)
|
|
153
|
-
callback!(null, result, info)
|
|
151
|
+
});
|
|
152
|
+
} while (result.length < allocations);
|
|
153
|
+
callback!(null, result, info);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
delete(keys: Entities, gaxOptions?: CallOptions): Promise<DeleteResponse
|
|
157
|
-
delete(keys: Entities, callback: DeleteCallback): void
|
|
158
|
-
delete(keys: Entities, gaxOptions: CallOptions, callback: DeleteCallback): void
|
|
156
|
+
delete(keys: Entities, gaxOptions?: CallOptions): Promise<DeleteResponse>;
|
|
157
|
+
delete(keys: Entities, callback: DeleteCallback): void;
|
|
158
|
+
delete(keys: Entities, gaxOptions: CallOptions, callback: DeleteCallback): void;
|
|
159
159
|
delete(
|
|
160
160
|
keys: entity.Key | entity.Key[],
|
|
161
161
|
gaxOptionsOrCallback?: CallOptions | DeleteCallback,
|
|
162
162
|
cb?: DeleteCallback
|
|
163
163
|
): void | Promise<DeleteResponse> {
|
|
164
|
-
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {}
|
|
165
|
-
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb
|
|
164
|
+
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
|
|
165
|
+
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
|
|
166
166
|
|
|
167
|
-
const result: CommitResponse[] = []
|
|
167
|
+
const result: CommitResponse[] = [];
|
|
168
168
|
|
|
169
169
|
for (const key of [keys].flat()) {
|
|
170
|
-
this.db.delete(this._keySerializer(key))
|
|
170
|
+
this.db.delete(this._keySerializer(key));
|
|
171
171
|
result.push({
|
|
172
172
|
mutationResults: [
|
|
173
173
|
{
|
|
@@ -177,179 +177,179 @@ export class Datastore extends OrigDatastore {
|
|
|
177
177
|
},
|
|
178
178
|
],
|
|
179
179
|
indexUpdates: 1, // number|null);
|
|
180
|
-
} as unknown as CommitResponse)
|
|
180
|
+
} as unknown as CommitResponse);
|
|
181
181
|
}
|
|
182
|
-
setImmediate(() => callback(null, result.length === 1 ? result[0] : (result as any)))
|
|
182
|
+
setImmediate(() => callback(null, result.length === 1 ? result[0] : (result as any)));
|
|
183
183
|
}
|
|
184
|
-
get(keys: entity.Key | entity.Key[], options?: CreateReadStreamOptions): Promise<GetResponse
|
|
185
|
-
get(keys: entity.Key | entity.Key[], callback: GetCallback): void
|
|
186
|
-
get(keys: entity.Key | entity.Key[], options: CreateReadStreamOptions, callback: GetCallback): void
|
|
184
|
+
get(keys: entity.Key | entity.Key[], options?: CreateReadStreamOptions): Promise<GetResponse>;
|
|
185
|
+
get(keys: entity.Key | entity.Key[], callback: GetCallback): void;
|
|
186
|
+
get(keys: entity.Key | entity.Key[], options: CreateReadStreamOptions, callback: GetCallback): void;
|
|
187
187
|
get(
|
|
188
188
|
keys: entity.Key | entity.Key[],
|
|
189
189
|
optionsOrCallback?: CreateReadStreamOptions | GetCallback,
|
|
190
190
|
cb?: GetCallback
|
|
191
191
|
): void | Promise<GetResponse> {
|
|
192
|
-
const options = typeof optionsOrCallback === 'object' && optionsOrCallback ? optionsOrCallback : {}
|
|
193
|
-
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb
|
|
192
|
+
const options = typeof optionsOrCallback === 'object' && optionsOrCallback ? optionsOrCallback : {};
|
|
193
|
+
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
|
|
194
194
|
|
|
195
195
|
if ([keys].flat().length === 0) {
|
|
196
|
-
throw Error('At least one Key object is required.')
|
|
196
|
+
throw Error('At least one Key object is required.');
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
const result: any[] = []
|
|
200
|
-
let lastK
|
|
199
|
+
const result: any[] = [];
|
|
200
|
+
let lastK;
|
|
201
201
|
for (let key of [keys].flat()) {
|
|
202
202
|
// dedupe
|
|
203
|
-
const k = this._keySerializer(key)
|
|
203
|
+
const k = this._keySerializer(key);
|
|
204
204
|
if (k !== lastK && this.db.has(k)) {
|
|
205
|
-
result.push(this.db.get(k))
|
|
205
|
+
result.push(this.db.get(k));
|
|
206
206
|
}
|
|
207
|
-
lastK = k
|
|
207
|
+
lastK = k;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
setImmediate(() => callback(null, Array.isArray(keys) ? result : (result[0] as any)))
|
|
210
|
+
setImmediate(() => callback(null, Array.isArray(keys) ? result : (result[0] as any)));
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
runQuery(query: Query, options?: RunQueryOptions): Promise<RunQueryResponse
|
|
214
|
-
runQuery(query: Query, options: RunQueryOptions, callback: RunQueryCallback): void
|
|
215
|
-
runQuery(query: Query, callback: RunQueryCallback): void
|
|
213
|
+
runQuery(query: Query, options?: RunQueryOptions): Promise<RunQueryResponse>;
|
|
214
|
+
runQuery(query: Query, options: RunQueryOptions, callback: RunQueryCallback): void;
|
|
215
|
+
runQuery(query: Query, callback: RunQueryCallback): void;
|
|
216
216
|
runQuery(
|
|
217
217
|
query: Query,
|
|
218
218
|
optionsOrCallback?: RunQueryOptions | RunQueryCallback,
|
|
219
219
|
cb?: RunQueryCallback
|
|
220
220
|
): void | Promise<RunQueryResponse> {
|
|
221
|
-
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}
|
|
222
|
-
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb
|
|
223
|
-
assert(query.kinds.length === 1)
|
|
224
|
-
const kind = query.kinds[0]
|
|
221
|
+
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
|
222
|
+
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
|
|
223
|
+
assert(query.kinds.length === 1);
|
|
224
|
+
const kind = query.kinds[0];
|
|
225
225
|
|
|
226
|
-
const reply: any[] = []
|
|
226
|
+
const reply: any[] = [];
|
|
227
227
|
const filtered = Array.from(this.db.entries()).filter(([ks, v]) => {
|
|
228
|
-
const k = JSON.parse(ks)
|
|
229
|
-
return k.kind === kind && k.namespace === query.namespace
|
|
230
|
-
})
|
|
228
|
+
const k = JSON.parse(ks);
|
|
229
|
+
return k.kind === kind && k.namespace === query.namespace;
|
|
230
|
+
});
|
|
231
231
|
|
|
232
232
|
if (query.filters.length === 0) {
|
|
233
233
|
for (let [ks, entity] of filtered) {
|
|
234
|
-
reply.push(entity)
|
|
234
|
+
reply.push(entity);
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
for (let filter of query.filters) {
|
|
239
239
|
if (filter.name === '__key__' && filter.op === 'HAS_ANCESTOR') {
|
|
240
|
-
const parent = filter.val.path.join('⭕️')
|
|
240
|
+
const parent = filter.val.path.join('⭕️');
|
|
241
241
|
for (let [ks, entity] of filtered) {
|
|
242
|
-
const k = JSON.parse(ks)
|
|
242
|
+
const k = JSON.parse(ks);
|
|
243
243
|
if (k.path.join('⭕️').startsWith(parent)) {
|
|
244
|
-
reply.push(entity)
|
|
244
|
+
reply.push(entity);
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
} else if (filter.op === '=') {
|
|
248
248
|
for (let [ks, entity] of filtered) {
|
|
249
249
|
if (entity[filter.name] == filter.val) {
|
|
250
|
-
reply.push(entity)
|
|
250
|
+
reply.push(entity);
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
} else if (filter.op === '>=') {
|
|
254
254
|
for (let [ks, entity] of filtered) {
|
|
255
255
|
if (entity[filter.name] >= filter.val) {
|
|
256
|
-
reply.push(entity)
|
|
256
|
+
reply.push(entity);
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
} else if (filter.op === '<') {
|
|
260
260
|
for (let [ks, entity] of filtered) {
|
|
261
261
|
if (entity[filter.name] >= filter.val) {
|
|
262
|
-
reply.push(entity)
|
|
262
|
+
reply.push(entity);
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
} else {
|
|
266
|
-
console.log('unknown filter', filter)
|
|
266
|
+
console.log('unknown filter', filter);
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
// TODO: handle query.limit
|
|
271
271
|
|
|
272
|
-
setImmediate(() => callback(null, reply, { moreResults: 'MORE_RESULTS_AFTER_LIMIT' }))
|
|
272
|
+
setImmediate(() => callback(null, reply, { moreResults: 'MORE_RESULTS_AFTER_LIMIT' }));
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
merge(entities: Entities): Promise<CommitResponse
|
|
276
|
-
merge(entities: Entities, callback: SaveCallback): void
|
|
275
|
+
merge(entities: Entities): Promise<CommitResponse>;
|
|
276
|
+
merge(entities: Entities, callback: SaveCallback): void;
|
|
277
277
|
merge(entities: Entities, callback?: SaveCallback): void | Promise<CommitResponse> {
|
|
278
|
-
throw Error('not implemented')
|
|
278
|
+
throw Error('not implemented');
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
insert(entities: Entities): Promise<InsertResponse
|
|
282
|
-
insert(entities: Entities, callback: InsertCallback): void
|
|
281
|
+
insert(entities: Entities): Promise<InsertResponse>;
|
|
282
|
+
insert(entities: Entities, callback: InsertCallback): void;
|
|
283
283
|
insert(entities: Entities, callback?: InsertCallback): void | Promise<InsertResponse> {
|
|
284
284
|
entities = [entities]
|
|
285
285
|
.flat()
|
|
286
286
|
.map(DatastoreRequest.prepareEntityObject_)
|
|
287
287
|
.map((x: PrepareEntityObjectResponse) => {
|
|
288
|
-
x.method = 'insert'
|
|
289
|
-
return x
|
|
290
|
-
})
|
|
288
|
+
x.method = 'insert';
|
|
289
|
+
return x;
|
|
290
|
+
});
|
|
291
291
|
|
|
292
|
-
this.save(entities, callback!)
|
|
292
|
+
this.save(entities, callback!);
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
update(entities: Entities): Promise<UpdateResponse
|
|
296
|
-
update(entities: Entities, callback: UpdateCallback): void
|
|
295
|
+
update(entities: Entities): Promise<UpdateResponse>;
|
|
296
|
+
update(entities: Entities, callback: UpdateCallback): void;
|
|
297
297
|
update(entities: Entities, callback?: UpdateCallback): void | Promise<UpdateResponse> {
|
|
298
298
|
entities = [entities]
|
|
299
299
|
.flat()
|
|
300
300
|
.map(DatastoreRequest.prepareEntityObject_)
|
|
301
301
|
.map((x: PrepareEntityObjectResponse) => {
|
|
302
|
-
x.method = 'update'
|
|
303
|
-
return x
|
|
304
|
-
})
|
|
302
|
+
x.method = 'update';
|
|
303
|
+
return x;
|
|
304
|
+
});
|
|
305
305
|
|
|
306
|
-
this.save(entities, callback!)
|
|
306
|
+
this.save(entities, callback!);
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
upsert(entities: Entities): Promise<UpsertResponse
|
|
310
|
-
upsert(entities: Entities, callback: UpsertCallback): void
|
|
309
|
+
upsert(entities: Entities): Promise<UpsertResponse>;
|
|
310
|
+
upsert(entities: Entities, callback: UpsertCallback): void;
|
|
311
311
|
upsert(entities: Entities, callback?: UpsertCallback): void | Promise<UpsertResponse> {
|
|
312
312
|
entities = [entities]
|
|
313
313
|
.flat()
|
|
314
314
|
.map(DatastoreRequest.prepareEntityObject_)
|
|
315
315
|
.map((x: PrepareEntityObjectResponse) => {
|
|
316
|
-
x.method = 'upsert'
|
|
317
|
-
return x
|
|
318
|
-
})
|
|
316
|
+
x.method = 'upsert';
|
|
317
|
+
return x;
|
|
318
|
+
});
|
|
319
319
|
|
|
320
|
-
this.save(entities, callback!)
|
|
320
|
+
this.save(entities, callback!);
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
-
save(entities: Entities, gaxOptions?: CallOptions): Promise<SaveResponse
|
|
324
|
-
save(entities: Entities, gaxOptions: CallOptions, callback: SaveCallback): void
|
|
325
|
-
save(entities: Entities, callback: SaveCallback): void
|
|
323
|
+
save(entities: Entities, gaxOptions?: CallOptions): Promise<SaveResponse>;
|
|
324
|
+
save(entities: Entities, gaxOptions: CallOptions, callback: SaveCallback): void;
|
|
325
|
+
save(entities: Entities, callback: SaveCallback): void;
|
|
326
326
|
save(
|
|
327
327
|
entities: Entities,
|
|
328
328
|
gaxOptionsOrCallback?: CallOptions | SaveCallback,
|
|
329
329
|
cb?: SaveCallback
|
|
330
330
|
): void | Promise<SaveResponse> {
|
|
331
|
-
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {}
|
|
332
|
-
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb
|
|
331
|
+
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
|
|
332
|
+
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
|
|
333
333
|
|
|
334
334
|
const methods: Record<string, boolean> = {
|
|
335
335
|
insert: true,
|
|
336
336
|
update: true,
|
|
337
337
|
upsert: true,
|
|
338
|
-
}
|
|
339
|
-
entities = [entities].flat()
|
|
338
|
+
};
|
|
339
|
+
entities = [entities].flat();
|
|
340
340
|
// Iterate over the entity objects, build a proto from all keys and values,
|
|
341
341
|
// then place in the correct mutation array (insert, update, etc).
|
|
342
|
-
const result: CommitResponse[] = []
|
|
343
|
-
|
|
342
|
+
const result: CommitResponse[] = [];
|
|
343
|
+
[entities]
|
|
344
344
|
.flat()
|
|
345
345
|
.map(DatastoreRequest.prepareEntityObject_)
|
|
346
346
|
.forEach((entityObject: Entity, index: number) => {
|
|
347
|
-
let method = 'upsert'
|
|
347
|
+
let method = 'upsert';
|
|
348
348
|
if (entityObject.method) {
|
|
349
349
|
if (methods[entityObject.method]) {
|
|
350
|
-
method = entityObject.method
|
|
350
|
+
method = entityObject.method;
|
|
351
351
|
} else {
|
|
352
|
-
throw new Error('Method ' + entityObject.method + ' not recognized.')
|
|
352
|
+
throw new Error('Method ' + entityObject.method + ' not recognized.');
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
355
|
// TODO: generate key
|
|
@@ -358,12 +358,12 @@ export class Datastore extends OrigDatastore {
|
|
|
358
358
|
const newKey =
|
|
359
359
|
entityObject.key.id === undefined
|
|
360
360
|
? this.key(entityObject.key.path)
|
|
361
|
-
: this.key([...entityObject.key.path.slice(0, -1), this.int(entityObject.key.path.slice(-1)[0])])
|
|
361
|
+
: this.key([...entityObject.key.path.slice(0, -1), this.int(entityObject.key.path.slice(-1)[0])]);
|
|
362
362
|
|
|
363
363
|
this.db.set(this._keySerializer(newKey), {
|
|
364
364
|
[Datastore.KEY]: newKey,
|
|
365
365
|
...entityObject.data,
|
|
366
|
-
})
|
|
366
|
+
});
|
|
367
367
|
|
|
368
368
|
result.push({
|
|
369
369
|
mutationResults: [
|
|
@@ -376,75 +376,75 @@ export class Datastore extends OrigDatastore {
|
|
|
376
376
|
},
|
|
377
377
|
],
|
|
378
378
|
indexUpdates: 1, // number|null);
|
|
379
|
-
} as unknown as CommitResponse)
|
|
380
|
-
})
|
|
381
|
-
setImmediate(() => callback(null, result[0] as any))
|
|
379
|
+
} as unknown as CommitResponse);
|
|
380
|
+
});
|
|
381
|
+
setImmediate(() => callback(null, result[0] as any));
|
|
382
382
|
}
|
|
383
383
|
|
|
384
|
-
static KEY: typeof entity.KEY_SYMBOL = entity.KEY_SYMBOL
|
|
385
|
-
KEY: typeof entity.KEY_SYMBOL = Datastore.KEY
|
|
386
|
-
static MORE_RESULTS_AFTER_CURSOR = 'MORE_RESULTS_AFTER_CURSOR'
|
|
387
|
-
MORE_RESULTS_AFTER_CURSOR = Datastore.MORE_RESULTS_AFTER_CURSOR
|
|
388
|
-
static MORE_RESULTS_AFTER_LIMIT = 'MORE_RESULTS_AFTER_LIMIT'
|
|
389
|
-
MORE_RESULTS_AFTER_LIMIT = Datastore.MORE_RESULTS_AFTER_LIMIT
|
|
390
|
-
static NO_MORE_RESULTS = 'NO_MORE_RESULTS'
|
|
391
|
-
NO_MORE_RESULTS = Datastore.NO_MORE_RESULTS
|
|
392
|
-
|
|
393
|
-
createQuery(kind?: string): Query
|
|
394
|
-
createQuery(kind?: string[]): Query
|
|
395
|
-
createQuery(namespace: string, kind: string): Query
|
|
396
|
-
createQuery(namespace: string, kind: string[]): Query
|
|
384
|
+
static KEY: typeof entity.KEY_SYMBOL = entity.KEY_SYMBOL;
|
|
385
|
+
KEY: typeof entity.KEY_SYMBOL = Datastore.KEY;
|
|
386
|
+
static MORE_RESULTS_AFTER_CURSOR = 'MORE_RESULTS_AFTER_CURSOR';
|
|
387
|
+
MORE_RESULTS_AFTER_CURSOR = Datastore.MORE_RESULTS_AFTER_CURSOR;
|
|
388
|
+
static MORE_RESULTS_AFTER_LIMIT = 'MORE_RESULTS_AFTER_LIMIT';
|
|
389
|
+
MORE_RESULTS_AFTER_LIMIT = Datastore.MORE_RESULTS_AFTER_LIMIT;
|
|
390
|
+
static NO_MORE_RESULTS = 'NO_MORE_RESULTS';
|
|
391
|
+
NO_MORE_RESULTS = Datastore.NO_MORE_RESULTS;
|
|
392
|
+
|
|
393
|
+
createQuery(kind?: string): Query;
|
|
394
|
+
createQuery(kind?: string[]): Query;
|
|
395
|
+
createQuery(namespace: string, kind: string): Query;
|
|
396
|
+
createQuery(namespace: string, kind: string[]): Query;
|
|
397
397
|
createQuery(namespaceOrKind?: string | string[], kind?: string | string[]): Query {
|
|
398
|
-
let namespace = namespaceOrKind as string
|
|
398
|
+
let namespace = namespaceOrKind as string;
|
|
399
399
|
if (!kind) {
|
|
400
|
-
kind = namespaceOrKind
|
|
401
|
-
namespace = this.namespace
|
|
400
|
+
kind = namespaceOrKind;
|
|
401
|
+
namespace = this.namespace!;
|
|
402
402
|
}
|
|
403
|
-
return new Query(this as any, namespace, [kind].flat() as string[])
|
|
403
|
+
return new Query(this as any, namespace, [kind].flat() as string[]);
|
|
404
404
|
}
|
|
405
|
-
key(options: entity.KeyOptions): entity.Key
|
|
406
|
-
key(path: PathType[]): entity.Key
|
|
407
|
-
key(path: string): entity.Key
|
|
405
|
+
key(options: entity.KeyOptions): entity.Key;
|
|
406
|
+
key(path: PathType[]): entity.Key;
|
|
407
|
+
key(path: string): entity.Key;
|
|
408
408
|
key(options: string | entity.KeyOptions | PathType[]): entity.Key {
|
|
409
409
|
const keyOptions = is.object(options)
|
|
410
410
|
? (options as entity.KeyOptions)
|
|
411
411
|
: {
|
|
412
412
|
namespace: this.namespace,
|
|
413
413
|
path: [options].flat() as PathType[],
|
|
414
|
-
}
|
|
415
|
-
return new entity.Key(keyOptions)
|
|
414
|
+
};
|
|
415
|
+
return new entity.Key(keyOptions);
|
|
416
416
|
}
|
|
417
417
|
static isKey(value?: unknown) {
|
|
418
|
-
return entity.isDsKey(value as any)
|
|
418
|
+
return entity.isDsKey(value as any);
|
|
419
419
|
}
|
|
420
420
|
isKey(value?: unknown) {
|
|
421
|
-
return Datastore.isKey(value)
|
|
421
|
+
return Datastore.isKey(value);
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
keyToLegacyUrlSafe(key: entity.Key, locationPrefix?: string): Promise<string
|
|
425
|
-
keyToLegacyUrlSafe(key: entity.Key, callback: KeyToLegacyUrlSafeCallback): void
|
|
426
|
-
keyToLegacyUrlSafe(key: entity.Key, locationPrefix: string, callback: KeyToLegacyUrlSafeCallback): void
|
|
424
|
+
keyToLegacyUrlSafe(key: entity.Key, locationPrefix?: string): Promise<string>;
|
|
425
|
+
keyToLegacyUrlSafe(key: entity.Key, callback: KeyToLegacyUrlSafeCallback): void;
|
|
426
|
+
keyToLegacyUrlSafe(key: entity.Key, locationPrefix: string, callback: KeyToLegacyUrlSafeCallback): void;
|
|
427
427
|
keyToLegacyUrlSafe(
|
|
428
428
|
key: entity.Key,
|
|
429
429
|
locationPrefixOrCallback?: string | KeyToLegacyUrlSafeCallback,
|
|
430
430
|
callback?: KeyToLegacyUrlSafeCallback
|
|
431
431
|
): Promise<string> | void {
|
|
432
|
-
const locationPrefix = typeof locationPrefixOrCallback === 'string' ? locationPrefixOrCallback : ''
|
|
433
|
-
callback = typeof locationPrefixOrCallback === 'function' ? locationPrefixOrCallback : callback
|
|
432
|
+
const locationPrefix = typeof locationPrefixOrCallback === 'string' ? locationPrefixOrCallback : '';
|
|
433
|
+
callback = typeof locationPrefixOrCallback === 'function' ? locationPrefixOrCallback : callback;
|
|
434
434
|
this.auth.getProjectId((err: any, projectId: any) => {
|
|
435
435
|
if (err) {
|
|
436
|
-
setImmediate(() => callback!(err))
|
|
437
|
-
return
|
|
436
|
+
setImmediate(() => callback!(err));
|
|
437
|
+
return;
|
|
438
438
|
}
|
|
439
|
-
setImmediate(() => callback!(null, urlSafeKey.legacyEncode(projectId!, key, locationPrefix)))
|
|
440
|
-
})
|
|
439
|
+
setImmediate(() => callback!(null, urlSafeKey.legacyEncode(projectId!, key, locationPrefix)));
|
|
440
|
+
});
|
|
441
441
|
}
|
|
442
442
|
|
|
443
443
|
keyFromLegacyUrlsafe(key: string): entity.Key {
|
|
444
|
-
return urlSafeKey.legacyDecode(key)
|
|
444
|
+
return urlSafeKey.legacyDecode(key);
|
|
445
445
|
}
|
|
446
446
|
transaction(options?: TransactionOptions) {
|
|
447
|
-
return new Transaction(this as any, options)
|
|
447
|
+
return new Transaction(this as any, options);
|
|
448
448
|
}
|
|
449
449
|
}
|
|
450
450
|
|
|
@@ -466,47 +466,47 @@ promisifyAll(Datastore, {
|
|
|
466
466
|
'keyFromLegacyUrlsafe',
|
|
467
467
|
'transaction',
|
|
468
468
|
],
|
|
469
|
-
})
|
|
469
|
+
});
|
|
470
470
|
|
|
471
|
-
export default Datastore
|
|
471
|
+
export default Datastore;
|
|
472
472
|
|
|
473
473
|
class Transaction extends DatastoreRequest {
|
|
474
|
-
namespace?: string
|
|
475
|
-
readOnly: boolean
|
|
476
|
-
request: any // Function
|
|
477
|
-
modifiedEntities_: ModifiedEntities
|
|
478
|
-
skipCommit?: boolean
|
|
474
|
+
namespace?: string;
|
|
475
|
+
readOnly: boolean;
|
|
476
|
+
request: any; // Function
|
|
477
|
+
modifiedEntities_: ModifiedEntities;
|
|
478
|
+
skipCommit?: boolean;
|
|
479
479
|
constructor(datastore: Datastore, options?: TransactionOptions) {
|
|
480
|
-
super()
|
|
480
|
+
super();
|
|
481
481
|
/**
|
|
482
482
|
* @name Transaction#datastore
|
|
483
483
|
* @type {Datastore}
|
|
484
484
|
*/
|
|
485
|
-
this.datastore = datastore
|
|
485
|
+
this.datastore = datastore;
|
|
486
486
|
|
|
487
487
|
/**
|
|
488
488
|
* @name Transaction#namespace
|
|
489
489
|
* @type {string}
|
|
490
490
|
*/
|
|
491
|
-
this.namespace = datastore.namespace
|
|
491
|
+
this.namespace = datastore.namespace;
|
|
492
492
|
|
|
493
|
-
options = options || {}
|
|
493
|
+
options = options || {};
|
|
494
494
|
|
|
495
|
-
this.id = options.id
|
|
496
|
-
this.readOnly = options.readOnly === true
|
|
495
|
+
this.id = options.id;
|
|
496
|
+
this.readOnly = options.readOnly === true;
|
|
497
497
|
|
|
498
498
|
// A queue for entity modifications made during the transaction.
|
|
499
|
-
this.modifiedEntities_ = []
|
|
499
|
+
this.modifiedEntities_ = [];
|
|
500
500
|
|
|
501
501
|
// Queue the callbacks that process the API responses.
|
|
502
|
-
this.requestCallbacks_ = []
|
|
502
|
+
this.requestCallbacks_ = [];
|
|
503
503
|
|
|
504
504
|
// Queue the requests to make when we send the transactional commit.
|
|
505
|
-
this.requests_ = []
|
|
505
|
+
this.requests_ = [];
|
|
506
506
|
}
|
|
507
|
-
commit(gaxOptions?: CallOptions): Promise<CommitResponse
|
|
508
|
-
commit(callback: CommitCallback): void
|
|
509
|
-
commit(gaxOptions: CallOptions, callback: CommitCallback): void
|
|
507
|
+
commit(gaxOptions?: CallOptions): Promise<CommitResponse>;
|
|
508
|
+
commit(callback: CommitCallback): void;
|
|
509
|
+
commit(gaxOptions: CallOptions, callback: CommitCallback): void;
|
|
510
510
|
commit(
|
|
511
511
|
gaxOptionsOrCallback?: CallOptions | CommitCallback,
|
|
512
512
|
cb?: CommitCallback
|
|
@@ -516,79 +516,79 @@ class Transaction extends DatastoreRequest {
|
|
|
516
516
|
? gaxOptionsOrCallback
|
|
517
517
|
: typeof cb === 'function'
|
|
518
518
|
? cb
|
|
519
|
-
: () => {}
|
|
520
|
-
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {}
|
|
519
|
+
: () => {};
|
|
520
|
+
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
|
|
521
521
|
|
|
522
522
|
if (this.skipCommit) {
|
|
523
|
-
setImmediate(callback)
|
|
524
|
-
return
|
|
523
|
+
setImmediate(callback);
|
|
524
|
+
return;
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
-
const keys: Entities = {}
|
|
527
|
+
const keys: Entities = {};
|
|
528
528
|
|
|
529
|
-
callback(null, undefined)
|
|
529
|
+
callback(null, undefined);
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
-
createQuery(kind?: string): Query
|
|
533
|
-
createQuery(kind?: string[]): Query
|
|
534
|
-
createQuery(namespace: string, kind: string): Query
|
|
535
|
-
createQuery(namespace: string, kind: string[]): Query
|
|
532
|
+
createQuery(kind?: string): Query;
|
|
533
|
+
createQuery(kind?: string[]): Query;
|
|
534
|
+
createQuery(namespace: string, kind: string): Query;
|
|
535
|
+
createQuery(namespace: string, kind: string[]): Query;
|
|
536
536
|
createQuery(namespaceOrKind?: string | string[], kind?: string | string[]): Query {
|
|
537
|
-
return this.datastore.createQuery.call(this, namespaceOrKind as string, kind as string[])
|
|
537
|
+
return this.datastore.createQuery.call(this, namespaceOrKind as string, kind as string[]);
|
|
538
538
|
}
|
|
539
539
|
|
|
540
540
|
createAggregationQuery(query: Query): AggregateQuery {
|
|
541
|
-
return this.datastore.createAggregationQuery.call(this, query)
|
|
541
|
+
return this.datastore.createAggregationQuery.call(this, query);
|
|
542
542
|
}
|
|
543
543
|
delete(entities?: Entities): any {
|
|
544
|
-
this.datastore.delete(entities)
|
|
544
|
+
this.datastore.delete(entities);
|
|
545
545
|
}
|
|
546
546
|
insert(entities: Entities): void {
|
|
547
|
-
this.save(entities)
|
|
547
|
+
this.save(entities);
|
|
548
548
|
}
|
|
549
549
|
|
|
550
|
-
rollback(callback: RollbackCallback): void
|
|
551
|
-
rollback(gaxOptions?: CallOptions): Promise<RollbackResponse
|
|
552
|
-
rollback(gaxOptions: CallOptions, callback: RollbackCallback): void
|
|
550
|
+
rollback(callback: RollbackCallback): void;
|
|
551
|
+
rollback(gaxOptions?: CallOptions): Promise<RollbackResponse>;
|
|
552
|
+
rollback(gaxOptions: CallOptions, callback: RollbackCallback): void;
|
|
553
553
|
rollback(
|
|
554
554
|
gaxOptionsOrCallback?: CallOptions | RollbackCallback,
|
|
555
555
|
cb?: RollbackCallback
|
|
556
556
|
): void | Promise<RollbackResponse> {
|
|
557
|
-
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {}
|
|
558
|
-
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb
|
|
557
|
+
const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
|
|
558
|
+
const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
|
|
559
559
|
|
|
560
|
-
callback(null, undefined)
|
|
560
|
+
callback(null, undefined);
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
run(options?: RunOptions): Promise<RunResponse
|
|
564
|
-
run(callback: RunCallback): void
|
|
565
|
-
run(options: RunOptions, callback: RunCallback): void
|
|
563
|
+
run(options?: RunOptions): Promise<RunResponse>;
|
|
564
|
+
run(callback: RunCallback): void;
|
|
565
|
+
run(options: RunOptions, callback: RunCallback): void;
|
|
566
566
|
run(optionsOrCallback?: RunOptions | RunCallback, cb?: RunCallback): void | Promise<RunResponse> {
|
|
567
|
-
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}
|
|
568
|
-
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb
|
|
567
|
+
const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
|
568
|
+
const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
|
|
569
569
|
|
|
570
570
|
const reqOpts = {
|
|
571
571
|
transactionOptions: {},
|
|
572
|
-
} as RequestOptions
|
|
572
|
+
} as RequestOptions;
|
|
573
573
|
|
|
574
574
|
if (options.readOnly || this.readOnly) {
|
|
575
|
-
reqOpts.transactionOptions!.readOnly = {}
|
|
575
|
+
reqOpts.transactionOptions!.readOnly = {};
|
|
576
576
|
}
|
|
577
577
|
|
|
578
578
|
if (options.transactionId || this.id) {
|
|
579
579
|
reqOpts.transactionOptions!.readWrite = {
|
|
580
580
|
previousTransaction: options.transactionId || this.id,
|
|
581
|
-
}
|
|
581
|
+
};
|
|
582
582
|
}
|
|
583
583
|
|
|
584
584
|
if (options.transactionOptions) {
|
|
585
|
-
reqOpts.transactionOptions = options.transactionOptions
|
|
585
|
+
reqOpts.transactionOptions = options.transactionOptions;
|
|
586
586
|
}
|
|
587
587
|
|
|
588
|
-
callback(null, this, undefined)
|
|
588
|
+
callback(null, this, undefined);
|
|
589
589
|
}
|
|
590
590
|
save(entities: Entities): void {
|
|
591
|
-
this.datastore.save(entities)
|
|
591
|
+
this.datastore.save(entities);
|
|
592
592
|
}
|
|
593
593
|
|
|
594
594
|
update(entities: Entities): void {
|
|
@@ -596,11 +596,11 @@ class Transaction extends DatastoreRequest {
|
|
|
596
596
|
.flat()
|
|
597
597
|
.map(DatastoreRequest.prepareEntityObject_)
|
|
598
598
|
.map((x: PrepareEntityObjectResponse) => {
|
|
599
|
-
x.method = 'update'
|
|
600
|
-
return x
|
|
601
|
-
})
|
|
599
|
+
x.method = 'update';
|
|
600
|
+
return x;
|
|
601
|
+
});
|
|
602
602
|
|
|
603
|
-
this.save(entities)
|
|
603
|
+
this.save(entities);
|
|
604
604
|
}
|
|
605
605
|
|
|
606
606
|
upsert(entities: Entities): void {
|
|
@@ -608,36 +608,36 @@ class Transaction extends DatastoreRequest {
|
|
|
608
608
|
.flat()
|
|
609
609
|
.map(DatastoreRequest.prepareEntityObject_)
|
|
610
610
|
.map((x: PrepareEntityObjectResponse) => {
|
|
611
|
-
x.method = 'upsert'
|
|
612
|
-
return x
|
|
613
|
-
})
|
|
611
|
+
x.method = 'upsert';
|
|
612
|
+
return x;
|
|
613
|
+
});
|
|
614
614
|
|
|
615
|
-
this.save(entities)
|
|
615
|
+
this.save(entities);
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
618
|
|
|
619
619
|
export type ModifiedEntities = Array<{
|
|
620
|
-
entity: { key: Entity }
|
|
621
|
-
method: string
|
|
622
|
-
args: Entity[]
|
|
623
|
-
}
|
|
624
|
-
export type RunResponse = [Transaction, google.datastore.v1.IBeginTransactionResponse]
|
|
620
|
+
entity: { key: Entity };
|
|
621
|
+
method: string;
|
|
622
|
+
args: Entity[];
|
|
623
|
+
}>;
|
|
624
|
+
export type RunResponse = [Transaction, google.datastore.v1.IBeginTransactionResponse];
|
|
625
625
|
export interface RunCallback {
|
|
626
626
|
(
|
|
627
627
|
error: Error | null,
|
|
628
628
|
transaction: Transaction | null,
|
|
629
629
|
response?: google.datastore.v1.IBeginTransactionResponse
|
|
630
|
-
): void
|
|
630
|
+
): void;
|
|
631
631
|
}
|
|
632
632
|
export interface RollbackCallback {
|
|
633
|
-
(error: Error | null, response?: google.datastore.v1.IRollbackResponse): void
|
|
633
|
+
(error: Error | null, response?: google.datastore.v1.IRollbackResponse): void;
|
|
634
634
|
}
|
|
635
|
-
export type RollbackResponse = [google.datastore.v1.IRollbackResponse]
|
|
635
|
+
export type RollbackResponse = [google.datastore.v1.IRollbackResponse];
|
|
636
636
|
export interface RunOptions {
|
|
637
|
-
readOnly?: boolean
|
|
638
|
-
transactionId?: string
|
|
639
|
-
transactionOptions?: TransactionOptions
|
|
640
|
-
gaxOptions?: CallOptions
|
|
637
|
+
readOnly?: boolean;
|
|
638
|
+
transactionId?: string;
|
|
639
|
+
transactionOptions?: TransactionOptions;
|
|
640
|
+
gaxOptions?: CallOptions;
|
|
641
641
|
}
|
|
642
642
|
/*! Developer Documentation
|
|
643
643
|
*
|
|
@@ -646,4 +646,4 @@ export interface RunOptions {
|
|
|
646
646
|
*/
|
|
647
647
|
promisifyAll(Transaction, {
|
|
648
648
|
exclude: ['createAggregationQuery', 'createQuery', 'delete', 'insert', 'save', 'update', 'upsert'],
|
|
649
|
-
})
|
|
649
|
+
});
|