1 | ;
|
2 | /*!
|
3 | * Copyright 2018 Google LLC.
|
4 | *
|
5 | * Licensed under the Apache License, Version 2.0 (the "License");
|
6 | * you may not use this file except in compliance with the License.
|
7 | * You may obtain a copy of the License at
|
8 | *
|
9 | * http://www.apache.org/licenses/LICENSE-2.0
|
10 | *
|
11 | * Unless required by applicable law or agreed to in writing, software
|
12 | * distributed under the License is distributed on an "AS IS" BASIS,
|
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 | * See the License for the specific language governing permissions and
|
15 | * limitations under the License.
|
16 | */
|
17 | Object.defineProperty(exports, "__esModule", { value: true });
|
18 | exports.DatastoreAdminClient = exports.DatastoreClient = exports.v1 = exports.Transaction = exports.Query = exports.DatastoreRequest = exports.Index = exports.Datastore = exports.or = exports.and = exports.PropertyFilter = exports.AggregateField = exports.Key = void 0;
|
19 | /**
|
20 | * @namespace google
|
21 | */
|
22 | /**
|
23 | * @namespace google.datastore.v1
|
24 | */
|
25 | /**
|
26 | * @namespace google.protobuf
|
27 | */
|
28 | const arrify = require("arrify");
|
29 | const extend = require("extend");
|
30 | const google_gax_1 = require("google-gax");
|
31 | const is = require("is");
|
32 | const stream_1 = require("stream");
|
33 | const entity_1 = require("./entity");
|
34 | const aggregate_1 = require("./aggregate");
|
35 | Object.defineProperty(exports, "AggregateField", { enumerable: true, get: function () { return aggregate_1.AggregateField; } });
|
36 | var Key = entity_1.entity.Key;
|
37 | exports.Key = Key;
|
38 | const filter_1 = require("./filter");
|
39 | Object.defineProperty(exports, "PropertyFilter", { enumerable: true, get: function () { return filter_1.PropertyFilter; } });
|
40 | Object.defineProperty(exports, "and", { enumerable: true, get: function () { return filter_1.and; } });
|
41 | Object.defineProperty(exports, "or", { enumerable: true, get: function () { return filter_1.or; } });
|
42 | const index_class_1 = require("./index-class");
|
43 | Object.defineProperty(exports, "Index", { enumerable: true, get: function () { return index_class_1.Index; } });
|
44 | const query_1 = require("./query");
|
45 | Object.defineProperty(exports, "Query", { enumerable: true, get: function () { return query_1.Query; } });
|
46 | const request_1 = require("./request");
|
47 | Object.defineProperty(exports, "DatastoreRequest", { enumerable: true, get: function () { return request_1.DatastoreRequest; } });
|
48 | const transaction_1 = require("./transaction");
|
49 | Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return transaction_1.Transaction; } });
|
50 | const promisify_1 = require("@google-cloud/promisify");
|
51 | const aggregate_2 = require("./aggregate");
|
52 | const { grpc } = new google_gax_1.GrpcClient();
|
53 | // Import the clients for each version supported by this package.
|
54 | const gapic = Object.freeze({
|
55 | v1: require('./v1'),
|
56 | });
|
57 | const urlSafeKey = new entity_1.entity.URLSafeKey();
|
58 | /**
|
59 | * Idiomatic class for interacting with Cloud Datastore. Uses the lower-level
|
60 | * {@link DatastoreClient} class under the hood.
|
61 | *
|
62 | * In addition to the constructor options shown here, the {@link Datastore}
|
63 | * class constructor accepts the same options accepted by
|
64 | * {@link DatastoreClient}.
|
65 | *
|
66 | * <h4>The Datastore Emulator</h4>
|
67 | *
|
68 | * Make sure you have the <a href="https://cloud.google.com/sdk/downloads">
|
69 | * gcloud SDK installed</a>, then run:
|
70 | *
|
71 | * <pre>
|
72 | * $ gcloud beta emulators datastore start --no-legacy
|
73 | * </pre>
|
74 | *
|
75 | * You will see the following printed:
|
76 | *
|
77 | * <pre>
|
78 | * [datastore] API endpoint: http://localhost:8005
|
79 | * [datastore] If you are using a library that supports the
|
80 | * DATASTORE_EMULATOR_HOST environment variable, run:
|
81 | * [datastore]
|
82 | * [datastore] export DATASTORE_EMULATOR_HOST=localhost:8005
|
83 | * [datastore]
|
84 | * [datastore] Dev App Server is now running.
|
85 | * </pre>
|
86 | *
|
87 | * Set that environment variable and your localhost Datastore will
|
88 | * automatically be used. You can also pass this address in manually with
|
89 | * `apiEndpoint`.
|
90 | *
|
91 | * Additionally, `DATASTORE_PROJECT_ID` is recognized. If you have this set,
|
92 | * you don't need to provide a `projectId`.
|
93 | *
|
94 | *
|
95 | * See {@link https://cloud.google.com/datastore/docs/concepts/overview| Cloud Datastore Concepts Overview}
|
96 | *
|
97 | * @param {object} [options] Configuration options.
|
98 | * @param {string} [options.apiEndpoint] Override the default API endpoint used
|
99 | * to reach Datastore. This is useful for connecting to your local Datastore
|
100 | * server (usually "http://localhost:8080").
|
101 | * @param {string} [options.namespace] Namespace to isolate transactions to.
|
102 | *
|
103 | * @example Import the client library
|
104 | * ```
|
105 | * const {Datastore} = require('@google-cloud/datastore');
|
106 | *
|
107 | * ```
|
108 | * @example Create a client that uses <a href="https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application">Application Default Credentials (ADC)</a>:
|
109 | * ```
|
110 | * const datastore = new Datastore();
|
111 | *
|
112 | * ```
|
113 | * @example Create a client with <a href="https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually">explicit credentials</a>:
|
114 | * ```
|
115 | * const datastore = new Datastore({
|
116 | * projectId: 'your-project-id',
|
117 | * keyFilename: '/path/to/keyfile.json'
|
118 | * });
|
119 | *
|
120 | * ```
|
121 | * @example Retrieving Records
|
122 | * ```
|
123 | * const {Datastore} = require('@google-cloud/datastore');
|
124 | * const datastore = new Datastore();
|
125 | *
|
126 | * // Records, called "entities" in Datastore, are retrieved by using a key. The
|
127 | * // key is more than a numeric identifier, it is a complex data structure that
|
128 | * // can be used to model relationships. The simplest key has a string `kind`
|
129 | * // value, and either a numeric `id` value, or a string `name` value.
|
130 | * //
|
131 | * // A single record can be retrieved with {@link Datastore#key} and
|
132 | * // {@link Datastore#get}.
|
133 | * //-
|
134 | * const key = datastore.key(['Company', 'Google']);
|
135 | *
|
136 | * datastore.get(key, function(err, entity) {
|
137 | * // entity = The record.
|
138 | * // entity[datastore.KEY] = The key for this entity.
|
139 | * });
|
140 | *
|
141 | * //-
|
142 | * // <h3>Querying Records</h3>
|
143 | * //
|
144 | * // Create a query with {@link Datastore#createQuery}.
|
145 | * //-
|
146 | * const query = datastore.createQuery('Company');
|
147 | *
|
148 | * //-
|
149 | * // Multiple records can be found that match criteria with
|
150 | * // {@link Query#filter}.
|
151 | * //-
|
152 | * query.filter('location', 'CA');
|
153 | *
|
154 | * //-
|
155 | * // Records can also be ordered with {@link Query#order}.
|
156 | * //-
|
157 | * query.order('name');
|
158 | *
|
159 | * //-
|
160 | * // The number of records returned can be specified with
|
161 | * // {@link Query#limit}.
|
162 | * //-
|
163 | * query.limit(5);
|
164 | *
|
165 | * //-
|
166 | * // Records' key structures can also be queried with
|
167 | * // {@link Query#hasAncestor}.
|
168 | * //-
|
169 | * const ancestorKey = datastore.key(['ParentCompany', 'Alphabet']);
|
170 | *
|
171 | * query.hasAncestor(ancestorKey);
|
172 | *
|
173 | * //-
|
174 | * // Run the query with {@link Datastore#runQuery}.
|
175 | * //-
|
176 | * datastore.runQuery(query, (err, entities) => {
|
177 | * // entities = An array of records.
|
178 | *
|
179 | * // Access the Key object for an entity.
|
180 | * const firstEntityKey = entities[0][datastore.KEY];
|
181 | * });
|
182 | *
|
183 | * ```
|
184 | * @example Paginating Records
|
185 | * ```
|
186 | * // Imagine building a website that allows a user to sift through hundreds of
|
187 | * // their contacts. You'll likely want to only display a subset of these at
|
188 | * // once, so you set a limit.
|
189 | * //-
|
190 | * const express = require('express');
|
191 | * const app = express();
|
192 | *
|
193 | * const NUM_RESULTS_PER_PAGE = 15;
|
194 | *
|
195 | * app.get('/contacts', (req, res) => {
|
196 | * const query = datastore.createQuery('Contacts')
|
197 | * .limit(NUM_RESULTS_PER_PAGE);
|
198 | *
|
199 | * if (req.query.nextPageCursor) {
|
200 | * query.start(req.query.nextPageCursor);
|
201 | * }
|
202 | *
|
203 | * datastore.runQuery(query, (err, entities, info) => {
|
204 | * if (err) {
|
205 | * // Error handling omitted.
|
206 | * return;
|
207 | * }
|
208 | *
|
209 | * // Respond to the front end with the contacts and the cursoring token
|
210 | * // from the query we just ran.
|
211 | * const frontEndResponse = {
|
212 | * contacts: entities
|
213 | * };
|
214 | *
|
215 | * // Check if more results may exist.
|
216 | * if (info.moreResults !== datastore.NO_MORE_RESULTS) {
|
217 | * frontEndResponse.nextPageCursor = info.endCursor;
|
218 | * }
|
219 | *
|
220 | * res.render('contacts', frontEndResponse);
|
221 | * });
|
222 | * });
|
223 | *
|
224 | * ```
|
225 | * @example Creating Records
|
226 | * ```
|
227 | * // New entities can be created and persisted with {@link Datastore#save}.
|
228 | * // The entity must have a key to be saved. If you don't specify an
|
229 | * // identifier for the key, one is generated for you.
|
230 | * //
|
231 | * // We will create a key with a `name` identifier, "Google".
|
232 | * //-
|
233 | * const key = datastore.key(['Company', 'Google']);
|
234 | *
|
235 | * const data = {
|
236 | * name: 'Google',
|
237 | * location: 'CA'
|
238 | * };
|
239 | *
|
240 | * datastore.save({
|
241 | * key: key,
|
242 | * data: data
|
243 | * }, (err) => {
|
244 | * if (!err) {
|
245 | * // Record saved successfully.
|
246 | * }
|
247 | * });
|
248 | *
|
249 | * //-
|
250 | * // We can verify the data was saved by using {@link Datastore#get}.
|
251 | * //-
|
252 | * datastore.get(key, (err, entity) => {
|
253 | * // entity = {
|
254 | * // name: 'Google',
|
255 | * // location: 'CA'
|
256 | * // }
|
257 | * });
|
258 | *
|
259 | * //-
|
260 | * // If we want to update this record, we can modify the data object and re-
|
261 | * // save it.
|
262 | * //-
|
263 | * data.symbol = 'GOOG';
|
264 | *
|
265 | * datastore.save({
|
266 | * key: key, // defined above (datastore.key(['Company', 'Google']))
|
267 | * data: data
|
268 | * }, (err, entity) => {
|
269 | * if (!err) {
|
270 | * // Record updated successfully.
|
271 | * }
|
272 | * });
|
273 | *
|
274 | * ```
|
275 | * @example Deleting Records
|
276 | * ```
|
277 | * // Entities can be removed from Datastore by passing the entity's key object
|
278 | * // to {@link Datastore#delete}.
|
279 | * //-
|
280 | * const key = datastore.key(['Company', 'Google']);
|
281 | *
|
282 | * datastore.delete(key, (err) => {
|
283 | * if (!err) {
|
284 | * // Record deleted successfully.
|
285 | * }
|
286 | * });
|
287 | *
|
288 | * ```
|
289 | * @example Transactions
|
290 | * ```
|
291 | * // Complex logic can be wrapped in a transaction with
|
292 | * // {@link Datastore#transaction}. All queries and updates run within
|
293 | * // the transaction will be applied when the `done` function is called.
|
294 | * //-
|
295 | * const transaction = datastore.transaction();
|
296 | *
|
297 | * transaction.run((err) => {
|
298 | * if (err) {
|
299 | * // Error handling omitted.
|
300 | * }
|
301 | *
|
302 | * const key = datastore.key(['Company', 'Google']);
|
303 | *
|
304 | * transaction.get(key, (err, entity) => {
|
305 | * if (err) {
|
306 | * // Error handling omitted.
|
307 | * }
|
308 | *
|
309 | * entity.symbol = 'GOOG';
|
310 | *
|
311 | * transaction.save(entity);
|
312 | *
|
313 | * transaction.commit((err) => {
|
314 | * if (!err) {
|
315 | * // Transaction committed successfully.
|
316 | * }
|
317 | * });
|
318 | * });
|
319 | * });
|
320 | *
|
321 | * ```
|
322 | * @example Queries with Ancestors
|
323 | * ```
|
324 | * const {Datastore} = require('@google-cloud/datastore');
|
325 | * const datastore = new Datastore();
|
326 | *
|
327 | * const customerId1 = 2993844;
|
328 | * const customerId2 = 4993882;
|
329 | * const customerKey1 = datastore.key(['Customer', customerId1]);
|
330 | * const customerKey2 = datastore.key(['Customer', customerId2]);
|
331 | * const cookieKey1 = datastore.key(['Customer', customerId1, 'Cookie',
|
332 | * 'cookie28839']); // child entity const cookieKey2 =
|
333 | * datastore.key(['Customer', customerId1, 'Cookie', 'cookie78984']); // child
|
334 | * entity const cookieKey3 = datastore.key(['Customer', customerId2, 'Cookie',
|
335 | * 'cookie93911']); // child entity
|
336 | *
|
337 | * const entities = [];
|
338 | *
|
339 | * entities.push({
|
340 | * key: customerKey1,
|
341 | * data: {
|
342 | * name: 'Jane Doe',
|
343 | * address: '4848 Liller'
|
344 | * }
|
345 | * });
|
346 | *
|
347 | * entities.push({
|
348 | * key: customerKey2,
|
349 | * data: {
|
350 | * name: 'John Smith',
|
351 | * address: '4848 Pine'
|
352 | * }
|
353 | * });
|
354 | *
|
355 | * entities.push({
|
356 | * key: cookieKey1,
|
357 | * data: {
|
358 | * cookieVal: 'dj83kks88rkld'
|
359 | * }
|
360 | * });
|
361 | *
|
362 | * entities.push({
|
363 | * key: cookieKey2,
|
364 | * data: {
|
365 | * cookieVal: 'sj843ka99s'
|
366 | * }
|
367 | * });
|
368 | *
|
369 | * entities.push({
|
370 | * key: cookieKey3,
|
371 | * data: {
|
372 | * cookieVal: 'otk82k2kw'
|
373 | * }
|
374 | * });
|
375 | *
|
376 | * datastore.upsert(entities);
|
377 | *
|
378 | * const query = datastore.createQuery().hasAncestor(customerKey1);
|
379 | *
|
380 | * datastore.runQuery(query, (err, entities) => {
|
381 | * for (let entity of entities) {
|
382 | * console.log(entity[datastore.KEY]);
|
383 | * }
|
384 | * });
|
385 | *
|
386 | * const query2 = datastore.createQuery().hasAncestor(customerKey2);
|
387 | *
|
388 | * datastore.runQuery(query2, (err, entities) => {
|
389 | * for (let entity of entities) {
|
390 | * console.log(entity[datastore.KEY]);
|
391 | * }
|
392 | * });
|
393 | *
|
394 | * datastore.runQuery(query2, (entities) => {
|
395 | * console.log(entities);
|
396 | * });
|
397 | * ```
|
398 | */
|
399 | class Datastore extends request_1.DatastoreRequest {
|
400 | constructor(options) {
|
401 | var _a;
|
402 | var _b;
|
403 | super();
|
404 | this.KEY = Datastore.KEY;
|
405 | this.MORE_RESULTS_AFTER_CURSOR = Datastore.MORE_RESULTS_AFTER_CURSOR;
|
406 | this.MORE_RESULTS_AFTER_LIMIT = Datastore.MORE_RESULTS_AFTER_LIMIT;
|
407 | this.NO_MORE_RESULTS = Datastore.NO_MORE_RESULTS;
|
408 | /**
|
409 | * {@link DatastoreRequest} class.
|
410 | *
|
411 | * @name Datastore.DatastoreRequest
|
412 | * @see DatastoreRequest
|
413 | * @type {constructor}
|
414 | */
|
415 | this.DatastoreRequest = request_1.DatastoreRequest;
|
416 | /**
|
417 | * {@link Query} class.
|
418 | *
|
419 | * @name Datastore.Query
|
420 | * @see Query
|
421 | * @type {constructor}
|
422 | */
|
423 | this.Query = query_1.Query;
|
424 | /**
|
425 | * {@link Transaction} class.
|
426 | *
|
427 | * @name Datastore.Transaction
|
428 | * @see Transaction
|
429 | * @type {constructor}
|
430 | */
|
431 | this.Transaction = transaction_1.Transaction;
|
432 | options = options || {};
|
433 | this.clients_ = new Map();
|
434 | this.datastore = this;
|
435 | /**
|
436 | * @name Datastore#namespace
|
437 | * @type {string}
|
438 | */
|
439 | this.namespace = options.namespace;
|
440 | options.projectId = options.projectId || process.env.DATASTORE_PROJECT_ID;
|
441 | this.defaultBaseUrl_ = 'datastore.googleapis.com';
|
442 | this.determineBaseUrl_(options.apiEndpoint);
|
443 | const scopes = Array.from(new Set([
|
444 | ...gapic.v1.DatastoreClient.scopes,
|
445 | ...gapic.v1.DatastoreAdminClient.scopes,
|
446 | ]));
|
447 | this.options = Object.assign({
|
448 | libName: 'gccl',
|
449 | libVersion: require('../../package.json').version,
|
450 | scopes,
|
451 | servicePath: this.baseUrl_,
|
452 | port: typeof this.port_ === 'number' ? this.port_ : 443,
|
453 | }, options);
|
454 | const isUsingLocalhost = this.baseUrl_ &&
|
455 | (this.baseUrl_.includes('localhost') ||
|
456 | this.baseUrl_.includes('127.0.0.1') ||
|
457 | this.baseUrl_.includes('::1'));
|
458 | const isEmulatorVariableSet = process.env.DATASTORE_EMULATOR_HOST;
|
459 | const isUsingEmulator = isUsingLocalhost || isEmulatorVariableSet;
|
460 | if (this.customEndpoint_ && isUsingEmulator) {
|
461 | (_a = (_b = this.options).sslCreds) !== null && _a !== void 0 ? _a : (_b.sslCreds = grpc.credentials.createInsecure());
|
462 | }
|
463 | this.auth = new google_gax_1.GoogleAuth(this.options);
|
464 | }
|
465 | /**
|
466 | * Create an aggregation query from a Query.
|
467 | *
|
468 | * @param {Query} query A Query object.
|
469 | */
|
470 | createAggregationQuery(query) {
|
471 | return new aggregate_2.AggregateQuery(query);
|
472 | }
|
473 | export(config, callback) {
|
474 | const reqOpts = {
|
475 | entityFilter: {},
|
476 | ...config,
|
477 | };
|
478 | if (reqOpts.bucket && reqOpts.outputUrlPrefix) {
|
479 | throw new Error('Both `bucket` and `outputUrlPrefix` were provided.');
|
480 | }
|
481 | if (!reqOpts.outputUrlPrefix) {
|
482 | if (typeof config.bucket === 'string') {
|
483 | reqOpts.outputUrlPrefix = `gs://${config.bucket.replace('gs://', '')}`;
|
484 | }
|
485 | else if (typeof config.bucket === 'object') {
|
486 | reqOpts.outputUrlPrefix = `gs://${config.bucket.name}`;
|
487 | }
|
488 | else {
|
489 | throw new Error('A Bucket object or URL must be provided.');
|
490 | }
|
491 | }
|
492 | if (reqOpts.kinds) {
|
493 | if (typeof config.entityFilter === 'object') {
|
494 | throw new Error('Both `entityFilter` and `kinds` were provided.');
|
495 | }
|
496 | reqOpts.entityFilter.kinds = reqOpts.kinds;
|
497 | }
|
498 | if (reqOpts.namespaces) {
|
499 | if (typeof config.entityFilter === 'object') {
|
500 | throw new Error('Both `entityFilter` and `namespaces` were provided.');
|
501 | }
|
502 | reqOpts.entityFilter.namespaceIds = reqOpts.namespaces;
|
503 | }
|
504 | delete reqOpts.bucket;
|
505 | delete reqOpts.gaxOptions;
|
506 | delete reqOpts.kinds;
|
507 | delete reqOpts.namespaces;
|
508 | this.request_({
|
509 | client: 'DatastoreAdminClient',
|
510 | method: 'exportEntities',
|
511 | reqOpts: reqOpts,
|
512 | gaxOpts: config.gaxOptions,
|
513 | },
|
514 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
515 | callback);
|
516 | }
|
517 | getIndexes(optionsOrCallback, cb) {
|
518 | let options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
|
519 | const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
|
520 | options = extend(true, {}, options);
|
521 | const gaxOpts = options.gaxOptions || {};
|
522 | const reqOpts = {
|
523 | pageSize: gaxOpts.pageSize,
|
524 | pageToken: gaxOpts.pageToken,
|
525 | ...options,
|
526 | };
|
527 | delete gaxOpts.pageSize;
|
528 | delete gaxOpts.pageToken;
|
529 | delete reqOpts.autoPaginate;
|
530 | delete reqOpts.gaxOptions;
|
531 | if (typeof options.autoPaginate === 'boolean' &&
|
532 | typeof gaxOpts.autoPaginate === 'undefined') {
|
533 | gaxOpts.autoPaginate = options.autoPaginate;
|
534 | }
|
535 | this.request_({
|
536 | client: 'DatastoreAdminClient',
|
537 | method: 'listIndexes',
|
538 | reqOpts,
|
539 | gaxOpts,
|
540 | },
|
541 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
542 | (err, ...resp) => {
|
543 | let indexes = [];
|
544 | if (resp[0]) {
|
545 | indexes = resp[0].map((index) => {
|
546 | const indexInstance = this.index(index.indexId);
|
547 | indexInstance.metadata = index;
|
548 | return indexInstance;
|
549 | });
|
550 | }
|
551 | const nextQuery = resp[1] ? Object.assign(options, resp[1]) : null;
|
552 | const apiResp = resp[2];
|
553 | callback(err, indexes, nextQuery, apiResp);
|
554 | });
|
555 | }
|
556 | /**
|
557 | * Get all of the indexes in this project as a readable object stream.
|
558 | *
|
559 | * @param {GetIndexesOptions} [options] Configuration object. See
|
560 | * {@link Datastore#getIndexes} for a complete list of options.
|
561 | * @returns {ReadableStream<Index>}
|
562 | */
|
563 | getIndexesStream(options) {
|
564 | const { gaxOptions, ...reqOpts } = options || {};
|
565 | return (0, stream_1.pipeline)(this.requestStream_({
|
566 | client: 'DatastoreAdminClient',
|
567 | method: 'listIndexesStream',
|
568 | reqOpts,
|
569 | gaxOpts: gaxOptions,
|
570 | }), new stream_1.Transform({
|
571 | objectMode: true,
|
572 | transform: (index, enc, next) => {
|
573 | const indexInstance = this.index(index.indexId);
|
574 | indexInstance.metadata = index;
|
575 | next(null, indexInstance);
|
576 | },
|
577 | }), () => { });
|
578 | }
|
579 | /**
|
580 | * Gets the database id that all requests will be run against.
|
581 | *
|
582 | * @returns {string} The database id that the current client is set to that
|
583 | * requests will run against.
|
584 | */
|
585 | getDatabaseId() {
|
586 | return this.options.databaseId;
|
587 | }
|
588 | getProjectId() {
|
589 | return this.auth.getProjectId();
|
590 | }
|
591 | import(config, callback) {
|
592 | const reqOpts = {
|
593 | entityFilter: {},
|
594 | ...config,
|
595 | };
|
596 | if (config.file && config.inputUrl) {
|
597 | throw new Error('Both `file` and `inputUrl` were provided.');
|
598 | }
|
599 | if (!reqOpts.inputUrl) {
|
600 | if (typeof config.file === 'string') {
|
601 | reqOpts.inputUrl = `gs://${config.file.replace('gs://', '')}`;
|
602 | }
|
603 | else if (typeof config.file === 'object') {
|
604 | reqOpts.inputUrl = `gs://${config.file.bucket.name}/${config.file.name}`;
|
605 | }
|
606 | else {
|
607 | throw new Error('An input URL must be provided.');
|
608 | }
|
609 | }
|
610 | if (reqOpts.kinds) {
|
611 | if (typeof config.entityFilter === 'object') {
|
612 | throw new Error('Both `entityFilter` and `kinds` were provided.');
|
613 | }
|
614 | reqOpts.entityFilter.kinds = reqOpts.kinds;
|
615 | }
|
616 | if (reqOpts.namespaces) {
|
617 | if (typeof config.entityFilter === 'object') {
|
618 | throw new Error('Both `entityFilter` and `namespaces` were provided.');
|
619 | }
|
620 | reqOpts.entityFilter.namespaceIds = reqOpts.namespaces;
|
621 | }
|
622 | delete reqOpts.file;
|
623 | delete reqOpts.gaxOptions;
|
624 | delete reqOpts.kinds;
|
625 | delete reqOpts.namespaces;
|
626 | this.request_({
|
627 | client: 'DatastoreAdminClient',
|
628 | method: 'importEntities',
|
629 | reqOpts: reqOpts,
|
630 | gaxOpts: config.gaxOptions,
|
631 | },
|
632 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
633 | callback);
|
634 | }
|
635 | /**
|
636 | * Get a reference to an Index.
|
637 | *
|
638 | * @param {string} id The index name or id.
|
639 | * @returns {Index}
|
640 | */
|
641 | index(id) {
|
642 | return new index_class_1.Index(this, id);
|
643 | }
|
644 | insert(entities, callback) {
|
645 | entities = arrify(entities)
|
646 | .map(request_1.DatastoreRequest.prepareEntityObject_)
|
647 | .map((x) => {
|
648 | x.method = 'insert';
|
649 | return x;
|
650 | });
|
651 | this.save(entities, callback);
|
652 | }
|
653 | save(entities, gaxOptionsOrCallback, cb) {
|
654 | entities = arrify(entities);
|
655 | const gaxOptions = typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
|
656 | const callback = typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb;
|
657 | const insertIndexes = {};
|
658 | const mutations = [];
|
659 | const methods = {
|
660 | insert: true,
|
661 | update: true,
|
662 | upsert: true,
|
663 | };
|
664 | // Iterate over the entity objects, build a proto from all keys and values,
|
665 | // then place in the correct mutation array (insert, update, etc).
|
666 | entities
|
667 | .map(request_1.DatastoreRequest.prepareEntityObject_)
|
668 | .forEach((entityObject, index) => {
|
669 | const mutation = {};
|
670 | let entityProto = {};
|
671 | let method = 'upsert';
|
672 | if (entityObject.method) {
|
673 | if (methods[entityObject.method]) {
|
674 | method = entityObject.method;
|
675 | }
|
676 | else {
|
677 | throw new Error('Method ' + entityObject.method + ' not recognized.');
|
678 | }
|
679 | }
|
680 | if (entityObject.excludeLargeProperties) {
|
681 | entityObject.excludeFromIndexes = entity_1.entity.findLargeProperties_(entityObject.data, '', entityObject.excludeFromIndexes);
|
682 | }
|
683 | if (!entity_1.entity.isKeyComplete(entityObject.key)) {
|
684 | insertIndexes[index] = true;
|
685 | }
|
686 | // @TODO remove in @google-cloud/datastore@2.0.0
|
687 | // This was replaced with a more efficient mechanism in the top-level
|
688 | // `excludeFromIndexes` option.
|
689 | if (Array.isArray(entityObject.data)) {
|
690 | entityProto.properties = entityObject.data.reduce((acc, data) => {
|
691 | const value = entity_1.entity.encodeValue(data.value, data.name.toString());
|
692 | if (typeof data.excludeFromIndexes === 'boolean') {
|
693 | const excluded = data.excludeFromIndexes;
|
694 | let values = value.arrayValue && value.arrayValue.values;
|
695 | if (values) {
|
696 | values = values.map((x) => {
|
697 | x.excludeFromIndexes = excluded;
|
698 | return x;
|
699 | });
|
700 | }
|
701 | else {
|
702 | value.excludeFromIndexes = data.excludeFromIndexes;
|
703 | }
|
704 | }
|
705 | acc[data.name] = value;
|
706 | return acc;
|
707 | }, {});
|
708 | }
|
709 | else {
|
710 | entityProto = entity_1.entity.entityToEntityProto(entityObject);
|
711 | }
|
712 | entityProto.key = entity_1.entity.keyToKeyProto(entityObject.key);
|
713 | mutation[method] = entityProto;
|
714 | mutations.push(mutation);
|
715 | });
|
716 | const reqOpts = {
|
717 | mutations,
|
718 | };
|
719 | function onCommit(err, resp) {
|
720 | if (err || !resp) {
|
721 | callback(err, resp);
|
722 | return;
|
723 | }
|
724 | arrify(resp.mutationResults).forEach((result, index) => {
|
725 | if (!result.key) {
|
726 | return;
|
727 | }
|
728 | if (insertIndexes[index]) {
|
729 | const id = entity_1.entity.keyFromKeyProto(result.key).id;
|
730 | entities[index].key.id = id;
|
731 | }
|
732 | });
|
733 | callback(null, resp);
|
734 | }
|
735 | if (this.id) {
|
736 | this.requests_.push(reqOpts);
|
737 | this.requestCallbacks_.push(onCommit);
|
738 | return;
|
739 | }
|
740 | this.request_({
|
741 | client: 'DatastoreClient',
|
742 | method: 'commit',
|
743 | reqOpts,
|
744 | gaxOpts: gaxOptions,
|
745 | }, onCommit);
|
746 | }
|
747 | update(entities, callback) {
|
748 | entities = arrify(entities)
|
749 | .map(request_1.DatastoreRequest.prepareEntityObject_)
|
750 | .map((x) => {
|
751 | x.method = 'update';
|
752 | return x;
|
753 | });
|
754 | this.save(entities, callback);
|
755 | }
|
756 | upsert(entities, callback) {
|
757 | entities = arrify(entities)
|
758 | .map(request_1.DatastoreRequest.prepareEntityObject_)
|
759 | .map((x) => {
|
760 | x.method = 'upsert';
|
761 | return x;
|
762 | });
|
763 | this.save(entities, callback);
|
764 | }
|
765 | /**
|
766 | * Helper function to get a Datastore Double object.
|
767 | *
|
768 | * @param {number} value The double value.
|
769 | * @returns {object}
|
770 | *
|
771 | * @example
|
772 | * ```
|
773 | * const {Datastore} = require('@google-cloud/datastore');
|
774 | * const datastore = new Datastore();
|
775 | * const threeDouble = datastore.double(3.0);
|
776 | * ```
|
777 | */
|
778 | static double(value) {
|
779 | return new entity_1.entity.Double(value);
|
780 | }
|
781 | double(value) {
|
782 | return Datastore.double(value);
|
783 | }
|
784 | /**
|
785 | * Helper function to check if something is a Datastore Double object.
|
786 | *
|
787 | * @param {*} value
|
788 | * @returns {boolean}
|
789 | *
|
790 | * @example
|
791 | * ```
|
792 | * const {Datastore} = require('@google-cloud/datastore');
|
793 | * const datastore = new Datastore();
|
794 | * datastore.isDouble(0.42); // false
|
795 | * datastore.isDouble(datastore.double(0.42)); // true
|
796 | * ```
|
797 | */
|
798 | static isDouble(value) {
|
799 | return entity_1.entity.isDsDouble(value);
|
800 | }
|
801 | isDouble(value) {
|
802 | return Datastore.isDouble(value);
|
803 | }
|
804 | /**
|
805 | * Helper function to get a Datastore Geo Point object.
|
806 | *
|
807 | * @param {object} coordinates Coordinate value.
|
808 | * @param {number} coordinates.latitude Latitudinal value.
|
809 | * @param {number} coordinates.longitude Longitudinal value.
|
810 | * @returns {object}
|
811 | *
|
812 | * @example
|
813 | * ```
|
814 | * const {Datastore} = require('@google-cloud/datastore');
|
815 | * const datastore = new Datastore();
|
816 | * const coordinates = {
|
817 | * latitude: 40.6894,
|
818 | * longitude: -74.0447
|
819 | * };
|
820 | *
|
821 | * const geoPoint = datastore.geoPoint(coordinates);
|
822 | *
|
823 | * //-
|
824 | * // List all companies that are located at 40.123 latitude
|
825 | * // and -74.0447 longitude.
|
826 | * //-
|
827 | * const query = datastore.createQuery('Company');
|
828 | * const companyQuery = query
|
829 | * .filter('geoPoint.latitude', datastore.double(40.123))
|
830 | * .filter('geoPoint.longitude', datastore.double(-74.0447));
|
831 | * ```
|
832 | */
|
833 | static geoPoint(coordinates) {
|
834 | return new entity_1.entity.GeoPoint(coordinates);
|
835 | }
|
836 | geoPoint(coordinates) {
|
837 | return Datastore.geoPoint(coordinates);
|
838 | }
|
839 | /**
|
840 | * Helper function to check if something is a Datastore Geo Point object.
|
841 | *
|
842 | * @param {*} value
|
843 | * @returns {boolean}
|
844 | *
|
845 | * @example
|
846 | * ```
|
847 | * const {Datastore} = require('@google-cloud/datastore');
|
848 | * const datastore = new Datastore();
|
849 | * const coordinates = {
|
850 | * latitude: 0,
|
851 | * longitude: 0
|
852 | * };
|
853 | *
|
854 | * datastore.isGeoPoint(coordinates); // false
|
855 | * datastore.isGeoPoint(datastore.geoPoint(coordinates)); // true
|
856 | * ```
|
857 | */
|
858 | static isGeoPoint(value) {
|
859 | return entity_1.entity.isDsGeoPoint(value);
|
860 | }
|
861 | isGeoPoint(value) {
|
862 | return Datastore.isGeoPoint(value);
|
863 | }
|
864 | /**
|
865 | * Helper function to get a Datastore Integer object.
|
866 | *
|
867 | * This is also useful when using an ID outside the bounds of a JavaScript
|
868 | * Number object.
|
869 | *
|
870 | * @param {number} value The integer value.
|
871 | * @returns {object}
|
872 | *
|
873 | * @example
|
874 | * ```
|
875 | * const {Datastore} = require('@google-cloud/datastore');
|
876 | * const datastore = new Datastore();
|
877 | * const sevenInteger = datastore.int(7);
|
878 | *
|
879 | * //-
|
880 | * // Create an Int to support long Key IDs.
|
881 | * //-
|
882 | * const key = datastore.key([
|
883 | * 'Kind',
|
884 | * datastore.int('100000000000001234')
|
885 | * ]);
|
886 | * ```
|
887 | */
|
888 | static int(value) {
|
889 | return new entity_1.entity.Int(value);
|
890 | }
|
891 | int(value) {
|
892 | return Datastore.int(value);
|
893 | }
|
894 | /**
|
895 | * Helper function to check if something is a Datastore Integer object.
|
896 | *
|
897 | * @param {*} value
|
898 | * @returns {boolean}
|
899 | *
|
900 | * @example
|
901 | * ```
|
902 | * const {Datastore} = require('@google-cloud/datastore');
|
903 | * const datastore = new Datastore();
|
904 | * datastore.isInt(42); // false
|
905 | * datastore.isInt(datastore.int(42)); // true
|
906 | * ```
|
907 | */
|
908 | static isInt(value) {
|
909 | return entity_1.entity.isDsInt(value);
|
910 | }
|
911 | isInt(value) {
|
912 | return Datastore.isInt(value);
|
913 | }
|
914 | createQuery(namespaceOrKind, kind) {
|
915 | let namespace = namespaceOrKind;
|
916 | if (!kind) {
|
917 | kind = namespaceOrKind;
|
918 | namespace = this.namespace;
|
919 | }
|
920 | return new query_1.Query(this, namespace, arrify(kind));
|
921 | }
|
922 | key(options) {
|
923 | const keyOptions = is.object(options)
|
924 | ? options
|
925 | : {
|
926 | namespace: this.namespace,
|
927 | path: arrify(options),
|
928 | };
|
929 | return new entity_1.entity.Key(keyOptions);
|
930 | }
|
931 | /**
|
932 | * Helper function to check if something is a Datastore Key object.
|
933 | *
|
934 | * @param {*} value
|
935 | * @returns {boolean}
|
936 | *
|
937 | * @example
|
938 | * ```
|
939 | * const {Datastore} = require('@google-cloud/datastore');
|
940 | * const datastore = new Datastore();
|
941 | * datastore.isKey({path: ['Company', 123]}); // false
|
942 | * datastore.isKey(datastore.key(['Company', 123])); // true
|
943 | * ```
|
944 | */
|
945 | static isKey(value) {
|
946 | return entity_1.entity.isDsKey(value);
|
947 | }
|
948 | isKey(value) {
|
949 | return Datastore.isKey(value);
|
950 | }
|
951 | keyToLegacyUrlSafe(key, locationPrefixOrCallback, callback) {
|
952 | const locationPrefix = typeof locationPrefixOrCallback === 'string'
|
953 | ? locationPrefixOrCallback
|
954 | : '';
|
955 | callback =
|
956 | typeof locationPrefixOrCallback === 'function'
|
957 | ? locationPrefixOrCallback
|
958 | : callback;
|
959 | this.auth.getProjectId((err, projectId) => {
|
960 | if (err) {
|
961 | callback(err);
|
962 | return;
|
963 | }
|
964 | callback(null, urlSafeKey.legacyEncode(projectId, key, locationPrefix));
|
965 | });
|
966 | }
|
967 | /**
|
968 | * Helper to convert URL safe key string to entity key object
|
969 | *
|
970 | * This is intended to work with the "legacy" representation of a
|
971 | * datastore "Key" used within Google App Engine (a so-called "Reference").
|
972 | *
|
973 | * @param {entity.Key} key Entity key object.
|
974 | * @param {string} locationPrefix Optional .
|
975 | * The location prefix of an App Engine project ID.
|
976 | * Often this value is 's~', but may also be 'e~', or other location prefixes
|
977 | * currently unknown.
|
978 | * @returns {string} Created urlsafe key.
|
979 | *
|
980 | * @example
|
981 | * ```
|
982 | * const {Datastore} = require('@google-cloud/datastore');
|
983 | * const datastore = new Datastore();
|
984 | * const urlSafeKey = 'ag9ncmFzcy1jbHVtcC00NzlyEwsSB0NvbXBhbnkiBkdvb2dsZQw';
|
985 | *
|
986 | * datastore.keyFromLegacyUrlsafe(key);
|
987 | *
|
988 | * ```
|
989 | */
|
990 | keyFromLegacyUrlsafe(key) {
|
991 | return urlSafeKey.legacyDecode(key);
|
992 | }
|
993 | /**
|
994 | * Create a new Transaction object.
|
995 | *
|
996 | * @param {object} [options] Configuration object.
|
997 | * @param {string} [options.id] The ID of a previously run transaction.
|
998 | * @param {boolean} [options.readOnly=false] A read-only transaction cannot
|
999 | * modify entities.
|
1000 | * @returns {Transaction}
|
1001 | *
|
1002 | * @example
|
1003 | * ```
|
1004 | * const {Datastore} = require('@google-cloud/datastore');
|
1005 | * const datastore = new Datastore();
|
1006 | * const transaction = datastore.transaction();
|
1007 | * ```
|
1008 | */
|
1009 | transaction(options) {
|
1010 | return new transaction_1.Transaction(this, options);
|
1011 | }
|
1012 | /**
|
1013 | * Determine the appropriate endpoint to use for API requests. If not
|
1014 | * explicitly defined, check for the "DATASTORE_EMULATOR_HOST" environment
|
1015 | * variable, used to connect to a local Datastore server.
|
1016 | *
|
1017 | * @private
|
1018 | *
|
1019 | * @param {string} customApiEndpoint Custom API endpoint.
|
1020 | */
|
1021 | determineBaseUrl_(customApiEndpoint) {
|
1022 | let baseUrl = this.defaultBaseUrl_;
|
1023 | const leadingProtocol = new RegExp('^https*://');
|
1024 | const trailingSlashes = new RegExp('/*$');
|
1025 | const port = new RegExp(':(\\d+)');
|
1026 | if (customApiEndpoint) {
|
1027 | baseUrl = customApiEndpoint;
|
1028 | this.customEndpoint_ = true;
|
1029 | }
|
1030 | else if (process.env.DATASTORE_EMULATOR_HOST) {
|
1031 | baseUrl = process.env.DATASTORE_EMULATOR_HOST;
|
1032 | this.customEndpoint_ = true;
|
1033 | }
|
1034 | if (port.test(baseUrl)) {
|
1035 | this.port_ = Number(baseUrl.match(port)[1]);
|
1036 | }
|
1037 | this.baseUrl_ = baseUrl
|
1038 | .replace(leadingProtocol, '')
|
1039 | .replace(port, '')
|
1040 | .replace(trailingSlashes, '');
|
1041 | }
|
1042 | }
|
1043 | exports.Datastore = Datastore;
|
1044 | /**
|
1045 | * Access the Key from an Entity object.
|
1046 | *
|
1047 | * @name Datastore.KEY
|
1048 | * @type {symbol}
|
1049 | */
|
1050 | /**
|
1051 | * Access the Key from an Entity object.
|
1052 | *
|
1053 | * @name Datastore#KEY
|
1054 | * @type {symbol}
|
1055 | */
|
1056 | Datastore.KEY = entity_1.entity.KEY_SYMBOL;
|
1057 | /**
|
1058 | * This is one of three values which may be returned from
|
1059 | * {@link Datastore#runQuery}, {@link Transaction#runQuery}, and
|
1060 | * {@link Query#run} as `info.moreResults`.
|
1061 | *
|
1062 | * There *may* be more results after the specified end cursor.
|
1063 | *
|
1064 | * @type {string}
|
1065 | */
|
1066 | Datastore.MORE_RESULTS_AFTER_CURSOR = 'MORE_RESULTS_AFTER_CURSOR';
|
1067 | /**
|
1068 | * This is one of three values which may be returned from
|
1069 | * {@link Datastore#runQuery}, {@link Transaction#runQuery}, and
|
1070 | * {@link Query#run} as `info.moreResults`.
|
1071 | *
|
1072 | * There *may* be more results after the specified limit.
|
1073 | *
|
1074 | * @type {string}
|
1075 | */
|
1076 | Datastore.MORE_RESULTS_AFTER_LIMIT = 'MORE_RESULTS_AFTER_LIMIT';
|
1077 | /**
|
1078 | * This is one of three values which may be returned from
|
1079 | * {@link Datastore#runQuery}, {@link Transaction#runQuery}, and
|
1080 | * {@link Query#run} as `info.moreResults`.
|
1081 | *
|
1082 | * There are no more results left to query for.
|
1083 | *
|
1084 | * @type {string}
|
1085 | */
|
1086 | Datastore.NO_MORE_RESULTS = 'NO_MORE_RESULTS';
|
1087 | /*! Developer Documentation
|
1088 | *
|
1089 | * All async methods (except for streams) will return a Promise in the event
|
1090 | * that a callback is omitted.
|
1091 | */
|
1092 | (0, promisify_1.promisifyAll)(Datastore, {
|
1093 | exclude: [
|
1094 | 'createAggregationQuery',
|
1095 | 'double',
|
1096 | 'isDouble',
|
1097 | 'geoPoint',
|
1098 | 'getDatabaseId',
|
1099 | 'getProjectId',
|
1100 | 'isGeoPoint',
|
1101 | 'index',
|
1102 | 'int',
|
1103 | 'isInt',
|
1104 | 'createQuery',
|
1105 | 'key',
|
1106 | 'isKey',
|
1107 | 'keyFromLegacyUrlsafe',
|
1108 | 'transaction',
|
1109 | ],
|
1110 | });
|
1111 | /**
|
1112 | * The default export of the `@google-cloud/datastore` package is the
|
1113 | * {@link Datastore} class.
|
1114 | *
|
1115 | * See the {@link Datastore} class for client methods and configuration options.
|
1116 | *
|
1117 | * @module {Datastore} @google-cloud/datastore
|
1118 | * @alias nodejs-datastore
|
1119 | *
|
1120 | * @example Install the client library with <a href="https://www.npmjs.com/">npm</a>:
|
1121 | * ```
|
1122 | * npm install --save
|
1123 | * ```
|
1124 | * @google-cloud/datastore
|
1125 | *
|
1126 | * @example Import the client library
|
1127 | * ```
|
1128 | * const {Datastore} = require('@google-cloud/datastore');
|
1129 | *
|
1130 | * ```
|
1131 | * @example Create a client that uses <a href="https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application">Application Default Credentials (ADC)</a>:
|
1132 | * ```
|
1133 | * const datastore = new Datastore();
|
1134 | *
|
1135 | * ```
|
1136 | * @example Create a client with <a href="https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually">explicit credentials</a>:
|
1137 | * ```
|
1138 | * const datastore = new Datastore({ projectId:
|
1139 | * 'your-project-id', keyFilename: '/path/to/keyfile.json'
|
1140 | * });
|
1141 | *
|
1142 | * ```
|
1143 | * @example <caption>include:samples/quickstart.js</caption>
|
1144 | * region_tag:datastore_quickstart
|
1145 | * Full quickstart example:
|
1146 | */
|
1147 | /**
|
1148 | * @name Datastore.v1
|
1149 | * @see v1.DatastoreClient
|
1150 | * @type {object}
|
1151 | * @property {constructor} DatastoreClient
|
1152 | * Reference to {@link v1.DatastoreClient}.
|
1153 | */
|
1154 | /**
|
1155 | * @name module:@google-cloud/datastore.v1
|
1156 | * @see v1.DatastoreClient
|
1157 | * @type {object}
|
1158 | * @property {constructor} DatastoreClient
|
1159 | * Reference to {@link v1.DatastoreClient}.
|
1160 | */
|
1161 | module.exports.v1 = gapic.v1;
|
1162 | const v1 = gapic.v1;
|
1163 | exports.v1 = v1;
|
1164 | var v1_1 = require("./v1");
|
1165 | Object.defineProperty(exports, "DatastoreClient", { enumerable: true, get: function () { return v1_1.DatastoreClient; } });
|
1166 | Object.defineProperty(exports, "DatastoreAdminClient", { enumerable: true, get: function () { return v1_1.DatastoreAdminClient; } });
|
1167 | //# sourceMappingURL=index.js.map |
\ | No newline at end of file |