Lots of small TypeScript tweaks & clarifications from review

This commit is contained in:
Tim Perry 2018-01-04 16:17:43 +00:00
parent 6ab60d0ccd
commit 612012aff8
9 changed files with 67 additions and 64 deletions

View File

@ -17,17 +17,15 @@ export function getOptionSignature(signature: string) {
export function parseSignature(option: OptionDefinition) {
let result = getOptionSignature(option.signature);
if (!_.isEmpty(option.alias)) {
if (_.isString(option.alias)) {
result += `, ${getOptionSignature(option.alias)}`;
} else {
for (let alias of option.alias!) {
result += `, ${getOptionSignature(alias)}`;
}
if (_.isArray(option.alias)) {
for (let alias of option.alias) {
result += `, ${getOptionSignature(alias)}`;
}
} else if (_.isString(option.alias)) {
result += `, ${getOptionSignature(option.alias)}`;
}
if (option.parameter != null) {
if (option.parameter) {
result += ` <${option.parameter}>`;
}

View File

@ -36,8 +36,7 @@ export function generateBaseConfig(application: ResinSdk.Application, options: {
vpnUrl: resin.settings.get('vpnUrl'),
registryUrl: resin.settings.get('registryUrl'),
deltaUrl: resin.settings.get('deltaUrl'),
pubNubKeys: resin.models.config.getAll().get('pubnub'),
mixpanelToken: resin.models.config.getAll().get('mixpanelToken'),
apiConfig: resin.models.config.getAll(),
}).then((results) => {
return deviceConfig.generate({
application,
@ -51,9 +50,9 @@ export function generateBaseConfig(application: ResinSdk.Application, options: {
registry: results.registryUrl,
delta: results.deltaUrl,
},
pubnub: results.pubNubKeys,
pubnub: results.apiConfig.pubnub,
mixpanel: {
token: results.mixpanelToken,
token: results.apiConfig.mixpanelToken,
},
}, options);
});
@ -61,7 +60,7 @@ export function generateBaseConfig(application: ResinSdk.Application, options: {
export function generateApplicationConfig(application: ResinSdk.Application, options: {}) {
return generateBaseConfig(application, options)
.tap(config => authenticateWithApplicationKey(config, application.id));
.tap(config => addApplicationKey(config, application.id));
}
export function generateDeviceConfig(
@ -76,10 +75,10 @@ export function generateDeviceConfig(
// 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 != null) {
return authenticateWithDeviceKey(config, device.uuid, deviceApiKey);
if (deviceApiKey) {
return addDeviceKey(config, device.uuid, deviceApiKey);
} else {
return authenticateWithApplicationKey(config, application.id);
return addApplicationKey(config, application.id);
}
});
}).then((config) => {
@ -93,14 +92,14 @@ export function generateDeviceConfig(
});
}
function authenticateWithApplicationKey(config: any, applicationNameOrId: string | number) {
function addApplicationKey(config: any, applicationNameOrId: string | number) {
return resin.models.application.generateApiKey(applicationNameOrId)
.tap((apiKey) => {
config.apiKey = apiKey;
});
}
function authenticateWithDeviceKey(config: any, uuid: string, customDeviceApiKey: string) {
function addDeviceKey(config: any, uuid: string, customDeviceApiKey: string) {
return Promise.try(() => {
return customDeviceApiKey || resin.models.device.generateDeviceKey(uuid);
}).tap((deviceApiKey) => {

View File

@ -26,6 +26,10 @@ import ResinSdk = require('resin-sdk');
import { execute } from 'president';
import { InitializeEmitter, OperationState } from 'resin-device-init';
const extractStreamAsync = Promise.promisify(rindle.extract);
const waitStreamAsync = Promise.promisify(rindle.wait);
const presidentExecuteAsync = Promise.promisify(execute);
const resin = ResinSdk.fromSharedOptions();
export function getGroupDefaults(
@ -39,8 +43,8 @@ export function getGroupDefaults(
}
export function stateToString(state: OperationState) {
const percentage = _.padStart(`${state.percentage}`, 3, '0') + '%';
const result = `${chalk.blue(percentage)} ${chalk.cyan(state.operation.command)}`;
const percentage = _.padStart(`${state.percentage}`, 3, '0');
const result = `${chalk.blue(percentage + '%')} ${chalk.cyan(state.operation.command)}`;
switch (state.operation.command) {
case 'copy':
@ -61,7 +65,6 @@ export function sudo(command: string[]) {
command = _.union(_.take(process.argv, 2), command);
const presidentExecuteAsync = Promise.promisify(execute);
return presidentExecuteAsync(command);
}
@ -75,7 +78,8 @@ export function getManifest(image: string, deviceType: string): Promise<ResinSdk
primary: 1,
},
path: '/device-type.json',
}).then(Promise.promisify(rindle.extract))
})
.then(extractStreamAsync)
.then(JSON.parse)
.catch(() => resin.models.device.getManifestBySlug(deviceType));
}
@ -86,7 +90,7 @@ export function osProgressHandler(step: InitializeEmitter) {
step.on('state', function(state) {
if (state.operation.command === 'burn') { return; }
return console.log(exports.stateToString(state));
console.log(exports.stateToString(state));
});
const progressBars = {
@ -96,7 +100,7 @@ export function osProgressHandler(step: InitializeEmitter) {
step.on('burn', state => progressBars[state.type].update(state));
return Promise.promisify(rindle.wait)(step);
return waitStreamAsync(step);
}
export function getArchAndDeviceType(applicationName: string): Promise<{ arch: string, device_type: string }> {
@ -104,9 +108,9 @@ export function getArchAndDeviceType(applicationName: string): Promise<{ arch: s
getApplication(applicationName),
resin.models.config.getDeviceTypes(),
function (app, deviceTypes) {
let config = _.find(deviceTypes, { slug: app.device_type });
const config = _.find(deviceTypes, { slug: app.device_type });
if (config == null) {
if (!config) {
throw new Error('Could not read application information!');
}
@ -116,11 +120,11 @@ export function getArchAndDeviceType(applicationName: string): Promise<{ arch: s
}
function getApplication(applicationName: string) {
let match;
// Check for an app of the form `user/application`, and send
// this off to a special handler (before importing any modules)
if (match = /(\w+)\/(\w+)/.exec(applicationName)) {
// that off to a special handler (before importing any modules)
const match = /(\w+)\/(\w+)/.exec(applicationName);
if (match) {
return resin.models.application.getAppByOwner(match[2], match[1]);
}

View File

@ -33,11 +33,9 @@ export class Logger {
error: logger.createLogStream('error'),
};
_.mapKeys(this.streams, function(stream, key) {
if (key !== 'debug') {
return stream.pipe(process.stdout);
} else {
if (process.env.DEBUG != null) { return stream.pipe(process.stdout); }
_.forEach(this.streams, function(stream, key) {
if (key !== 'debug' || process.env.DEBUG) {
stream.pipe(process.stdout);
}
});

View File

@ -25,8 +25,8 @@ import messages = require('./messages');
const resin = ResinSdk.fromSharedOptions();
export function authenticate(options: {}) {
form.run([{
export function authenticate(options: {}): Promise<void> {
return form.run([{
message: 'Email:',
name: 'email',
type: 'input',
@ -44,13 +44,17 @@ export function authenticate(options: {}) {
return form.ask({
message: 'Two factor auth challenge:',
name: 'code',
type: 'input'}).then(resin.auth.twoFactor.challenge)
.catch((error: any) => resin.auth.logout().then(() => {
if ((error.name === 'ResinRequestError') && (error.statusCode === 401)) {
throw new Error('Invalid two factor authentication code');
}
throw error;
}));
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;
});
});
});
}
@ -132,8 +136,10 @@ export function selectOrCreateApplication() {
if (!hasAnyApplications) return;
return resin.models.application.getAll().then((applications) => {
let appOptions: { name: string, value: string | null }[];
appOptions = _.map(applications, application => ({
const appOptions = _.map<
ResinSdk.Application,
{ name: string, value: string | null }
>(applications, application => ({
name: `${application.app_name} (${application.device_type})`,
value: application.app_name,
}));
@ -150,7 +156,9 @@ export function selectOrCreateApplication() {
});
});
}).then((application) => {
if (application != null) return application;
if (application) {
return application;
}
return form.ask({
message: 'Choose a Name for your new application',
@ -189,13 +197,13 @@ export function awaitDevice(uuid: string) {
export function inferOrSelectDevice(preferredUuid: string) {
return resin.models.device.getAll()
.filter((device: ResinSdk.Device) => device.is_online)
.then((onlineDevices: ResinSdk.Device[]) => {
.filter<ResinSdk.Device>((device) => device.is_online)
.then((onlineDevices) => {
if (_.isEmpty(onlineDevices)) {
throw new Error('You don\'t have any devices online');
}
let defaultUuid = Array.from(_.map(onlineDevices, 'uuid')).includes(preferredUuid) ?
const defaultUuid = _.map(onlineDevices, 'uuid').includes(preferredUuid) ?
preferredUuid :
onlineDevices[0].uuid;

View File

@ -1,5 +1,3 @@
import { ReadStream } from 'fs';
export async function buffer(stream: NodeJS.ReadableStream, bufferFile: string) {
const Promise = await import('bluebird');
const fs = await import('fs');
@ -7,14 +5,15 @@ export async function buffer(stream: NodeJS.ReadableStream, bufferFile: string)
const fileWriteStream = fs.createWriteStream(bufferFile);
return new Promise(function(resolve, reject) {
return stream
stream
.on('error', reject)
.on('end', resolve)
.pipe(fileWriteStream);
}).then(() => new Promise(function(resolve, reject) {
fs.createReadStream(bufferFile)
.on('open', function(this: ReadStream) {
resolve(this);
}).on('error', reject);
const stream = fs.createReadStream(bufferFile);
stream
.on('open', () => resolve(stream))
.on('error', reject);
}));
}

View File

@ -34,18 +34,14 @@ if (!isRoot()) {
});
}
export function hasAvailableUpdate() {
return notifier != null;
}
export function notify() {
if (!exports.hasAvailableUpdate()) {
if (!notifier) {
return;
}
notifier.notify({ defer: false });
if (notifier.update != null) {
return 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

@ -1,4 +1,5 @@
declare module 'resin-device-init' {
import * as Promise from 'bluebird';
import { EventEmitter } from 'events';
interface OperationState {

View File

@ -1,4 +1,4 @@
declare module 'resin-sdk-preconfiguredasd' {
declare module 'resin-sdk-preconfigured' {
import { ResinSDK } from 'resin-sdk';
let sdk: ResinSDK;
export = sdk;