UNPKG

6.13 kBJavaScriptView Raw
1const yargs = require('yargs');
2
3const logger = require('./lib/logger');
4const { parseTimeString } = require('./lib/timeUtil');
5const { deployHandler, createHandler, invokeHandler, listHandler,
6 logsHandler, loginHandler, removeHandler, perfHandler } = require('./lib');
7
8/**
9 * Prints the provided message(along with optionally displayed help)
10 * and then exits the process with a code of 1.
11 *
12 * @param message - string to print before exiting
13 * @param displayHelp - should help be displayed before your error?
14 */
15const msgAndExit = function msgAndExit(message, displayHelp) {
16 if (displayHelp) yargs.showHelp();
17 logger.error(message);
18 process.exit(1);
19};
20
21const handleCommand = async function handleCommand(options, specificHandler) {
22 const cmdSeq = options._;
23 // `_` is the array holding all commands given to yargs
24 if (cmdSeq.length > 1) {
25 msgAndExit(`Invalid subcommand ${cmdSeq[1]} for command ${cmdSeq[0]}`, true);
26 }
27
28 await specificHandler(options);
29 process.exit(0);
30};
31
32const runtimes = require('./lib/runtimes');
33
34yargs
35 .option('path', {
36 alias: 'p',
37 describe: 'Use directory dir. "create" will create this directory if needed.',
38 type: 'string',
39 global: true,
40 })
41 .usage(
42`Binaris command line interface
43
44Usage: $0 <command> [options]` // eslint-disable-line comma-dangle
45 )
46 .command('create <runtime> <function> [options]', 'Create a function from template', (yargs0) => {
47 yargs0
48 .usage('Usage: $0 create <runtime> <function> [options]')
49 .positional('runtime', {
50 choices: runtimes,
51 type: 'string',
52 })
53 .positional('function', {
54 describe: 'Function name',
55 type: 'string',
56 });
57 }, async (argv) => {
58 await handleCommand(argv, createHandler);
59 })
60 .command('deploy <function> [options]', 'Deploys a function to the cloud', (yargs0) => {
61 yargs0
62 .usage('Usage: $0 deploy <function> [options]')
63 .positional('function', {
64 describe: 'Function name',
65 type: 'string',
66 });
67 }, async (argv) => {
68 await handleCommand(argv, deployHandler);
69 })
70 .command('remove <function> [options]', 'Remove a previously deployed function', (yargs0) => {
71 yargs0
72 .usage('Usage: $0 remove <function> [options]')
73 .positional('function', {
74 describe: 'Function name',
75 type: 'string',
76 });
77 }, async (argv) => {
78 await handleCommand(argv, removeHandler);
79 })
80 .command('invoke <function> [options]', 'Invoke a Binaris function', (yargs0) => {
81 yargs0
82 .usage('Usage: $0 invoke <function> [options]')
83 .positional('function', {
84 describe: 'Function name',
85 type: 'string',
86 })
87 .option('json', {
88 alias: 'j',
89 describe: 'Path to file containing JSON data',
90 type: 'string',
91 })
92 .option('data', {
93 alias: 'd',
94 describe: 'Data to send with invocation',
95 type: 'string',
96 })
97 .example(
98` // invoke a function
99 bn invoke foo
100
101 // invoke using JSON file data
102 bn invoke foo --json ./path/to/myfile.json
103
104 // invoke foo and send JSON data in the body
105 bn invoke foo --data '{ "name": "helloworld" }'`);
106 }, async (argv) => {
107 await handleCommand(argv, invokeHandler);
108 })
109 .command('list [options]', 'List all deployed functions', (yargs0) => {
110 yargs0
111 .usage('Usage: $0 list [options]')
112 .option('json', { describe: 'Output as JSON' });
113 }, async (argv) => {
114 await handleCommand(argv, listHandler);
115 })
116 .command('perf <function> [options]', 'Measure invocation latency (experimental)', (yargs0) => {
117 yargs0
118 .usage('Usage: $0 perf <function> [options]')
119 .positional('function', {
120 describe: 'Function name',
121 type: 'string',
122 })
123 .option('maxRequests', {
124 alias: 'n',
125 describe: 'Number of invocations to perform',
126 type: 'number',
127 default: 5000,
128 })
129 .option('concurrency', {
130 alias: 'c',
131 describe: 'How many requests run concurrently',
132 type: 'number',
133 default: 1,
134 })
135 .example(
136` // Run performance test on function foo (100 invocations, serially)
137 bn perf foo
138
139 // Run performance test with 1,000 invocations
140 bn perf foo -n 1000
141
142 // Run performance test with 1,000 invocations and 4 concurrent connections
143 bn perf foo -n 1000 -c 4
144`);
145 }, async (argv) => {
146 await handleCommand(argv, perfHandler);
147 })
148 .command('logs <function> [options]', 'Print the logs of a function', (yargs0) => {
149 yargs0
150 .usage('Usage: $0 logs <function> [options]')
151 .positional('function', {
152 describe: 'Function name',
153 type: 'string',
154 })
155 .option('tail', {
156 alias: 't',
157 describe: 'Outputs logs in "tail -f" fashion',
158 type: 'boolean',
159 })
160 .option('since', {
161 alias: 's',
162 describe: 'Outputs logs after the given ISO timestamp',
163 type: 'string',
164 })
165 .example(
166` // retrieve all logs
167 bn logs foo
168
169 // tail all logs
170 bn logs foo --tail
171
172 // ISO
173 bn logs foo --since 2018-03-09T22:12:21.861Z
174
175 // unix
176 bn logs foo --since 1520816105798
177
178 // offset format
179 bn logs foo --since 3d
180 bn logs foo --since 13hours
181 bn logs foo --since 9s`);
182 }, async (argv) => {
183 if (argv.since) {
184 try {
185 // eslint-disable-next-line no-param-reassign
186 argv.since = parseTimeString(argv.since);
187 } catch (err) {
188 msgAndExit(err.message);
189 }
190 }
191 await handleCommand(argv, logsHandler);
192 })
193 .command('login', 'Login to your Binaris account using an API key', (yargs0) => {
194 yargs0
195 .usage('Usage: $0 login');
196 }, async () => {
197 await loginHandler();
198 })
199 // .strict()
200 .demand(1, 'Please provide at least 1 valid command')
201 .help('help')
202 .alias('help', 'h')
203 .wrap(null);
204
205const commands = yargs.getCommandInstance().getCommands();
206// first command pushed to command stack(from user input)
207const currCommand = yargs.argv._[0];
208
209if (currCommand && commands.indexOf(currCommand) === -1) {
210 msgAndExit(`Unknown command: '${currCommand}'`, true);
211}
212