UNPKG

38.1 kBJavaScriptView Raw
1"use strict";
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 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.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 */
28const arrify = require("arrify");
29const extend = require("extend");
30const google_gax_1 = require("google-gax");
31const is = require("is");
32const stream_1 = require("stream");
33const entity_1 = require("./entity");
34const aggregate_1 = require("./aggregate");
35Object.defineProperty(exports, "AggregateField", { enumerable: true, get: function () { return aggregate_1.AggregateField; } });
36var Key = entity_1.entity.Key;
37exports.Key = Key;
38const filter_1 = require("./filter");
39Object.defineProperty(exports, "PropertyFilter", { enumerable: true, get: function () { return filter_1.PropertyFilter; } });
40Object.defineProperty(exports, "and", { enumerable: true, get: function () { return filter_1.and; } });
41Object.defineProperty(exports, "or", { enumerable: true, get: function () { return filter_1.or; } });
42const index_class_1 = require("./index-class");
43Object.defineProperty(exports, "Index", { enumerable: true, get: function () { return index_class_1.Index; } });
44const query_1 = require("./query");
45Object.defineProperty(exports, "Query", { enumerable: true, get: function () { return query_1.Query; } });
46const request_1 = require("./request");
47Object.defineProperty(exports, "DatastoreRequest", { enumerable: true, get: function () { return request_1.DatastoreRequest; } });
48const transaction_1 = require("./transaction");
49Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return transaction_1.Transaction; } });
50const promisify_1 = require("@google-cloud/promisify");
51const aggregate_2 = require("./aggregate");
52const { grpc } = new google_gax_1.GrpcClient();
53// Import the clients for each version supported by this package.
54const gapic = Object.freeze({
55 v1: require('./v1'),
56});
57const 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 */
399class 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}
1043exports.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 */
1056Datastore.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 */
1066Datastore.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 */
1076Datastore.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 */
1086Datastore.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 */
1161module.exports.v1 = gapic.v1;
1162const v1 = gapic.v1;
1163exports.v1 = v1;
1164var v1_1 = require("./v1");
1165Object.defineProperty(exports, "DatastoreClient", { enumerable: true, get: function () { return v1_1.DatastoreClient; } });
1166Object.defineProperty(exports, "DatastoreAdminClient", { enumerable: true, get: function () { return v1_1.DatastoreAdminClient; } });
1167//# sourceMappingURL=index.js.map
\No newline at end of file