| /* |
| * Copyright 2015-2016 IBM Corporation |
| * |
| * 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. |
| */ |
| |
| var argv = require('argv'), |
| prompt = require('inquirer'), |
| lister = require('./commands/list'), |
| options = require('./options'), |
| rewriter = require('./rewriter'), |
| columnify = require('columnify'); |
| |
| var commandHandlers; // defined below. helping out jshint here |
| var help = { |
| handler: function help() { |
| console.log('The available commands are:'); |
| console.log(); |
| |
| var grouped = {}; |
| for (var x in commandHandlers) { |
| if (commandHandlers.hasOwnProperty(x)) { |
| var already = grouped[commandHandlers[x].description]; |
| if (already) { |
| grouped[commandHandlers[x].description] = already + ', ' + x; |
| } else { |
| grouped[commandHandlers[x].description] = x; |
| } |
| } |
| } |
| |
| var pruned = []; |
| for (var d in grouped) { |
| if (grouped.hasOwnProperty(d)) { |
| pruned.push({ command: grouped[d], description: d }); |
| } |
| } |
| |
| console.log(columnify(pruned, { minWidth: 18 })); |
| }, |
| description: 'Print this help text' |
| }; |
| var attach = { |
| handler: rewriter.attach, |
| enumerate: lister.list, |
| description: 'Attach to an action', |
| synchronous: true, |
| options: [{ name: 'all', short: 'a', type: 'string', description: 'Instrument the action, plus any rules or sequences in which it takes part' }] |
| }; |
| var detach = { |
| handler: rewriter.detach, |
| description: 'Detatch from an action', |
| synchronous: true |
| }; |
| var exit = { |
| handler: function(wskprops) { |
| console.log('Cleaning up'); |
| rewriter.clean(wskprops, process.exit); // note: clean versus detachAll |
| }, |
| description: 'Quit the debugger', |
| synchronous: true |
| }; |
| var invoke = { |
| handler: rewriter.invoke, |
| description: 'Invoke an action', |
| needsEventBus: true, |
| synchronous: true |
| }; |
| var fire = { |
| handler: require('./commands/fire').fire, |
| description: 'Fire a trigger', |
| synchronous: true |
| }; |
| var list = { |
| handler: lister.listToConsole, |
| description: 'List available actions', |
| synchronous: true, |
| options: [{ name: 'full', short: 'f', type: 'string', description: 'Show all actions, including debugging artifacts' }] |
| }; |
| var inspect = { |
| handler: require('./commands/inspect').inspect, |
| description: 'Inspect the details of an OpenWhisk action', |
| synchronous: true |
| }; |
| var clean = { |
| handler: rewriter.clean, |
| description: 'Clean up debugging artifacts', |
| synchronous: true |
| }; |
| var create = { |
| handler: require('./commands/create').create, |
| description: 'Create an action', |
| synchronous: true |
| }; |
| var createTrigger = { |
| handler: require('./commands/create-trigger').create, |
| description: 'Create a trigger', |
| synchronous: true |
| }; |
| var createRule = { |
| handler: require('./commands/create-rule').create, |
| description: 'Create a rule', |
| synchronous: true |
| }; |
| var deleteAction = { |
| handler: require('./commands/delete').deleteAction, |
| description: 'Delete an action', |
| synchronous: true |
| }; |
| var deleteTrigger = { |
| handler: require('./commands/delete-trigger').delete, |
| description: 'Delete a trigger', |
| synchronous: true |
| }; |
| var deleteRule = { |
| handler: require('./commands/delete-rule').delete, |
| description: 'Delete a rule', |
| synchronous: true |
| }; |
| var diff = { |
| handler: require('./commands/diff').diff, |
| description: 'Show the pending diffs of a given action', |
| synchronous: true |
| }; |
| var publish = { |
| handler: require('./commands/publish').publish, |
| description: 'Publish pending changes to a given action', |
| synchronous: true |
| }; |
| var cli = { |
| handler: options.update.bind(undefined, 'use-cli-debugger', undefined), |
| description: 'Use the CLI debugger, when available', |
| synchronous: true |
| }; |
| commandHandlers = { |
| list: list, |
| l: list, |
| |
| cli: cli, |
| |
| invoke: invoke, |
| i: invoke, |
| |
| inspect: inspect, |
| ins: inspect, |
| get: inspect, |
| |
| fire: fire, |
| f: fire, |
| |
| attach: attach, |
| a: attach, |
| |
| detach: detach, |
| d: detach, |
| |
| diff: diff, |
| publish: publish, |
| p: publish, |
| |
| exit: exit, |
| quit: exit, |
| e: exit, |
| q: exit, |
| |
| clean: clean, |
| c: clean, |
| |
| create: create, |
| 'create-trigger': createTrigger, |
| 'create-rule': createRule, |
| delete: deleteAction, |
| 'delete-trigger': deleteTrigger, |
| 'delete-rule': deleteRule, |
| |
| help: help, |
| h: help, |
| '?': help |
| }; |
| |
| /** |
| * This is the read-eval-print loop. |
| * |
| * @param wskprops is a map that provides the user's NAMESPACE and AUTH settings |
| * @param eventBus will be used to post and listen for inter-function communication |
| * @param attachTo if the user requested to attach to an action on launch |
| * |
| */ |
| function repl(wskprops, eventBus, attachTo) { |
| function handleReplCommand(response) { |
| if (response.command.length === 0) { |
| // user hit return; |
| return repl(wskprops, eventBus); |
| } |
| |
| var commandLine = response.command.split(/\s+/); |
| var command = commandLine.shift(); |
| var handler = commandHandlers[command]; |
| |
| var options; |
| if (handler.options) { |
| argv.clear(); |
| argv.description = 'Usage: ' + command + ' [options]'; |
| argv.options.help.example = ''; |
| argv.options.help.onset = (args) => { |
| argv.help(args.mod); |
| }; |
| options = argv.option(handler.options).run(commandLine).options; |
| } |
| |
| if (handler.synchronous) { |
| // the second parameter is the call back to the repl |
| // when done with the synchronous operation |
| commandLine.unshift(repl.bind(undefined, wskprops, eventBus)); |
| } |
| |
| if (handler.options) { |
| commandLine.unshift(options); |
| } |
| |
| if (handler.needsEventBus) { |
| commandLine.unshift(eventBus); |
| } |
| |
| // the first parameter is wskprops |
| commandLine.unshift(wskprops); |
| |
| commandLine.push(response.command); |
| |
| // call to the handler! |
| try { |
| handler.handler.apply(undefined, commandLine); |
| } catch (e) { |
| console.error(e); |
| } |
| |
| if (!handler.synchronous) { |
| // if async, then restart the repl right away |
| repl(wskprops, eventBus); |
| } |
| } /* end of handleReplCommand */ |
| |
| if (attachTo) { |
| handleReplCommand({ command: 'attach ' + attachTo }); |
| } else { |
| prompt.prompt([{ |
| name: 'command', message: '(wskdb)', |
| prefixMessage: '', // override the default question mark prefix |
| validate: function(line) { |
| var commandLine = line.split(/\s+/); |
| return line.length === 0 || commandHandlers[commandLine[0]] ? true : 'Invalid command'; |
| } |
| }]).then(handleReplCommand); |
| } |
| } |
| |
| exports.repl = repl; |