diff --git a/appengine/loopback/.eslintignore b/appengine/loopback/.eslintignore new file mode 100644 index 00000000000..44f397018c4 --- /dev/null +++ b/appengine/loopback/.eslintignore @@ -0,0 +1 @@ +/client/ \ No newline at end of file diff --git a/appengine/loopback/.eslintrc b/appengine/loopback/.eslintrc new file mode 100644 index 00000000000..a6e52975a0f --- /dev/null +++ b/appengine/loopback/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "loopback" +} \ No newline at end of file diff --git a/appengine/loopback/.jshintignore b/appengine/loopback/.jshintignore deleted file mode 100644 index ee8c771c5ad..00000000000 --- a/appengine/loopback/.jshintignore +++ /dev/null @@ -1,2 +0,0 @@ -/client/ -/node_modules/ diff --git a/appengine/loopback/.jshintrc b/appengine/loopback/.jshintrc deleted file mode 100644 index feb092894fa..00000000000 --- a/appengine/loopback/.jshintrc +++ /dev/null @@ -1,21 +0,0 @@ -{ - "node": true, - "esnext": true, - "bitwise": true, - "camelcase": true, - "eqeqeq": true, - "eqnull": true, - "immed": true, - "indent": 2, - "latedef": "nofunc", - "newcap": true, - "nonew": true, - "noarg": true, - "quotmark": "single", - "regexp": true, - "undef": true, - "unused": false, - "trailing": true, - "sub": true, - "maxlen": 80 -} diff --git a/appengine/loopback/client/index.html b/appengine/loopback/client/index.html deleted file mode 100644 index c3b7cc826a2..00000000000 --- a/appengine/loopback/client/index.html +++ /dev/null @@ -1,5 +0,0 @@ -LoopBack - -

Hello World!

-

LoopBack.js on Google App Engine.

- \ No newline at end of file diff --git a/appengine/loopback/common/models/message.js b/appengine/loopback/common/models/message.js new file mode 100644 index 00000000000..fc94c5a3be8 --- /dev/null +++ b/appengine/loopback/common/models/message.js @@ -0,0 +1,8 @@ +module.exports = function(Message) { + Message.greet = function(msg, cb) { + process.nextTick(function() { + msg = msg || 'hello'; + cb(null, 'Sender says ' + msg + ' to receiver'); + }); + }; +}; diff --git a/appengine/loopback/common/models/message.json b/appengine/loopback/common/models/message.json new file mode 100644 index 00000000000..4edf66b2835 --- /dev/null +++ b/appengine/loopback/common/models/message.json @@ -0,0 +1,24 @@ +{ + "name": "Message", + "base": "Model", + "properties": {}, + "methods": { + "greet": { + "isStatic": true, + "accepts": [{ + "arg": "msg", + "type": "string", + "http": { + "source": "query" + } + }], + "returns": { + "arg": "greeting", + "type": "string" + }, + "http": { + "verb": "get" + } + } + } +} diff --git a/appengine/loopback/common/models/person.js b/appengine/loopback/common/models/person.js deleted file mode 100644 index 244f6425027..00000000000 --- a/appengine/loopback/common/models/person.js +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -'use strict'; - -module.exports = function(Person) { - -}; diff --git a/appengine/loopback/common/models/person.json b/appengine/loopback/common/models/person.json deleted file mode 100644 index 095bf6a148f..00000000000 --- a/appengine/loopback/common/models/person.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "person", - "plural": "people", - "base": "User", - "idInjection": true, - "options": { - "validateUpsert": true - }, - "properties": { - "name": { - "type": "string", - "required": true - }, - "email": { - "type": "string", - "required": true - } - }, - "validations": [], - "relations": {}, - "acls": [], - "methods": {} -} diff --git a/appengine/loopback/package.json b/appengine/loopback/package.json index c1bbc98c777..14566b745db 100644 --- a/appengine/loopback/package.json +++ b/appengine/loopback/package.json @@ -8,19 +8,26 @@ "engines": { "node": ">=4.3.2" }, + "main": "server/server.js", "scripts": { - "pretest": "jshint .", - "start": "node server/server.js" + "lint": "eslint .", + "start": "node .", + "posttest": "npm run lint && nsp check" }, "dependencies": { - "compression": "1.0.3", - "cors": "2.5.2", - "errorhandler": "1.1.1", - "jshint": "2.5.6", - "loopback": "2.14.0", - "loopback-boot": "2.6.5", - "loopback-datasource-juggler": "2.19.0", - "loopback-explorer": "1.1.0", - "serve-favicon": "2.0.1" + "compression": "^1.0.3", + "cors": "^2.5.2", + "helmet": "^1.3.0", + "loopback-boot": "^2.6.5", + "loopback-component-explorer": "^2.4.0", + "serve-favicon": "^2.0.1", + "strong-error-handler": "^1.0.1", + "loopback-datasource-juggler": "^2.39.0", + "loopback": "^2.22.0" + }, + "devDependencies": { + "eslint": "^2.13.1", + "eslint-config-loopback": "^4.0.0", + "nsp": "^2.1.0" } } diff --git a/appengine/loopback/server/boot/authentication.js b/appengine/loopback/server/boot/authentication.js index a87cd081619..8e88d4b555e 100644 --- a/appengine/loopback/server/boot/authentication.js +++ b/appengine/loopback/server/boot/authentication.js @@ -1,3 +1,5 @@ +'use strict'; + module.exports = function enableAuthentication(server) { // enable authentication server.enableAuth(); diff --git a/appengine/loopback/server/boot/explorer.js b/appengine/loopback/server/boot/explorer.js deleted file mode 100644 index e42a69ac6e2..00000000000 --- a/appengine/loopback/server/boot/explorer.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = function mountLoopBackExplorer(server) { - var explorer; - try { - explorer = require('loopback-explorer'); - } catch(err) { - // Print the message only when the app was started via `server.listen()`. - // Do not print any message when the project is used as a component. - server.once('started', function(baseUrl) { - console.log( - 'Run `npm install loopback-explorer` to enable the LoopBack explorer' - ); - }); - return; - } - - var restApiRoot = server.get('restApiRoot'); - - var explorerApp = explorer(server, { basePath: restApiRoot }); - server.use('/explorer', explorerApp); - server.once('started', function() { - var baseUrl = server.get('url').replace(/\/$/, ''); - // express 4.x (loopback 2.x) uses `mountpath` - // express 3.x (loopback 1.x) uses `route` - var explorerPath = explorerApp.mountpath || explorerApp.route; - console.log('Browse your REST API at %s%s', baseUrl, explorerPath); - }); -}; diff --git a/appengine/loopback/server/boot/rest-api.js b/appengine/loopback/server/boot/rest-api.js deleted file mode 100644 index 256579a8132..00000000000 --- a/appengine/loopback/server/boot/rest-api.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = function mountRestApi(server) { - var restApiRoot = server.get('restApiRoot'); - server.use(restApiRoot, server.loopback.rest()); -}; diff --git a/appengine/loopback/server/boot/root.js b/appengine/loopback/server/boot/root.js new file mode 100644 index 00000000000..6adce90ad35 --- /dev/null +++ b/appengine/loopback/server/boot/root.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = function(server) { + // Install a `/` route that returns server status + var router = server.loopback.Router(); + router.get('/', server.loopback.status()); + server.use(router); +}; diff --git a/appengine/loopback/server/component-config.json b/appengine/loopback/server/component-config.json new file mode 100644 index 00000000000..f36959a488c --- /dev/null +++ b/appengine/loopback/server/component-config.json @@ -0,0 +1,5 @@ +{ + "loopback-component-explorer": { + "mountPath": "/explorer" + } +} diff --git a/appengine/loopback/server/config.json b/appengine/loopback/server/config.json index 3b1707641b1..40d45f4d637 100644 --- a/appengine/loopback/server/config.json +++ b/appengine/loopback/server/config.json @@ -1,11 +1,9 @@ { "restApiRoot": "/api", "host": "0.0.0.0", - "port": 8080, + "port": 3000, "remoting": { - "context": { - "enableHttpContext": false - }, + "context": false, "rest": { "normalizeHttpPath": false, "xml": false @@ -19,9 +17,7 @@ "limit": "100kb" }, "cors": false, - "errorHandler": { - "disableStackTrace": false - } + "handleErrors": false }, "legacyExplorer": false } diff --git a/appengine/loopback/server/middleware.development.json b/appengine/loopback/server/middleware.development.json new file mode 100644 index 00000000000..071c11a30ee --- /dev/null +++ b/appengine/loopback/server/middleware.development.json @@ -0,0 +1,10 @@ +{ + "final:after": { + "strong-error-handler": { + "params": { + "debug": true, + "log": true + } + } + } +} diff --git a/appengine/loopback/server/middleware.json b/appengine/loopback/server/middleware.json index b1cd5063259..fbfff8165de 100644 --- a/appengine/loopback/server/middleware.json +++ b/appengine/loopback/server/middleware.json @@ -10,21 +10,41 @@ "credentials": true, "maxAge": 86400 } + }, + "helmet#xssFilter": {}, + "helmet#frameguard": { + "params": [ + "deny" + ] + }, + "helmet#hsts": { + "params": { + "maxAge": 0, + "includeSubdomains": true + } + }, + "helmet#hidePoweredBy": {}, + "helmet#ieNoOpen": {}, + "helmet#noSniff": {}, + "helmet#noCache": { + "enabled": false } }, "session": {}, "auth": {}, "parse": {}, - "routes": {}, - "files": { - "loopback#static": { - "params": "$!../client" + "routes": { + "loopback#rest": { + "paths": [ + "${restApiRoot}" + ] } }, + "files": {}, "final": { "loopback#urlNotFound": {} }, "final:after": { - "errorhandler": {} + "strong-error-handler": {} } } diff --git a/appengine/loopback/server/model-config.json b/appengine/loopback/server/model-config.json index 411cb8a401e..30be974de8c 100644 --- a/appengine/loopback/server/model-config.json +++ b/appengine/loopback/server/model-config.json @@ -32,8 +32,7 @@ "dataSource": "db", "public": false }, - "person": { - "dataSource": "db", - "public": true + "Message": { + "dataSource": null } } diff --git a/appengine/loopback/server/server.js b/appengine/loopback/server/server.js index ec3e5443551..ef738abce20 100644 --- a/appengine/loopback/server/server.js +++ b/appengine/loopback/server/server.js @@ -1,19 +1,5 @@ -// 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. - 'use strict'; -// [START server] var loopback = require('loopback'); var boot = require('loopback-boot'); @@ -23,20 +9,21 @@ app.start = function() { // start the web server return app.listen(function() { app.emit('started'); - console.log('Web server listening at: %s', app.get('url')); + var baseUrl = app.get('url').replace(/\/$/, ''); + console.log('Web server listening at: %s', baseUrl); + if (app.get('loopback-component-explorer')) { + var explorerPath = app.get('loopback-component-explorer').mountPath; + console.log('Browse your REST API at %s%s', baseUrl, explorerPath); + } }); }; // Bootstrap the application, configure models, datasources and middleware. // Sub-apps like REST API are mounted via boot scripts. boot(app, __dirname, function(err) { - if (err) { - throw err; - } + if (err) throw err; // start the server if `$ node server.js` - if (require.main === module) { + if (require.main === module) app.start(); - } }); -// [START server] \ No newline at end of file diff --git a/appengine/system-test/all.test.js b/appengine/system-test/all.test.js index e6e34758b7b..080654f8b9c 100644 --- a/appengine/system-test/all.test.js +++ b/appengine/system-test/all.test.js @@ -131,7 +131,7 @@ var sampleTests = [ dir: 'appengine/loopback', cmd: 'node', args: ['server/server.js'], - msg: 'LoopBack.js on Google App Engine.', + msg: 'started', code: 304 }, { diff --git a/logging/package.json b/logging/package.json index abb9cd91505..990db1599c5 100644 --- a/logging/package.json +++ b/logging/package.json @@ -9,10 +9,10 @@ "system-test": "cd ..; npm run st -- logging/system-test/*.test.js" }, "dependencies": { - "@google-cloud/logging": "0.5.0", - "@google-cloud/storage": "0.4.0", + "@google-cloud/logging": "0.5.1", + "@google-cloud/storage": "0.5.0", "express": "4.14.0", - "fluent-logger": "2.0.1", + "fluent-logger": "2.2.0", "yargs": "6.4.0" }, "devDependencies": { diff --git a/logging/system-test/quickstart.test.js b/logging/system-test/quickstart.test.js index f942f7a0edb..d33d99878f5 100644 --- a/logging/system-test/quickstart.test.js +++ b/logging/system-test/quickstart.test.js @@ -42,7 +42,7 @@ describe(`logging:quickstart`, () => { const log = logging.log(logName); const text = `Hello, world!`; - const entry = log.entry({ type: `global` }, text); + const entry = log.entry({ resource: { type: `global` } }, text); log.write(entry, (err, apiResponse) => { _callback(err, apiResponse); assert.ifError(err); diff --git a/pubsub/README.md b/pubsub/README.md index 25584bf640a..9a4f0b3553a 100644 --- a/pubsub/README.md +++ b/pubsub/README.md @@ -30,30 +30,31 @@ allows you to send and receive messages between independent applications. View the [documentation][topics_docs] or the [source code][topics_code]. -__Usage:__ `node topics --help` +__Usage:__ `node topics.js --help` ``` Commands: - list Lists all topics in the current project. - create Creates a new topic. - delete Deletes the a topic. - publish Publishes a message. - getPolicy Gets the IAM policy for a topic. - setPolicy Sets the IAM policy for a topic. - testPermissions Tests the permissions for a topic. + list Lists all topics in the current project. + create Creates a new topic. + delete Deletes a topic. + publish Publishes a message to a topic. + publish-ordered Publishes an ordered message to a topic. + get-policy Gets the IAM policy for a topic. + set-policy Sets the IAM policy for a topic. + test-permissions Tests the permissions for a topic. Options: - --help Show help [boolean] + --help Show help [boolean] Examples: - node topics.js list Lists all topics in the current project. - node topics.js create greetings Creates a new topic named "greetings". - node topics.js delete greetings Deletes a topic named "greetings". - node topics.js publish greetings "Hello, world!" Publishes a simple message. - node topics.js publish greetings '{"data":"Hello, world!"}' Publishes a JSON message. - node topics.js getPolicy greetings Gets the IAM policy for a topic named "greetings". - node topics.js setPolicy greetings Sets the IAM policy for a topic named "greetings". - node topics.js testPermissions greetings Tests the permissions for a topic named "greetings". + node topics.js list + node topics.js create my-topic + node topics.js delete my-topic + node topics.js publish my-topic "Hello, world!" + node topics.js publish my-topic '{"data":"Hello, world!"}' + node topics.js get-policy greetings + node topics.js set-policy greetings + node topics.js test-permissions greetings For more information, see https://cloud.google.com/pubsub/docs ``` @@ -65,7 +66,7 @@ For more information, see https://cloud.google.com/pubsub/docs View the [documentation][subscriptions_docs] or the [source code][subscriptions_code]. -__Usage:__ `node subscriptions --help` +__Usage:__ `node subscriptions.js --help` ``` Commands: @@ -81,26 +82,19 @@ Commands: test-permissions Tests the permissions for a subscription. Options: - --help Show help [boolean] + --help Show help [boolean] Examples: - node subscriptions.js list Lists all subscriptions in the current project. - node subscriptions.js list greetings Lists all subscriptions for a topic named "greetings". - node subscriptions.js create greetings greetings-worker-1 Creates a subscription named "greetings-worker-1" to a - topic named "greetings". - node subscriptions.js create-push greetings Creates a push subscription named "greetings-worker-1" - greetings-worker-1 to a topic named "greetings". - node subscriptions.js get greetings-worker-1 Gets the metadata for a subscription named - "greetings-worker-1". - node subscriptions.js delete greetings-worker-1 Deletes a subscription named "greetings-worker-1". - node subscriptions.js pull greetings-worker-1 Pulls messages for a subscription named - "greetings-worker-1". - node subscriptions.js get-policy greetings-worker-1 Gets the IAM policy for a subscription named - "greetings-worker-1". - node subscriptions.js set-policy greetings-worker-1 Sets the IAM policy for a subscription named - "greetings-worker-1". - node subscriptions.js test-permissions greetings-worker-1 Tests the permissions for a subscription named - "greetings-worker-1". + node subscriptions.js list + node subscriptions.js list my-topic + node subscriptions.js create my-topic worker-1 + node subscriptions.js create-push my-topic worker-1 + node subscriptions.js get worker-1 + node subscriptions.js delete worker-1 + node subscriptions.js pull worker-1 + node subscriptions.js get-policy worker-1 + node subscriptions.js set-policy worker-1 + node subscriptions.js test-permissions worker-1 For more information, see https://cloud.google.com/pubsub/docs ``` diff --git a/pubsub/package.json b/pubsub/package.json index 17c1001dd49..c71c475b3f1 100644 --- a/pubsub/package.json +++ b/pubsub/package.json @@ -5,17 +5,14 @@ "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 -- pubsub/system-test/*.test.js" }, "dependencies": { - "@google-cloud/pubsub": "^0.1.1", - "yargs": "^5.0.0" + "@google-cloud/pubsub": "0.5.0", + "yargs": "6.4.0" }, "devDependencies": { - "async": "^2.0.1", - "mocha": "^3.0.2", - "node-uuid": "^1.4.7" + "node-uuid": "1.4.7" }, "engines": { "node": ">=4.3.2" diff --git a/pubsub/quickstart.js b/pubsub/quickstart.js index 6f4f44e970a..e32d8d93981 100644 --- a/pubsub/quickstart.js +++ b/pubsub/quickstart.js @@ -31,12 +31,9 @@ const pubsubClient = PubSub({ const topicName = 'my-new-topic'; // Creates the new topic -pubsubClient.createTopic(topicName, (err, topic) => { - if (err) { - console.error(err); - return; - } - - console.log(`Topic ${topic.name} created.`); -}); +pubsubClient.createTopic(topicName) + .then((results) => { + const topic = results[0]; + console.log(`Topic ${topic.name} created.`); + }); // [END pubsub_quickstart] diff --git a/pubsub/subscriptions.js b/pubsub/subscriptions.js index 7bd79e643e3..cb89ac6d0e7 100644 --- a/pubsub/subscriptions.js +++ b/pubsub/subscriptions.js @@ -26,165 +26,155 @@ const PubSub = require(`@google-cloud/pubsub`); // [START pubsub_list_subscriptions] -function listSubscriptions (callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function listSubscriptions () { + // Instantiates a client + const pubsub = PubSub(); // Lists all subscriptions in the current project - pubsubClient.getSubscriptions((err, subscriptions) => { - if (err) { - callback(err); - return; - } + return pubsub.getSubscriptions() + .then((results) => { + const subscriptions = results[0]; + + console.log('Subscriptions:'); + subscriptions.forEach((subscription) => console.log(subscription.name)); - console.log(`Subscriptions:`); - subscriptions.forEach((subscription) => console.log(subscription.name)); - callback(); - }); + return subscriptions; + }); } // [END pubsub_list_subscriptions] // [START pubsub_list_topic_subscriptions] -function listTopicSubscriptions (topicName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function listTopicSubscriptions (topicName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); + const topic = pubsub.topic(topicName); // Lists all subscriptions for the topic - topic.getSubscriptions((err, subscriptions) => { - if (err) { - callback(err); - return; - } + return topic.getSubscriptions() + .then((results) => { + const subscriptions = results[0]; + + console.log(`Subscriptions for ${topicName}:`); + subscriptions.forEach((subscription) => console.log(subscription.name)); - console.log(`Subscriptions for ${topicName}:`); - subscriptions.forEach((subscription) => console.log(subscription.name)); - callback(); - }); + return subscriptions; + }); } // [END pubsub_list_topic_subscriptions] // [START pubsub_create_subscription] -function createSubscription (topicName, subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function createSubscription (topicName, subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); + const topic = pubsub.topic(topicName); // Creates a new subscription, e.g. "my-new-subscription" - topic.subscribe(subscriptionName, (err, subscription) => { - if (err) { - callback(err); - return; - } + return topic.subscribe(subscriptionName) + .then((results) => { + const subscription = results[0]; + + console.log(`Subscription ${subscription.name} created.`); - console.log(`Subscription ${subscription.name} created.`); - callback(); - }); + return subscription; + }); } // [END pubsub_create_subscription] // [START pubsub_create_push_subscription] -function createPushSubscription (topicName, subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function createPushSubscription (topicName, subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); + const topic = pubsub.topic(topicName); - // Creates a new push subscription, e.g. "my-new-subscription" - topic.subscribe(subscriptionName, { + const options = { pushConfig: { // Set to an HTTPS endpoint of your choice. If necessary, register // (authorize) the domain on which the server is hosted. - pushEndpoint: `https://${pubsubClient.projectId}.appspot.com/push` - } - }, (err, subscription) => { - if (err) { - callback(err); - return; + pushEndpoint: `https://${pubsub.projectId}.appspot.com/push` } + }; - console.log(`Subscription ${subscription.name} created.`); - callback(); - }); + // Creates a new push subscription, e.g. "my-new-subscription" + return topic.subscribe(subscriptionName, options) + .then((results) => { + const subscription = results[0]; + + console.log(`Subscription ${subscription.name} created.`); + + return subscription; + }); } // [END pubsub_create_push_subscription] // [START pubsub_delete_subscription] -function deleteSubscription (subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function deleteSubscription (subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing subscription, e.g. "my-subscription" - const subscription = pubsubClient.subscription(subscriptionName); + const subscription = pubsub.subscription(subscriptionName); // Deletes the subscription - subscription.delete((err) => { - if (err) { - callback(err); - return; - } - - console.log(`Subscription ${subscription.name} deleted.`); - callback(); - }); + return subscription.delete() + .then(() => { + console.log(`Subscription ${subscription.name} deleted.`); + }); } // [END pubsub_delete_subscription] // [START pubsub_get_subscription] -function getSubscription (subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function getSubscription (subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing subscription, e.g. "my-subscription" - const subscription = pubsubClient.subscription(subscriptionName); + const subscription = pubsub.subscription(subscriptionName); // Gets the metadata for the subscription - subscription.getMetadata((err, metadata) => { - if (err) { - callback(err); - return; - } + return subscription.getMetadata() + .then((results) => { + const metadata = results[0]; + + console.log(`Subscription: ${metadata.name}`); + console.log(`Topic: ${metadata.topic}`); + console.log(`Push config: ${metadata.pushConfig.pushEndpoint}`); + console.log(`Ack deadline: ${metadata.ackDeadlineSeconds}s`); - console.log(`Subscription: ${metadata.name}`); - console.log(`Topic: ${metadata.topic}`); - console.log(`Push config: ${metadata.pushConfig.pushEndpoint}`); - console.log(`Ack deadline: ${metadata.ackDeadlineSeconds}s`); - callback(); - }); + return metadata; + }); } // [END pubsub_get_subscription] // [START pubsub_pull_messages] -function pullMessages (subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function pullMessages (subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing subscription, e.g. "my-subscription" - const subscription = pubsubClient.subscription(subscriptionName); + const subscription = pubsub.subscription(subscriptionName); // Pulls messages. Set returnImmediately to false to block until messages are // received. - subscription.pull({ returnImmediately: true }, (err, messages) => { - if (err) { - callback(err); - return; - } + return subscription.pull() + .then((results) => { + const messages = results[0]; - console.log(`Received ${messages.length} messages.`); + console.log(`Received ${messages.length} messages.`); - messages.forEach((message) => { - console.log(`* %d %j %j`, message.id, message.data, message.attributes); - }); + messages.forEach((message) => { + console.log(`* %d %j %j`, message.id, message.data, message.attributes); + }); - // Acknowledges received messages. If you do not acknowledge, Pub/Sub will - // redeliver the message. - subscription.ack(messages.map((message) => message.ackId), callback); - }); + // Acknowledges received messages. If you do not acknowledge, Pub/Sub will + // redeliver the message. + return subscription.ack(messages.map((message) => message.ackId)); + }); } // [END pubsub_pull_messages] @@ -201,83 +191,79 @@ function setSubscribeCounterValue (value) { // [START pubsub_pull_ordered_messages] const outstandingMessages = {}; -function pullOrderedMessages (subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function pullOrderedMessages (subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing subscription, e.g. "my-subscription" - const subscription = pubsubClient.subscription(subscriptionName); + const subscription = pubsub.subscription(subscriptionName); // Pulls messages. Set returnImmediately to false to block until messages are // received. - subscription.pull({ returnImmediately: true }, (err, messages) => { - if (err) { - callback(err); - return; - } - - // Pub/Sub messages are unordered, so here we manually order messages by - // their "counterId" attribute which was set when they were published. - messages.forEach((message) => { - outstandingMessages[message.attributes.counterId] = message; - }); - - const outstandingIds = Object.keys(outstandingMessages).map((counterId) => +counterId); - outstandingIds.sort(); - - outstandingIds.forEach((counterId) => { - const counter = getSubscribeCounterValue(); - const message = outstandingMessages[counterId]; - - if (counterId < counter) { - // The message has already been processed - subscription.ack(message.ackId); - delete outstandingMessages[counterId]; - } else if (counterId === counter) { - // Process the message - console.log(`* %d %j %j`, message.id, message.data, message.attributes); - - setSubscribeCounterValue(counterId + 1); - subscription.ack(message.ackId); - delete outstandingMessages[counterId]; - } else { - // Have not yet processed the message on which this message is dependent - return false; - } + return subscription.pull() + .then((results) => { + const messages = results[0]; + + // Pub/Sub messages are unordered, so here we manually order messages by + // their "counterId" attribute which was set when they were published. + messages.forEach((message) => { + outstandingMessages[message.attributes.counterId] = message; + }); + + const outstandingIds = Object.keys(outstandingMessages).map((counterId) => +counterId); + outstandingIds.sort(); + + outstandingIds.forEach((counterId) => { + const counter = getSubscribeCounterValue(); + const message = outstandingMessages[counterId]; + + if (counterId < counter) { + // The message has already been processed + subscription.ack(message.ackId); + delete outstandingMessages[counterId]; + } else if (counterId === counter) { + // Process the message + console.log(`* %d %j %j`, message.id, message.data, message.attributes); + + setSubscribeCounterValue(counterId + 1); + subscription.ack(message.ackId); + delete outstandingMessages[counterId]; + } else { + // Have not yet processed the message on which this message is dependent + return false; + } + }); }); - callback(); - }); } // [END pubsub_pull_ordered_messages] // [START pubsub_get_subscription_policy] -function getSubscriptionPolicy (subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function getSubscriptionPolicy (subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing subscription, e.g. "my-subscription" - const subscription = pubsubClient.subscription(subscriptionName); + const subscription = pubsub.subscription(subscriptionName); // Retrieves the IAM policy for the subscription - subscription.iam.getPolicy((err, policy) => { - if (err) { - callback(err); - return; - } + return subscription.iam.getPolicy() + .then((results) => { + const policy = results[0]; + + console.log(`Policy for subscription: %j.`, policy.bindings); - console.log(`Policy for subscription: %j.`, policy.bindings); - callback(); - }); + return policy; + }); } // [END pubsub_get_subscription_policy] // [START pubsub_set_subscription_policy] -function setSubscriptionPolicy (subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function setSubscriptionPolicy (subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing subscription, e.g. "my-subscription" - const subscription = pubsubClient.subscription(subscriptionName); + const subscription = pubsub.subscription(subscriptionName); // The new IAM policy const newPolicy = { @@ -296,25 +282,24 @@ function setSubscriptionPolicy (subscriptionName, callback) { }; // Updates the IAM policy for the subscription - subscription.iam.setPolicy(newPolicy, (err, updatedPolicy) => { - if (err) { - callback(err); - return; - } + return subscription.iam.setPolicy(newPolicy) + .then((results) => { + const updatedPolicy = results[0]; + + console.log(`Updated policy for subscription: %j`, updatedPolicy.bindings); - console.log(`Updated policy for subscription: %j`, updatedPolicy.bindings); - callback(); - }); + return updatedPolicy; + }); } // [END pubsub_set_subscription_policy] // [START pubsub_test_subscription_permissions] -function testSubscriptionPermissions (subscriptionName, callback) { - // Instantiates the client library - const pubsubClient = PubSub(); +function testSubscriptionPermissions (subscriptionName) { + // Instantiates a client + const pubsub = PubSub(); // References an existing subscription, e.g. "my-subscription" - const subscription = pubsubClient.subscription(subscriptionName); + const subscription = pubsub.subscription(subscriptionName); const permissionsToTest = [ `pubsub.subscriptions.consume`, @@ -322,87 +307,95 @@ function testSubscriptionPermissions (subscriptionName, callback) { ]; // Tests the IAM policy for the specified subscription - subscription.iam.testPermissions(permissionsToTest, (err, permissions) => { - if (err) { - callback(err); - return; - } + subscription.iam.testPermissions(permissionsToTest) + .then((results) => { + const permissions = results[0]; + + console.log(`Tested permissions for subscription: %j`, permissions); - console.log(`Tested permissions for subscription: %j`, permissions); - callback(); - }); + return permissions; + }); } // [END pubsub_test_subscription_permissions] -// The command-line program -const cli = require(`yargs`); -const makeHandler = require(`../utils`).makeHandler; - -const program = module.exports = { - listSubscriptions: listSubscriptions, - listTopicSubscriptions: listTopicSubscriptions, - createSubscription: createSubscription, - createPushSubscription: createPushSubscription, - deleteSubscription: deleteSubscription, - getSubscription: getSubscription, - pullMessages: pullMessages, - pullOrderedMessages: pullOrderedMessages, - getSubscriptionPolicy: getSubscriptionPolicy, - setSubscriptionPolicy: setSubscriptionPolicy, - testSubscriptionPermissions: testSubscriptionPermissions, - main: (args) => { - // Run the command-line program - cli.help().strict().parse(args).argv; - } -}; - -cli +module.exports = { pullOrderedMessages }; + +const cli = require(`yargs`) .demand(1) - .command(`list [topicName]`, `Lists all subscriptions in the current project, optionally filtering by a topic.`, {}, (options) => { - if (options.topicName) { - program.listTopicSubscriptions(options.topicName, makeHandler(false)); - } else { - program.listSubscriptions(makeHandler(false)); + .command( + `list [topicName]`, + `Lists all subscriptions in the current project, optionally filtering by a topic.`, + {}, + (opts) => { + if (opts.topicName) { + listTopicSubscriptions(opts.topicName); + } else { + listSubscriptions(); + } } - }) - .command(`create `, `Creates a new subscription.`, {}, (options) => { - program.createSubscription(options.topicName, options.subscriptionName, makeHandler(false)); - }) - .command(`create-push `, `Creates a new push subscription.`, {}, (options) => { - program.createPushSubscription(options.topicName, options.subscriptionName, makeHandler(false)); - }) - .command(`delete `, `Deletes a subscription.`, {}, (options) => { - program.deleteSubscription(options.subscriptionName, makeHandler(false)); - }) - .command(`get `, `Gets the metadata for a subscription.`, {}, (options) => { - program.getSubscription(options.subscriptionName, makeHandler(false)); - }) - .command(`pull `, `Pulls messages for a subscription.`, {}, (options) => { - program.pullMessages(options.subscriptionName, makeHandler(false)); - }) - .command(`get-policy `, `Gets the IAM policy for a subscription.`, {}, (options) => { - program.getSubscriptionPolicy(options.subscriptionName, makeHandler(false)); - }) - .command(`set-policy `, `Sets the IAM policy for a subscription.`, {}, (options) => { - program.setSubscriptionPolicy(options.subscriptionName, makeHandler(false)); - }) - .command(`test-permissions `, `Tests the permissions for a subscription.`, {}, (options) => { - program.testSubscriptionPermissions(options.subscriptionName, makeHandler(false)); - }) - .example(`node $0 list`, `Lists all subscriptions in the current project.`) - .example(`node $0 list greetings`, `Lists all subscriptions for a topic named "greetings".`) - .example(`node $0 create greetings greetings-worker-1`, `Creates a subscription named "greetings-worker-1" to a topic named "greetings".`) - .example(`node $0 create-push greetings greetings-worker-1`, `Creates a push subscription named "greetings-worker-1" to a topic named "greetings".`) - .example(`node $0 get greetings-worker-1`, `Gets the metadata for a subscription named "greetings-worker-1".`) - .example(`node $0 delete greetings-worker-1`, `Deletes a subscription named "greetings-worker-1".`) - .example(`node $0 pull greetings-worker-1`, `Pulls messages for a subscription named "greetings-worker-1".`) - .example(`node $0 get-policy greetings-worker-1`, `Gets the IAM policy for a subscription named "greetings-worker-1".`) - .example(`node $0 set-policy greetings-worker-1`, `Sets the IAM policy for a subscription named "greetings-worker-1".`) - .example(`node $0 test-permissions greetings-worker-1`, `Tests the permissions for a subscription named "greetings-worker-1".`) + ) + .command( + `create `, + `Creates a new subscription.`, + {}, + (opts) => createSubscription(opts.topicName, opts.subscriptionName) + ) + .command( + `create-push `, + `Creates a new push subscription.`, + {}, + (opts) => createPushSubscription(opts.topicName, opts.subscriptionName) + ) + .command( + `delete `, + `Deletes a subscription.`, + {}, + (opts) => deleteSubscription(opts.subscriptionName) + ) + .command( + `get `, + `Gets the metadata for a subscription.`, + {}, + (opts) => getSubscription(opts.subscriptionName) + ) + .command( + `pull `, + `Pulls messages for a subscription.`, + {}, + (opts) => pullMessages(opts.subscriptionName) + ) + .command( + `get-policy `, + `Gets the IAM policy for a subscription.`, + {}, + (opts) => getSubscriptionPolicy(opts.subscriptionName) + ) + .command( + `set-policy `, + `Sets the IAM policy for a subscription.`, + {}, + (opts) => setSubscriptionPolicy(opts.subscriptionName) + ) + .command( + `test-permissions `, + `Tests the permissions for a subscription.`, + {}, + (opts) => testSubscriptionPermissions(opts.subscriptionName) + ) + .example(`node $0 list`) + .example(`node $0 list my-topic`) + .example(`node $0 create my-topic worker-1`) + .example(`node $0 create-push my-topic worker-1`) + .example(`node $0 get worker-1`) + .example(`node $0 delete worker-1`) + .example(`node $0 pull worker-1`) + .example(`node $0 get-policy worker-1`) + .example(`node $0 set-policy worker-1`) + .example(`node $0 test-permissions worker-1`) .wrap(120) .recommendCommands() .epilogue(`For more information, see https://cloud.google.com/pubsub/docs`); if (module === require.main) { - program.main(process.argv.slice(2)); + cli.help().strict().argv; } diff --git a/pubsub/system-test/quickstart.test.js b/pubsub/system-test/quickstart.test.js index dffc6589ce1..29bb0d3f372 100644 --- a/pubsub/system-test/quickstart.test.js +++ b/pubsub/system-test/quickstart.test.js @@ -24,39 +24,32 @@ const projectId = process.env.GCLOUD_PROJECT; const fullTopicName = `projects/${projectId}/topics/${topicName}`; describe(`pubsub:quickstart`, () => { - let pubsubMock, PubSubMock; - - after((done) => { - pubsub.topic(topicName).delete(() => { - // Ignore any error, the topic might not have been created - done(); - }); - }); + after(() => pubsub.topic(topicName).delete().catch(() => {})); it(`should create a topic`, (done) => { const expectedTopicName = `my-new-topic`; - - pubsubMock = { - createTopic: (_topicName, _callback) => { + const pubsubMock = { + createTopic: (_topicName) => { assert.equal(_topicName, expectedTopicName); - assert.equal(typeof _callback, 'function'); - - pubsub.createTopic(topicName, (err, topic, apiResponse) => { - _callback(err, topic, apiResponse); - assert.ifError(err); - assert.notEqual(topic, undefined); - assert.equal(topic.name, fullTopicName); - assert.notEqual(apiResponse, undefined); - assert.equal(console.log.calledOnce, true); - assert.deepEqual(console.log.firstCall.args, [`Topic ${topic.name} created.`]); - done(); - }); + + return pubsub.createTopic(topicName) + .then((results) => { + const topic = results[0]; + assert.equal(topic.name, fullTopicName); + + setTimeout(() => { + assert.equal(console.log.callCount, 1); + assert.deepEqual(console.log.getCall(0).args, [`Topic ${topic.name} created.`]); + done(); + }, 200); + + return results; + }); } }; - PubSubMock = sinon.stub().returns(pubsubMock); proxyquire(`../quickstart`, { - '@google-cloud/pubsub': PubSubMock + '@google-cloud/pubsub': sinon.stub().returns(pubsubMock) }); }); }); diff --git a/pubsub/system-test/subscriptions.test.js b/pubsub/system-test/subscriptions.test.js index 4f3850f62b2..d530eb6ba80 100644 --- a/pubsub/system-test/subscriptions.test.js +++ b/pubsub/system-test/subscriptions.test.js @@ -15,7 +15,6 @@ 'use strict'; -const async = require(`async`); const pubsub = require(`@google-cloud/pubsub`)(); const uuid = require(`node-uuid`); const path = require(`path`); @@ -32,44 +31,33 @@ const fullSubscriptionNameTwo = `projects/${projectId}/subscriptions/${subscript const cmd = `node subscriptions.js`; describe(`pubsub:subscriptions`, () => { - before((done) => { - pubsub.createTopic(topicName, (err) => { - assert.ifError(err); - done(); - }); - }); + before(() => pubsub.createTopic(topicName)); - after((done) => { - pubsub.subscription(subscriptionNameOne).delete(() => { - // Ignore any error - pubsub.subscription(subscriptionNameTwo).delete(() => { - // Ignore any error - pubsub.topic(topicName).delete(() => { - // Ignore any error - done(); - }); - }); - }); + after(() => { + return pubsub.subscription(subscriptionNameOne).delete() + .then(() => pubsub.subscription(subscriptionNameTwo).delete(), () => {}) + .then(() => pubsub.topic(topicName).delete(), () => {}) + .catch(() => {}); }); - it(`should create a subscription`, (done) => { + it(`should create a subscription`, () => { const output = run(`${cmd} create ${topicName} ${subscriptionNameOne}`, cwd); assert.equal(output, `Subscription ${fullSubscriptionNameOne} created.`); - pubsub.subscription(subscriptionNameOne).exists((err, exists) => { - assert.ifError(err); - assert.equal(exists, true); - done(); - }); + return pubsub.subscription(subscriptionNameOne).exists() + .then((results) => { + const exists = results[0]; + assert.equal(exists, true); + }); }); - it(`should create a push subscription`, (done) => { + it(`should create a push subscription`, () => { const output = run(`${cmd} create-push ${topicName} ${subscriptionNameTwo}`, cwd); assert.equal(output, `Subscription ${fullSubscriptionNameTwo} created.`); - pubsub.subscription(subscriptionNameTwo).exists((err, exists) => { - assert.ifError(err); - assert.equal(exists, true); - done(); - }); + return pubsub.subscription(subscriptionNameTwo).exists() + .then((results) => { + const exists = results[0]; + assert.equal(exists, true); + }); }); it(`should get metadata for a subscription`, () => { @@ -85,117 +73,111 @@ describe(`pubsub:subscriptions`, () => { // Listing is eventually consistent. Give the indexes time to update. setTimeout(() => { const output = run(`${cmd} list`, cwd); - assert.notEqual(output.indexOf(`Subscriptions:`), -1); - assert.notEqual(output.indexOf(fullSubscriptionNameOne), -1); - assert.notEqual(output.indexOf(fullSubscriptionNameTwo), -1); + assert.equal(output.includes(`Subscriptions:`), true); + assert.equal(output.includes(fullSubscriptionNameOne), true); + assert.equal(output.includes(fullSubscriptionNameTwo), true); done(); }, 5000); }); - it(`should list subscriptions for a topic`, (done) => { - // Listing is eventually consistent. Give the indexes time to update. + it(`should list subscriptions for a topic`, () => { const output = run(`${cmd} list ${topicName}`, cwd); - assert.notEqual(output.indexOf(`Subscriptions for ${topicName}:`), -1); - assert.notEqual(output.indexOf(fullSubscriptionNameOne), -1); - assert.notEqual(output.indexOf(fullSubscriptionNameTwo), -1); - done(); + assert.equal(output.includes(`Subscriptions for ${topicName}:`), true); + assert.equal(output.includes(fullSubscriptionNameOne), true); + assert.equal(output.includes(fullSubscriptionNameTwo), true); }); - it(`should pull messages`, (done) => { + it(`should pull messages`, () => { const expected = `Hello, world!`; - pubsub.topic(topicName).publish({ data: expected }, (err, messageIds) => { - assert.ifError(err); - setTimeout(() => { + return pubsub.topic(topicName).publish(expected) + .then((results) => { + const messageIds = results[0]; const output = run(`${cmd} pull ${subscriptionNameOne}`, cwd); const expectedOutput = `Received ${messageIds.length} messages.\n` + `* ${messageIds[0]} "${expected}" {}`; assert.equal(output, expectedOutput); - done(); - }, 2000); - }); + }); }); - it(`should pull ordered messages`, (done) => { + it(`should pull ordered messages`, () => { const subscriptions = require('../subscriptions'); const expected = `Hello, world!`; const publishedMessageIds = []; - async.waterfall([ - (cb) => { - pubsub.topic(topicName).publish({ data: expected, attributes: { counterId: '3' } }, cb); - }, - (messageIds, apiResponse, cb) => { + return pubsub.topic(topicName).publish({ data: expected, attributes: { counterId: '3' } }, { raw: true }) + .then((results) => { + const messageIds = results[0]; publishedMessageIds.push(messageIds[0]); - setTimeout(() => subscriptions.pullOrderedMessages(subscriptionNameOne, cb), 2000); - }, - (cb) => { + return subscriptions.pullOrderedMessages(subscriptionNameOne); + }) + .then(() => { assert.equal(console.log.callCount, 0); - pubsub.topic(topicName).publish({ data: expected, attributes: { counterId: '1' } }, cb); - }, - (messageIds, apiResponse, cb) => { + return pubsub.topic(topicName).publish({ data: expected, attributes: { counterId: '1' } }, { raw: true }); + }) + .then((results) => { + const messageIds = results[0]; publishedMessageIds.push(messageIds[0]); - setTimeout(() => subscriptions.pullOrderedMessages(subscriptionNameOne, cb), 2000); - }, - (cb) => { + return subscriptions.pullOrderedMessages(subscriptionNameOne); + }) + .then(() => { assert.equal(console.log.callCount, 1); assert.deepEqual(console.log.firstCall.args, [`* %d %j %j`, publishedMessageIds[1], expected, { counterId: '1' }]); - pubsub.topic(topicName).publish({ data: expected, attributes: { counterId: '1' } }, cb); - }, - (messageIds, apiResponse, cb) => { - pubsub.topic(topicName).publish({ data: expected, attributes: { counterId: '2' } }, cb); - }, - (messageIds, apiResponse, cb) => { + return pubsub.topic(topicName).publish({ data: expected, attributes: { counterId: '1' } }, { raw: true }); + }) + .then((results) => { + return pubsub.topic(topicName).publish({ data: expected, attributes: { counterId: '2' } }, { raw: true }); + }) + .then((results) => { + const messageIds = results[0]; publishedMessageIds.push(messageIds[0]); - setTimeout(() => subscriptions.pullOrderedMessages(subscriptionNameOne, cb), 2000); - }, - (cb) => { + return subscriptions.pullOrderedMessages(subscriptionNameOne); + }) + .then(() => { assert.equal(console.log.callCount, 3); assert.deepEqual(console.log.secondCall.args, [`* %d %j %j`, publishedMessageIds[2], expected, { counterId: '2' }]); assert.deepEqual(console.log.thirdCall.args, [`* %d %j %j`, publishedMessageIds[0], expected, { counterId: '3' }]); - cb(); - } - ], done); + }); }); - it(`should set the IAM policy for a subscription`, (done) => { + it(`should set the IAM policy for a subscription`, () => { run(`${cmd} set-policy ${subscriptionNameOne}`, cwd); - pubsub.subscription(subscriptionNameOne).iam.getPolicy((err, policy) => { - assert.ifError(err); - assert.deepEqual(policy.bindings, [ - { - role: `roles/pubsub.editor`, - members: [`group:cloud-logs@google.com`] - }, - { - role: `roles/pubsub.viewer`, - members: [`allUsers`] - } - ]); - done(); - }); + return pubsub.subscription(subscriptionNameOne).iam.getPolicy() + .then((results) => { + const policy = results[0]; + assert.deepEqual(policy.bindings, [ + { + role: `roles/pubsub.editor`, + members: [`group:cloud-logs@google.com`] + }, + { + role: `roles/pubsub.viewer`, + members: [`allUsers`] + } + ]); + }); }); - it(`should get the IAM policy for a subscription`, (done) => { - pubsub.subscription(subscriptionNameOne).iam.getPolicy((err, policy) => { - assert.ifError(err); - const output = run(`${cmd} get-policy ${subscriptionNameOne}`, cwd); - assert.equal(output, `Policy for subscription: ${JSON.stringify(policy.bindings)}.`); - done(); - }); + it(`should get the IAM policy for a subscription`, () => { + pubsub.subscription(subscriptionNameOne).iam.getPolicy() + .then((results) => { + const policy = results[0]; + const output = run(`${cmd} get-policy ${subscriptionNameOne}`, cwd); + assert.equal(output, `Policy for subscription: ${JSON.stringify(policy.bindings)}.`); + }); }); it(`should test permissions for a subscription`, () => { const output = run(`${cmd} test-permissions ${subscriptionNameOne}`, cwd); - assert.notEqual(output.indexOf(`Tested permissions for subscription`), -1); + assert.equal(output.includes(`Tested permissions for subscription`), true); }); - it(`should delete a subscription`, (done) => { + it(`should delete a subscription`, () => { const output = run(`${cmd} delete ${subscriptionNameOne}`, cwd); assert.equal(output, `Subscription ${fullSubscriptionNameOne} deleted.`); - pubsub.subscription(subscriptionNameOne).exists((err, exists) => { - assert.ifError(err); - assert.equal(exists, false); - done(); - }); + return pubsub.subscription(subscriptionNameOne).exists() + .then((results) => { + const exists = results[0]; + assert.equal(exists, false); + }); }); }); diff --git a/pubsub/system-test/topics.test.js b/pubsub/system-test/topics.test.js index 92da7067dd0..5369427b34f 100644 --- a/pubsub/system-test/topics.test.js +++ b/pubsub/system-test/topics.test.js @@ -15,7 +15,6 @@ 'use strict'; -const async = require(`async`); const pubsub = require(`@google-cloud/pubsub`)(); const uuid = require(`node-uuid`); const path = require(`path`); @@ -30,138 +29,123 @@ const message = { data: `Hello, world!` }; const cmd = `node topics.js`; describe(`pubsub:topics`, () => { - after((done) => { - pubsub.subscription(subscriptionName).delete(() => { - // Ignore any error - pubsub.topic(topicName).delete(() => { - // Ignore any error - done(); - }); - }); + after(() => { + return pubsub.subscription(subscriptionName).delete() + .then(() => pubsub.topic(topicName).delete(), () => {}) + .catch(() => {}); }); - it(`should create a topic`, (done) => { + it(`should create a topic`, () => { const output = run(`${cmd} create ${topicName}`, cwd); assert.equal(output, `Topic ${fullTopicName} created.`); - pubsub.topic(topicName).exists((err, exists) => { - assert.ifError(err); - assert.equal(exists, true); - done(); - }); + return pubsub.topic(topicName).exists() + .then((results) => { + const exists = results[0]; + assert.equal(exists, true); + }); }); it(`should list topics`, (done) => { // Listing is eventually consistent. Give the indexes time to update. setTimeout(() => { const output = run(`${cmd} list`, cwd); - assert.notEqual(output.indexOf(`Topics:`), -1); - assert.notEqual(output.indexOf(fullTopicName), -1); + assert.equal(output.includes(`Topics:`), true); + assert.equal(output.includes(fullTopicName), true); done(); }, 5000); }); - it(`should publish a simple message`, (done) => { - async.waterfall([ - (cb) => { - pubsub.topic(topicName).subscribe(subscriptionName, cb); - }, - (subscription, apiResponse, cb) => { + it(`should publish a simple message`, () => { + return pubsub.topic(topicName).subscribe(subscriptionName) + .then((results) => { + const subscription = results[0]; run(`${cmd} publish ${topicName} "${message.data}"`, cwd); - setTimeout(() => subscription.pull(cb), 2000); - }, - (messages, apiResponse, cb) => { + return subscription.pull(); + }) + .then((results) => { + const messages = results[0]; assert.equal(messages[0].data, message.data); - cb(); - } - ], done); + }); }); - it(`should publish a JSON message`, (done) => { - async.waterfall([ - (cb) => { - pubsub.topic(topicName).subscribe(subscriptionName, { reuseExisting: true }, cb); - }, - (subscription, apiResponse, cb) => { + it(`should publish a JSON message`, () => { + return pubsub.topic(topicName).subscribe(subscriptionName, { reuseExisting: true }) + .then((results) => { + const subscription = results[0]; run(`${cmd} publish ${topicName} '${JSON.stringify(message)}'`, cwd); - setTimeout(() => subscription.pull(cb), 2000); - }, - (messages, apiResponse, cb) => { + return subscription.pull(); + }) + .then((results) => { + const messages = results[0]; assert.deepEqual(messages[0].data, message); - cb(); - } - ], done); + }); }); - it(`should publish ordered messages`, (done) => { - const topics = require('../topics'); + it(`should publish ordered messages`, () => { + const topics = require(`../topics`); let subscription; - async.waterfall([ - (cb) => { - pubsub.topic(topicName).subscribe(subscriptionName, { reuseExisting: true }, cb); - }, - (_subscription, apiResponse, cb) => { - subscription = _subscription; - topics.publishOrderedMessage(topicName, message.data, cb); - }, - (cb) => { - setTimeout(() => subscription.pull(cb), 2000); - }, - (messages, apiResponse, cb) => { + return pubsub.topic(topicName).subscribe(subscriptionName, { reuseExisting: true }) + .then((results) => { + subscription = results[0]; + return topics.publishOrderedMessage(topicName, message.data); + }) + .then(() => subscription.pull()) + .then((results) => { + const messages = results[0]; assert.equal(messages[0].data, message.data); assert.equal(messages[0].attributes.counterId, '1'); - topics.publishOrderedMessage(topicName, message.data, cb); - }, - (cb) => { - setTimeout(() => subscription.pull(cb), 2000); - }, - (messages, apiResponse, cb) => { + return topics.publishOrderedMessage(topicName, message.data); + }) + .then(() => subscription.pull()) + .then((results) => { + const messages = results[0]; assert.equal(messages[0].data, message.data); assert.equal(messages[0].attributes.counterId, '2'); - topics.publishOrderedMessage(topicName, message.data, cb); - } - ], done); + return topics.publishOrderedMessage(topicName, message.data); + }); }); - it(`should set the IAM policy for a topic`, (done) => { + it(`should set the IAM policy for a topic`, () => { run(`${cmd} set-policy ${topicName}`, cwd); - pubsub.topic(topicName).iam.getPolicy((err, policy) => { - assert.ifError(err); - assert.deepEqual(policy.bindings, [ - { - role: `roles/pubsub.editor`, - members: [`group:cloud-logs@google.com`] - }, - { - role: `roles/pubsub.viewer`, - members: [`allUsers`] - } - ]); - done(); - }); + + return pubsub.topic(topicName).iam.getPolicy() + .then((results) => { + const policy = results[0]; + assert.deepEqual(policy.bindings, [ + { + role: `roles/pubsub.editor`, + members: [`group:cloud-logs@google.com`] + }, + { + role: `roles/pubsub.viewer`, + members: [`allUsers`] + } + ]); + }); }); - it(`should get the IAM policy for a topic`, (done) => { - pubsub.topic(topicName).iam.getPolicy((err, policy) => { - assert.ifError(err); - const output = run(`${cmd} get-policy ${topicName}`, cwd); - assert.equal(output, `Policy for topic: ${JSON.stringify(policy.bindings)}.`); - done(); - }); + it(`should get the IAM policy for a topic`, () => { + return pubsub.topic(topicName).iam.getPolicy() + .then((results) => { + const policy = results[0]; + const output = run(`${cmd} get-policy ${topicName}`, cwd); + assert.equal(output, `Policy for topic: ${JSON.stringify(policy.bindings)}.`); + }); }); it(`should test permissions for a topic`, () => { const output = run(`${cmd} test-permissions ${topicName}`, cwd); - assert.notEqual(output.indexOf(`Tested permissions for topic`), -1); + assert.equal(output.includes(`Tested permissions for topic`), true); }); - it(`should delete a topic`, (done) => { + it(`should delete a topic`, () => { const output = run(`${cmd} delete ${topicName}`, cwd); assert.equal(output, `Topic ${fullTopicName} deleted.`); - pubsub.topic(topicName).exists((err, exists) => { - assert.ifError(err); - assert.equal(exists, false); - done(); - }); + return pubsub.topic(topicName).exists() + .then((results) => { + const exists = results[0]; + assert.equal(exists, false); + }); }); }); diff --git a/pubsub/test/quickstart.test.js b/pubsub/test/quickstart.test.js deleted file mode 100644 index 45c9dec7ccc..00000000000 --- a/pubsub/test/quickstart.test.js +++ /dev/null @@ -1,44 +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`).noCallThru(); - -describe(`pubsub:quickstart`, () => { - let pubsubMock, PubSubMock; - const error = new Error(`error`); - const expectedTopicName = `my-new-topic`; - - before(() => { - pubsubMock = { - createTopic: sinon.stub().yields(error) - }; - PubSubMock = sinon.stub().returns(pubsubMock); - }); - - it(`should handle error`, () => { - proxyquire(`../quickstart`, { - '@google-cloud/pubsub': PubSubMock - }); - - assert.equal(PubSubMock.calledOnce, true); - assert.deepEqual(PubSubMock.firstCall.args, [{ projectId: 'YOUR_PROJECT_ID' }]); - assert.equal(pubsubMock.createTopic.calledOnce, true); - assert.deepEqual(pubsubMock.createTopic.firstCall.args.slice(0, -1), [expectedTopicName]); - assert.equal(console.error.calledOnce, true); - assert.deepEqual(console.error.firstCall.args, [error]); - }); -}); diff --git a/pubsub/test/subscriptions.test.js b/pubsub/test/subscriptions.test.js deleted file mode 100644 index 281e7f15d88..00000000000 --- a/pubsub/test/subscriptions.test.js +++ /dev/null @@ -1,65 +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').noCallThru(); - -describe(`pubsub:subscriptions`, () => { - it(`should handle errors`, () => { - const topicName = `foo`; - const subscriptionName = `bar`; - const error = new Error(`error`); - const callback = sinon.spy(); - const subscriptionMock = { - delete: sinon.stub().yields(error), - getMetadata: sinon.stub().yields(error), - pull: sinon.stub().yields(error), - iam: { - getPolicy: sinon.stub().yields(error), - setPolicy: sinon.stub().yields(error), - testPermissions: sinon.stub().yields(error) - } - }; - const topicMock = { - subscribe: sinon.stub().yields(error), - getSubscriptions: sinon.stub().yields(error) - }; - const pubsubMock = { - topic: sinon.stub().returns(topicMock), - subscription: sinon.stub().returns(subscriptionMock), - getSubscriptions: sinon.stub().yields(error) - }; - const PubSubMock = sinon.stub().returns(pubsubMock); - const program = proxyquire(`../subscriptions`, { - '@google-cloud/pubsub': PubSubMock - }); - - program.createSubscription(topicName, subscriptionName, callback); - program.createPushSubscription(topicName, subscriptionName, callback); - program.deleteSubscription(subscriptionName, callback); - program.getSubscription(subscriptionName, callback); - program.listSubscriptions(callback); - program.listTopicSubscriptions(topicName, callback); - program.pullMessages(subscriptionName, callback); - program.pullOrderedMessages(subscriptionName, callback); - program.getSubscriptionPolicy(subscriptionName, callback); - program.setSubscriptionPolicy(subscriptionName, callback); - program.testSubscriptionPermissions(subscriptionName, callback); - - assert.equal(callback.callCount, 11); - assert.equal(callback.alwaysCalledWithExactly(error), true); - }); -}); diff --git a/pubsub/test/topics.test.js b/pubsub/test/topics.test.js deleted file mode 100644 index 72539ff0a7e..00000000000 --- a/pubsub/test/topics.test.js +++ /dev/null @@ -1,56 +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`).noCallThru(); - -describe(`pubsub:topics`, () => { - it(`should handle errors`, () => { - const topicName = `foo`; - const error = new Error(`error`); - const callback = sinon.spy(); - const topicMock = { - publish: sinon.stub().yields(error), - delete: sinon.stub().yields(error), - iam: { - getPolicy: sinon.stub().yields(error), - setPolicy: sinon.stub().yields(error), - testPermissions: sinon.stub().yields(error) - } - }; - const pubsubMock = { - topic: sinon.stub().returns(topicMock), - getTopics: sinon.stub().yields(error), - createTopic: sinon.stub().yields(error) - }; - const PubSubMock = sinon.stub().returns(pubsubMock); - const program = proxyquire(`../topics`, { - '@google-cloud/pubsub': PubSubMock - }); - - program.createTopic(topicName, callback); - program.deleteTopic(topicName, callback); - program.publishMessage(topicName, {}, callback); - program.publishOrderedMessage(topicName, {}, callback); - program.listTopics(callback); - program.getTopicPolicy(topicName, callback); - program.setTopicPolicy(topicName, callback); - program.testTopicPermissions(topicName, callback); - - assert.equal(callback.callCount, 8); - assert.equal(callback.alwaysCalledWithExactly(error), true); - }); -}); diff --git a/pubsub/topics.js b/pubsub/topics.js index b6c19702356..43d1a14b8af 100644 --- a/pubsub/topics.js +++ b/pubsub/topics.js @@ -26,94 +26,73 @@ const PubSub = require(`@google-cloud/pubsub`); // [START pubsub_list_topics] -function listTopics (callback) { +function listTopics () { // Instantiates a client - const pubsubClient = PubSub(); + const pubsub = PubSub(); // Lists all topics in the current project - pubsubClient.getTopics((err, topics) => { - if (err) { - callback(err); - return; - } + return pubsub.getTopics() + .then((results) => { + const topics = results[0]; + + console.log('Topics:'); + topics.forEach((topic) => console.log(topic.name)); - console.log('Topics:'); - topics.forEach((topic) => console.log(topic.name)); - callback(); - }); + return topics; + }); } // [END pubsub_list_topics] // [START pubsub_create_topic] -function createTopic (topicName, callback) { +function createTopic (topicName) { // Instantiates a client - const pubsubClient = PubSub(); + const pubsub = PubSub(); // Creates a new topic, e.g. "my-new-topic" - pubsubClient.createTopic(topicName, (err, topic) => { - if (err) { - callback(err); - return; - } + return pubsub.createTopic(topicName) + .then((results) => { + const topic = results[0]; - console.log(`Topic ${topic.name} created.`); - callback(); - }); + console.log(`Topic ${topic.name} created.`); + + return topic; + }); } // [END pubsub_create_topic] // [START pubsub_delete_topic] -function deleteTopic (topicName, callback) { +function deleteTopic (topicName) { // Instantiates a client - const pubsubClient = PubSub(); + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); + const topic = pubsub.topic(topicName); // Deletes the topic - topic.delete((err) => { - if (err) { - callback(err); - return; - } - - console.log(`Topic ${topic.name} deleted.`); - callback(); - }); + return topic.delete() + .then(() => { + console.log(`Topic ${topic.name} deleted.`); + }); } // [END pubsub_delete_topic] // [START pubsub_publish_message] -function publishMessage (topicName, data, callback) { +function publishMessage (topicName, data) { // Instantiates a client - const pubsubClient = PubSub(); + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); - - /** - * In Node.js, a PubSub message requires a "data" property, which can have a - * string or an object as its value. An optional "attributes" property can be - * an object of key/value pairs, where the keys and values are both strings. - * See https://cloud.google.com/pubsub/reference/rpc/google.pubsub.v1#google.pubsub.v1.PubsubMessage - * - * Topic#publish() takes either a single message object or an array of message - * objects. See https://googlecloudplatform.github.io/google-cloud-node/#/docs/pubsub/latest/pubsub/topic?method=publish - */ - const message = { - data: data - }; + const topic = pubsub.topic(topicName); - // Publishes the message - topic.publish(message, (err, messageIds) => { - if (err) { - callback(err); - return; - } + // Publishes the message, e.g. "Hello, world!" or { amount: 599.00, status: 'pending' } + return topic.publish(data) + .then((results) => { + const messageIds = results[0]; - console.log(`Message ${messageIds[0]} published.`); - callback(); - }); + console.log(`Message ${messageIds[0]} published.`); + + return messageIds; + }); } // [END pubsub_publish_message] @@ -128,75 +107,65 @@ function setPublishCounterValue (value) { } // [START pubsub_publish_ordered_message] -function publishOrderedMessage (topicName, data, callback) { +function publishOrderedMessage (topicName, data) { // Instantiates a client - const pubsubClient = PubSub(); + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); - - /** - * In Node.js, a PubSub message requires a "data" property, which can have a - * string or an object as its value. An optional "attributes" property can be - * an object of key/value pairs, where the keys and values are both strings. - * See https://cloud.google.com/pubsub/reference/rpc/google.pubsub.v1#google.pubsub.v1.PubsubMessage - * - * Topic#publish() takes either a single message object or an array of message - * objects. See https://googlecloudplatform.github.io/google-cloud-node/#/docs/pubsub/latest/pubsub/topic?method=publish - */ + const topic = pubsub.topic(topicName); + const message = { data: data, // Pub/Sub messages are unordered, so assign an order id to the message to // manually order messages attributes: { - counterId: '' + getPublishCounterValue() + counterId: `${getPublishCounterValue()}` } }; - topic.publish(message, (err, messageIds) => { - if (err) { - callback(err); - return; - } + // Publishes the message, use raw: true to pass a message with attributes + return topic.publish(message, { raw: true }) + .then((results) => { + const messageIds = results[0]; + + // Update the counter value + setPublishCounterValue(+message.attributes.counterId + 1); - // Update the counter value - setPublishCounterValue(+message.attributes.counterId + 1); + console.log(`Message ${messageIds[0]} published.`); - console.log(`Message ${messageIds[0]} published.`); - callback(); - }); + return messageIds; + }); } // [END pubsub_publish_ordered_message] // [START pubsub_get_topic_policy] -function getTopicPolicy (topicName, callback) { +function getTopicPolicy (topicName) { // Instantiates a client - const pubsubClient = PubSub(); + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); + const topic = pubsub.topic(topicName); // Retrieves the IAM policy for the topic - topic.iam.getPolicy((err, policy) => { - if (err) { - callback(err); - return; - } + return topic.iam.getPolicy() + .then((results) => { + const policy = results[0]; - console.log(`Policy for topic: %j.`, policy.bindings); - callback(); - }); + console.log(`Policy for topic: %j.`, policy.bindings); + + return policy; + }); } // [END pubsub_get_topic_policy] // [START pubsub_set_topic_policy] -function setTopicPolicy (topicName, callback) { +function setTopicPolicy (topicName) { // Instantiates a client - const pubsubClient = PubSub(); + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); + const topic = pubsub.topic(topicName); // The new IAM policy const newPolicy = { @@ -215,25 +184,24 @@ function setTopicPolicy (topicName, callback) { }; // Updates the IAM policy for the topic - topic.iam.setPolicy(newPolicy, (err, updatedPolicy) => { - if (err) { - callback(err); - return; - } + return topic.iam.setPolicy(newPolicy) + .then((results) => { + const updatedPolicy = results[0]; + + console.log(`Updated policy for topic: %j`, updatedPolicy.bindings); - console.log(`Updated policy for topic: %j`, updatedPolicy.bindings); - callback(); - }); + return updatedPolicy; + }); } // [END pubsub_set_topic_policy] // [START pubsub_test_topic_permissions] -function testTopicPermissions (topicName, callback) { +function testTopicPermissions (topicName) { // Instantiates a client - const pubsubClient = PubSub(); + const pubsub = PubSub(); // References an existing topic, e.g. "my-topic" - const topic = pubsubClient.topic(topicName); + const topic = pubsub.topic(topicName); const permissionsToTest = [ `pubsub.topics.attachSubscription`, @@ -242,78 +210,95 @@ function testTopicPermissions (topicName, callback) { ]; // Tests the IAM policy for the specified topic - topic.iam.testPermissions(permissionsToTest, (err, permissions) => { - if (err) { - callback(err); - return; - } + return topic.iam.testPermissions(permissionsToTest) + .then((results) => { + const permissions = results[0]; - console.log(`Tested permissions for topic: %j`, permissions); + console.log(`Tested permissions for topic: %j`, permissions); - callback(); - }); + return permissions; + }); } // [END pubsub_test_topic_permissions] -// The command-line program -const cli = require(`yargs`); -const noop = require(`../utils`).noop; - -const program = module.exports = { - listTopics: listTopics, - createTopic: createTopic, - deleteTopic: deleteTopic, - publishMessage: publishMessage, - publishOrderedMessage: publishOrderedMessage, - getTopicPolicy: getTopicPolicy, - setTopicPolicy: setTopicPolicy, - testTopicPermissions: testTopicPermissions, - main: (args) => { - // Run the command-line program - cli.help().strict().parse(args).argv; - } -}; - -cli +module.exports = { publishOrderedMessage }; + +const cli = require(`yargs`) .demand(1) - .command(`list`, `Lists all topics in the current project.`, {}, (options) => { - program.listTopics(noop); - }) - .command(`create `, `Creates a new topic.`, {}, (options) => { - program.createTopic(options.topicName, noop); - }) - .command(`delete `, `Deletes a topic.`, {}, (options) => { - program.deleteTopic(options.topicName, noop); - }) - .command(`publish `, `Publishes a message.`, {}, (options) => { - try { - options.message = JSON.parse(options.message); - } catch (err) { - // Ignore error + .command( + `list`, + `Lists all topics in the current project.`, + {}, + listTopics + ) + .command( + `create `, + `Creates a new topic.`, + {}, + (opts) => createTopic(opts.topicName) + ) + .command( + `delete `, + `Deletes a topic.`, + {}, + (opts) => deleteTopic(opts.topicName) + ) + .command( + `publish `, + `Publishes a message to a topic.`, + {}, + (opts) => { + try { + opts.message = JSON.parse(opts.message); + } catch (err) { + // Ignore error + } + publishMessage(opts.topicName, opts.message); + } + ) + .command( + `publish-ordered `, + `Publishes an ordered message to a topic.`, + {}, + (opts) => { + try { + opts.message = JSON.parse(opts.message); + } catch (err) { + // Ignore error + } + publishOrderedMessage(opts.topicName, opts.message); } - program.publishMessage(options.topicName, options.message, noop); - }) - .command(`get-policy `, `Gets the IAM policy for a topic.`, {}, (options) => { - program.getTopicPolicy(options.topicName, noop); - }) - .command(`set-policy `, `Sets the IAM policy for a topic.`, {}, (options) => { - program.setTopicPolicy(options.topicName, noop); - }) - .command(`test-permissions `, `Tests the permissions for a topic.`, {}, (options) => { - program.testTopicPermissions(options.topicName, noop); - }) - .example(`node $0 list`, `Lists all topics in the current project.`) - .example(`node $0 create greetings`, `Creates a new topic named "greetings".`) - .example(`node $0 delete greetings`, `Deletes a topic named "greetings".`) - .example(`node $0 publish greetings "Hello, world!"`, `Publishes a simple message.`) - .example(`node $0 publish greetings \`{"data":"Hello, world!"}\``, `Publishes a JSON message.`) - .example(`node $0 get-policy greetings`, `Gets the IAM policy for a topic named "greetings".`) - .example(`node $0 set-policy greetings`, `Sets the IAM policy for a topic named "greetings".`) - .example(`node $0 test-permissions greetings`, `Tests the permissions for a topic named "greetings".`) + ) + .command( + `get-policy `, + `Gets the IAM policy for a topic.`, + {}, + (opts) => getTopicPolicy(opts.topicName) + ) + .command( + `set-policy `, + `Sets the IAM policy for a topic.`, + {}, + (opts) => setTopicPolicy(opts.topicName) + ) + .command( + `test-permissions `, + `Tests the permissions for a topic.`, + {}, + (opts) => testTopicPermissions(opts.topicName) + ) + .example(`node $0 list`) + .example(`node $0 create my-topic`) + .example(`node $0 delete my-topic`) + .example(`node $0 publish my-topic "Hello, world!"`) + .example(`node $0 publish my-topic '{"data":"Hello, world!"}'`) + .example(`node $0 get-policy greetings`) + .example(`node $0 set-policy greetings`) + .example(`node $0 test-permissions greetings`) .wrap(120) .recommendCommands() .epilogue(`For more information, see https://cloud.google.com/pubsub/docs`); if (module === require.main) { - program.main(process.argv.slice(2)); + cli.help().strict().argv; } diff --git a/trace/package.json b/trace/package.json index c9f3b34a734..88b585f1a8f 100644 --- a/trace/package.json +++ b/trace/package.json @@ -9,7 +9,7 @@ }, "scripts": { "start": "node app.js", - "test": "cd ..; npm run t -- trace/test/*.test.js", + "test": "cd ..; npm run t -- trace/test/*.test.js" }, "dependencies": { "@google/cloud-trace": "0.5.10",