Start using Prettier

Change-Type: patch
This commit is contained in:
Tim Perry 2018-01-09 16:05:24 +01:00
parent 6c988241eb
commit 83a76f7d6f
21 changed files with 451 additions and 325 deletions

5
.prettierrc Normal file
View File

@ -0,0 +1,5 @@
{
"single-quote": true,
"trailing-comma": "all",
"use-tabs": true
}

View File

@ -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'),
),
);
});
});
});

View File

@ -4,13 +4,13 @@ import * as path from 'path';
import * as markdown from './markdown';
import { Document, Category } from './doc-types';
const result = <Document> {};
const result = <Document>{};
result.title = capitanodoc.title;
result.introduction = capitanodoc.introduction;
result.categories = [];
for (let commandCategory of capitanodoc.categories) {
const category = <Category> {};
const category = <Category>{};
category.title = commandCategory.title;
category.commands = [];

View File

@ -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, '60-')
.replace(/>/g, '-62-')
.replace(/\[/g, '')
.replace(/\]/g, '-')
.replace(/--/g, '-')
.replace(/\.\.\./g, '')
.replace(/\|/g, '')
.toLowerCase();
return (
'#' +
command.signature
.replace(/\s/g, '-')
.replace(/</g, '60-')
.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)}`;

View File

@ -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;
}

View File

@ -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: <string>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: <string> 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);
});

View File

@ -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);

View File

@ -1 +1,2 @@
export const sentryDsn = 'https://56d2a46124614b01b0f4086897e96110:6e175465accc41b595a96947155f61fb@sentry.io/149239';
export const sentryDsn =
'https://56d2a46124614b01b0f4086897e96110:6e175465accc41b595a96947155f61fb@sentry.io/149239';

View File

@ -19,11 +19,16 @@ import patterns = require('./utils/patterns');
import Raven = require('raven');
import Promise = require('bluebird');
const captureException = Promise.promisify<string, Error>(Raven.captureException, { context: Raven });
const captureException = Promise.promisify<string, Error>(
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));
};

View File

@ -9,34 +9,40 @@ import packageJSON = require('../package.json');
const resin = ResinSdk.fromSharedOptions();
const getMatchCommandAsync = Promise.promisify(Capitano.state.getMatchCommand);
const getMixpanel = _.memoize<any>(() => resin.models.config.getAll().get('mixpanelToken').then(Mixpanel.init));
const getMixpanel = _.memoize<any>(() =>
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);
}

View File

@ -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;
});
}

View File

@ -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<ResinSdk.DeviceType> {
export function getManifest(
image: string,
deviceType: string,
): Promise<ResinSdk.DeviceType> {
// 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],
};
}
}

View File

@ -26,36 +26,49 @@ import messages = require('./messages');
const resin = ResinSdk.fromSharedOptions();
export function authenticate(options: {}): Promise<void> {
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<void> => {
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<ResinSdk.Device>((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<ResinSdk.Device>(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) {

View File

@ -20,14 +20,17 @@ import capitano = require('capitano');
import patterns = require('./patterns');
export function register(regex: RegExp): Promise<void> {
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);
});
}

View File

@ -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);
}),
);
}

View File

@ -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',
);
}
}

View File

@ -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"
}
}
}

View File

@ -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;
};
}

View File

@ -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;
}

View File

@ -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<InitializeEmitter>;
export function initialize(
image: string,
deviceType: string,
config: {},
): Promise<InitializeEmitter>;
}

View File

@ -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 {