diff --git a/README.md b/README.md
index ea192d8b3f..97fd745519 100644
--- a/README.md
+++ b/README.md
@@ -9,8 +9,8 @@ on Google Cloud Platform.
[slack_badge]: https://img.shields.io/badge/slack-nodejs%20on%20gcp-E01563.svg
[slack_link]: https://gcp-slack.appspot.com/
-[build_badge]: https://img.shields.io/travis/GoogleCloudPlatform/nodejs-docs-samples.svg?style=flat
-[build_link]: https://travis-ci.org/GoogleCloudPlatform/nodejs-docs-samples
+[build_badge]: https://img.shields.io/circleci/project/github/GoogleCloudPlatform/nodejs-docs-samples/master.svg?style=flat
+[build_link]: https://circleci.com/gh/GoogleCloudPlatform/nodejs-docs-samples
[cov_badge]: https://img.shields.io/codecov/c/github/GoogleCloudPlatform/nodejs-docs-samples/master.svg?style=flat
[cov_link]: https://codecov.io/github/GoogleCloudPlatform/nodejs-docs-samples?branch=master
[cloud]: https://cloud.google.com/
@@ -32,22 +32,22 @@ on Google Cloud Platform.
* [Google Container Engine](#google-container-engine)
* [Google Cloud Functions (Alpha)](#google-cloud-functions-alpha)
* [**Storage and Databases**](#storage-and-databases)
- * [Google Cloud Datastore (Beta)](#google-cloud-datastore-beta)
+ * [Google Cloud Datastore](#google-cloud-datastore)
* [Google Cloud Storage](#google-cloud-storage)
* [**Big Data**](#big-data)
* [Google BigQuery](#google-bigquery)
* [Google Cloud Pub/Sub](#google-cloud-pubsub)
* [**Machine Learning**](#machine-learning)
- * [Google Cloud Natural Language API (Beta)](#google-cloud-natural-language-api-beta)
+ * [Google Cloud Natural Language API](#google-cloud-natural-language-api)
* [Google Cloud Prediction API](#google-cloud-prediction-api)
* [Google Cloud Speech API (Beta)](#google-cloud-speech-api-beta)
* [Google Translate API](#google-translate-api)
* [Google Cloud Vision API](#google-cloud-vision-api)
* [**Management Tools**](#management-tools)
- * [Stackdriver Debugger (Beta)](#stackdriver-debugger-beta)
- * [Stackdriver Logging (Beta)](#stackdriver-logging-beta)
- * [Stackdriver Monitoring (Beta)](#stackdriver-monitoring-beta)
- * [Stackdriver Trace (Beta)](#stackdriver-trace-beta)
+ * [Stackdriver Debugger](#stackdriver-debugger)
+ * [Stackdriver Logging](#stackdriver-logging)
+ * [Stackdriver Monitoring](#stackdriver-monitoring)
+ * [Stackdriver Trace](#stackdriver-trace)
* [**Networking**](#management-tools)
* [Google Cloud DNS](#google-cloud-dns)
* [Other sample applications](#other-sample-applications)
@@ -151,21 +151,6 @@ on Google Cloud Platform.
### How to run the tests
1. Read the [Contributing Guide][contrib].
-1. Set the `TEST_BUCKET_NAME` environment variable to the name of a test Google
-Cloud Storage bucket:
-
- Linux:
-
- export TEST_BUCKET_NAME=your-bucket-name
-
- Windows:
-
- set TEST_BUCKET_NAME=your-bucket-name
-
- Windows (PowerShell):
-
- $env:TEST_BUCKET_NAME="your-bucket-name"
-
1. In a terminal, start Redis:
redis-server
@@ -198,14 +183,14 @@ Cloud Storage bucket:
###
Google Cloud Node.js client library
-The idiomatic client for Google Cloud Platform services.
+The recommended, idiomatic client for Google Cloud Platform services.
* [Documentation](https://googlecloudplatform.github.io/gcloud-node/)
* [Source code](https://github.com/GoogleCloudPlatform/gcloud-node)
###
Google API Node.js client library
-Node.js client library for Google APIs.
+An older Node.js client library for making REST requests to Google APIs.
* [Documentation](http://google.github.io/google-api-nodejs-client/)
* [Source code](https://github.com/google/google-api-nodejs-client)
@@ -261,7 +246,7 @@ View the [Cloud Functions Node.js samples][functions_samples].
### Storage and Databases
-#### Google Cloud Datastore (Beta)
+#### Google Cloud Datastore
[Cloud Datastore][datastore_docs] is a NoSQL document database built for
automatic scaling, high performance, and ease of application development.
@@ -305,7 +290,7 @@ View the [Cloud Pub/Sub Node.js samples][pubsub_samples].
### Machine Learning
-#### Google Cloud Natural Language API (Beta)
+#### Google Cloud Natural Language API
[Cloud Natural Language API][language_docs] provides natural language
understanding technologies to developers, including sentiment analysis, entity
@@ -361,7 +346,7 @@ View the [Cloud Vision API Node.js samples][vision_samples].
### Management Tools
-#### Stackdriver Debugger (Beta)
+#### Stackdriver Debugger
[Stackdriver Debugger][debugger_docs] makes it easier to view the application
state without adding logging statements.
@@ -371,7 +356,7 @@ View the [Stackdriver Debugger Node.js sample][debugger_sample].
[debugger_docs]: https://cloud.google.com/debugger/docs/
[debugger_sample]: debugger
-#### Stackdriver Logging (Beta)
+#### Stackdriver Logging
[Stackdriver Logging][logging_docs] allows you to store, search, analyze,
monitor, and alert on log data and events from Google Cloud Platform and Amazon
@@ -382,7 +367,7 @@ View the [Stackdriver Logging Node.js samples][logging_samples].
[logging_docs]: https://cloud.google.com/logging/docs/
[logging_samples]: logging
-#### Stackdriver Monitoring (Beta)
+#### Stackdriver Monitoring
[Stackdriver Monitoring][monitoring_docs] collects metrics, events, and metadata
from Google Cloud Platform, Amazon Web Services (AWS), hosted uptime probes,
@@ -394,7 +379,7 @@ View the [Stackdriver Monitoring Node.js samples][monitoring_samples].
[monitoring_docs]: https://cloud.google.com/monitoring/docs/
[monitoring_samples]: monitoring
-#### Stackdriver Trace (Beta)
+#### Stackdriver Trace
[Stackdriver Trace][trace_docs] is a distributed tracing system for Google Cloud
Platform that collects latency data from App Engine applications and displays it
diff --git a/datastore/README.md b/datastore/README.md
index 5c34edc732..f7500f62ee 100644
--- a/datastore/README.md
+++ b/datastore/README.md
@@ -33,15 +33,26 @@ View the [documentation][tasks_docs] or the [source code][tasks_code].
__Run the sample:__
-Usage: `node tasks [args]...`
-
-Print usage:
-
- node tasks
-
-Example:
-
- node tasks list
+Usage: `node tasks.js [args]...`
+
+```
+Commands:
+ new Adds a task with a description .
+ done Marks the specified task as done.
+ list Lists all tasks ordered by creation time.
+ delete Deletes a task.
+
+Options:
+ --help Show help [boolean]
+
+Examples:
+ node tasks.js new "Buy milk" Adds a task with description "Buy milk".
+ node tasks.js done 12345 Marks task 12345 as Done.
+ node tasks.js list Lists all tasks ordered by creation time
+ node tasks.js delete 12345 Deletes task 12345.
+
+For more information, see https://cloud.google.com/datastore/docs
+```
[tasks_docs]: https://cloud.google.com/datastore/docs/datastore-api-tutorial
[tasks_code]: tasks.js
diff --git a/datastore/concepts.js b/datastore/concepts.js
index 658f8cb578..ccf1f79a06 100644
--- a/datastore/concepts.js
+++ b/datastore/concepts.js
@@ -1,1352 +1,1244 @@
-// Copyright 2015, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/**
+ * Copyright 2016, Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
'use strict';
-var asyncUtil = require('async');
+const assert = require('power-assert');
// By default, the client will authenticate using the service account file
// specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
// the project specified by the GCLOUD_PROJECT environment variable. See
// https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication
-var Datastore = require('@google-cloud/datastore');
+const Datastore = require('@google-cloud/datastore');
-module.exports = {
- Entity: Entity,
- Index: Index,
- Metadata: Metadata,
- Query: Query,
- Transaction: Transaction
-};
+function makeStub () {
+ return sinon.stub().returns(Promise.resolve([]));
+}
// This mock is used in the documentation snippets.
-var datastore = {
- delete: function () {},
- get: function () {},
- insert: function () {},
- key: function () {},
- update: function () {},
- upsert: function () {},
- runQuery: function () {},
- save: function () {}
+let datastore = {
+ delete: makeStub(),
+ get: makeStub(),
+ insert: makeStub(),
+ key: makeStub(),
+ update: makeStub(),
+ upsert: makeStub(),
+ runQuery: sinon.stub().returns(Promise.resolve([[]])),
+ save: makeStub()
};
-function Entity (projectId) {
- var options = {
- projectId: projectId
- };
-
- this.datastore = Datastore(options);
-
- // To create the keys, we have to use this instance of Datastore.
- datastore.key = this.datastore.key;
-
- this.incompleteKey = this.getIncompleteKey();
- this.namedKey = this.getNamedKey();
- this.keyWithParent = this.getKeyWithParent();
- this.keyWithMultiLevelParent = this.getKeyWithMultiLevelParent();
+class TestHelper {
+ constructor (projectId) {
+ const options = {
+ projectId: projectId
+ };
+ this.datastore = Datastore(options);
+ }
}
-Entity.prototype.getIncompleteKey = function () {
- // [START incomplete_key]
- var taskKey = datastore.key('Task');
- // [END incomplete_key]
-
- return taskKey;
-};
-
-Entity.prototype.getNamedKey = function () {
- // [START named_key]
- var taskKey = datastore.key([
- 'Task',
- 'sampleTask'
- ]);
- // [END named_key]
-
- return taskKey;
-};
+class Entity extends TestHelper {
+ constructor (projectId) {
+ super(projectId);
+ // To create the keys, we have to use this instance of Datastore.
+ datastore.key = this.datastore.key;
-Entity.prototype.getKeyWithParent = function () {
- // [START key_with_parent]
- var taskKey = datastore.key([
- 'TaskList',
- 'default',
- 'Task',
- 'sampleTask'
- ]);
- // [END key_with_parent]
-
- return taskKey;
-};
-
-Entity.prototype.getKeyWithMultiLevelParent = function () {
- // [START key_with_multilevel_parent]
- var taskKey = datastore.key([
- 'User',
- 'alice',
- 'TaskList',
- 'default',
- 'Task',
- 'sampleTask'
- ]);
- // [END key_with_multilevel_parent]
-
- return taskKey;
-};
+ this.incompleteKey = this.getIncompleteKey();
+ this.namedKey = this.getNamedKey();
+ this.keyWithParent = this.getKeyWithParent();
+ this.keyWithMultiLevelParent = this.getKeyWithMultiLevelParent();
+ }
-Entity.prototype.getTask = function () {
- // [START basic_entity]
- var task = {
- category: 'Personal',
- done: false,
- priority: 4,
- description: 'Learn Cloud Datastore'
- };
- // [END basic_entity]
-
- return task;
-};
+ getIncompleteKey () {
+ // [START incomplete_key]
+ const taskKey = datastore.key('Task');
+ // [END incomplete_key]
-Entity.prototype.testIncompleteKey = function (callback) {
- this.datastore.save({
- key: this.incompleteKey,
- data: {}
- }, callback);
-};
+ return taskKey;
+ }
-Entity.prototype.testNamedKey = function (callback) {
- this.datastore.save({
- key: this.namedKey,
- data: {}
- }, callback);
-};
+ getNamedKey () {
+ // [START named_key]
+ const taskKey = datastore.key([
+ 'Task',
+ 'sampleTask'
+ ]);
+ // [END named_key]
-Entity.prototype.testKeyWithParent = function (callback) {
- this.datastore.save({
- key: this.keyWithParent,
- data: {}
- }, callback);
-};
+ return taskKey;
+ }
-Entity.prototype.testKeyWithMultiLevelParent = function (callback) {
- this.datastore.save({
- key: this.keyWithMultiLevelParent,
- data: {}
- }, callback);
-};
+ getKeyWithParent () {
+ // [START key_with_parent]
+ const taskKey = datastore.key([
+ 'TaskList',
+ 'default',
+ 'Task',
+ 'sampleTask'
+ ]);
+ // [END key_with_parent]
+
+ return taskKey;
+ }
-Entity.prototype.testEntityWithParent = function (callback) {
- var taskKey = this.keyWithParent;
+ getKeyWithMultiLevelParent () {
+ // [START key_with_multilevel_parent]
+ const taskKey = datastore.key([
+ 'User',
+ 'alice',
+ 'TaskList',
+ 'default',
+ 'Task',
+ 'sampleTask'
+ ]);
+ // [END key_with_multilevel_parent]
+
+ return taskKey;
+ }
- // [START entity_with_parent]
- var task = {
- key: taskKey,
- data: {
+ getTask () {
+ // [START basic_entity]
+ const task = {
category: 'Personal',
done: false,
priority: 4,
description: 'Learn Cloud Datastore'
- }
- };
- // [END entity_with_parent]
-
- this.datastore.save(task, callback);
-};
-
-Entity.prototype.testProperties = function (callback) {
- // jshint camelcase:false
- // [START properties]
- var task = [
- {
- name: 'category',
- value: 'Personal'
- },
- {
- name: 'created',
- value: new Date()
- },
- {
- name: 'done',
- value: false
- },
- {
- name: 'priority',
- value: 4
- },
- {
- name: 'percent_complete',
- value: 10.0
- },
- {
- name: 'description',
- value: 'Learn Cloud Datastore',
- excludeFromIndexes: true
- }
- ];
- // [END properties]
-
- this.datastore.save({
- key: this.incompleteKey,
- data: task
- }, callback);
-};
-
-Entity.prototype.testArrayValue = function (callback) {
- // [START array_value]
- var task = {
- tags: [
- 'fun',
- 'programming'
- ],
- collaborators: [
- 'alice',
- 'bob'
- ]
- };
- // [END array_value]
-
- this.datastore.save({
- key: this.incompleteKey,
- data: task
- }, callback);
-};
-
-Entity.prototype.testBasicEntity = function (callback) {
- this.datastore.save({
- key: this.getIncompleteKey(),
- data: this.getTask()
- }, callback);
-};
+ };
+ // [END basic_entity]
-Entity.prototype.testUpsert = function (callback) {
- var taskKey = this.getIncompleteKey();
- var task = this.getTask();
-
- // [START upsert]
- datastore.upsert({
- key: taskKey,
- data: task
- }, function (err) {
- if (!err) {
- // Task inserted successfully.
- }
- });
- // [END upsert]
+ return task;
+ }
- this.datastore.upsert({
- key: this.datastore.key(['Task', 1]),
- data: task
- }, callback);
-};
+ testIncompleteKey () {
+ return this.datastore.save({
+ key: this.incompleteKey,
+ data: {}
+ });
+ }
-Entity.prototype.testInsert = function (callback) {
- var taskKey = this.getIncompleteKey();
- var task = this.getTask();
-
- // [START insert]
- datastore.insert({
- key: taskKey,
- data: task
- }, function (err) {
- if (!err) {
- // Task inserted successfully.
- }
- });
- // [END insert]
-
- this.datastore.save({
- method: 'insert',
- key: taskKey,
- data: task
- }, callback);
-};
+ testNamedKey () {
+ return this.datastore.save({
+ key: this.namedKey,
+ data: {}
+ });
+ }
-Entity.prototype.testLookup = function (callback) {
- var self = this;
- var taskKey = this.getIncompleteKey();
-
- // jshint unused:false
- // [START lookup]
- datastore.get(taskKey, function (err, entity) {
- if (!err) {
- // Task found.
-
- // entity.data = {
- // category: 'Personal',
- // done: false,
- // priority: 4,
- // description: 'Learn Cloud Datastore'
- // };
- }
- });
- // [END lookup]
-
- this.datastore.save({
- method: 'insert',
- key: taskKey,
- data: {}
- }, function (err) {
- if (err) {
- callback(err);
- return;
- }
+ testKeyWithParent () {
+ return this.datastore.save({
+ key: this.keyWithParent,
+ data: {}
+ });
+ }
- self.datastore.get(taskKey, callback);
- });
-};
+ testKeyWithMultiLevelParent () {
+ return this.datastore.save({
+ key: this.keyWithMultiLevelParent,
+ data: {}
+ });
+ }
-Entity.prototype.testUpdate = function (callback) {
- var self = this;
- var taskKey = this.getIncompleteKey();
- var task = this.getTask();
-
- // [START update]
- datastore.update({
- key: taskKey,
- data: task
- }, function (err) {
- if (!err) {
- // Task updated successfully.
- }
- });
- // [END update]
-
- this.datastore.save({
- method: 'insert',
- key: taskKey,
- data: {}
- }, function (err) {
- if (err) {
- callback(err);
- return;
- }
+ testEntityWithParent () {
+ const taskKey = this.keyWithParent;
- self.datastore.update({
+ // [START entity_with_parent]
+ const task = {
key: taskKey,
- data: task
- }, callback);
- });
-};
-
-Entity.prototype.testDelete = function (callback) {
- var self = this;
- var taskKey = this.getIncompleteKey();
-
- // [START delete]
- datastore.delete(taskKey, function (err) {
- if (!err) {
- // Task deleted successfully.
- }
- });
- // [END delete]
-
- this.datastore.save({
- method: 'insert',
- key: taskKey,
- data: {}
- }, function (err) {
- if (err) {
- callback(err);
- return;
- }
-
- self.datastore.delete(taskKey, callback);
- });
-};
-
-Entity.prototype.testBatchUpsert = function (callback) {
- var taskKey1 = this.datastore.key(['Task', 1]);
- var taskKey2 = this.datastore.key(['Task', 2]);
-
- var task1 = {
- category: 'Personal',
- done: false,
- priority: 4,
- description: 'Learn Cloud Datastore'
- };
-
- var task2 = {
- category: 'Work',
- done: false,
- priority: 8,
- description: 'Integrate Cloud Datastore'
- };
-
- // [START batch_upsert]
- datastore.upsert([
- {
- key: taskKey1,
- data: task1
- },
- {
- key: taskKey2,
- data: task2
- }
- ], function (err) {
- if (!err) {
- // Tasks inserted successfully.
- }
- });
- // [END batch_upsert]
-
- this.datastore.upsert([
- {
- key: taskKey1,
- data: task1
- },
- {
- key: taskKey2,
- data: task2
- }
- ], callback);
-};
-
-Entity.prototype.testBatchLookup = function (callback) {
- var taskKey1 = this.datastore.key(['Task', 1]);
- var taskKey2 = this.datastore.key(['Task', 2]);
-
- // jshint unused:false
- // [START batch_lookup]
- datastore.get([
- taskKey1,
- taskKey2
- ], function (err, tasks) {
- if (!err) {
- // Tasks retrieved successfully.
- }
- });
- // [END batch_lookup]
-
- this.datastore.get([
- taskKey1,
- taskKey2
- ], callback);
-};
-
-Entity.prototype.testBatchDelete = function (callback) {
- var taskKey1 = this.datastore.key(['Task', 1]);
- var taskKey2 = this.datastore.key(['Task', 2]);
-
- // [START batch_delete]
- datastore.delete([
- taskKey1,
- taskKey2
- ], function (err) {
- if (!err) {
- // Tasks deleted successfully.
- }
- });
- // [END batch_delete]
-
- this.datastore.delete([
- taskKey1,
- taskKey2
- ], callback);
-};
-
-function Index (projectId) {
- var options = {
- projectId: projectId
- };
-
- this.datastore = Datastore(options);
-}
-
-Index.prototype.testUnindexedPropertyQuery = function (callback) {
- var datastore = this.datastore;
+ data: {
+ category: 'Personal',
+ done: false,
+ priority: 4,
+ description: 'Learn Cloud Datastore'
+ }
+ };
+ // [END entity_with_parent]
- // [START unindexed_property_query]
- var query = datastore.createQuery('Task')
- .filter('description', '=', 'A task description.');
- // [END unindexed_property_query]
+ return this.datastore.save(task);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testProperties () {
+ // [START properties]
+ const task = [
+ {
+ name: 'category',
+ value: 'Personal'
+ },
+ {
+ name: 'created',
+ value: new Date()
+ },
+ {
+ name: 'done',
+ value: false
+ },
+ {
+ name: 'priority',
+ value: 4
+ },
+ {
+ name: 'percent_complete',
+ value: 10.0
+ },
+ {
+ name: 'description',
+ value: 'Learn Cloud Datastore',
+ excludeFromIndexes: true
+ }
+ ];
+ // [END properties]
-Index.prototype.testExplodingProperties = function (callback) {
- var original = datastore.key;
- datastore.key = this.datastore.key;
+ return this.datastore.save({
+ key: this.incompleteKey,
+ data: task
+ });
+ }
- // [START exploding_properties]
- var task = {
- method: 'insert',
- key: datastore.key('Task'),
- data: {
+ testArrayValue () {
+ // [START array_value]
+ const task = {
tags: [
'fun',
- 'programming',
- 'learn'
+ 'programming'
],
collaborators: [
'alice',
- 'bob',
- 'charlie'
- ],
- created: new Date()
- }
- };
- // [END exploding_properties]
-
- datastore.key = original;
-
- this.datastore.save(task, callback);
-};
+ 'bob'
+ ]
+ };
+ // [END array_value]
-function Metadata (projectId) {
- var options = {
- projectId: projectId
- };
+ return this.datastore.save({
+ key: this.incompleteKey,
+ data: task
+ });
+ }
- this.datastore = Datastore(options);
-}
+ testBasicEntity () {
+ return this.datastore.save({
+ key: this.getIncompleteKey(),
+ data: this.getTask()
+ });
+ }
-Metadata.prototype.testNamespaceRunQuery = function (callback) {
- var self = this;
+ testUpsert () {
+ const taskKey = this.getIncompleteKey();
+ const task = this.getTask();
- datastore.createQuery = this.datastore.createQuery;
- datastore.key = this.datastore.key;
+ // [START upsert]
+ const entity = {
+ key: taskKey,
+ data: task
+ };
- var startNamespace = 'Animals';
- var endNamespace = 'Zoos';
+ datastore.upsert(entity)
+ .then(() => {
+ // Task inserted successfully.
+ });
+ // [END upsert]
- this.datastore.save([
- {
- key: datastore.key({
- namespace: 'Animals',
- path: ['Ant', 1]
- }),
- data: {}
- }
- ], function (err) {
- if (err) {
- callback(err);
- return;
- }
+ return this.datastore.upsert({
+ key: this.datastore.key(['Task', 1]),
+ data: task
+ });
+ }
- // jshint unused:false
- // [START namespace_run_query]
- var query = datastore.createQuery('__namespace__')
- .select('__key__')
- .filter('__key__', '>=', datastore.key(['__namespace__', startNamespace]))
- .filter('__key__', '<', datastore.key(['__namespace__', endNamespace]));
+ testInsert () {
+ const taskKey = this.getIncompleteKey();
+ const task = this.getTask();
- datastore.runQuery(query, function (err, entities) {
- if (err) {
- // An error occurred while running the query.
- return;
- }
+ // [START insert]
+ const entity = {
+ key: taskKey,
+ data: task
+ };
- var namespaces = entities.map(function (entity) {
- return entity.key.path.pop();
+ datastore.insert(entity)
+ .then(() => {
+ // Task inserted successfully.
});
- console.log('namespaces', namespaces);
- });
- // [END namespace_run_query]
+ // [END insert]
- self.datastore.runQuery(query, callback);
- });
-};
+ return this.datastore.save({
+ method: 'insert',
+ key: taskKey,
+ data: task
+ });
+ }
-Metadata.prototype.testKindRunQuery = function (callback) {
- datastore.createQuery = this.datastore.createQuery;
+ testLookup () {
+ const taskKey = this.getIncompleteKey();
+
+ // [START lookup]
+ datastore.get(taskKey)
+ .then((results) => {
+ // Task found.
+ const entity = results[0];
+
+ // entity = {
+ // category: 'Personal',
+ // done: false,
+ // priority: 4,
+ // description: 'Learn Cloud Datastore'
+ // };
+ console.log(entity);
+ });
+ // [END lookup]
- // jshint unused:false
- // [START kind_run_query]
- var query = datastore.createQuery('__kind__')
- .select('__key__');
+ return this.datastore.save({
+ method: 'insert',
+ key: taskKey,
+ data: {}
+ }).then(() => this.datastore.get(taskKey));
+ }
- datastore.runQuery(query, function (err, entities) {
- if (err) {
- // An error occurred while running the query.
- return;
- }
+ testUpdate () {
+ const taskKey = this.getIncompleteKey();
+ const task = this.getTask();
- var kinds = entities.map(function (entity) {
- return entity.key.path.pop();
- });
- console.log('kinds', kinds);
- });
- // [END kind_run_query]
+ // [START update]
+ const entity = {
+ key: taskKey,
+ data: task
+ };
- this.datastore.runQuery(query, callback);
-};
+ datastore.update(entity)
+ .then(() => {
+ // Task updated successfully.
+ });
+ // [END update]
-Metadata.prototype.testPropertyRunQuery = function (callback) {
- datastore.createQuery = this.datastore.createQuery;
+ return this.datastore.save({
+ method: 'insert',
+ key: taskKey,
+ data: {}
+ }).then(() => this.datastore.update({ key: taskKey, data: task }));
+ }
- // [START property_run_query]
- var query = datastore.createQuery('__property__')
- .select('__key__');
+ testDelete () {
+ const taskKey = this.getIncompleteKey();
- datastore.runQuery(query, function (err, entities) {
- if (err) {
- // An error occurred while running the query.
- return;
- }
+ // [START delete]
+ datastore.delete(taskKey)
+ .then(() => {
+ // Task deleted successfully.
+ });
+ // [END delete]
- var propertiesByKind = {};
+ return this.datastore.save({
+ method: 'insert',
+ key: taskKey,
+ data: {}
+ }).then(() => this.datastore.delete(taskKey));
+ }
- entities.forEach(function (entity) {
- var kind = entity.key.path[1];
- var propertyName = entity.key.path[3];
+ testBatchUpsert () {
+ const taskKey1 = this.datastore.key(['Task', 1]);
+ const taskKey2 = this.datastore.key(['Task', 2]);
- propertiesByKind[kind] = propertiesByKind[kind] || [];
- propertiesByKind[kind].push(propertyName);
- });
- });
- // [END property_run_query]
+ const task1 = {
+ category: 'Personal',
+ done: false,
+ priority: 4,
+ description: 'Learn Cloud Datastore'
+ };
- this.datastore.runQuery(query, callback);
-};
+ const task2 = {
+ category: 'Work',
+ done: false,
+ priority: 8,
+ description: 'Integrate Cloud Datastore'
+ };
-Metadata.prototype.testPropertyByKindRunQuery = function (callback) {
- var datastore = this.datastore;
+ // [START batch_upsert]
+ const entities = [
+ {
+ key: taskKey1,
+ data: task1
+ },
+ {
+ key: taskKey2,
+ data: task2
+ }
+ ];
- // jshint camelcase:false
- // [START property_by_kind_run_query]
- var ancestorKey = datastore.key(['__kind__', 'Task']);
+ datastore.upsert(entities)
+ .then(() => {
+ // Tasks inserted successfully.
+ });
+ // [END batch_upsert]
+
+ return this.datastore.upsert([
+ {
+ key: taskKey1,
+ data: task1
+ },
+ {
+ key: taskKey2,
+ data: task2
+ }
+ ]);
+ }
- var query = datastore.createQuery('__property__')
- .hasAncestor(ancestorKey);
+ testBatchLookup () {
+ const taskKey1 = this.datastore.key(['Task', 1]);
+ const taskKey2 = this.datastore.key(['Task', 2]);
- datastore.runQuery(query, function (err, entities) {
- if (err) {
- // An error occurred while running the query.
- return;
- }
+ // [START batch_lookup]
+ const keys = [taskKey1, taskKey2];
- var representationsByProperty = {};
+ datastore.get(keys)
+ .then((results) => {
+ // Tasks retrieved successfully.
+ const tasks = results[0];
- entities.forEach(function (entity) {
- var propertyName = entity.key.path.pop();
- var propertyType = entity.data.property_representation;
+ console.log(tasks);
+ });
+ // [END batch_lookup]
- representationsByProperty[propertyName] = propertyType;
- });
- });
- // [END property_by_kind_run_query]
+ return this.datastore.get([taskKey1, taskKey2]);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testBatchDelete () {
+ const taskKey1 = this.datastore.key(['Task', 1]);
+ const taskKey2 = this.datastore.key(['Task', 2]);
-function Query (projectId) {
- var options = {
- projectId: projectId
- };
+ // [START batch_delete]
+ const keys = [taskKey1, taskKey2];
- this.datastore = Datastore(options);
+ datastore.delete(keys)
+ .then(() => {
+ // Tasks deleted successfully.
+ });
+ // [END batch_delete]
- this.basicQuery = this.getBasicQuery();
- this.projectionQuery = this.getProjectionQuery();
- this.ancestorQuery = this.getAncestorQuery();
+ return this.datastore.delete([taskKey1, taskKey2]);
+ }
}
-Query.prototype.getBasicQuery = function () {
- var datastore = this.datastore;
+class Index extends TestHelper {
+ testUnindexedPropertyQuery () {
+ const datastore = this.datastore;
- // [START basic_query]
- var query = datastore.createQuery('Task')
- .filter('done', '=', false)
- .filter('priority', '>=', 4)
- .order('priority', {
- descending: true
- });
- // [END basic_query]
+ // [START unindexed_property_query]
+ const query = datastore.createQuery('Task')
+ .filter('description', '=', 'A task description.');
+ // [END unindexed_property_query]
- return query;
-};
+ return this.datastore.runQuery(query);
+ }
+
+ testExplodingProperties () {
+ const original = datastore.key;
+ datastore.key = this.datastore.key;
-Query.prototype.getProjectionQuery = function () {
- var datastore = this.datastore;
+ // [START exploding_properties]
+ const task = {
+ method: 'insert',
+ key: datastore.key('Task'),
+ data: {
+ tags: [
+ 'fun',
+ 'programming',
+ 'learn'
+ ],
+ collaborators: [
+ 'alice',
+ 'bob',
+ 'charlie'
+ ],
+ created: new Date()
+ }
+ };
+ // [END exploding_properties]
- // [START projection_query]
- var query = datastore.createQuery('Task')
- .select(['priority', 'percent_complete']);
- // [END projection_query]
+ datastore.key = original;
- return query;
-};
+ return this.datastore.save(task)
+ .then(() => {
+ assert(task.key);
+ assert(task.key.id);
+ });
+ }
+}
-Query.prototype.getAncestorQuery = function () {
- var datastore = this.datastore;
+class Metadata extends TestHelper {
+ testNamespaceRunQuery () {
+ const datastore = this.datastore;
- // [START ancestor_query]
- var ancestorKey = datastore.key(['TaskList', 'default']);
+ const startNamespace = 'Animals';
+ const endNamespace = 'Zoos';
- var query = datastore.createQuery('Task')
- .hasAncestor(ancestorKey);
- // [END ancestor_query]
+ return datastore.save({
+ key: datastore.key({
+ namespace: 'Animals',
+ path: ['Ant', 1]
+ }),
+ data: {}
+ })
+ .then(() => {
+ // [START namespace_run_query]
+ function runNamespaceQuery (startNamespace, endNamespace) {
+ const startKey = datastore.key(['__namespace__', startNamespace]);
+ const endKey = datastore.key(['__namespace__', endNamespace]);
+
+ const query = datastore.createQuery('__namespace__')
+ .select('__key__')
+ .filter('__key__', '>=', startKey)
+ .filter('__key__', '<', endKey);
+
+ return datastore.runQuery(query)
+ .then((results) => {
+ const entities = results[0];
+ const namespaces = entities.map((entity) => entity[datastore.KEY].name);
+
+ console.log('Namespaces:');
+ namespaces.forEach((namespace) => console.log(namespace));
+
+ return namespaces;
+ });
+ }
+ // [END namespace_run_query]
- return query;
-};
+ return runNamespaceQuery(startNamespace, endNamespace);
+ })
+ .then((namespaces) => {
+ assert.deepEqual(namespaces, ['Animals']);
+ });
+ }
-Query.prototype.testRunQuery = function (callback) {
- var query = this.basicQuery;
+ testKindRunQuery () {
+ const datastore = this.datastore;
- // jshint unused:false
- // [START run_query]
- datastore.runQuery(query, function (err, tasks) {
- if (!err) {
- // Task entities found.
- }
- });
- // [END run_query]
+ // [START kind_run_query]
+ function runKindQuery () {
+ const query = datastore.createQuery('__kind__')
+ .select('__key__');
- this.datastore.runQuery(query, callback);
-};
+ return datastore.runQuery(query)
+ .then((results) => {
+ const entities = results[0];
+ const kinds = entities.map((entity) => entity[datastore.KEY].name);
-Query.prototype.testPropertyFilter = function (callback) {
- var datastore = this.datastore;
+ console.log('Kinds:');
+ kinds.forEach((kind) => console.log(kind));
- // [START property_filter]
- var query = datastore.createQuery('Task')
- .filter('done', '=', false);
- // [END property_filter]
+ return kinds;
+ });
+ }
+ // [END kind_run_query]
- this.datastore.runQuery(query, callback);
-};
+ return runKindQuery()
+ .then((kinds) => {
+ assert.equal(kinds.includes('Account'), true);
+ });
+ }
-Query.prototype.testCompositeFilter = function (callback) {
- var datastore = this.datastore;
+ testPropertyRunQuery () {
+ const datastore = this.datastore;
- // [START composite_filter]
- var query = datastore.createQuery('Task')
- .filter('done', '=', false)
- .filter('priority', '=', 4);
- // [END composite_filter]
+ // [START property_run_query]
+ function runPropertyQuery () {
+ const query = datastore.createQuery('__property__')
+ .select('__key__');
- this.datastore.runQuery(query, callback);
-};
+ return datastore.runQuery(query)
+ .then((results) => {
+ const entities = results[0];
+ const propertiesByKind = {};
-Query.prototype.testKeyFilter = function (callback) {
- var datastore = this.datastore;
+ entities.forEach((entity) => {
+ const key = entity[datastore.KEY];
+ const kind = key.path[1];
+ const property = key.path[3];
- // [START key_filter]
- var query = datastore.createQuery('Task')
- .filter('__key__', '>', datastore.key(['Task', 'someTask']));
- // [END key_filter]
+ propertiesByKind[kind] = propertiesByKind[kind] || [];
+ propertiesByKind[kind].push(property);
+ });
- this.datastore.runQuery(query, callback);
-};
+ console.log('Properties by Kind:');
+ for (let key in propertiesByKind) {
+ console.log(key, propertiesByKind[key]);
+ }
-Query.prototype.testAscendingSort = function (callback) {
- var datastore = this.datastore;
+ return propertiesByKind;
+ });
+ }
+ // [END property_run_query]
- // [START ascending_sort]
- var query = datastore.createQuery('Task')
- .order('created');
- // [END ascending_sort]
+ return runPropertyQuery()
+ .then((propertiesByKind) => {
+ assert.deepEqual(propertiesByKind.Account, ['balance']);
+ });
+ }
- this.datastore.runQuery(query, callback);
-};
+ testPropertyByKindRunQuery () {
+ const datastore = this.datastore;
-Query.prototype.testDescendingSort = function (callback) {
- var datastore = this.datastore;
+ // [START property_by_kind_run_query]
+ function runPropertyByKindQuery () {
+ const ancestorKey = datastore.key(['__kind__', 'Account']);
- // [START descending_sort]
- var query = datastore.createQuery('Task')
- .order('created', {
- descending: true
- });
- // [END descending_sort]
+ const query = datastore.createQuery('__property__')
+ .hasAncestor(ancestorKey);
- this.datastore.runQuery(query, callback);
-};
+ return datastore.runQuery(query)
+ .then((results) => {
+ const entities = results[0];
-Query.prototype.testMultiSort = function (callback) {
- var datastore = this.datastore;
+ const representationsByProperty = {};
- // [START multi_sort]
- var query = datastore.createQuery('Task')
- .order('priority', {
- descending: true
- })
- .order('created');
- // [END multi_sort]
+ entities.forEach((entity) => {
+ const key = entity[datastore.KEY];
+ const propertyName = key.name;
+ const propertyType = entity.property_representation;
- this.datastore.runQuery(query, callback);
-};
+ representationsByProperty[propertyName] = propertyType;
+ });
-Query.prototype.testKindlessQuery = function (callback) {
- var datastore = this.datastore;
- var lastSeenKey = this.datastore.key(['Task', Date.now()]);
+ console.log('Task property representations:');
+ for (let key in representationsByProperty) {
+ console.log(key, representationsByProperty[key]);
+ }
- // [START kindless_query]
- var query = datastore.createQuery()
- .filter('__key__', '>', lastSeenKey)
- .limit(1);
- // [END kindless_query]
+ return representationsByProperty;
+ });
+ }
+ // [END property_by_kind_run_query]
- this.datastore.runQuery(query, callback);
-};
+ return runPropertyByKindQuery()
+ .then((propertiesByKind) => {
+ assert.deepEqual(propertiesByKind, {
+ balance: ['INT64']
+ });
+ });
+ }
+}
-Query.prototype.testRunQueryProjection = function (callback) {
- var self = this;
- var query = this.projectionQuery;
+class Query extends TestHelper {
+ constructor (projectId) {
+ super(projectId);
- // Overwrite the mock to actually run the query.
- datastore.runQuery = function (query, queryCallback) {
- // Restore the mock.
- datastore.runQuery = function () {};
+ this.basicQuery = this.getBasicQuery();
+ this.projectionQuery = this.getProjectionQuery();
+ this.ancestorQuery = this.getAncestorQuery();
+ }
- self.datastore.runQuery(query, function (err) {
- if (err) {
- return callback(err);
- }
+ getBasicQuery () {
+ const datastore = this.datastore;
- queryCallback.apply(null, arguments);
+ // [START basic_query]
+ const query = datastore.createQuery('Task')
+ .filter('done', '=', false)
+ .filter('priority', '>=', 4)
+ .order('priority', {
+ descending: true
+ });
+ // [END basic_query]
- if (priorities.length === 0 || percentCompletes.length === 0) {
- callback(new Error('Projection lists did not build up.'));
- } else {
- callback();
- }
- });
- };
+ return query;
+ }
- // jshint unused:false, camelcase:false
- // [START run_query_projection]
- var priorities = [];
- var percentCompletes = [];
+ getProjectionQuery () {
+ const datastore = this.datastore;
- datastore.runQuery(query, function (err, tasks) {
- if (err) {
- // An error occurred while running the query.
- return;
- }
+ // [START projection_query]
+ const query = datastore.createQuery('Task')
+ .select(['priority', 'percent_complete']);
+ // [END projection_query]
- tasks.forEach(function (task) {
- priorities.push(task.data.priority);
- percentCompletes.push(task.data.percent_complete);
- });
- });
- // [END run_query_projection]
-};
+ return query;
+ }
-Query.prototype.testKeysOnlyQuery = function (callback) {
- var datastore = this.datastore;
+ getAncestorQuery () {
+ const datastore = this.datastore;
- // [START keys_only_query]
- var query = datastore.createQuery()
- .select('__key__')
- .limit(1);
- // [END keys_only_query]
+ // [START ancestor_query]
+ const ancestorKey = datastore.key(['TaskList', 'default']);
- this.datastore.runQuery(query, callback);
-};
+ const query = datastore.createQuery('Task')
+ .hasAncestor(ancestorKey);
+ // [END ancestor_query]
-Query.prototype.testDistinctQuery = function (callback) {
- var datastore = this.datastore;
+ return query;
+ }
- // [START distinct_query]
- var query = datastore.createQuery('Task')
- .groupBy(['category', 'priority'])
- .order('category')
- .order('priority');
- // [END distinct_query]
+ testRunQuery () {
+ const query = this.basicQuery;
- this.datastore.runQuery(query, callback);
-};
+ // [START run_query]
+ datastore.runQuery(query)
+ .then((results) => {
+ // Task entities found.
+ const tasks = results[0];
-Query.prototype.testDistinctOnQuery = function (callback) {
- var datastore = this.datastore;
+ console.log('Tasks:');
+ tasks.forEach((task) => console.log(task));
+ });
+ // [END run_query]
- // [START distinct_on_query]
- var query = datastore.createQuery('Task')
- .groupBy('category')
- .order('category')
- .order('priority');
- // [END distinct_on_query]
+ return this.datastore.runQuery(query);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testPropertyFilter () {
+ const datastore = this.datastore;
-Query.prototype.testArrayValueInequalityRange = function (callback) {
- var datastore = this.datastore;
+ // [START property_filter]
+ const query = datastore.createQuery('Task')
+ .filter('done', '=', false);
+ // [END property_filter]
- // [START array_value_inequality_range]
- var query = datastore.createQuery('Task')
- .filter('tag', '>', 'learn')
- .filter('tag', '<', 'math');
- // [END array_value_inequality_range]
+ return this.datastore.runQuery(query);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testCompositeFilter () {
+ const datastore = this.datastore;
-Query.prototype.testArrayValueEquality = function (callback) {
- var datastore = this.datastore;
+ // [START composite_filter]
+ const query = datastore.createQuery('Task')
+ .filter('done', '=', false)
+ .filter('priority', '=', 4);
+ // [END composite_filter]
- // [START array_value_equality]
- var query = datastore.createQuery('Task')
- .filter('tag', '=', 'fun')
- .filter('tag', '=', 'programming');
- // [END array_value_equality]
+ return this.datastore.runQuery(query);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testKeyFilter () {
+ const datastore = this.datastore;
-Query.prototype.testInequalityRange = function (callback) {
- var datastore = this.datastore;
+ // [START key_filter]
+ const query = datastore.createQuery('Task')
+ .filter('__key__', '>', datastore.key(['Task', 'someTask']));
+ // [END key_filter]
- // [START inequality_range]
- var query = datastore.createQuery('Task')
- .filter('created', '>', new Date('1990-01-01T00:00:00z'))
- .filter('created', '<', new Date('2000-12-31T23:59:59z'));
- // [END inequality_range]
+ return this.datastore.runQuery(query);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testAscendingSort () {
+ const datastore = this.datastore;
-Query.prototype.testInequalityInvalid = function (callback) {
- var datastore = this.datastore;
+ // [START ascending_sort]
+ const query = datastore.createQuery('Task')
+ .order('created');
+ // [END ascending_sort]
- // [START inequality_invalid]
- var query = datastore.createQuery('Task')
- .filter('priority', '>', 3)
- .filter('created', '>', new Date('1990-01-01T00:00:00z'));
- // [END inequality_invalid]
+ return this.datastore.runQuery(query);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testDescendingSort () {
+ const datastore = this.datastore;
-Query.prototype.testEqualAndInequalityRange = function (callback) {
- var datastore = this.datastore;
+ // [START descending_sort]
+ const query = datastore.createQuery('Task')
+ .order('created', {
+ descending: true
+ });
+ // [END descending_sort]
- // [START equal_and_inequality_range]
- var query = datastore.createQuery('Task')
- .filter('priority', '=', 4)
- .filter('done', '=', false)
- .filter('created', '>', new Date('1990-01-01T00:00:00z'))
- .filter('created', '<', new Date('2000-12-31T23:59:59z'));
- // [END equal_and_inequality_range]
+ return this.datastore.runQuery(query);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testMultiSort () {
+ const datastore = this.datastore;
-Query.prototype.testInequalitySort = function (callback) {
- var datastore = this.datastore;
+ // [START multi_sort]
+ const query = datastore.createQuery('Task')
+ .order('priority', {
+ descending: true
+ })
+ .order('created');
+ // [END multi_sort]
- // [START inequality_sort]
- var query = datastore.createQuery('Task')
- .filter('priority', '>', 3)
- .order('priority')
- .order('created');
- // [END inequality_sort]
+ return this.datastore.runQuery(query);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testKindlessQuery () {
+ const datastore = this.datastore;
+ const lastSeenKey = this.datastore.key(['Task', Date.now()]);
-Query.prototype.testInequalitySortInvalidNotSame = function (callback) {
- var datastore = this.datastore;
+ // [START kindless_query]
+ const query = datastore.createQuery()
+ .filter('__key__', '>', lastSeenKey)
+ .limit(1);
+ // [END kindless_query]
- // [START inequality_sort_invalid_not_same]
- var query = datastore.createQuery('Task')
- .filter('priority', '>', 3)
- .order('created');
- // [END inequality_sort_invalid_not_same]
+ return this.datastore.runQuery(query);
+ }
- this.datastore.runQuery(query, callback);
-};
+ testRunQueryProjection () {
+ const datastore = this.datastore;
+ const query = this.projectionQuery;
-Query.prototype.testInequalitySortInvalidNotFirst = function (callback) {
- var datastore = this.datastore;
+ // [START run_query_projection]
+ function runProjectionQuery () {
+ const priorities = [];
+ const percentCompletes = [];
- // [START inequality_sort_invalid_not_first]
- var query = datastore.createQuery('Task')
- .filter('priority', '>', 3)
- .order('created')
- .order('priority');
- // [END inequality_sort_invalid_not_first]
+ return datastore.runQuery(query)
+ .then((results) => {
+ const tasks = results[0];
- this.datastore.runQuery(query, callback);
-};
+ tasks.forEach((task) => {
+ priorities.push(task.priority);
+ percentCompletes.push(task.percent_complete);
+ });
-Query.prototype.testLimit = function (callback) {
- var datastore = this.datastore;
+ return {
+ priorities: priorities,
+ percentCompletes: percentCompletes
+ };
+ });
+ }
+ // [END run_query_projection]
- // [START limit]
- var query = datastore.createQuery('Task')
- .limit(5);
- // [END limit]
+ return runProjectionQuery();
+ }
- this.datastore.runQuery(query, callback);
-};
+ testKeysOnlyQuery () {
+ const datastore = this.datastore;
-Query.prototype.testCursorPaging = function (callback) {
- var pageSize = 1;
- var pageCursor = '';
+ // [START keys_only_query]
+ const query = datastore.createQuery()
+ .select('__key__')
+ .limit(1);
+ // [END keys_only_query]
- datastore.createQuery = this.datastore.createQuery;
+ return this.datastore.runQuery(query);
+ }
- // [START cursor_paging]
- // By default, gcloud-node will automatically paginate through all of the
- // results that match a query. However, this sample implements manual
- // pagination using limits and cursor tokens.
- var query = datastore.createQuery('Task')
- .limit(pageSize)
- .start(pageCursor);
+ testDistinctQuery () {
+ const datastore = this.datastore;
- this.datastore.runQuery(query, function (err, results, info) {
- if (err) {
- // An error occurred while running the query.
- return;
- }
+ // [START distinct_query]
+ const query = datastore.createQuery('Task')
+ .groupBy(['category', 'priority'])
+ .order('category')
+ .order('priority');
+ // [END distinct_query]
- var nextPageCursor;
+ return this.datastore.runQuery(query);
+ }
- if (info.moreResults !== Datastore.NO_MORE_RESULTS) {
- // If there are more results to retrieve, the end cursor is
- // automatically set on `info`. To get this value directly, access
- // the `endCursor` property.
- nextPageCursor = info.endCursor;
- } else {
- // No more results exist.
- }
- console.log('nextPageCursor', nextPageCursor);
- });
- // [END cursor_paging]
-
- delete datastore.createQuery;
- this.datastore.runQuery(query, function (err, results, info) {
- if (err) {
- callback(err);
- return;
- }
+ testDistinctOnQuery () {
+ const datastore = this.datastore;
- if (!info || !info.endCursor) {
- callback(new Error('An `info` with an `endCursor` is not present.'));
- } else {
- callback();
- }
- });
-};
+ // [START distinct_on_query]
+ const query = datastore.createQuery('Task')
+ .groupBy('category')
+ .order('category')
+ .order('priority');
+ // [END distinct_on_query]
-Query.prototype.testEventualConsistentQuery = function () {
- // [START eventual_consistent_query]
- // Read consistency cannot be specified in gcloud-node.
- // [END eventual_consistent_query]
-};
+ return this.datastore.runQuery(query);
+ }
-// [START transactional_update]
-function transferFunds (fromKey, toKey, amount, callback) {
- var transaction = datastore.transaction();
+ testArrayValueInequalityRange () {
+ const datastore = this.datastore;
- transaction.run(function (err) {
- if (err) {
- return callback(err);
- }
+ // [START array_value_inequality_range]
+ const query = datastore.createQuery('Task')
+ .filter('tag', '>', 'learn')
+ .filter('tag', '<', 'math');
+ // [END array_value_inequality_range]
- transaction.get([
- fromKey,
- toKey
- ], function (err, accounts) {
- if (err) {
- return transaction.rollback(function (_err) {
- return callback(_err || err);
- });
- }
+ return this.datastore.runQuery(query);
+ }
- accounts[0].data.balance -= amount;
- accounts[1].data.balance += amount;
+ testArrayValueEquality () {
+ const datastore = this.datastore;
- transaction.save(accounts);
+ // [START array_value_equality]
+ const query = datastore.createQuery('Task')
+ .filter('tag', '=', 'fun')
+ .filter('tag', '=', 'programming');
+ // [END array_value_equality]
- transaction.commit(function (err) {
- if (err) {
- return callback(err);
- }
+ return this.datastore.runQuery(query);
+ }
- // The transaction completed successfully.
- callback();
- });
- });
- });
-}
-// [END transactional_update]
+ testInequalityRange () {
+ const datastore = this.datastore;
-function Transaction (projectId) {
- var options = {
- projectId: projectId
- };
+ // [START inequality_range]
+ const query = datastore.createQuery('Task')
+ .filter('created', '>', new Date('1990-01-01T00:00:00z'))
+ .filter('created', '<', new Date('2000-12-31T23:59:59z'));
+ // [END inequality_range]
- this.datastore = Datastore(options);
+ return this.datastore.runQuery(query);
+ }
- this.fromKey = this.datastore.key(['Bank', 1, 'Account', 1]);
- this.toKey = this.datastore.key(['Bank', 1, 'Account', 2]);
+ testInequalityInvalid () {
+ const datastore = this.datastore;
- this.originalBalance = 100;
- this.amountToTransfer = 10;
-}
+ // [START inequality_invalid]
+ const query = datastore.createQuery('Task')
+ .filter('priority', '>', 3)
+ .filter('created', '>', new Date('1990-01-01T00:00:00z'));
+ // [END inequality_invalid]
-Transaction.prototype.restoreBankAccountBalances = function (config, callback) {
- var saveArray = config.keys.map(function (key) {
- return {
- key: key,
- data: {
- balance: config.balance
- }
- };
- });
+ return this.datastore.runQuery(query);
+ }
- this.datastore.save(saveArray, callback);
-};
+ testEqualAndInequalityRange () {
+ const datastore = this.datastore;
-Transaction.prototype.testTransactionalUpdate = function (callback) {
- var self = this;
-
- var fromKey = this.fromKey;
- var toKey = this.toKey;
- var originalBalance = this.originalBalance;
- var amountToTransfer = this.amountToTransfer;
-
- this.restoreBankAccountBalances({
- keys: [fromKey, toKey],
- balance: originalBalance
- }, function (err) {
- if (err) {
- callback(err);
- return;
- }
+ // [START equal_and_inequality_range]
+ const query = datastore.createQuery('Task')
+ .filter('priority', '=', 4)
+ .filter('done', '=', false)
+ .filter('created', '>', new Date('1990-01-01T00:00:00z'))
+ .filter('created', '<', new Date('2000-12-31T23:59:59z'));
+ // [END equal_and_inequality_range]
- // Overwrite so the real Datastore instance is used in `transferFunds`.
- var datastoreMock = datastore;
- datastore = self.datastore;
+ return this.datastore.runQuery(query);
+ }
- transferFunds(fromKey, toKey, amountToTransfer, function (err) {
- // Restore `datastore` to the mock API.
- datastore = datastoreMock;
+ testInequalitySort () {
+ const datastore = this.datastore;
- if (err) {
- callback(err);
- return;
- }
+ // [START inequality_sort]
+ const query = datastore.createQuery('Task')
+ .filter('priority', '>', 3)
+ .order('priority')
+ .order('created');
+ // [END inequality_sort]
- self.datastore.get([
- fromKey,
- toKey
- ], function (err, accounts) {
- if (err) {
- callback(err);
- return;
- }
+ return this.datastore.runQuery(query);
+ }
- var transactionWasSuccessful =
- accounts[0].data.balance === originalBalance - amountToTransfer &&
- accounts[1].data.balance === originalBalance + amountToTransfer;
+ testInequalitySortInvalidNotSame () {
+ const datastore = this.datastore;
- if (!transactionWasSuccessful) {
- callback(new Error('Accounts were not updated successfully.'));
- } else {
- callback();
- }
- });
- });
- });
-};
+ // [START inequality_sort_invalid_not_same]
+ const query = datastore.createQuery('Task')
+ .filter('priority', '>', 3)
+ .order('created');
+ // [END inequality_sort_invalid_not_same]
-Transaction.prototype.testTransactionalRetry = function (callback) {
- // Overwrite so the real Datastore instance is used in `transferFunds`.
- var datastoreMock = datastore;
- datastore = this.datastore;
-
- var originalCallback = callback;
- callback = function () {
- // Restore `datastore` to the mock API.
- datastore = datastoreMock;
- originalCallback.apply(null, arguments);
- };
-
- var fromKey = this.fromKey;
- var toKey = this.toKey;
-
- this.restoreBankAccountBalances({
- keys: [fromKey, toKey],
- balance: this.originalBalance
- }, function (err) {
- if (err) {
- callback(err);
- return;
- }
+ return this.datastore.runQuery(query);
+ }
- // [START transactional_retry]
- var async = require('async');
+ testInequalitySortInvalidNotFirst () {
+ const datastore = this.datastore;
- function attemptTransfer (callback) {
- transferFunds(fromKey, toKey, 10, callback);
- }
+ // [START inequality_sort_invalid_not_first]
+ const query = datastore.createQuery('Task')
+ .filter('priority', '>', 3)
+ .order('created')
+ .order('priority');
+ // [END inequality_sort_invalid_not_first]
- async.retry(5, attemptTransfer, callback);
- // [END transactional_retry]
- });
-};
+ return this.datastore.runQuery(query);
+ }
-Transaction.prototype.testTransactionalGetOrCreate = function (callback) {
- var taskKey = this.datastore.key(['Task', Date.now()]);
+ testLimit () {
+ const datastore = this.datastore;
- // Overwrite so the real Datastore instance is used in `transferFunds`.
- var datastoreMock = datastore;
- datastore = this.datastore;
+ // [START limit]
+ const query = datastore.createQuery('Task')
+ .limit(5);
+ // [END limit]
- var originalCallback = callback;
- callback = function () {
- // Restore `datastore` to the mock API.
- datastore = datastoreMock;
- originalCallback.apply(null, arguments);
- };
+ return this.datastore.runQuery(query);
+ }
- // [START transactional_get_or_create]
- function getOrCreate (taskKey, taskData, callback) {
- var taskEntity = {
- key: taskKey,
- data: taskData
- };
+ testCursorPaging () {
+ const datastore = this.datastore;
+ const pageSize = 1;
- var transaction = datastore.transaction();
+ // [START cursor_paging]
+ // By default, google-cloud-node will automatically paginate through all of
+ // the results that match a query. However, this sample implements manual
+ // pagination using limits and cursor tokens.
+ function runPageQuery (pageCursor) {
+ let query = datastore.createQuery('Task')
+ .limit(pageSize);
- transaction.run(function (err) {
- if (err) {
- return callback(err);
+ if (pageCursor) {
+ query = query.start(pageCursor);
}
- transaction.get(taskKey, function (err, task) {
- if (err) {
- // An error occurred while getting the values.
- return transaction.rollback(function (_err) {
- return callback(_err || err);
- });
- }
+ return datastore.runQuery(query)
+ .then((results) => {
+ const entities = results[0];
+ const info = results[1];
+
+ if (info.moreResults !== Datastore.NO_MORE_RESULTS) {
+ // If there are more results to retrieve, the end cursor is
+ // automatically set on `info`. To get this value directly, access
+ // the `endCursor` property.
+ return runPageQuery(info.endCursor)
+ .then((results) => {
+ // Concatenate entities
+ results[0] = entities.concat(results[0]);
+ return results;
+ });
+ }
- if (task) {
- // The task entity already exists.
- transaction.rollback(callback);
- } else {
- // Create the task entity.
- transaction.save(taskEntity);
- transaction.commit(function (err) {
- if (err) {
- return callback(err);
- }
- // The transaction completed successfully.
- callback(null, taskEntity);
- });
+ return [entities, info];
+ });
+ }
+ // [END cursor_paging]
+
+ return runPageQuery()
+ .then((results) => {
+ const entities = results[0];
+ assert.equal(Array.isArray(entities), true);
+ const info = results[1];
+ if (!info || !info.endCursor) {
+ throw new Error('An `info` with an `endCursor` is not present.');
}
});
- });
}
- // [END transactional_get_or_create]
-
- asyncUtil.series([
- // Create:
- testWithCreateBehavior,
- // Then try to get it:
- testWithGetBehavior
- ], callback);
-
- function testWithCreateBehavior (callback) {
- getOrCreate(taskKey, {}, function (err, task) {
- if (err) {
- callback(err);
- return;
- }
- if (!task) {
- return callback(new Error('Entity was not created successfully.'));
- }
- callback();
- });
+ testEventualConsistentQuery () {
+ // [START eventual_consistent_query]
+ // Read consistency cannot be specified in google-cloud-node.
+ // [END eventual_consistent_query]
}
+}
- function testWithGetBehavior (callback) {
- getOrCreate(taskKey, {}, function (err, task) {
- if (err) {
- callback(err);
- return;
- }
+// [START transactional_update]
+function transferFunds (fromKey, toKey, amount) {
+ const transaction = datastore.transaction();
+
+ return transaction.run()
+ .then(() => Promise.all([transaction.get(fromKey), transaction.get(toKey)]))
+ .then((results) => {
+ const accounts = results
+ .map((result) => result[0]);
+
+ accounts[0].balance -= amount;
+ accounts[1].balance += amount;
+
+ transaction.save([
+ {
+ key: fromKey,
+ data: accounts[0]
+ },
+ {
+ key: toKey,
+ data: accounts[1]
+ }
+ ]);
- if (!task) {
- return callback(new Error('Entity was not retrieved successfully.'));
- }
- callback();
+ return transaction.commit();
+ })
+ .catch(() => transaction.rollback());
+}
+// [END transactional_update]
+
+class Transaction extends TestHelper {
+ constructor (projectId) {
+ super(projectId);
+ this.fromKey = this.datastore.key(['Bank', 1, 'Account', 1]);
+ this.toKey = this.datastore.key(['Bank', 1, 'Account', 2]);
+
+ this.originalBalance = 100;
+ this.amountToTransfer = 10;
+ }
+
+ restoreBankAccountBalances (config) {
+ const entities = config.keys.map((key) => {
+ return {
+ key: key,
+ data: {
+ balance: config.balance
+ }
+ };
});
+
+ return this.datastore.save(entities);
}
-};
-Transaction.prototype.testSingleEntityGroupReadOnly = function (callback) {
- // Overwrite so the real Datastore instance is used in `transferFunds`.
- var datastoreMock = datastore;
- datastore = this.datastore;
+ testTransactionalUpdate () {
+ const fromKey = this.fromKey;
+ const toKey = this.toKey;
+ const originalBalance = this.originalBalance;
+ const amountToTransfer = this.amountToTransfer;
+ const datastoreMock = datastore;
- var originalCallback = callback;
- callback = function () {
- // Restore `datastore` to the mock API.
- datastore = datastoreMock;
- originalCallback.apply(null, arguments);
- };
+ // Overwrite so the real Datastore instance is used in `transferFunds`.
+ datastore = this.datastore;
- // [START transactional_single_entity_group_read_only]
- function getTaskListEntities (callback) {
- var taskListEntities;
+ return this.restoreBankAccountBalances({
+ keys: [fromKey, toKey],
+ balance: originalBalance
+ })
+ .then(() => transferFunds(fromKey, toKey, amountToTransfer))
+ .then(() => Promise.all([this.datastore.get(fromKey), this.datastore.get(toKey)]))
+ .then((results) => {
+ const accounts = results.map((result) => result[0]);
+ // Restore `datastore` to the mock API.
+ datastore = datastoreMock;
+ assert.equal(accounts[0].balance, originalBalance - amountToTransfer);
+ assert.equal(accounts[1].balance, originalBalance + amountToTransfer);
+ })
+ .catch((err) => {
+ // Restore `datastore` to the mock API.
+ datastore = datastoreMock;
+ return Promise.reject(err);
+ });
+ }
- var transaction = datastore.transaction();
+ testTransactionalRetry () {
+ // Overwrite so the real Datastore instance is used in `transferFunds`.
+ const datastoreMock = datastore;
+ datastore = this.datastore;
- transaction.run(function (err) {
- if (err) {
- return callback(err);
- }
+ const fromKey = this.fromKey;
+ const toKey = this.toKey;
- var taskListKey = datastore.key(['TaskList', 'default']);
+ return this.restoreBankAccountBalances({
+ keys: [fromKey, toKey],
+ balance: this.originalBalance
+ })
+ .then(() => {
+ // [START transactional_retry]
+ function transferFundsWithRetry () {
+ const maxTries = 5;
+ let currentAttempt = 1;
+ let delay = 100;
+
+ function tryRequest () {
+ return transferFunds(fromKey, toKey, 10)
+ .catch((err) => {
+ if (currentAttempt <= maxTries) {
+ // Use exponential backoff
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ currentAttempt++;
+ delay *= 2;
+ tryRequest().then(resolve, reject);
+ }, delay);
+ });
+ }
+ return Promise.reject(err);
+ });
+ }
- datastore.get(taskListKey, function (err) {
- if (err) {
- return transaction.rollback(function (_err) {
- return callback(_err || err);
- });
+ return tryRequest(1, 5);
}
+ // [END transactional_retry]
+ return transferFundsWithRetry();
+ })
+ .then(() => {
+ // Restore `datastore` to the mock API.
+ datastore = datastoreMock;
+ })
+ .catch(() => {
+ // Restore `datastore` to the mock API.
+ datastore = datastoreMock;
+ });
+ }
- var query = datastore.createQuery('Task')
- .hasAncestor(taskListKey);
+ testTransactionalGetOrCreate () {
+ const taskKey = this.datastore.key(['Task', Date.now()]);
- datastore.runQuery(query, function (err, entities) {
- if (err) {
- // An error occurred while running the query.
- return transaction.rollback(function (_err) {
- return callback(_err || err);
- });
+ // Overwrite so the real Datastore instance is used in `transferFunds`.
+ const datastoreMock = datastore;
+ datastore = this.datastore;
+
+ // [START transactional_get_or_create]
+ function getOrCreate (taskKey, taskData) {
+ const taskEntity = {
+ key: taskKey,
+ data: taskData
+ };
+
+ const transaction = datastore.transaction();
+
+ return transaction.run()
+ .then(() => transaction.get(taskKey))
+ .then((results) => {
+ const task = results[0];
+ if (task) {
+ // The task entity already exists.
+ return transaction.rollback();
+ } else {
+ // Create the task entity.
+ transaction.save(taskEntity);
+ return transaction.commit();
}
-
- taskListEntities = entities;
- transaction.commit(function (err) {
- if (err) {
- return callback(err);
- }
-
- // The transaction completed successfully.
- callback(null, taskListEntities);
- });
- });
+ })
+ .then(() => taskEntity)
+ .catch(() => transaction.rollback());
+ }
+ // [END transactional_get_or_create]
+
+ return getOrCreate(taskKey, {})
+ .then((task) => {
+ assert(task, 'Should have a task.');
+ return getOrCreate(taskKey, {});
+ })
+ .then((task) => {
+ assert(task, 'Should have a task.');
+ // Restore `datastore` to the mock API.
+ datastore = datastoreMock;
+ })
+ .catch((err) => {
+ // Restore `datastore` to the mock API.
+ datastore = datastoreMock;
+ return Promise.reject(err);
});
- });
}
- // [END transactional_single_entity_group_read_only]
- getTaskListEntities(function (err, entities) {
- if (err) {
- callback(err);
- return;
+ testSingleEntityGroupReadOnly () {
+ // Overwrite so the real Datastore instance is used in `transferFunds`.
+ const datastoreMock = datastore;
+ datastore = this.datastore;
+
+ // [START transactional_single_entity_group_read_only]
+ function getTaskListEntities () {
+ let taskList, taskListEntities;
+
+ const transaction = datastore.transaction();
+ const taskListKey = datastore.key(['TaskList', 'default']);
+
+ return transaction.run()
+ .then(() => datastore.get(taskListKey))
+ .then((results) => {
+ taskList = results[0];
+ const query = datastore.createQuery('Task')
+ .hasAncestor(taskListKey);
+ return datastore.runQuery(query);
+ })
+ .then((results) => {
+ taskListEntities = results[0];
+ return transaction.commit();
+ })
+ .then(() => [taskList, taskListEntities])
+ .catch(() => transaction.rollback());
}
+ // [END transactional_single_entity_group_read_only]
+
+ return getTaskListEntities()
+ .then((results) => {
+ // Restore `datastore` to the mock API.
+ datastore = datastoreMock;
+ assert.equal(results.length, 2);
+ assert.equal(Array.isArray(results[1]), true);
+ }, (err) => {
+ // Restore `datastore` to the mock API.
+ datastore = datastoreMock;
+ return Promise.reject(err);
+ });
+ }
+}
- if (!entities) {
- return callback(new Error('Entities were not retrieved successfully.'));
- }
- callback();
- });
+module.exports = {
+ Entity: Entity,
+ Index: Index,
+ Metadata: Metadata,
+ Query: Query,
+ Transaction: Transaction
};
diff --git a/datastore/error.js b/datastore/error.js
index 4ed1c93c94..a9434e4845 100644
--- a/datastore/error.js
+++ b/datastore/error.js
@@ -1,34 +1,37 @@
-// Copyright 2016, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/**
+ * Copyright 2016, Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
'use strict';
-// By default, the client will authenticate using the service account file
-// specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
-// the project specified by the GCLOUD_PROJECT environment variable. See
-// https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication
-var Datastore = require('@google-cloud/datastore');
-
-// Instantiate a datastore client
-var datastore = Datastore();
+const Datastore = require('@google-cloud/datastore');
// [START error]
-function runQuery (cb) {
- var query = datastore.createQuery(['Company']).start('badrequest');
-
- datastore.runQuery(query, function (err, entities) {
- // Check for an error
- if (err) {
+function runQuery () {
+ // Instantiates a client
+ const datastore = Datastore();
+
+ const query = datastore.createQuery(['Company']).start('badrequest');
+
+ return datastore.runQuery(query)
+ .then((results) => {
+ const entities = results[0];
+ console.log('Entities:');
+ entities.forEach((entity) => console.log(entity));
+ return entities;
+ })
+ .catch((err) => {
console.log(err.errors); // [...]
console.log(err.code); // 400
console.log(err.message); // "Bad Request"
@@ -38,21 +41,17 @@ function runQuery (cb) {
// For example, treat permission error like no entities were found
if (err.code === 403) {
- return cb(null, []);
+ return [];
}
// Forward the error to the caller
- return cb(err);
- }
-
- // We're good
- return cb(null, entities);
- });
+ return Promise.reject(err);
+ });
}
// [END error]
exports.runQuery = runQuery;
if (module === require.main) {
- runQuery(console.log);
+ exports.runQuery();
}
diff --git a/datastore/package.json b/datastore/package.json
index 009de7d153..837c76e9a5 100644
--- a/datastore/package.json
+++ b/datastore/package.json
@@ -5,16 +5,11 @@
"license": "Apache Version 2.0",
"author": "Google Inc.",
"scripts": {
- "test": "mocha -R spec -t 120000 --require intelli-espower-loader ../test/_setup.js test/*.test.js",
- "system-test": "mocha -R spec -t 120000 --require intelli-espower-loader ../system-test/_setup.js system-test/*.test.js"
+ "test": "cd ..; npm run st -- datastore/system-test/*.test.js"
},
"dependencies": {
- "@google-cloud/datastore": "^0.1.1",
- "async": "^2.0.1",
- "yargs": "^5.0.0"
- },
- "devDependencies": {
- "mocha": "^3.0.2"
+ "@google-cloud/datastore": "^0.5.0",
+ "yargs": "^6.4.0"
},
"engines": {
"node": ">=4.3.2"
diff --git a/datastore/quickstart.js b/datastore/quickstart.js
index 7925508374..2e07f62457 100644
--- a/datastore/quickstart.js
+++ b/datastore/quickstart.js
@@ -23,7 +23,7 @@ const Datastore = require('@google-cloud/datastore');
const projectId = 'YOUR_PROJECT_ID';
// Instantiates a client
-const datastoreClient = Datastore({
+const datastore = Datastore({
projectId: projectId
});
@@ -32,7 +32,7 @@ const kind = 'Task';
// The name/ID for the new entity
const name = 'sampletask1';
// The Cloud Datastore key for the new entity
-const taskKey = datastoreClient.key([kind, name]);
+const taskKey = datastore.key([kind, name]);
// Prepares the new entity
const task = {
@@ -43,12 +43,8 @@ const task = {
};
// Saves the entity
-datastoreClient.save(task, (err) => {
- if (err) {
- console.error(err);
- return;
- }
-
- console.log(`Saved ${task.key.name}: ${task.data.description}`);
-});
+datastore.save(task)
+ .then(() => {
+ console.log(`Saved ${task.key.name}: ${task.data.description}`);
+ });
// [END datastore_quickstart]
diff --git a/datastore/system-test/concepts.test.js b/datastore/system-test/concepts.test.js
index 74bb3b143b..2365dae13c 100644
--- a/datastore/system-test/concepts.test.js
+++ b/datastore/system-test/concepts.test.js
@@ -1,36 +1,40 @@
-// Copyright 2015, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/**
+ * Copyright 2016, Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-'use strict';
-
-var testUtil = require('./util');
-var concepts = require('../concepts');
-var transaction;
-var metadata;
-var index;
-var query;
-var entity;
-
-var Transaction = concepts.Transaction;
-var Metadata = concepts.Metadata;
-var Index = concepts.Index;
-var Entity = concepts.Entity;
-var Query = concepts.Query;
+'use strict';
-describe('datastore:concepts', function () {
- before(function () {
- var projectId = process.env.GCLOUD_PROJECT || 'nodejs-docs-samples';
+const assert = require(`power-assert`);
+const concepts = require(`../concepts`);
+
+let transaction;
+let metadata;
+let index;
+let query;
+let entity;
+
+const Transaction = concepts.Transaction;
+const Metadata = concepts.Metadata;
+const Index = concepts.Index;
+const Entity = concepts.Entity;
+const Query = concepts.Query;
+
+describe(`datastore:concepts`, () => {
+ before(() => {
+ const projectId = process.env.GCLOUD_PROJECT;
+ assert.equal(!!projectId, true, `You must set the GCLOUD_PROJECT env var!`);
transaction = new Transaction(projectId);
metadata = new Metadata(projectId);
index = new Index(projectId);
@@ -38,245 +42,108 @@ describe('datastore:concepts', function () {
query = new Query(projectId);
});
- after(function (done) {
- var datastore = transaction.datastore;
- var query = datastore.createQuery('Task');
-
- testUtil.deleteEntities(datastore, query, done);
- });
-
- // Transactions
-
- it('performs a transactional update', function (done) {
- transaction.testTransactionalUpdate(done);
- });
-
- it('performs retries if necessary', function (done) {
- transaction.testTransactionalRetry(done);
- });
-
- it('performs a get or create', function (done) {
- transaction.testTransactionalGetOrCreate(done);
- });
-
- it('gets a snapshot of task list entities', function (done) {
- transaction.testSingleEntityGroupReadOnly(done);
- });
-
- // Metadata
-
- it('performs a namespace query', function (done) {
- metadata.testNamespaceRunQuery(done);
- });
-
- it('performs a kind query', function (done) {
- metadata.testKindRunQuery(done);
- });
-
- it('performs a property query', function (done) {
- metadata.testPropertyRunQuery(done);
- });
-
- it('performs a property by kind query', function (done) {
- metadata.testPropertyByKindRunQuery(done);
- });
-
- // Indexes
-
- it(
- 'performs a query with a filter on an unindexed property',
- function (done) {
- index.testUnindexedPropertyQuery(done);
- }
- );
-
- it('inserts arrays of data', function (done) {
- index.testExplodingProperties(done);
- });
-
- // Queries
-
- it('performs a basic query', function (done) {
- query.testRunQuery(done);
- });
-
- it('performs a query with a property filter', function (done) {
- query.testPropertyFilter(done);
- });
-
- it('performs a query with a composite filter', function (done) {
- query.testCompositeFilter(done);
- });
-
- it('performs a query with a key filter', function (done) {
- query.testKeyFilter(done);
- });
-
- it('performs a query with ascending sort', function (done) {
- query.testAscendingSort(done);
- });
-
- it('performs a query with descending sort', function (done) {
- query.testDescendingSort(done);
- });
-
- it('performs a query with multi sort', function (done) {
- query.testMultiSort(done);
- });
-
- it('performs a kindless query', function (done) {
- query.testKindlessQuery(done);
- });
-
- it('performs a projection query', function (done) {
- entity.testProperties(function (err, tasks) {
- console.log(err, tasks);
- assert.ifError(err);
- setTimeout(function () {
- query.testRunQueryProjection(done);
- }, 1000);
+ after(() => {
+ const datastore = transaction.datastore;
+ const query = datastore.createQuery(`Task`).select(`__key__`);
+ return datastore.runQuery(query)
+ .then((results) => datastore.delete(results[0].map((entity) => entity[datastore.KEY])));
+ });
+
+ describe(`Transactions`, () => {
+ it(`performs a transactional update`, () => transaction.testTransactionalUpdate());
+ it(`performs retries if necessary`, () => transaction.testTransactionalRetry());
+ it(`performs a get or create`, () => transaction.testTransactionalGetOrCreate());
+ it(`gets a snapshot of task list entities`, () => transaction.testSingleEntityGroupReadOnly());
+ });
+
+ describe(`Metadata`, () => {
+ it(`performs a namespace query`, () => metadata.testNamespaceRunQuery());
+ it(`performs a kind query`, () => metadata.testKindRunQuery());
+ it(`performs a property query`, () => metadata.testPropertyRunQuery());
+ it(`performs a property by kind query`, () => metadata.testPropertyByKindRunQuery());
+ });
+
+ describe(`Indexes`, () => {
+ it(`performs a query with a filter on an unindexed property`, () => index.testUnindexedPropertyQuery());
+ it(`inserts arrays of data`, () => index.testExplodingProperties());
+ });
+
+ describe(`Queries`, () => {
+ it(`performs a basic query`, () => query.testRunQuery());
+ it(`performs a query with a property filter`, () => query.testPropertyFilter());
+ it(`performs a query with a composite filter`, () => query.testCompositeFilter());
+ it(`performs a query with a key filter`, () => query.testKeyFilter());
+ it(`performs a query with ascending sort`, () => query.testAscendingSort());
+ it(`performs a query with descending sort`, () => query.testDescendingSort());
+ it(`performs a query with multi sort`, () => query.testMultiSort());
+ it(`performs a kindless query`, () => query.testKindlessQuery());
+ it('performs a projection query', () => {
+ return entity.testProperties()
+ .then(() => {
+ return new Promise((resolve, reject) => {
+ setTimeout(function () {
+ query.testRunQueryProjection().then(resolve, reject);
+ }, 1000);
+ });
+ })
+ .then((results) => {
+ assert.deepEqual(results, {
+ priorities: [4],
+ percentCompletes: [10]
+ });
+ });
});
- });
-
- it('performs a keys only query', function (done) {
- query.testKeysOnlyQuery(done);
- });
-
- it('performs a distinct query', function (done) {
- query.testDistinctQuery(done);
- });
-
- it('performs a distinct on query', function (done) {
- query.testDistinctOnQuery(done);
- });
-
- it('performs an array value inequality query', function (done) {
- query.testArrayValueInequalityRange(done);
- });
-
- it('performs an array value equality query', function (done) {
- query.testArrayValueEquality(done);
- });
-
- it('performs an inequality range query', function (done) {
- query.testInequalityRange(done);
- });
-
- it('returns an error from an invalid query', function (done) {
- query.testInequalityInvalid(function (err) {
- assert(err);
- done();
+ it(`performs a keys only query`, () => query.testKeysOnlyQuery());
+ it(`performs a distinct query`, () => query.testDistinctQuery());
+ it(`performs a distinct on query`, () => query.testDistinctOnQuery());
+ it(`performs an array value inequality query`, () => query.testArrayValueInequalityRange());
+ it(`performs an array value equality query`, () => query.testArrayValueEquality());
+ it(`performs an inequality range query`, () => query.testInequalityRange());
+ it(`returns an error from an invalid query`, () => {
+ return query.testInequalityInvalid()
+ .then(() => assert.fail(), (err) => assert(err));
});
- });
-
- it('performs an equal and inequality range query', function (done) {
- query.testEqualAndInequalityRange(done);
- });
-
- it('performs an equality sort query', function (done) {
- query.testInequalitySort(done);
- });
-
- it(
- 'returns an error when not sorted on filtered property',
- function (done) {
- query.testInequalitySortInvalidNotSame(function (err) {
- assert(err);
- done();
- });
- }
- );
-
- it(
- 'returns an error when not sorted on first filter prop',
- function (done) {
- query.testInequalitySortInvalidNotFirst(function (err) {
- assert(err);
- done();
- });
- }
- );
-
- it('performs a query with a limit', function (done) {
- query.testLimit(done);
- });
-
- it('allows manual pagination through results', function (done) {
- entity.testBatchUpsert(function (err) {
- assert.ifError(err);
- setTimeout(function () {
- query.testCursorPaging(done);
- }, 1000);
+ it(`performs an equal and inequality range query`, () => query.testEqualAndInequalityRange());
+ it(`performs an equality sort query`, () => query.testInequalitySort());
+ it(`returns an error when not sorted on filtered property`, () => {
+ return query.testInequalitySortInvalidNotSame()
+ .then(() => assert.fail(), (err) => assert(err));
});
- });
-
- it.skip('performs an ancestor query', function (done) {
- query.testEventualConsistentQuery(done);
- });
-
- // Entities
-
- it('saves with an incomplete key', function (done) {
- entity.testIncompleteKey(done);
- });
-
- it('saves with a named key', function (done) {
- entity.testNamedKey(done);
- });
-
- it('saves a key with a parent', function (done) {
- entity.testKeyWithParent(done);
- });
-
- it('saves a key with multiple parents', function (done) {
- entity.testKeyWithMultiLevelParent(done);
- });
-
- it('saves an entity with a parent', function (done) {
- entity.testEntityWithParent(done);
- });
-
- it('saves an entity with properties', function (done) {
- entity.testProperties(done);
- });
-
- it('saves an entity with arrays', function (done) {
- entity.testArrayValue(done);
- });
-
- it('saves a basic entity', function (done) {
- entity.testBasicEntity(done);
- });
-
- it('saves with an upsert', function (done) {
- entity.testUpsert(done);
- });
-
- it('saves with an insert', function (done) {
- entity.testInsert(done);
- });
-
- it('performs a lookup', function (done) {
- entity.testLookup(done);
- });
-
- it('saves with an update', function (done) {
- entity.testUpdate(done);
- });
-
- it('deletes an entity', function (done) {
- entity.testDelete(done);
- });
-
- it('performs a batch upsert', function (done) {
- entity.testBatchUpsert(done);
- });
-
- it('performs a batch lookup', function (done) {
- entity.testBatchLookup(done);
- });
-
- it('performs a batch delete', function (done) {
- entity.testBatchDelete(done);
+ it(`returns an error when not sorted on first filter prop`, () => {
+ return query.testInequalitySortInvalidNotFirst()
+ .then(() => assert.fail(), (err) => assert(err));
+ });
+ it(`performs a query with a limit`, () => query.testLimit());
+ it(`allows manual pagination through results`, () => {
+ return entity.testBatchUpsert()
+ .then(() => {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ query.testCursorPaging()
+ .then(resolve, reject);
+ }, 1000);
+ });
+ });
+ });
+ it(`performs an ancestor query`, () => query.testEventualConsistentQuery());
+ });
+
+ describe(`Entities`, () => {
+ it(`saves with an incomplete key`, () => entity.testIncompleteKey());
+ it(`saves with a named key`, () => entity.testNamedKey());
+ it(`saves a key with a parent`, () => entity.testKeyWithParent());
+ it(`saves a key with multiple parents`, () => entity.testKeyWithMultiLevelParent());
+ it(`saves an entity with a parent`, () => entity.testEntityWithParent());
+ it(`saves an entity with properties`, () => entity.testProperties());
+ it(`saves an entity with arrays`, () => entity.testArrayValue());
+ it(`saves a basic entity`, () => entity.testBasicEntity());
+ it(`saves with an upsert`, () => entity.testUpsert());
+ it(`saves with an insert`, () => entity.testInsert());
+ it(`performs a lookup`, () => entity.testLookup());
+ it(`saves with an update`, () => entity.testUpdate());
+ it(`deletes an entity`, () => entity.testDelete());
+ it(`performs a batch upsert`, () => entity.testBatchUpsert());
+ it(`performs a batch lookup`, () => entity.testBatchLookup());
+ it(`performs a batch delete`, () => entity.testBatchDelete());
});
});
diff --git a/datastore/system-test/error.test.js b/datastore/system-test/error.test.js
index ef304b6086..578ec64c87 100644
--- a/datastore/system-test/error.test.js
+++ b/datastore/system-test/error.test.js
@@ -1,26 +1,31 @@
-// Copyright 2015-2016, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/**
+ * Copyright 2016, Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
'use strict';
-var error = require('../error');
+const error = require('../error');
-describe('datastore:error', function () {
- it('should have an error', function (done) {
- error.runQuery(function (err) {
- assert(err);
- assert.equal(err.code, 400);
- done();
- });
+describe(`datastore:error`, () => {
+ it(`should have an error`, () => {
+ return error.runQuery()
+ .then(() => {
+ assert.fail(`should have failed!`);
+ })
+ .catch((err) => {
+ assert(err);
+ assert.equal(err.code, 400);
+ });
});
});
diff --git a/datastore/system-test/quickstart.test.js b/datastore/system-test/quickstart.test.js
index b385261116..38522bb4ea 100644
--- a/datastore/system-test/quickstart.test.js
+++ b/datastore/system-test/quickstart.test.js
@@ -17,47 +17,42 @@
const proxyquire = require(`proxyquire`).noPreserveCache();
const datastore = proxyquire(`@google-cloud/datastore`, {})();
+const entity = { description: `Buy milk` };
const kind = `Task`;
const name = `sampletask1`;
-const key = datastore.key(kind, name);
+const key = datastore.key([kind, name]);
describe(`datastore:quickstart`, () => {
- let datastoreMock, DatastoreMock;
-
- after((done) => {
- datastore.delete(key, () => {
- // Ignore any error, the entity might not have been created
- done();
- });
- });
+ before(() => datastore.delete(key).catch(() => {}));
+ after(() => datastore.delete(key).catch(() => {}));
it(`should get a task from Datastore`, (done) => {
- datastoreMock = {
- key (...args) {
- return datastore.key(...args);
- },
+ const datastoreMock = {
+ key: (...args) => datastore.key(...args),
- save (_task, _callback) {
+ save: (_task) => {
assert.equal(_task.key.kind, kind);
assert.equal(_task.key.name, name);
- assert.deepEqual(_task.data, {
- description: `Buy milk`
- });
- assert.equal(typeof _callback, 'function');
-
- datastore.save(_task, (err) => {
- _callback(err);
- assert.ifError(err);
- assert.equal(console.log.calledOnce, true);
- assert.deepEqual(console.log.firstCall.args, [`Saved ${_task.key.name}: ${_task.data.description}`]);
- done();
- });
+ assert.deepEqual(_task.data, entity);
+
+ return datastore.save(_task)
+ .then(() => {
+ setTimeout(() => {
+ datastore.get(key)
+ .then((results) => {
+ const task = results[0];
+ assert.deepEqual(task, entity);
+ assert.equal(console.log.calledWith(`Saved ${name}: ${entity.description}`), true);
+ done();
+ })
+ .catch(done);
+ }, 200);
+ }, done);
}
};
- DatastoreMock = sinon.stub().returns(datastoreMock);
proxyquire(`../quickstart`, {
- '@google-cloud/datastore': DatastoreMock
+ '@google-cloud/datastore': sinon.stub().returns(datastoreMock)
});
});
});
diff --git a/datastore/system-test/tasks.test.js b/datastore/system-test/tasks.test.js
index 3d7e94e2a4..1d4913a999 100644
--- a/datastore/system-test/tasks.test.js
+++ b/datastore/system-test/tasks.test.js
@@ -1,62 +1,68 @@
-// Copyright 2015-2016, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/**
+ * Copyright 2016, Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
'use strict';
-var async = require('async');
-var tasks = require('../tasks');
-var taskIds = [];
-
-describe('datastore:tasks', function () {
- after(function (done) {
- async.parallel(taskIds.map(function (taskId) {
- return function (cb) {
- tasks.deleteEntity(taskId, cb);
- };
- }), done);
- });
+const path = require(`path`);
+const datastore = require(`@google-cloud/datastore`)();
+const run = require(`../../utils`).run;
- it('should add a task', function (done) {
- getTaskId(done);
- });
+const cmd = `node tasks.js`;
+const cwd = path.join(__dirname, `..`);
+
+describe(`datastore:tasks`, () => {
+ const description = `description`;
+ let key;
- it('should mark a task as done', function (done) {
- getTaskId(function (err, taskId) {
- assert.ifError(err);
- tasks.updateEntity(taskId, done);
- });
+ after(() => datastore.delete(key).catch(() => {}));
+
+ it(`should add a task`, () => {
+ const expected = /^Task (\d+) created successfully.$/;
+ const parts = run(`${cmd} new "${description}"`, cwd).match(expected);
+ assert.equal(expected.test(parts[0]), true);
+ return datastore.get(datastore.key([`Task`, parseInt(parts[1], 10)]))
+ .then((results) => {
+ const task = results[0];
+ key = task[datastore.KEY];
+ assert.equal(task.description, description);
+ });
});
- it('should list tasks', function (done) {
- tasks.retrieveEntities(done);
+ it(`should mark a task as done`, () => {
+ const expected = `Task ${key.id} updated successfully.`;
+ assert.equal(run(`${cmd} done ${key.id}`, cwd), expected);
+ return datastore.get(key)
+ .then((results) => {
+ assert.equal(results[0].done, true);
+ });
});
- it('should delete a task', function (done) {
- getTaskId(function (err, taskId) {
- assert.ifError(err);
- tasks.deleteEntity(taskId, done);
- });
+ it(`should list tasks`, (done) => {
+ setTimeout(() => {
+ const output = run(`${cmd} list`, cwd);
+ assert.equal(output.includes(key.id), true);
+ done();
+ }, 5000);
});
- function getTaskId (callback) {
- tasks.addEntity('description', function (err, taskKey) {
- if (err) {
- return callback(err);
- }
-
- var taskId = taskKey.path.pop();
- taskIds.push(taskId);
- callback(null, taskId);
- });
- }
+ it(`should delete a task`, () => {
+ const expected = `Task ${key.id} deleted successfully.`;
+ assert.equal(run(`${cmd} delete ${key.id}`, cwd), expected);
+ return datastore.get(key)
+ .then((results) => {
+ assert.equal(results[0], undefined);
+ });
+ });
});
diff --git a/datastore/system-test/util.js b/datastore/system-test/util.js
deleted file mode 100644
index 1c47393b60..0000000000
--- a/datastore/system-test/util.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-'use strict';
-
-module.exports = {
- deleteEntities: function (datastore, query, callback) {
- datastore.runQuery(query, function (err, entities) {
- if (err) {
- return callback(err);
- }
-
- var keys = entities.map(function (entity) {
- return entity.key;
- });
-
- datastore.delete(keys, callback);
- });
- }
-};
diff --git a/datastore/tasks.js b/datastore/tasks.js
old mode 100755
new mode 100644
index 7d8230778f..d60016a94e
--- a/datastore/tasks.js
+++ b/datastore/tasks.js
@@ -1,15 +1,17 @@
-// Copyright 2015-2016, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/**
+ * Copyright 2016, Google, Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
'use strict';
@@ -17,11 +19,11 @@
// By default, the client will authenticate using the service account file
// specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
// the project specified by the GCLOUD_PROJECT environment variable. See
-// https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication
-var Datastore = require('@google-cloud/datastore');
+// https://googlecloudplatform.github.io/google-cloud-node/#/docs/datastore/latest/guides/authentication
+const Datastore = require('@google-cloud/datastore');
-// Instantiate a datastore client
-var datastore = Datastore();
+// Instantiates a client
+const datastore = Datastore();
// [END build_service]
/*
@@ -46,7 +48,7 @@ npm install
5. With the gcloud SDK, be sure you are authenticated:
```sh
-gcloud auth login
+gcloud beta auth application-default login
```
6. At a command prompt, run the following, where `` is the ID of
@@ -62,10 +64,9 @@ node tasks
*/
// [START add_entity]
-function addTask (description, callback) {
- var taskKey = datastore.key('Task');
-
- datastore.save({
+function addTask (description) {
+ const taskKey = datastore.key('Task');
+ const entity = {
key: taskKey,
data: [
{
@@ -82,129 +83,110 @@ function addTask (description, callback) {
value: false
}
]
- }, function (err) {
- if (err) {
- return callback(err);
- }
-
- var taskId = taskKey.path.pop();
- console.log('Task %d created successfully.', taskId);
- return callback(null, taskKey);
- });
+ };
+
+ return datastore.save(entity)
+ .then(() => {
+ console.log(`Task ${taskKey.id} created successfully.`);
+ return taskKey;
+ });
}
// [END add_entity]
// [START update_entity]
-function markDone (taskId, callback) {
- var transaction = datastore.transaction();
-
- transaction.run(function (err) {
- if (err) {
- return callback(err);
- }
-
- var taskKey = datastore.key([
- 'Task',
- taskId
- ]);
-
- transaction.get(taskKey, function (err, task) {
- if (err) {
- // An error occurred while getting the task
- return transaction.rollback(function (_err) {
- return callback(err || _err);
- });
- }
-
- task.data.done = true;
-
- transaction.save(task);
-
- // Commit the transaction
- transaction.commit(function (err) {
- if (err) {
- return callback(err);
- }
+function markDone (taskId) {
+ const transaction = datastore.transaction();
+ const taskKey = datastore.key([
+ 'Task',
+ taskId
+ ]);
- // The transaction completed successfully.
- console.log('Task %d updated successfully.', taskId);
- return callback(null);
+ return transaction.run()
+ .then(() => transaction.get(taskKey))
+ .then((results) => {
+ const task = results[0];
+ task.done = true;
+ transaction.save({
+ key: taskKey,
+ data: task
});
- });
- });
+ return transaction.commit();
+ })
+ .then(() => {
+ // The transaction completed successfully.
+ console.log(`Task ${taskId} updated successfully.`);
+ })
+ .catch(() => transaction.rollback());
}
// [END update_entity]
// [START retrieve_entities]
-function listTasks (callback) {
- var query = datastore.createQuery('Task')
+function listTasks () {
+ const query = datastore.createQuery('Task')
.order('created');
- datastore.runQuery(query, function (err, tasks) {
- if (err) {
- return callback(err);
- }
+ return datastore.runQuery(query)
+ .then((results) => {
+ const tasks = results[0];
- console.log('Found %d task(s)!', tasks.length);
- return callback(null, tasks);
- });
+ console.log('Tasks:');
+ tasks.forEach((task) => {
+ const taskKey = task[datastore.KEY];
+ console.log(taskKey.id, task);
+ });
+
+ return tasks;
+ });
}
// [END retrieve_entities]
// [START delete_entity]
-function deleteTask (taskId, callback) {
- var taskKey = datastore.key([
+function deleteTask (taskId) {
+ const taskKey = datastore.key([
'Task',
taskId
]);
- datastore.delete(taskKey, function (err) {
- if (err) {
- return callback(err);
- }
-
- console.log('Task %d deleted successfully.', taskId);
- return callback(null);
- });
+ return datastore.delete(taskKey)
+ .then(() => {
+ console.log(`Task ${taskId} deleted successfully.`);
+ });
}
// [END delete_entity]
-var cli = require('yargs');
-var makeHandler = require('../utils').makeHandler;
-
-var program = module.exports = {
- addEntity: addTask,
- updateEntity: markDone,
- retrieveEntities: listTasks,
- deleteEntity: deleteTask,
- main: function (args) {
- // Run the command-line program
- cli.help().strict().parse(args).argv;
- }
-};
-
-cli
+require(`yargs`)
.demand(1)
- .command('new ', 'Adds a task with a description .', {}, function (options) {
- addTask(options.description, makeHandler());
- })
- .command('done ', 'Marks the specified task as done.', {}, function (options) {
- markDone(options.taskId, makeHandler());
- })
- .command('list', 'Lists all tasks ordered by creation time.', {}, function (options) {
- listTasks(makeHandler());
- })
- .command('delete ', 'Deletes a task.', {}, function (options) {
- deleteTask(options.taskId, makeHandler());
- })
- .example('node $0 new "Buy milk"', 'Adds a task with description "Buy milk".')
- .example('node $0 done 12345', 'Marks task 12345 as Done.')
- .example('node $0 list', 'Lists all tasks ordered by creation time')
- .example('node $0 delete 12345', 'Deletes task 12345.')
+ .command(
+ `new `,
+ `Adds a task with a description .`,
+ {},
+ (opts) => addTask(opts.description)
+ )
+ .command(
+ `done `,
+ `Marks the specified task as done.`,
+ {},
+ (opts) => markDone(opts.taskId)
+ )
+ .command(
+ `list`,
+ `Lists all tasks ordered by creation time.`,
+ {},
+ listTasks
+ )
+ .command(
+ `delete `,
+ `Deletes a task.`,
+ {},
+ (opts) => deleteTask(opts.taskId)
+ )
+ .example(`node $0 new "Buy milk"`, `Adds a task with description "Buy milk".`)
+ .example(`node $0 done 12345`, `Marks task 12345 as Done.`)
+ .example(`node $0 list`, `Lists all tasks ordered by creation time`)
+ .example(`node $0 delete 12345`, `Deletes task 12345.`)
.wrap(120)
.recommendCommands()
- .epilogue('For more information, see https://cloud.google.com/datastore/docs');
-
-if (module === require.main) {
- program.main(process.argv.slice(2));
-}
+ .epilogue(`For more information, see https://cloud.google.com/datastore/docs`)
+ .help()
+ .strict()
+ .argv;
diff --git a/datastore/test/concepts.test.js b/datastore/test/concepts.test.js
deleted file mode 100644
index 8deb451a29..0000000000
--- a/datastore/test/concepts.test.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-'use strict';
-
-describe('datastore:concepts', function () {
- it('should be tested');
-});
diff --git a/datastore/test/error.test.js b/datastore/test/error.test.js
deleted file mode 100644
index 6396d45d5f..0000000000
--- a/datastore/test/error.test.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-'use strict';
-
-describe('datastore:error', function () {
- it('should be tested');
-});
diff --git a/datastore/test/quickstart.test.js b/datastore/test/quickstart.test.js
deleted file mode 100644
index 1d37c24007..0000000000
--- a/datastore/test/quickstart.test.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright 2016, Google, Inc.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-'use strict';
-
-const proxyquire = require(`proxyquire`).noPreserveCache();
-
-describe(`datastore:quickstart`, () => {
- let datastoreMock, DatastoreMock;
- const error = new Error(`error`);
- const mockKey = {};
-
- before(() => {
- datastoreMock = {
- save: sinon.stub().yields(error),
- key: sinon.stub().returns(mockKey)
- };
- DatastoreMock = sinon.stub().returns(datastoreMock);
- });
-
- it(`should handle error`, () => {
- proxyquire(`../quickstart`, {
- '@google-cloud/datastore': DatastoreMock
- });
-
- assert.equal(DatastoreMock.calledOnce, true);
- assert.deepEqual(DatastoreMock.firstCall.args, [{ projectId: 'YOUR_PROJECT_ID' }]);
- assert.equal(datastoreMock.save.calledOnce, true);
- assert.deepEqual(datastoreMock.save.firstCall.args.slice(0, -1), [{
- key: mockKey,
- data: {
- description: 'Buy milk'
- }
- }]);
- assert.equal(console.error.calledOnce, true);
- assert.deepEqual(console.error.firstCall.args, [error]);
- });
-});
diff --git a/datastore/test/tasks.test.js b/datastore/test/tasks.test.js
deleted file mode 100644
index 2353d821f9..0000000000
--- a/datastore/test/tasks.test.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016, Google, Inc.
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-'use strict';
-
-describe('datastore:tasks', function () {
- it('should be tested');
-});
diff --git a/language/package.json b/language/package.json
index f95e29b9fd..30d16f2d7a 100644
--- a/language/package.json
+++ b/language/package.json
@@ -5,7 +5,7 @@
"license": "Apache Version 2.0",
"author": "Google Inc.",
"scripts": {
- "test": "cd ..; npm run st -- language/system-test/*"
+ "test": "cd ..; npm run st -- language/system-test/*.test.js"
},
"dependencies": {
"@google-cloud/language": "^0.6.0",