Skip to content

Commit 3607c6b

Browse files
authored
Switch to yargs. (#189)
1 parent 300bd5c commit 3607c6b

30 files changed

+566
-438
lines changed

bigquery/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ analytics data warehouse.
1313
* [Samples](#samples)
1414
* [Create A Simple Application With the API](#create-a-simple-application-with-the-api)
1515
* [Datasets](#datasets)
16+
* [Queries](#queries)
1617
* [Tables](#tables)
1718

1819
## Setup
@@ -72,6 +73,32 @@ For more information, see https://cloud.google.com/bigquery/docs
7273
[datasets_docs]: https://cloud.google.com/bigquery/docs
7374
[datasets_code]: datasets.js
7475

76+
### Queries
77+
78+
View the [documentation][queries_docs] or the [source code][queries_code].
79+
80+
__Usage:__ `node queries --help`
81+
82+
```
83+
Commands:
84+
sync <query> Run a synchronous query.
85+
async <query> Start an asynchronous query.
86+
poll <jobId> Get the status of a job.
87+
88+
Options:
89+
--help Show help [boolean]
90+
91+
Examples:
92+
node queries sync "SELECT * FROM publicdata:samples.natality LIMIT 5;"
93+
node queries async "SELECT * FROM publicdata:samples.natality LIMIT 5;"
94+
node queries poll 12345
95+
96+
For more information, see https://cloud.google.com/bigquery/docs
97+
```
98+
99+
[queries_docs]: https://cloud.google.com/bigquery/docs
100+
[queries_code]: queries.js
101+
75102
### Tables
76103

77104
View the [documentation][tables_docs] or the [source code][tables_code].

bigquery/query.js renamed to bigquery/queries.js

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// See the License for the specific language governing permissions and
1212
// limitations under the License.
1313

14-
// [START complete]
14+
// [START all]
1515
/**
1616
* Command-line application to perform an synchronous query in BigQuery.
1717
*
@@ -127,51 +127,41 @@ function asyncPoll (jobId, callback) {
127127
});
128128
}
129129
// [END async_query]
130+
// [END all]
130131

131-
// [START usage]
132-
function printUsage () {
133-
console.log('Usage:');
134-
console.log('\nCommands:\n');
135-
console.log('\tnode query sync QUERY');
136-
console.log('\tnode query async QUERY');
137-
console.log('\tnode query poll JOB_ID');
138-
console.log('\nExamples:\n');
139-
console.log('\tnode query sync "SELECT * FROM publicdata:samples.natality LIMIT 5;"');
140-
console.log('\tnode query async "SELECT * FROM publicdata:samples.natality LIMIT 5;"');
141-
console.log('\tnode query poll 12345');
142-
}
143-
// [END usage]
144-
145-
// The command-line program:
146-
var program = {
147-
// Print usage instructions.
148-
printUsage: printUsage,
132+
// The command-line program
133+
var cli = require('yargs');
134+
var makeHandler = require('../utils').makeHandler;
149135

150-
// Exports
136+
var program = module.exports = {
151137
asyncQuery: asyncQuery,
152138
asyncPoll: asyncPoll,
153139
syncQuery: syncQuery,
154140
bigquery: bigquery,
155-
156-
// Run the sample.
157-
main: function (args, cb) {
158-
var command = args.shift();
159-
var arg = args.shift();
160-
if (command === 'sync') {
161-
this.syncQuery(arg, cb);
162-
} else if (command === 'async') {
163-
this.asyncQuery(arg, cb);
164-
} else if (command === 'poll') {
165-
this.asyncPoll(arg, cb);
166-
} else {
167-
this.printUsage();
168-
}
141+
main: function (args) {
142+
// Run the command-line program
143+
cli.help().strict().parse(args).argv;
169144
}
170145
};
171146

147+
cli
148+
.demand(1)
149+
.command('sync <query>', 'Run a synchronous query.', {}, function (options) {
150+
program.syncQuery(options.query, makeHandler());
151+
})
152+
.command('async <query>', 'Start an asynchronous query.', {}, function (options) {
153+
program.asyncQuery(options.query, makeHandler());
154+
})
155+
.command('poll <jobId>', 'Get the status of a job.', {}, function (options) {
156+
program.asyncPoll(options.jobId, makeHandler());
157+
})
158+
.example('node $0 sync "SELECT * FROM publicdata:samples.natality LIMIT 5;"')
159+
.example('node $0 async "SELECT * FROM publicdata:samples.natality LIMIT 5;"')
160+
.example('node $0 poll 12345')
161+
.wrap(80)
162+
.recommendCommands()
163+
.epilogue('For more information, see https://cloud.google.com/bigquery/docs');
164+
172165
if (module === require.main) {
173-
program.main(process.argv.slice(2), console.log);
166+
program.main(process.argv.slice(2));
174167
}
175-
// [END complete]
176-
177-
module.exports = program;

bigquery/system-test/query.test.js renamed to bigquery/system-test/queries.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
'use strict';
1515

16-
var example = require('../query');
16+
var example = require('../queries');
1717

1818
describe('bigquery:query', function () {
1919
describe('sync_query', function () {

bigquery/test/query.test.js renamed to bigquery/test/queries.test.js

Lines changed: 29 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function getSample () {
4343
var BigQueryMock = sinon.stub().returns(bigqueryMock);
4444

4545
return {
46-
program: proxyquire('../query', {
46+
program: proxyquire('../queries', {
4747
'@google-cloud/bigquery': BigQueryMock
4848
}),
4949
mocks: {
@@ -58,49 +58,6 @@ function getSample () {
5858
}
5959

6060
describe('bigquery:query', function () {
61-
describe('main', function () {
62-
it('should show usage based on arguments', function () {
63-
var program = getSample().program;
64-
sinon.stub(program, 'printUsage');
65-
66-
program.main([]);
67-
assert(program.printUsage.calledOnce);
68-
69-
program.main(['-h']);
70-
assert(program.printUsage.calledTwice);
71-
72-
program.main(['--help']);
73-
assert(program.printUsage.calledThrice);
74-
});
75-
76-
it('should run the correct commands', function () {
77-
var program = getSample().program;
78-
sinon.stub(program, 'syncQuery');
79-
sinon.stub(program, 'asyncQuery');
80-
sinon.stub(program, 'asyncPoll');
81-
82-
program.main(['sync']);
83-
assert(program.syncQuery.calledOnce);
84-
85-
program.main(['async']);
86-
assert(program.asyncQuery.calledOnce);
87-
88-
program.main(['poll']);
89-
assert(program.asyncPoll.calledOnce);
90-
});
91-
92-
it('should execute queries', function () {
93-
var example = getSample();
94-
sinon.stub(example.program, 'syncQuery');
95-
96-
example.program.main(['foo'], function (err, data) {
97-
assert.ifError(err);
98-
assert(example.program.syncQuery.calledWith({ query: 'foo' }));
99-
assert.deepEqual(data, example.mocks.natality);
100-
});
101-
});
102-
});
103-
10461
describe('syncQuery', function () {
10562
var query = 'foo';
10663

@@ -246,19 +203,35 @@ describe('bigquery:query', function () {
246203
});
247204
});
248205

249-
describe('printUsage', function () {
250-
it('should print usage', function () {
206+
describe('main', function () {
207+
var query = 'foo';
208+
var jobId = 'foo';
209+
210+
it('should call syncQuery', function () {
251211
var program = getSample().program;
252-
program.printUsage();
253-
assert(console.log.calledWith('Usage:'));
254-
assert(console.log.calledWith('\nCommands:\n'));
255-
assert(console.log.calledWith('\tnode query sync QUERY'));
256-
assert(console.log.calledWith('\tnode query async QUERY'));
257-
assert(console.log.calledWith('\tnode query poll JOB_ID'));
258-
assert(console.log.calledWith('\nExamples:\n'));
259-
assert(console.log.calledWith('\tnode query sync "SELECT * FROM publicdata:samples.natality LIMIT 5;"'));
260-
assert(console.log.calledWith('\tnode query async "SELECT * FROM publicdata:samples.natality LIMIT 5;"'));
261-
assert(console.log.calledWith('\tnode query poll 12345'));
212+
213+
sinon.stub(program, 'syncQuery');
214+
program.main(['sync', query]);
215+
assert.equal(program.syncQuery.calledOnce, true);
216+
assert.deepEqual(program.syncQuery.firstCall.args.slice(0, -1), [query]);
217+
});
218+
219+
it('should call asyncQuery', function () {
220+
var program = getSample().program;
221+
222+
sinon.stub(program, 'asyncQuery');
223+
program.main(['async', query]);
224+
assert.equal(program.asyncQuery.calledOnce, true);
225+
assert.deepEqual(program.asyncQuery.firstCall.args.slice(0, -1), [query]);
226+
});
227+
228+
it('should call asyncPoll', function () {
229+
var program = getSample().program;
230+
231+
sinon.stub(program, 'asyncPoll');
232+
program.main(['poll', jobId]);
233+
assert.equal(program.asyncPoll.calledOnce, true);
234+
assert.deepEqual(program.asyncPoll.firstCall.args.slice(0, -1), [jobId]);
262235
});
263236
});
264237
});

logging/logs.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ function deleteLog (name, callback) {
116116

117117
// The command-line program
118118
var cli = require('yargs');
119+
var utils = require('../utils');
119120

120121
var program = module.exports = {
121122
listLogEntries: listLogEntries,
@@ -129,7 +130,7 @@ var program = module.exports = {
129130

130131
cli
131132
.demand(1)
132-
.command('list', 'List log entries in the authenticated project.', {
133+
.command('list', 'List log entries.', {
133134
filter: {
134135
alias: 'f',
135136
type: 'string',
@@ -149,7 +150,7 @@ cli
149150
description: 'Sort results.'
150151
}
151152
}, function (options) {
152-
program.listLogEntries(options, console.log);
153+
program.listLogEntries(utils.pick(options, ['filter', 'limit', 'sort']), utils.makeHandler());
153154
})
154155
.command('write <name> <resource> <entry>', 'Write a log entry.', {}, function (options) {
155156
try {
@@ -162,12 +163,12 @@ cli
162163
} catch (err) {
163164
return console.error('"entry" must be a valid JSON string!');
164165
}
165-
program.writeLogEntry(options, console.log);
166+
program.writeLogEntry(utils.pick(options, ['name', 'resource', 'entry']), utils.makeHandler());
166167
})
167168
.command('delete <name>', 'Delete a Log.', {}, function (options) {
168-
program.deleteLog(options.name, console.log);
169+
program.deleteLog(options.name, utils.makeHandler(false));
169170
})
170-
.example('node $0 list', 'List all log entires.')
171+
.example('node $0 list', 'List all log entries.')
171172
.example('node $0 list -f "severity = ERROR" -s "timestamp" -l 2', 'List up to 2 error entries, sorted by timestamp ascending.')
172173
.example('node $0 write my-log \'{"type":"gae_app","labels":{"module_id":"default"}}\' \'{"message":"Hello World!"}\'', 'Write a log entry.')
173174
.example('node $0 delete my-log', 'Delete "my-log".')

logging/sinks.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ function deleteSink (name, callback) {
150150

151151
// The command-line program
152152
var cli = require('yargs');
153+
var utils = require('../utils');
153154

154155
var program = module.exports = {
155156
createSink: createSink,
@@ -181,24 +182,24 @@ cli
181182
description: 'The type of destination.'
182183
}
183184
}, function (options) {
184-
program.createSink(options, console.log);
185+
program.createSink(utils.pick(options, ['name', 'destination', 'filter', 'type']), utils.makeHandler(false));
185186
})
186187
.command('get <name>', 'Get the metadata for the specified sink.', {}, function (options) {
187-
program.getSinkMetadata(options.name, console.log);
188+
program.getSinkMetadata(options.name, utils.makeHandler());
188189
})
189190
.command('list', 'List all sinks in the authenticated project.', {}, function () {
190-
program.listSinks(console.log);
191+
program.listSinks(utils.makeHandler(true, 'id'));
191192
})
192193
.command('update <name> <metadata>', 'Update the metadata for the specified sink.', {}, function (options) {
193194
try {
194195
options.metadata = JSON.parse(options.metadata);
195196
} catch (err) {
196197
return console.error('"metadata" must be a valid JSON string!');
197198
}
198-
program.updateSink(options, console.log);
199+
program.updateSink(utils.pick(options, ['name', 'metadata']), utils.makeHandler(false));
199200
})
200201
.command('delete <name>', 'Delete the specified sink.', {}, function (options) {
201-
program.deleteSink(options.name, console.log);
202+
program.deleteSink(options.name, utils.makeHandler(false));
202203
})
203204
.example('node $0 create my-sink my-bucket --type bucket', 'Create a new sink named "my-sink" that exports logs to a Cloud Storage bucket.')
204205
.example('node $0 create my-sink my-dataset --type dataset', 'Create a new sink named "my-sink" that exports logs to a BigQuery dataset.')

logging/test/logs.test.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,25 @@ describe('logging:entries', function () {
157157

158158
sinon.stub(program, 'listLogEntries');
159159
program.main(['list', '-f', '"' + filter + '"', '-l', 1, '-s', 'field']);
160-
assert(program.listLogEntries.calledOnce);
160+
assert.equal(program.listLogEntries.calledOnce, true);
161+
assert.deepEqual(program.listLogEntries.firstCall.args.slice(0, -1), [{
162+
filter: '"' + filter + '"',
163+
limit: 1,
164+
sort: 'field'
165+
}]);
161166
});
162167

163168
it('should call writeLogEntry', function () {
164169
var program = getSample().program;
165170

166171
sinon.stub(program, 'writeLogEntry');
167172
program.main(['write', logName, '{}', '{}']);
168-
assert.equal(program.writeLogEntry.callCount, 1);
173+
assert.equal(program.writeLogEntry.calledOnce, true);
174+
assert.deepEqual(program.writeLogEntry.firstCall.args.slice(0, -1), [{
175+
name: logName,
176+
resource: {},
177+
entry: {}
178+
}]);
169179
});
170180

171181
it('should validate args and call writeLogEntry', function () {
@@ -174,16 +184,18 @@ describe('logging:entries', function () {
174184
sinon.stub(program, 'writeLogEntry');
175185
program.main(['write', logName, '"{"invalid', '"{"invalid']);
176186
assert.equal(program.writeLogEntry.called, false, 'writeLogEntry should not have been called');
177-
assert(console.error.calledWith('"resource" must be a valid JSON string!'));
178-
assert(console.error.calledWith('"entry" must be a valid JSON string!'));
187+
assert.equal(console.error.calledTwice, true);
188+
assert.deepEqual(console.error.firstCall.args, ['"resource" must be a valid JSON string!']);
189+
assert.deepEqual(console.error.secondCall.args, ['"entry" must be a valid JSON string!']);
179190
});
180191

181192
it('should call deleteLog', function () {
182193
var program = getSample().program;
183194

184195
sinon.stub(program, 'deleteLog');
185196
program.main(['delete', logName]);
186-
assert(program.deleteLog.calledOnce);
197+
assert.equal(program.deleteLog.calledOnce, true);
198+
assert.deepEqual(program.deleteLog.firstCall.args.slice(0, -1), [logName]);
187199
});
188200
});
189201
});

0 commit comments

Comments
 (0)