diff --git a/automation/capitanodoc/markdown.ts b/automation/capitanodoc/markdown.ts index bb570d5a..d7752a89 100644 --- a/automation/capitanodoc/markdown.ts +++ b/automation/capitanodoc/markdown.ts @@ -24,7 +24,7 @@ import { CapitanoCommand, Category, Document, OclifCommand } from './doc-types'; import * as utils from './utils'; function renderCapitanoCommand(command: CapitanoCommand): string[] { - const result = [`## ${ent.encode(command.signature)}`, command.help]; + const result = [`## ${ent.encode(command.signature)}`, command.help!]; if (!_.isEmpty(command.options)) { result.push('### Options'); diff --git a/automation/check-doc.js b/automation/check-doc.js index 276b55b0..7b60e968 100644 --- a/automation/check-doc.js +++ b/automation/check-doc.js @@ -67,9 +67,7 @@ async function checkBuildTimestamps() { file) for three reasons: 1. To update the CLI markdown documentation (in case any command-line options were updated, added or removed). - 2. To reveal coffeelint warnings that the CI currently ignores (in case any - Coffeescript files were modified). - 3. To catch Typescript type check errors sooner and reduce overall waiting time, + 2. To catch Typescript type check errors sooner and reduce overall waiting time, given that balena-cli CI builds/tests are currently rather lengthy. If you need/wish to bypass this check without running \`npm run build\`, run: diff --git a/bin/balena-dev b/bin/balena-dev index a43a63e9..f79ea16f 100755 --- a/bin/balena-dev +++ b/bin/balena-dev @@ -13,7 +13,6 @@ process.env.UV_THREADPOOL_SIZE = '64'; require('fast-boot2').start({ cacheFile: '.fast-boot.json', }); -require('coffeescript/register'); const path = require('path'); const rootDir = path.join(__dirname, '..'); diff --git a/gulpfile.coffee b/gulpfile.coffee index 4b741030..c5623375 100644 --- a/gulpfile.coffee +++ b/gulpfile.coffee @@ -1,14 +1,12 @@ path = require('path') gulp = require('gulp') -coffee = require('gulp-coffee') inlinesource = require('gulp-inline-source') shell = require('gulp-shell') packageJSON = require('./package.json') OPTIONS = files: - coffee: [ 'lib/**/*.coffee', 'gulpfile.coffee' ] - app: 'lib/**/*.coffee' + coffee: [ 'gulpfile.coffee' ] tests: 'tests/**/*.spec.js' pages: 'lib/auth/pages/*.ejs' directories: @@ -19,13 +17,7 @@ gulp.task 'pages', -> .pipe(inlinesource()) .pipe(gulp.dest('build/auth/pages')) -gulp.task 'coffee', -> - gulp.src(OPTIONS.files.app) - .pipe(coffee(bare: true, header: true)) - .pipe(gulp.dest(OPTIONS.directories.build)) - gulp.task 'build', gulp.series [ - 'coffee', 'pages' ] diff --git a/lib/app-capitano.coffee b/lib/app-capitano.coffee deleted file mode 100644 index 521d6dc2..00000000 --- a/lib/app-capitano.coffee +++ /dev/null @@ -1,143 +0,0 @@ -### -Copyright 2016-2019 Balena - -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. -### - -Promise = require('bluebird') -capitano = require('capitano') -actions = require('./actions') -events = require('./events') - -capitano.permission 'user', (done) -> - require('./utils/patterns').exitIfNotLoggedIn() - .then(done, done) - -capitano.command - signature: '*' - action: (params, options, done) -> - capitano.execute(command: 'help', done) - process.exitCode = process.exitCode || 1 - -capitano.globalOption - signature: 'help' - boolean: true - alias: 'h' - -capitano.globalOption - signature: 'version' - boolean: true - alias: 'v' - -# ---------- Help Module ---------- -capitano.command(actions.help.help) - -# ---------- Api key module ---------- -capitano.command(actions.apiKey.generate) - -# ---------- App Module ---------- -capitano.command(actions.app.create) -capitano.command(actions.app.list) -capitano.command(actions.app.remove) -capitano.command(actions.app.restart) -capitano.command(actions.app.info) - -# ---------- Auth Module ---------- -capitano.command(actions.auth.login) -capitano.command(actions.auth.logout) -capitano.command(actions.auth.whoami) - -# ---------- Device Module ---------- -capitano.command(actions.device.list) -capitano.command(actions.device.rename) -capitano.command(actions.device.init) -capitano.command(actions.device.remove) -capitano.command(actions.device.identify) -capitano.command(actions.device.reboot) -capitano.command(actions.device.shutdown) -capitano.command(actions.device.enableDeviceUrl) -capitano.command(actions.device.disableDeviceUrl) -capitano.command(actions.device.getDeviceUrl) -capitano.command(actions.device.hasDeviceUrl) -capitano.command(actions.device.register) -capitano.command(actions.device.move) -capitano.command(actions.device.osUpdate) -capitano.command(actions.device.info) - -# ---------- Tags Module ---------- -capitano.command(actions.tags.list) -capitano.command(actions.tags.set) -capitano.command(actions.tags.remove) - -# ---------- OS Module ---------- -capitano.command(actions.os.versions) -capitano.command(actions.os.download) -capitano.command(actions.os.buildConfig) -capitano.command(actions.os.initialize) - -# ---------- Config Module ---------- -capitano.command(actions.config.read) -capitano.command(actions.config.write) -capitano.command(actions.config.inject) -capitano.command(actions.config.reconfigure) -capitano.command(actions.config.generate) - -# ---------- Logs Module ---------- -capitano.command(actions.logs.logs) - -# ---------- Tunnel Module ---------- -capitano.command(actions.tunnel.tunnel) - -# ---------- Preload Module ---------- -capitano.command(actions.preload) - -# ---------- SSH Module ---------- -capitano.command(actions.ssh.ssh) - -# ---------- Local balenaOS Module ---------- -capitano.command(actions.local.configure) -capitano.command(actions.local.flash) - -# ---------- Public utils ---------- -capitano.command(actions.util.availableDrives) - -#------------ Local build and deploy ------- -capitano.command(actions.build) -capitano.command(actions.deploy) - -#------------ Push/remote builds ------- -capitano.command(actions.push.push) - -exports.run = (argv) -> - cli = capitano.parse(argv.slice(2)) - runCommand = -> - capitanoExecuteAsync = Promise.promisify(capitano.execute) - if cli.global?.help - capitanoExecuteAsync(command: "help #{cli.command ? ''}") - else - capitanoExecuteAsync(cli) - - trackCommand = -> - getMatchCommandAsync = Promise.promisify(capitano.state.getMatchCommand) - getMatchCommandAsync(cli.command) - .then (command) -> - # cmdSignature is literally a string like, for example: - # "push " - # ("applicationOrDevice" is NOT replaced with its actual value) - # In case of failures like an nonexistent or invalid command, - # command.signature.toString() returns '*' - cmdSignature = command.signature.toString() - events.trackCommand(cmdSignature) - - Promise.all([trackCommand(), runCommand()]) - .catch(require('./errors').handleError) diff --git a/lib/app-capitano.d.ts b/lib/app-capitano.d.ts deleted file mode 100644 index 1aac72e2..00000000 --- a/lib/app-capitano.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @license - * Copyright 2019 Balena Ltd. - * - * 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. - */ - -export async function run(argv: string[]); diff --git a/lib/app-capitano.js b/lib/app-capitano.js new file mode 100644 index 00000000..d46247a3 --- /dev/null +++ b/lib/app-capitano.js @@ -0,0 +1,159 @@ +/* +Copyright 2016-2020 Balena + +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. +*/ + +import * as Promise from 'bluebird'; + +import * as capitano from 'capitano'; +import * as actions from './actions'; +import * as events from './events'; + +capitano.permission('user', done => + require('./utils/patterns') + .exitIfNotLoggedIn() + .then(done, done), +); + +capitano.command({ + signature: '*', + action(_params, _options, done) { + capitano.execute({ command: 'help' }, done); + process.exitCode = process.exitCode || 1; + }, +}); + +capitano.globalOption({ + signature: 'help', + boolean: true, + alias: 'h', +}); + +capitano.globalOption({ + signature: 'version', + boolean: true, + alias: 'v', +}); + +// ---------- Help Module ---------- +capitano.command(actions.help.help); + +// ---------- Api key module ---------- +capitano.command(actions.apiKey.generate); + +// ---------- App Module ---------- +capitano.command(actions.app.create); +capitano.command(actions.app.list); +capitano.command(actions.app.remove); +capitano.command(actions.app.restart); +capitano.command(actions.app.info); + +// ---------- Auth Module ---------- +capitano.command(actions.auth.login); +capitano.command(actions.auth.logout); +capitano.command(actions.auth.whoami); + +// ---------- Device Module ---------- +capitano.command(actions.device.list); +capitano.command(actions.device.rename); +capitano.command(actions.device.init); +capitano.command(actions.device.remove); +capitano.command(actions.device.identify); +capitano.command(actions.device.reboot); +capitano.command(actions.device.shutdown); +capitano.command(actions.device.enableDeviceUrl); +capitano.command(actions.device.disableDeviceUrl); +capitano.command(actions.device.getDeviceUrl); +capitano.command(actions.device.hasDeviceUrl); +capitano.command(actions.device.register); +capitano.command(actions.device.move); +capitano.command(actions.device.osUpdate); +capitano.command(actions.device.info); + +// ---------- Tags Module ---------- +capitano.command(actions.tags.list); +capitano.command(actions.tags.set); +capitano.command(actions.tags.remove); + +// ---------- OS Module ---------- +capitano.command(actions.os.versions); +capitano.command(actions.os.download); +capitano.command(actions.os.buildConfig); +capitano.command(actions.os.initialize); + +// ---------- Config Module ---------- +capitano.command(actions.config.read); +capitano.command(actions.config.write); +capitano.command(actions.config.inject); +capitano.command(actions.config.reconfigure); +capitano.command(actions.config.generate); + +// ---------- Logs Module ---------- +capitano.command(actions.logs.logs); + +// ---------- Tunnel Module ---------- +capitano.command(actions.tunnel.tunnel); + +// ---------- Preload Module ---------- +capitano.command(actions.preload); + +// ---------- SSH Module ---------- +capitano.command(actions.ssh.ssh); + +// ---------- Local balenaOS Module ---------- +capitano.command(actions.local.configure); +capitano.command(actions.local.flash); + +// ---------- Public utils ---------- +capitano.command(actions.util.availableDrives); + +//------------ Local build and deploy ------- +capitano.command(actions.build); +capitano.command(actions.deploy); + +//------------ Push/remote builds ------- +capitano.command(actions.push.push); + +export function run(argv) { + const cli = capitano.parse(argv.slice(2)); + const runCommand = function() { + const capitanoExecuteAsync = Promise.promisify(capitano.execute); + if (cli.global?.help) { + return capitanoExecuteAsync({ + command: `help ${cli.command ?? ''}`, + }); + } else { + return capitanoExecuteAsync(cli); + } + }; + + const trackCommand = function() { + const getMatchCommandAsync = Promise.promisify( + capitano.state.getMatchCommand, + ); + return getMatchCommandAsync(cli.command).then(function(command) { + // cmdSignature is literally a string like, for example: + // "push " + // ("applicationOrDevice" is NOT replaced with its actual value) + // In case of failures like an nonexistent or invalid command, + // command.signature.toString() returns '*' + const cmdSignature = command.signature.toString(); + return events.trackCommand(cmdSignature); + }); + }; + + return Promise.all([trackCommand(), runCommand()]).catch( + require('./errors').handleError, + ); +} diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 74a0d54d..91c753bb 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -7027,19 +7027,6 @@ } } }, - "gulp-coffee": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/gulp-coffee/-/gulp-coffee-2.3.5.tgz", - "integrity": "sha512-PbgPGZVyYFnBTYtfYkVN6jcK8Qsuh3BxycPzvu8y5lZroCw3/x1m25KeyEDX110KsVLDmJxoULjscR21VEN4wA==", - "dev": true, - "requires": { - "coffeescript": "^1.10.0", - "gulp-util": "^3.0.2", - "merge": "^1.2.0", - "through2": "^2.0.1", - "vinyl-sourcemaps-apply": "^0.2.1" - } - }, "gulp-inline-source": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/gulp-inline-source/-/gulp-inline-source-2.1.0.tgz", @@ -9162,12 +9149,6 @@ "trim-newlines": "^1.0.0" } }, - "merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true - }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -18201,15 +18182,6 @@ } } }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "^0.5.1" - } - }, "walkdir": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", diff --git a/package.json b/package.json index b52a1a0c..ab8816ba 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "catch-uncommitted": "ts-node --transpile-only automation/run.ts catch-uncommitted", "ci": "npm run test && npm run catch-uncommitted", "watch": "gulp watch", - "lint": "balena-lint lib/ tests/ && balena-lint -e ts -e js --typescript --fix automation/ lib/ typings/ tests/", + "lint": "balena-lint -e ts -e js --typescript --fix automation/ lib/ typings/ tests/", "update": "ts-node --transpile-only ./automation/update-module.ts", "prepublishOnly": "npm run build" }, @@ -148,7 +148,6 @@ "filehound": "^1.17.4", "fs-extra": "^8.0.1", "gulp": "^4.0.1", - "gulp-coffee": "^2.2.0", "gulp-inline-source": "^2.1.0", "gulp-shell": "^0.5.2", "husky": "^4.2.5", diff --git a/typings/capitano/index.d.ts b/typings/capitano/index.d.ts index b23dfbb9..054cc431 100644 --- a/typings/capitano/index.d.ts +++ b/typings/capitano/index.d.ts @@ -21,7 +21,9 @@ declare module 'capitano' { export interface Cli { command: string; options: {}; - global: {}; + global: { + help?: boolean; + }; } export interface OptionDefinition { @@ -35,10 +37,10 @@ declare module 'capitano' { export interface CommandDefinition

{ signature: string; - description: string; - help: string; + description?: string; + help?: string; options?: Partial; - permission?: 'user'; + permission?: string; // This should be 'user' but without full typescript we cannot enforce it root?: boolean; primary?: boolean; hidden?: boolean; @@ -68,7 +70,7 @@ declare module 'capitano' { required: boolean | string; } - export function command(command: CommandDefinition): void; + export function command(command: CommandDefinition): void; export const state: { getMatchCommand: ( @@ -78,4 +80,14 @@ declare module 'capitano' { commands: Command[]; globalOptions: OptionDefinition[]; }; + + export function execute( + args: any, + callback: (err?: any, result: any) => void, + ): void; + export function globalOption(option: OptionDefinition): void; + export function permission( + permissionName: string, + callback: (done: () => void) => void, + ): void; }