From 83a76f7d6ffee59d504ce362aac3acea23639770 Mon Sep 17 00:00:00 2001 From: Tim Perry Date: Tue, 9 Jan 2018 16:05:24 +0100 Subject: [PATCH] Start using Prettier Change-Type: patch --- .prettierrc | 5 + automation/build-bin.ts | 48 +++--- automation/capitanodoc/index.ts | 4 +- automation/capitanodoc/markdown.ts | 36 ++-- automation/custom-types.d.ts | 5 +- automation/deploy-bin.ts | 85 +++++---- lib/actions/settings.ts | 3 +- lib/config.ts | 3 +- lib/errors.ts | 18 +- lib/events.ts | 52 +++--- lib/utils/config.ts | 106 +++++++----- lib/utils/helpers.ts | 60 ++++--- lib/utils/patterns.ts | 268 ++++++++++++++++------------- lib/utils/plugins.ts | 23 +-- lib/utils/streams.ts | 24 +-- lib/utils/update.ts | 4 +- package.json | 6 +- typings/capitano.d.ts | 5 +- typings/president.d.ts | 5 +- typings/resin-device-init.d.ts | 12 +- typings/update-notifier.d.ts | 4 +- 21 files changed, 451 insertions(+), 325 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..3ddc0537 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "single-quote": true, + "trailing-comma": "all", + "use-tabs": true +} diff --git a/automation/build-bin.ts b/automation/build-bin.ts index 0d65b013..c5882e1b 100755 --- a/automation/build-bin.ts +++ b/automation/build-bin.ts @@ -7,28 +7,30 @@ const ROOT = path.join(__dirname, '..'); console.log('Building package...\n'); -execPkg([ - '--target', 'host', - '--output', 'build-bin/resin', - 'package.json' -]).then(() => fs.copy( - path.join(ROOT, 'node_modules', 'opn', 'xdg-open'), - path.join(ROOT, 'build-bin', 'xdg-open') -)).then(() => { - return filehound.create() - .paths(path.join(ROOT, 'node_modules')) - .ext(['node', 'dll']) - .find(); -}).then((nativeExtensions) => { - console.log(`\nCopying to build-bin:\n${nativeExtensions.join('\n')}`); +execPkg(['--target', 'host', '--output', 'build-bin/resin', 'package.json']) + .then(() => + fs.copy( + path.join(ROOT, 'node_modules', 'opn', 'xdg-open'), + path.join(ROOT, 'build-bin', 'xdg-open'), + ), + ) + .then(() => { + return filehound + .create() + .paths(path.join(ROOT, 'node_modules')) + .ext(['node', 'dll']) + .find(); + }) + .then(nativeExtensions => { + console.log(`\nCopying to build-bin:\n${nativeExtensions.join('\n')}`); - return nativeExtensions.map((extPath) => { - return fs.copy( - extPath, - extPath.replace( - path.join(ROOT, 'node_modules'), - path.join(ROOT, 'build-bin') - ) - ); + return nativeExtensions.map(extPath => { + return fs.copy( + extPath, + extPath.replace( + path.join(ROOT, 'node_modules'), + path.join(ROOT, 'build-bin'), + ), + ); + }); }); -}); diff --git a/automation/capitanodoc/index.ts b/automation/capitanodoc/index.ts index 875ee344..ced97fd7 100644 --- a/automation/capitanodoc/index.ts +++ b/automation/capitanodoc/index.ts @@ -4,13 +4,13 @@ import * as path from 'path'; import * as markdown from './markdown'; import { Document, Category } from './doc-types'; -const result = {}; +const result = {}; result.title = capitanodoc.title; result.introduction = capitanodoc.introduction; result.categories = []; for (let commandCategory of capitanodoc.categories) { - const category = {}; + const category = {}; category.title = commandCategory.title; category.commands = []; diff --git a/automation/capitanodoc/markdown.ts b/automation/capitanodoc/markdown.ts index 2a2d7510..3d740d13 100644 --- a/automation/capitanodoc/markdown.ts +++ b/automation/capitanodoc/markdown.ts @@ -10,7 +10,9 @@ export function renderCommand(command: Command) { result += '\n### Options'; for (let option of command.options!) { - result += `\n\n#### ${utils.parseSignature(option)}\n\n${option.description}`; + result += `\n\n#### ${utils.parseSignature(option)}\n\n${ + option.description + }`; } result += '\n'; @@ -30,27 +32,31 @@ export function renderCategory(category: Category) { } function getAnchor(command: Command) { - return '#' + command.signature - .replace(/\s/g,'-') - .replace(//g, '-62-') - .replace(/\[/g, '') - .replace(/\]/g, '-') - .replace(/--/g, '-') - .replace(/\.\.\./g, '') - .replace(/\|/g, '') - .toLowerCase(); + return ( + '#' + + command.signature + .replace(/\s/g, '-') + .replace(//g, '-62-') + .replace(/\[/g, '') + .replace(/\]/g, '-') + .replace(/--/g, '-') + .replace(/\.\.\./g, '') + .replace(/\|/g, '') + .toLowerCase() + ); } export function renderToc(categories: Category[]) { let result = `# Table of contents\n`; for (let category of categories) { - result += `\n- ${category.title}\n\n`; for (let command of category.commands) { - result += `\t- [${ent.encode(command.signature)}](${getAnchor(command)})\n`; + result += `\t- [${ent.encode(command.signature)}](${getAnchor( + command, + )})\n`; } } @@ -58,7 +64,9 @@ export function renderToc(categories: Category[]) { } export function render(doc: Document) { - let result = `# ${doc.title}\n\n${doc.introduction}\n\n${renderToc(doc.categories)}`; + let result = `# ${doc.title}\n\n${doc.introduction}\n\n${renderToc( + doc.categories, + )}`; for (let category of doc.categories) { result += `\n${renderCategory(category)}`; diff --git a/automation/custom-types.d.ts b/automation/custom-types.d.ts index 03240a27..21ec5fad 100644 --- a/automation/custom-types.d.ts +++ b/automation/custom-types.d.ts @@ -29,7 +29,10 @@ declare module 'publish-release' { html_url: string; } - let publishRelease: (args: PublishOptions, callback: (e: Error, release: Release) => void) => void; + let publishRelease: ( + args: PublishOptions, + callback: (e: Error, release: Release) => void, + ) => void; export = publishRelease; } diff --git a/automation/deploy-bin.ts b/automation/deploy-bin.ts index 5a5e192c..fe0ca5da 100644 --- a/automation/deploy-bin.ts +++ b/automation/deploy-bin.ts @@ -14,43 +14,54 @@ const { GITHUB_TOKEN } = process.env; const ROOT = path.join(__dirname, '..'); const version = 'v' + packageJSON.version; -const outputFile = path.join(ROOT, 'build-zip', `resin-cli-${version}-${os.platform()}-${os.arch()}.zip`); +const outputFile = path.join( + ROOT, + 'build-zip', + `resin-cli-${version}-${os.platform()}-${os.arch()}.zip`, +); -mkdirpAsync(path.dirname(outputFile)).then(() => new Promise((resolve, reject) => { - console.log('Zipping build...'); +mkdirpAsync(path.dirname(outputFile)) + .then( + () => + new Promise((resolve, reject) => { + console.log('Zipping build...'); - let archive = archiver('zip', { - zlib: { level: 7 }, + let archive = archiver('zip', { + zlib: { level: 7 }, + }); + archive.directory(path.join(ROOT, 'build-bin'), 'resin-cli'); + + let outputStream = fs.createWriteStream(outputFile); + + outputStream.on('close', resolve); + outputStream.on('error', reject); + + archive.on('error', reject); + archive.on('warning', console.warn); + + archive.pipe(outputStream); + archive.finalize(); + }), + ) + .then(() => { + console.log('Build zipped'); + console.log('Publishing build...'); + + return publishReleaseAsync({ + token: GITHUB_TOKEN, + owner: 'resin-io', + repo: 'resin-cli', + tag: version, + name: `Resin-CLI ${version}`, + reuseRelease: true, + assets: [outputFile], + }); + }) + .then(release => { + console.log(`Release ${version} successful: ${release.html_url}`); + }) + .catch(err => { + console.error('Release failed'); + console.error(err); + process.exit(1); }); - archive.directory(path.join(ROOT, 'build-bin'), 'resin-cli'); - - let outputStream = fs.createWriteStream(outputFile); - - outputStream.on('close', resolve); - outputStream.on('error', reject); - - archive.on('error', reject); - archive.on('warning', console.warn); - - archive.pipe(outputStream); - archive.finalize(); -})).then(() => { - console.log('Build zipped'); - console.log('Publishing build...'); - - return publishReleaseAsync({ - token: GITHUB_TOKEN, - owner: 'resin-io', - repo: 'resin-cli', - tag: version, - name: `Resin-CLI ${version}`, - reuseRelease: true, - assets: [outputFile], - }); -}).then((release) => { - console.log(`Release ${version} successful: ${release.html_url}`); -}).catch((err) => { - console.error('Release failed'); - console.error(err); - process.exit(1); -}); diff --git a/lib/actions/settings.ts b/lib/actions/settings.ts index ae76c00d..ff66af10 100644 --- a/lib/actions/settings.ts +++ b/lib/actions/settings.ts @@ -30,7 +30,8 @@ Examples: const resin = (await import('resin-sdk')).fromSharedOptions(); const prettyjson = await import('prettyjson'); - return resin.settings.getAll() + return resin.settings + .getAll() .then(prettyjson.render) .then(console.log) .nodeify(done); diff --git a/lib/config.ts b/lib/config.ts index 8d5e0918..7e6ab7b5 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -1 +1,2 @@ -export const sentryDsn = 'https://56d2a46124614b01b0f4086897e96110:6e175465accc41b595a96947155f61fb@sentry.io/149239'; +export const sentryDsn = + 'https://56d2a46124614b01b0f4086897e96110:6e175465accc41b595a96947155f61fb@sentry.io/149239'; diff --git a/lib/errors.ts b/lib/errors.ts index 979f56ad..6e9bf9ec 100644 --- a/lib/errors.ts +++ b/lib/errors.ts @@ -19,11 +19,16 @@ import patterns = require('./utils/patterns'); import Raven = require('raven'); import Promise = require('bluebird'); -const captureException = Promise.promisify(Raven.captureException, { context: Raven }); +const captureException = Promise.promisify( + Raven.captureException, + { context: Raven }, +); exports.handle = function(error: any) { let message = errors.interpret(error); - if ((message == null)) { return; } + if (message == null) { + return; + } if (process.env.DEBUG) { message = error.stack; @@ -32,8 +37,9 @@ exports.handle = function(error: any) { patterns.printErrorMessage(message); return captureException(error) - .timeout(1000) - .catch(function() { - // Ignore any errors (from error logging, or timeouts) - }).finally(() => process.exit(error.exitCode || 1)); + .timeout(1000) + .catch(function() { + // Ignore any errors (from error logging, or timeouts) + }) + .finally(() => process.exit(error.exitCode || 1)); }; diff --git a/lib/events.ts b/lib/events.ts index c5c539fd..04d528da 100644 --- a/lib/events.ts +++ b/lib/events.ts @@ -9,34 +9,40 @@ import packageJSON = require('../package.json'); const resin = ResinSdk.fromSharedOptions(); const getMatchCommandAsync = Promise.promisify(Capitano.state.getMatchCommand); -const getMixpanel = _.memoize(() => resin.models.config.getAll().get('mixpanelToken').then(Mixpanel.init)); +const getMixpanel = _.memoize(() => + resin.models.config + .getAll() + .get('mixpanelToken') + .then(Mixpanel.init), +); export function trackCommand(capitanoCli: Capitano.Cli) { return Promise.props({ resinUrl: resin.settings.get('resinUrl'), username: resin.auth.whoami().catchReturn(undefined), mixpanel: getMixpanel(), - }).then(({ username, resinUrl, mixpanel }) => { - return getMatchCommandAsync(capitanoCli.command).then((command) => { - Raven.mergeContext({ - user: { - id: username, - username, - }, - }); - - return mixpanel.track(`[CLI] ${command.signature.toString()}`, { - distinct_id: username, - argv: process.argv.join(' '), - version: packageJSON.version, - node: process.version, - arch: process.arch, - resinUrl, - platform: process.platform, - command: capitanoCli, - }); - }); }) - .timeout(100) - .catchReturn(undefined); + .then(({ username, resinUrl, mixpanel }) => { + return getMatchCommandAsync(capitanoCli.command).then(command => { + Raven.mergeContext({ + user: { + id: username, + username, + }, + }); + + return mixpanel.track(`[CLI] ${command.signature.toString()}`, { + distinct_id: username, + argv: process.argv.join(' '), + version: packageJSON.version, + node: process.version, + arch: process.arch, + resinUrl, + platform: process.platform, + command: capitanoCli, + }); + }); + }) + .timeout(100) + .catchReturn(undefined); } diff --git a/lib/utils/config.ts b/lib/utils/config.ts index 5a797197..65fc16a4 100644 --- a/lib/utils/config.ts +++ b/lib/utils/config.ts @@ -20,7 +20,10 @@ import deviceConfig = require('resin-device-config'); const resin = ResinSdk.fromSharedOptions(); -export function generateBaseConfig(application: ResinSdk.Application, options: {}) { +export function generateBaseConfig( + application: ResinSdk.Application, + options: {}, +) { options = _.mapValues(options, function(value, key) { if (key === 'appUpdatePollInterval') { return value * 60 * 1000; @@ -37,30 +40,37 @@ export function generateBaseConfig(application: ResinSdk.Application, options: { registryUrl: resin.settings.get('registryUrl'), deltaUrl: resin.settings.get('deltaUrl'), apiConfig: resin.models.config.getAll(), - }).then((results) => { - return deviceConfig.generate({ - application, - user: { - id: results.userId, - username: results.username, + }).then(results => { + return deviceConfig.generate( + { + application, + user: { + id: results.userId, + username: results.username, + }, + endpoints: { + api: results.apiUrl, + vpn: results.vpnUrl, + registry: results.registryUrl, + delta: results.deltaUrl, + }, + pubnub: results.apiConfig.pubnub, + mixpanel: { + token: results.apiConfig.mixpanelToken, + }, }, - endpoints: { - api: results.apiUrl, - vpn: results.vpnUrl, - registry: results.registryUrl, - delta: results.deltaUrl, - }, - pubnub: results.apiConfig.pubnub, - mixpanel: { - token: results.apiConfig.mixpanelToken, - }, - }, options); + options, + ); }); } -export function generateApplicationConfig(application: ResinSdk.Application, options: {}) { - return generateBaseConfig(application, options) - .tap(config => addApplicationKey(config, application.id)); +export function generateApplicationConfig( + application: ResinSdk.Application, + options: {}, +) { + return generateBaseConfig(application, options).tap(config => + addApplicationKey(config, application.id), + ); } export function generateDeviceConfig( @@ -68,41 +78,43 @@ export function generateDeviceConfig( deviceApiKey: string | null, options: {}, ) { - return resin.models.application.get(device.application_name) - .then(application => { - return generateBaseConfig(application, options) - .tap((config) => { - // Device API keys are only safe for ResinOS 2.0.3+. We could somehow obtain - // the expected version for this config and generate one when we know it's safe, - // but instead for now we fall back to app keys unless the user has explicitly opted in. - if (deviceApiKey) { - return addDeviceKey(config, device.uuid, deviceApiKey); - } else { - return addApplicationKey(config, application.id); - } - }); - }).then((config) => { - // Associate a device, to prevent the supervisor - // from creating another one on its own. - config.registered_at = Math.floor(Date.now() / 1000); - config.deviceId = device.id; - config.uuid = device.uuid; + return resin.models.application + .get(device.application_name) + .then(application => { + return generateBaseConfig(application, options).tap(config => { + // Device API keys are only safe for ResinOS 2.0.3+. We could somehow obtain + // the expected version for this config and generate one when we know it's safe, + // but instead for now we fall back to app keys unless the user has explicitly opted in. + if (deviceApiKey) { + return addDeviceKey(config, device.uuid, deviceApiKey); + } else { + return addApplicationKey(config, application.id); + } + }); + }) + .then(config => { + // Associate a device, to prevent the supervisor + // from creating another one on its own. + config.registered_at = Math.floor(Date.now() / 1000); + config.deviceId = device.id; + config.uuid = device.uuid; - return config; - }); + return config; + }); } function addApplicationKey(config: any, applicationNameOrId: string | number) { - return resin.models.application.generateApiKey(applicationNameOrId) - .tap((apiKey) => { - config.apiKey = apiKey; - }); + return resin.models.application + .generateApiKey(applicationNameOrId) + .tap(apiKey => { + config.apiKey = apiKey; + }); } function addDeviceKey(config: any, uuid: string, customDeviceApiKey: string) { return Promise.try(() => { return customDeviceApiKey || resin.models.device.generateDeviceKey(uuid); - }).tap((deviceApiKey) => { + }).tap(deviceApiKey => { config.deviceApiKey = deviceApiKey; }); } diff --git a/lib/utils/helpers.ts b/lib/utils/helpers.ts index b0bc8e3c..de4a02bd 100644 --- a/lib/utils/helpers.ts +++ b/lib/utils/helpers.ts @@ -32,25 +32,31 @@ const presidentExecuteAsync = Promise.promisify(execute); const resin = ResinSdk.fromSharedOptions(); -export function getGroupDefaults( - group: { options: { name: string, default?: string }[] }, -): { [name: string]: string | undefined } { +export function getGroupDefaults(group: { + options: { name: string; default?: string }[]; +}): { [name: string]: string | undefined } { return _.chain(group) .get('options') - .map((question) => [ question.name, question.default ]) + .map(question => [question.name, question.default]) .fromPairs() .value(); } export function stateToString(state: OperationState) { const percentage = _.padStart(`${state.percentage}`, 3, '0'); - const result = `${chalk.blue(percentage + '%')} ${chalk.cyan(state.operation.command)}`; + const result = `${chalk.blue(percentage + '%')} ${chalk.cyan( + state.operation.command, + )}`; switch (state.operation.command) { case 'copy': - return `${result} ${state.operation.from.path} -> ${state.operation.to.path}`; + return `${result} ${state.operation.from.path} -> ${ + state.operation.to.path + }`; case 'replace': - return `${result} ${state.operation.file.path}, ${state.operation.copy} -> ${state.operation.replace}`; + return `${result} ${state.operation.file.path}, ${ + state.operation.copy + } -> ${state.operation.replace}`; case 'run-script': return `${result} ${state.operation.script}`; default: @@ -68,20 +74,24 @@ export function sudo(command: string[]) { return presidentExecuteAsync(command); } -export function getManifest(image: string, deviceType: string): Promise { +export function getManifest( + image: string, + deviceType: string, +): Promise { // Attempt to read manifest from the first // partition, but fallback to the API if // we encounter any errors along the way. - return imagefs.read({ - image, - partition: { - primary: 1, - }, - path: '/device-type.json', - }) - .then(extractStreamAsync) - .then(JSON.parse) - .catch(() => resin.models.device.getManifestBySlug(deviceType)); + return imagefs + .read({ + image, + partition: { + primary: 1, + }, + path: '/device-type.json', + }) + .then(extractStreamAsync) + .then(JSON.parse) + .catch(() => resin.models.device.getManifestBySlug(deviceType)); } export function osProgressHandler(step: InitializeEmitter) { @@ -89,7 +99,9 @@ export function osProgressHandler(step: InitializeEmitter) { step.on('stderr', process.stderr.write.bind(process.stderr)); step.on('state', function(state) { - if (state.operation.command === 'burn') { return; } + if (state.operation.command === 'burn') { + return; + } console.log(exports.stateToString(state)); }); @@ -103,11 +115,13 @@ export function osProgressHandler(step: InitializeEmitter) { return waitStreamAsync(step); } -export function getArchAndDeviceType(applicationName: string): Promise<{ arch: string, device_type: string }> { +export function getArchAndDeviceType( + applicationName: string, +): Promise<{ arch: string; device_type: string }> { return Promise.join( getApplication(applicationName), resin.models.config.getDeviceTypes(), - function (app, deviceTypes) { + function(app, deviceTypes) { const config = _.find(deviceTypes, { slug: app.device_type }); if (!config) { @@ -139,12 +153,12 @@ export function getSubShellCommand(command: string) { if (os.platform() === 'win32') { return { program: 'cmd.exe', - args: [ '/s', '/c', command ], + args: ['/s', '/c', command], }; } else { return { program: '/bin/sh', - args: [ '-c', command ], + args: ['-c', command], }; } } diff --git a/lib/utils/patterns.ts b/lib/utils/patterns.ts index e2daa81c..3b61d557 100644 --- a/lib/utils/patterns.ts +++ b/lib/utils/patterns.ts @@ -26,36 +26,49 @@ import messages = require('./messages'); const resin = ResinSdk.fromSharedOptions(); export function authenticate(options: {}): Promise { - return form.run([{ - message: 'Email:', - name: 'email', - type: 'input', - validate: validation.validateEmail, - }, { - message: 'Password:', - name: 'password', - type: 'password', - }], { override: options }) - .then(resin.auth.login) - .then(resin.auth.twoFactor.isPassed) - .then((isTwoFactorAuthPassed: boolean) => { - if (isTwoFactorAuthPassed) { return; } + return form + .run( + [ + { + message: 'Email:', + name: 'email', + type: 'input', + validate: validation.validateEmail, + }, + { + message: 'Password:', + name: 'password', + type: 'password', + }, + ], + { override: options }, + ) + .then(resin.auth.login) + .then(resin.auth.twoFactor.isPassed) + .then((isTwoFactorAuthPassed: boolean) => { + if (isTwoFactorAuthPassed) { + return; + } - return form.ask({ - message: 'Two factor auth challenge:', - name: 'code', - type: 'input', - }) - .then(resin.auth.twoFactor.challenge) - .catch((error: any) => { - return resin.auth.logout().then(() => { - if ((error.name === 'ResinRequestError') && (error.statusCode === 401)) { - throw new Error('Invalid two factor authentication code'); - } - throw error; - }); + return form + .ask({ + message: 'Two factor auth challenge:', + name: 'code', + type: 'input', + }) + .then(resin.auth.twoFactor.challenge) + .catch((error: any) => { + return resin.auth.logout().then(() => { + if ( + error.name === 'ResinRequestError' && + error.statusCode === 401 + ) { + throw new Error('Invalid two factor authentication code'); + } + throw error; + }); + }); }); - }); } export function askLoginType() { @@ -63,25 +76,29 @@ export function askLoginType() { message: 'How would you like to login?', name: 'loginType', type: 'list', - choices: [{ - name: 'Web authorization (recommended)', - value: 'web', - }, { - name: 'Credentials', - value: 'credentials', - }, { - name: 'Authentication token', - value: 'token', - }, { - name: 'I don\'t have a Resin account!', - value: 'register', - }], + choices: [ + { + name: 'Web authorization (recommended)', + value: 'web', + }, + { + name: 'Credentials', + value: 'credentials', + }, + { + name: 'Authentication token', + value: 'token', + }, + { + name: "I don't have a Resin account!", + value: 'register', + }, + ], }); } export function selectDeviceType() { - return resin.models.device.getSupportedDeviceTypes() - .then(deviceTypes => { + return resin.models.device.getSupportedDeviceTypes().then(deviceTypes => { return form.ask({ message: 'Device Type', type: 'list', @@ -90,10 +107,16 @@ export function selectDeviceType() { }); } -export function confirm(yesOption: string, message: string, yesMessage: string) { - return Promise.try(function () { +export function confirm( + yesOption: string, + message: string, + yesMessage: string, +) { + return Promise.try(function() { if (yesOption) { - if (yesMessage) { console.log(yesMessage); } + if (yesMessage) { + console.log(yesMessage); + } return true; } @@ -109,73 +132,79 @@ export function confirm(yesOption: string, message: string, yesMessage: string) }); } -export function selectApplication(filter: (app: ResinSdk.Application) => boolean) { - resin.models.application.hasAny().then(function(hasAnyApplications) { - if (!hasAnyApplications) { - throw new Error('You don\'t have any applications'); - } - - return resin.models.application.getAll(); - }) - .filter(filter || _.constant(true)) - .then(applications => { - return form.ask({ - message: 'Select an application', - type: 'list', - choices: _.map(applications, application => - ({ - name: `${application.app_name} (${application.device_type})`, - value: application.app_name, - }), - )}); - }); -} - -export function selectOrCreateApplication() { - return resin.models.application.hasAny().then((hasAnyApplications) => { - if (!hasAnyApplications) return; - - return resin.models.application.getAll().then((applications) => { - const appOptions = _.map< - ResinSdk.Application, - { name: string, value: string | null } - >(applications, application => ({ - name: `${application.app_name} (${application.device_type})`, - value: application.app_name, - })); - - appOptions.unshift({ - name: 'Create a new application', - value: null, - }); +export function selectApplication( + filter: (app: ResinSdk.Application) => boolean, +) { + resin.models.application + .hasAny() + .then(function(hasAnyApplications) { + if (!hasAnyApplications) { + throw new Error("You don't have any applications"); + } + return resin.models.application.getAll(); + }) + .filter(filter || _.constant(true)) + .then(applications => { return form.ask({ message: 'Select an application', type: 'list', - choices: appOptions, + choices: _.map(applications, application => ({ + name: `${application.app_name} (${application.device_type})`, + value: application.app_name, + })), }); }); - }).then((application) => { - if (application) { - return application; - } +} - return form.ask({ - message: 'Choose a Name for your new application', - type: 'input', - validate: validation.validateApplicationName, +export function selectOrCreateApplication() { + return resin.models.application + .hasAny() + .then(hasAnyApplications => { + if (!hasAnyApplications) return; + + return resin.models.application.getAll().then(applications => { + const appOptions = _.map< + ResinSdk.Application, + { name: string; value: string | null } + >(applications, application => ({ + name: `${application.app_name} (${application.device_type})`, + value: application.app_name, + })); + + appOptions.unshift({ + name: 'Create a new application', + value: null, + }); + + return form.ask({ + message: 'Select an application', + type: 'list', + choices: appOptions, + }); + }); + }) + .then(application => { + if (application) { + return application; + } + + return form.ask({ + message: 'Choose a Name for your new application', + type: 'input', + validate: validation.validateApplicationName, + }); }); - }); } export function awaitDevice(uuid: string) { - return resin.models.device.getName(uuid) - .then((deviceName) => { - const spinner = new visuals.Spinner(`Waiting for ${deviceName} to come online`); + return resin.models.device.getName(uuid).then(deviceName => { + const spinner = new visuals.Spinner( + `Waiting for ${deviceName} to come online`, + ); const poll = (): Promise => { - return resin.models.device.isOnline(uuid) - .then(function(isOnline) { + return resin.models.device.isOnline(uuid).then(function(isOnline) { if (isOnline) { spinner.stop(); console.info(`The device **${deviceName}** is online!`); @@ -196,27 +225,28 @@ export function awaitDevice(uuid: string) { } export function inferOrSelectDevice(preferredUuid: string) { - return resin.models.device.getAll() - .filter((device) => device.is_online) - .then((onlineDevices) => { - if (_.isEmpty(onlineDevices)) { - throw new Error('You don\'t have any devices online'); - } + return resin.models.device + .getAll() + .filter(device => device.is_online) + .then(onlineDevices => { + if (_.isEmpty(onlineDevices)) { + throw new Error("You don't have any devices online"); + } - const defaultUuid = _.map(onlineDevices, 'uuid').includes(preferredUuid) ? - preferredUuid : - onlineDevices[0].uuid; + const defaultUuid = _.map(onlineDevices, 'uuid').includes(preferredUuid) + ? preferredUuid + : onlineDevices[0].uuid; - return form.ask({ - message: 'Select a device', - type: 'list', - default: defaultUuid, - choices: _.map(onlineDevices, device => ({ - name: `${device.name || 'Untitled'} (${device.uuid.slice(0, 7)})`, - value: device.uuid, - }), - )}); - }); + return form.ask({ + message: 'Select a device', + type: 'list', + default: defaultUuid, + choices: _.map(onlineDevices, device => ({ + name: `${device.name || 'Untitled'} (${device.uuid.slice(0, 7)})`, + value: device.uuid, + })), + }); + }); } export function printErrorMessage(message: string) { diff --git a/lib/utils/plugins.ts b/lib/utils/plugins.ts index 1896c7b9..2f981bbf 100644 --- a/lib/utils/plugins.ts +++ b/lib/utils/plugins.ts @@ -20,14 +20,17 @@ import capitano = require('capitano'); import patterns = require('./patterns'); export function register(regex: RegExp): Promise { - return nplugm.list(regex).map(async function(plugin: any) { - const command = await import(plugin); - command.plugin = true; - if (!_.isArray(command)) { - return capitano.command(command); - } - return _.each(command, capitano.command); - }).catch((error: Error) => { - return patterns.printErrorMessage(error.message); - }); + return nplugm + .list(regex) + .map(async function(plugin: any) { + const command = await import(plugin); + command.plugin = true; + if (!_.isArray(command)) { + return capitano.command(command); + } + return _.each(command, capitano.command); + }) + .catch((error: Error) => { + return patterns.printErrorMessage(error.message); + }); } diff --git a/lib/utils/streams.ts b/lib/utils/streams.ts index aa580e8f..eac69779 100644 --- a/lib/utils/streams.ts +++ b/lib/utils/streams.ts @@ -1,4 +1,7 @@ -export async function buffer(stream: NodeJS.ReadableStream, bufferFile: string) { +export async function buffer( + stream: NodeJS.ReadableStream, + bufferFile: string, +) { const Promise = await import('bluebird'); const fs = await import('fs'); @@ -6,14 +9,15 @@ export async function buffer(stream: NodeJS.ReadableStream, bufferFile: string) return new Promise(function(resolve, reject) { stream - .on('error', reject) - .on('end', resolve) - .pipe(fileWriteStream); - }).then(() => new Promise(function(resolve, reject) { - const stream = fs.createReadStream(bufferFile); + .on('error', reject) + .on('end', resolve) + .pipe(fileWriteStream); + }).then( + () => + new Promise(function(resolve, reject) { + const stream = fs.createReadStream(bufferFile); - stream - .on('open', () => resolve(stream)) - .on('error', reject); - })); + stream.on('open', () => resolve(stream)).on('error', reject); + }), + ); } diff --git a/lib/utils/update.ts b/lib/utils/update.ts index a34624e6..ca795125 100644 --- a/lib/utils/update.ts +++ b/lib/utils/update.ts @@ -42,6 +42,8 @@ export function notify() { notifier.notify({ defer: false }); if (notifier.update != null) { - console.log('Notice that you might need administrator privileges depending on your setup\n'); + console.log( + 'Notice that you might need administrator privileges depending on your setup\n', + ); } } diff --git a/package.json b/package.json index 62823c3d..62125edf 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "scripts": { "prebuild": "rimraf build/ build-bin/ build-zip/", "build": "npm run build:src && npm run build:bin", - "build:src": "npm run lint && gulp build && tsc && npm run build:doc", + "build:src": "npm run prettify && npm run lint && gulp build && tsc && npm run build:doc", "build:doc": "mkdirp doc/ && ts-node automation/capitanodoc/index.ts > doc/cli.markdown", "build:bin": "ts-node --type-check -P automation automation/build-bin.ts", "release": "npm run build && ts-node --type-check -P automation automation/deploy-bin.ts", @@ -39,6 +39,7 @@ "test": "gulp test", "ci": "npm run test && catch-uncommitted", "watch": "gulp watch", + "prettify": "prettier --write \"{lib,tests,automation,typings}/**/*.ts\"", "lint": "resin-lint lib/ tests/ && resin-lint --typescript automation/ lib/ typings/ tests/", "prepublish": "require-npm4-to-publish", "prepublishOnly": "npm run build" @@ -71,6 +72,7 @@ "gulp-shell": "^0.5.2", "mochainon": "^2.0.0", "pkg": "^4.3.0-beta.1", + "prettier": "^1.9.2", "publish-release": "^1.3.3", "require-npm4-to-publish": "^1.0.0", "resin-lint": "^1.5.0", @@ -147,4 +149,4 @@ "optionalDependencies": { "removedrive": "^1.0.0" } -} \ No newline at end of file +} diff --git a/typings/capitano.d.ts b/typings/capitano.d.ts index 1958a6db..aaa385b3 100644 --- a/typings/capitano.d.ts +++ b/typings/capitano.d.ts @@ -48,6 +48,9 @@ declare module 'capitano' { export function command(command: CommandDefinition): void; export const state: { - getMatchCommand: (signature: string, callback: (e: Error, cmd: Command) => void) => void + getMatchCommand: ( + signature: string, + callback: (e: Error, cmd: Command) => void, + ) => void; }; } diff --git a/typings/president.d.ts b/typings/president.d.ts index 485052a6..c831ac3b 100644 --- a/typings/president.d.ts +++ b/typings/president.d.ts @@ -1,3 +1,6 @@ declare module 'president' { - export function execute(command: string[], callback: (err: Error) => void): void; + export function execute( + command: string[], + callback: (err: Error) => void, + ): void; } diff --git a/typings/resin-device-init.d.ts b/typings/resin-device-init.d.ts index 2ba03252..a759c16d 100644 --- a/typings/resin-device-init.d.ts +++ b/typings/resin-device-init.d.ts @@ -3,7 +3,11 @@ declare module 'resin-device-init' { import { EventEmitter } from 'events'; interface OperationState { - operation: CopyOperation | ReplaceOperation | RunScriptOperation | BurnOperation; + operation: + | CopyOperation + | ReplaceOperation + | RunScriptOperation + | BurnOperation; percentage: number; } @@ -56,5 +60,9 @@ declare module 'resin-device-init' { on(event: 'burn', callback: (state: BurnProgress) => void): void; } - export function initialize(image: string, deviceType: string, config: {}): Promise; + export function initialize( + image: string, + deviceType: string, + config: {}, + ): Promise; } diff --git a/typings/update-notifier.d.ts b/typings/update-notifier.d.ts index 9afc8ed5..267b4601 100644 --- a/typings/update-notifier.d.ts +++ b/typings/update-notifier.d.ts @@ -4,7 +4,9 @@ declare module 'update-notifier' { export = UpdateNotifier; - function UpdateNotifier(settings?: UpdateNotifier.Settings): UpdateNotifier.UpdateNotifier; + function UpdateNotifier( + settings?: UpdateNotifier.Settings, + ): UpdateNotifier.UpdateNotifier; namespace UpdateNotifier { class UpdateNotifier {