Bump resin-multibuild (2.1.4), docker-progress (3.0.5), resin-lint (3.0.1)

The new resin-multibuild and docker-progress versions widen the range
of errors caught by the 'balena push' and 'balena build' commands.

Change-type: patch
Signed-off-by: Paulo Castro <paulo@balena.io>
This commit is contained in:
Paulo Castro
2019-03-12 22:07:57 +00:00
parent da86d3303f
commit a883948d56
36 changed files with 508 additions and 175 deletions

View File

@ -1,6 +1,22 @@
import * as path from 'path'; /**
import * as fs from 'fs-extra'; * @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.
*/
import * as filehound from 'filehound'; import * as filehound from 'filehound';
import * as fs from 'fs-extra';
import * as path from 'path';
import { exec as execPkg } from 'pkg'; import { exec as execPkg } from 'pkg';
const ROOT = path.join(__dirname, '..'); const ROOT = path.join(__dirname, '..');

View File

@ -1,27 +1,46 @@
import capitanodoc = require('../../capitanodoc'); /**
* @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.
*/
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as path from 'path'; import * as path from 'path';
import capitanodoc = require('../../capitanodoc');
import { Category, Document } from './doc-types';
import * as markdown from './markdown'; import * as markdown from './markdown';
import { Document, Category } from './doc-types';
const result = <Document>{}; const result: Document = {
result.title = capitanodoc.title; title: capitanodoc.title,
result.introduction = capitanodoc.introduction; introduction: capitanodoc.introduction,
result.categories = []; categories: [],
};
for (let commandCategory of capitanodoc.categories) { for (const commandCategory of capitanodoc.categories) {
const category = <Category>{}; const category: Category = {
category.title = commandCategory.title; title: commandCategory.title,
category.commands = []; commands: [],
};
for (let file of commandCategory.files) { for (const file of commandCategory.files) {
// tslint:disable-next-line:no-var-requires // tslint:disable-next-line:no-var-requires
const actions: any = require(path.join(process.cwd(), file)); const actions: any = require(path.join(process.cwd(), file));
if (actions.signature) { if (actions.signature) {
category.commands.push(_.omit(actions, 'action')); category.commands.push(_.omit(actions, 'action'));
} else { } else {
for (let actionName of Object.keys(actions)) { for (const actionName of Object.keys(actions)) {
const actionCommand = actions[actionName]; const actionCommand = actions[actionName];
category.commands.push(_.omit(actionCommand, 'action')); category.commands.push(_.omit(actionCommand, 'action'));
} }

View File

@ -1,7 +1,24 @@
import * as _ from 'lodash'; /**
* @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.
*/
import * as ent from 'ent'; import * as ent from 'ent';
import * as _ from 'lodash';
import { Category, Command, Document } from './doc-types';
import * as utils from './utils'; import * as utils from './utils';
import { Document, Category, Command } from './doc-types';
export function renderCommand(command: Command) { export function renderCommand(command: Command) {
let result = `## ${ent.encode(command.signature)}\n\n${command.help}\n`; let result = `## ${ent.encode(command.signature)}\n\n${command.help}\n`;
@ -9,7 +26,7 @@ export function renderCommand(command: Command) {
if (!_.isEmpty(command.options)) { if (!_.isEmpty(command.options)) {
result += '\n### Options'; result += '\n### Options';
for (let option of command.options!) { for (const option of command.options!) {
result += `\n\n#### ${utils.parseSignature(option)}\n\n${ result += `\n\n#### ${utils.parseSignature(option)}\n\n${
option.description option.description
}`; }`;
@ -24,7 +41,7 @@ export function renderCommand(command: Command) {
export function renderCategory(category: Category) { export function renderCategory(category: Category) {
let result = `# ${category.title}\n`; let result = `# ${category.title}\n`;
for (let command of category.commands) { for (const command of category.commands) {
result += `\n${renderCommand(command)}`; result += `\n${renderCommand(command)}`;
} }
@ -51,10 +68,10 @@ function getAnchor(command: Command) {
export function renderToc(categories: Category[]) { export function renderToc(categories: Category[]) {
let result = `# Table of contents\n`; let result = `# Table of contents\n`;
for (let category of categories) { for (const category of categories) {
result += `\n- ${category.title}\n\n`; result += `\n- ${category.title}\n\n`;
for (let command of category.commands) { for (const command of category.commands) {
result += `\t- [${ent.encode(command.signature)}](${getAnchor( result += `\t- [${ent.encode(command.signature)}](${getAnchor(
command, command,
)})\n`; )})\n`;
@ -69,7 +86,7 @@ export function render(doc: Document) {
doc.categories, doc.categories,
)}`; )}`;
for (let category of doc.categories) { for (const category of doc.categories) {
result += `\n${renderCategory(category)}`; result += `\n${renderCategory(category)}`;
} }

View File

@ -1,6 +1,22 @@
/**
* @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.
*/
import { OptionDefinition } from 'capitano'; import { OptionDefinition } from 'capitano';
import * as _ from 'lodash';
import * as ent from 'ent'; import * as ent from 'ent';
import * as _ from 'lodash';
export function getOptionPrefix(signature: string) { export function getOptionPrefix(signature: string) {
if (signature.length > 1) { if (signature.length > 1) {
@ -18,7 +34,7 @@ export function parseSignature(option: OptionDefinition) {
let result = getOptionSignature(option.signature); let result = getOptionSignature(option.signature);
if (_.isArray(option.alias)) { if (_.isArray(option.alias)) {
for (let alias of option.alias) { for (const alias of option.alias) {
result += `, ${getOptionSignature(alias)}`; result += `, ${getOptionSignature(alias)}`;
} }
} else if (_.isString(option.alias)) { } else if (_.isString(option.alias)) {

View File

@ -1,10 +1,27 @@
/**
* @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.
*/
import * as archiver from 'archiver';
import * as Promise from 'bluebird'; import * as Promise from 'bluebird';
import * as path from 'path';
import * as os from 'os';
import * as fs from 'fs-extra'; import * as fs from 'fs-extra';
import * as mkdirp from 'mkdirp'; import * as mkdirp from 'mkdirp';
import * as os from 'os';
import * as path from 'path';
import * as publishRelease from 'publish-release'; import * as publishRelease from 'publish-release';
import * as archiver from 'archiver';
import * as packageJSON from '../package.json'; import * as packageJSON from '../package.json';
const publishReleaseAsync = Promise.promisify(publishRelease); const publishReleaseAsync = Promise.promisify(publishRelease);
@ -26,12 +43,12 @@ mkdirpAsync(path.dirname(outputFile))
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
console.log('Zipping build...'); console.log('Zipping build...');
let archive = archiver('zip', { const archive = archiver('zip', {
zlib: { level: 7 }, zlib: { level: 7 },
}); });
archive.directory(path.join(ROOT, 'build-bin'), 'balena-cli'); archive.directory(path.join(ROOT, 'build-bin'), 'balena-cli');
let outputStream = fs.createWriteStream(outputFile); const outputStream = fs.createWriteStream(outputFile);
outputStream.on('close', resolve); outputStream.on('close', resolve);
outputStream.on('error', reject); outputStream.on('error', reject);
@ -48,7 +65,7 @@ mkdirpAsync(path.dirname(outputFile))
console.log('Publishing build...'); console.log('Publishing build...');
return publishReleaseAsync({ return publishReleaseAsync({
token: <string>GITHUB_TOKEN, token: GITHUB_TOKEN || '',
owner: 'balena-io', owner: 'balena-io',
repo: 'balena-cli', repo: 'balena-cli',
tag: version, tag: version,

View File

@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { ApplicationVariable, DeviceVariable } from 'balena-sdk';
import { CommandDefinition } from 'capitano'; import { CommandDefinition } from 'capitano';
import * as commandOptions from './command-options';
import { normalizeUuidProp } from '../utils/normalization';
import { DeviceVariable, ApplicationVariable } from 'balena-sdk';
import { stripIndent } from 'common-tags'; import { stripIndent } from 'common-tags';
import { normalizeUuidProp } from '../utils/normalization';
import * as commandOptions from './command-options';
const getReservedPrefixes = async (): Promise<string[]> => { const getReservedPrefixes = async (): Promise<string[]> => {
const balena = (await import('balena-sdk')).fromSharedOptions(); const balena = (await import('balena-sdk')).fromSharedOptions();
const settings = await balena.settings.getAll(); const settings = await balena.settings.getAll();

View File

@ -17,17 +17,17 @@ limitations under the License.
import { CommandDefinition } from 'capitano'; import { CommandDefinition } from 'capitano';
import chalk from 'chalk'; import chalk from 'chalk';
import { stripIndent } from 'common-tags'; import { stripIndent } from 'common-tags';
import * as sdk from 'etcher-sdk'; import * as SDK from 'etcher-sdk';
async function getDrive(options: { async function getDrive(options: {
drive?: string; drive?: string;
}): Promise<sdk.sourceDestination.BlockDevice> { }): Promise<SDK.sourceDestination.BlockDevice> {
const sdk = await import('etcher-sdk'); const sdk = await import('etcher-sdk');
const adapter = new sdk.scanner.adapters.BlockDeviceAdapter(() => false); const adapter = new sdk.scanner.adapters.BlockDeviceAdapter(() => false);
const scanner = new sdk.scanner.Scanner([adapter]); const scanner = new sdk.scanner.Scanner([adapter]);
await scanner.start(); await scanner.start();
let drive: sdk.sourceDestination.BlockDevice; let drive: SDK.sourceDestination.BlockDevice;
if (options.drive !== undefined) { if (options.drive !== undefined) {
const d = scanner.getBy('device', options.drive); const d = scanner.getBy('device', options.drive);
if (d === undefined || !(d instanceof sdk.sourceDestination.BlockDevice)) { if (d === undefined || !(d instanceof sdk.sourceDestination.BlockDevice)) {
@ -49,7 +49,6 @@ export const flash: CommandDefinition<
> = { > = {
signature: 'local flash <image>', signature: 'local flash <image>',
description: 'Flash an image to a drive', description: 'Flash an image to a drive',
//root: true,
help: stripIndent` help: stripIndent`
Use this command to flash a balenaOS image to a drive. Use this command to flash a balenaOS image to a drive.
@ -111,7 +110,7 @@ export const flash: CommandDefinition<
// onFail // onFail
console.log(chalk.red.bold(error.message)); console.log(chalk.red.bold(error.message));
}, },
(progress: sdk.multiWrite.MultiDestinationProgress) => { (progress: SDK.multiWrite.MultiDestinationProgress) => {
// onProgress // onProgress
progressBars[progress.type].update(progress); progressBars[progress.type].update(progress);
}, },

View File

@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { BalenaSDK } from 'balena-sdk';
import { CommandDefinition } from 'capitano'; import { CommandDefinition } from 'capitano';
import { stripIndent } from 'common-tags'; import { stripIndent } from 'common-tags';
import { BalenaSDK } from 'balena-sdk';
import { registrySecretsHelp } from '../utils/messages'; import { registrySecretsHelp } from '../utils/messages';

View File

@ -14,11 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import * as Bluebird from 'bluebird'; import * as Bluebird from 'bluebird';
import * as _ from 'lodash';
import { CommandDefinition } from 'capitano'; import { CommandDefinition } from 'capitano';
import { stripIndent } from 'common-tags'; import { stripIndent } from 'common-tags';
import * as _ from 'lodash';
import { createServer, Server, Socket } from 'net';
import { isArray } from 'util'; import { isArray } from 'util';
import { Socket, Server, createServer } from 'net';
import { tunnelConnectionToDevice } from '../utils/tunnel'; import { tunnelConnectionToDevice } from '../utils/tunnel';
interface Args { interface Args {
@ -30,7 +31,7 @@ interface Options {
} }
class DeviceIsOfflineError extends Error { class DeviceIsOfflineError extends Error {
uuid: string; public uuid: string;
constructor(uuid: string) { constructor(uuid: string) {
super(`Device '${uuid}' is offline`); super(`Device '${uuid}' is offline`);
this.uuid = uuid; this.uuid = uuid;
@ -68,7 +69,7 @@ export const tunnel: CommandDefinition<Args, Options> = {
# map remote port 22222 to localhost:22222 # map remote port 22222 to localhost:22222
$ balena tunnel abcde12345 -p 22222 $ balena tunnel abcde12345 -p 22222
# map remote port 22222 to localhost:222 # map remote port 22222 to localhost:222
$ balena tunnel abcde12345 -p 22222:222 $ balena tunnel abcde12345 -p 22222:222
@ -146,29 +147,30 @@ export const tunnel: CommandDefinition<Args, Options> = {
} }
// grab the groups // grab the groups
// tslint:disable-next-line:prefer-const
let [, remotePort, localAddress, localPort] = regexResult; let [, remotePort, localAddress, localPort] = regexResult;
if ( if (
!isValidPort(parseInt(localPort)) || !isValidPort(parseInt(localPort, undefined)) ||
!isValidPort(parseInt(remotePort)) !isValidPort(parseInt(remotePort, undefined))
) { ) {
throw new InvalidPortMappingError(mapping); throw new InvalidPortMappingError(mapping);
} }
// default bind to localAddress // default bind to localAddress
if (localAddress == undefined) { if (localAddress == null) {
localAddress = 'localhost'; localAddress = 'localhost';
} }
// default use same port number locally as remote // default use same port number locally as remote
if (localPort == undefined) { if (localPort == null) {
localPort = remotePort; localPort = remotePort;
} }
return { return {
localPort: parseInt(localPort), localPort: parseInt(localPort, undefined),
localAddress, localAddress,
remotePort: parseInt(remotePort), remotePort: parseInt(remotePort, undefined),
}; };
}) })
.map(({ localPort, localAddress, remotePort }) => { .map(({ localPort, localAddress, remotePort }) => {

View File

@ -14,11 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import * as Promise from 'bluebird';
import { stripIndent } from 'common-tags';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as os from 'os'; import * as os from 'os';
import * as Raven from 'raven'; import * as Raven from 'raven';
import * as Promise from 'bluebird';
import { stripIndent } from 'common-tags';
import * as patterns from './utils/patterns'; import * as patterns from './utils/patterns';

View File

@ -1,10 +1,26 @@
/**
* @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.
*/
import BalenaSdk = require('balena-sdk');
import Promise = require('bluebird');
import * as Capitano from 'capitano'; import * as Capitano from 'capitano';
import _ = require('lodash'); import _ = require('lodash');
import Mixpanel = require('mixpanel'); import Mixpanel = require('mixpanel');
import Raven = require('raven'); import Raven = require('raven');
import Promise = require('bluebird');
import BalenaSdk = require('balena-sdk');
import packageJSON = require('../package.json'); import packageJSON = require('../package.json');
const getBalenaSdk = _.once(() => BalenaSdk.fromSharedOptions()); const getBalenaSdk = _.once(() => BalenaSdk.fromSharedOptions());

View File

@ -333,6 +333,7 @@ tagServiceImages = (docker, images, serviceImages) ->
Promise.map images, (d) -> Promise.map images, (d) ->
serviceImage = serviceImages[d.serviceName] serviceImage = serviceImages[d.serviceName]
imageName = serviceImage.is_stored_at__image_location imageName = serviceImage.is_stored_at__image_location
# coffeelint: disable-next-line=check_scope ("Variable is assigned to but never read")
[ _match, registry, repo, tag = 'latest' ] = /(.*?)\/(.*?)(?::([^/]*))?$/.exec(imageName) [ _match, registry, repo, tag = 'latest' ] = /(.*?)\/(.*?)(?::([^/]*))?$/.exec(imageName)
name = "#{registry}/#{repo}" name = "#{registry}/#{repo}"
docker.getImage(d.name).tag({ repo: name, tag, force: true }) docker.getImage(d.name).tag({ repo: name, tag, force: true })

View File

@ -16,9 +16,10 @@
*/ */
import * as Bluebird from 'bluebird'; import * as Bluebird from 'bluebird';
import * as Stream from 'stream';
import { Composition } from 'resin-compose-parse'; import { Composition } from 'resin-compose-parse';
import * as Stream from 'stream';
import { Pack } from 'tar-stream'; import { Pack } from 'tar-stream';
import Logger = require('./logger'); import Logger = require('./logger');
interface Image { interface Image {

View File

@ -14,13 +14,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import * as _ from 'lodash';
import * as Bluebird from 'bluebird'; import * as Bluebird from 'bluebird';
import * as tar from 'tar-stream'; import * as _ from 'lodash';
import { Readable } from 'stream';
import * as MultiBuild from 'resin-multibuild';
import { Composition } from 'resin-compose-parse'; import { Composition } from 'resin-compose-parse';
import * as MultiBuild from 'resin-multibuild';
import { Readable } from 'stream';
import * as tar from 'tar-stream';
import { DeviceInfo } from './device/api'; import { DeviceInfo } from './device/api';
import Logger = require('./logger'); import Logger = require('./logger');

View File

@ -13,13 +13,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import Promise = require('bluebird');
import BalenaSdk = require('balena-sdk'); import BalenaSdk = require('balena-sdk');
import Promise = require('bluebird');
import * as semver from 'resin-semver'; import * as semver from 'resin-semver';
const balena = BalenaSdk.fromSharedOptions(); const balena = BalenaSdk.fromSharedOptions();
type ImgConfig = { interface ImgConfig {
applicationName: string; applicationName: string;
applicationId: number; applicationId: number;
deviceType: string; deviceType: string;
@ -46,7 +46,7 @@ type ImgConfig = {
deviceId?: number; deviceId?: number;
uuid?: string; uuid?: string;
registered_at?: number; registered_at?: number;
}; }
export function generateBaseConfig( export function generateBaseConfig(
application: BalenaSdk.Application, application: BalenaSdk.Application,

View File

@ -1,9 +1,24 @@
/**
* @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.
*/
import * as Bluebird from 'bluebird'; import * as Bluebird from 'bluebird';
import * as request from 'request'; import * as request from 'request';
import * as Stream from 'stream'; import * as Stream from 'stream';
import Logger = require('../logger'); import Logger = require('../logger');
import * as ApiErrors from './errors'; import * as ApiErrors from './errors';
export interface DeviceResponse { export interface DeviceResponse {
@ -145,10 +160,11 @@ export class DeviceAPI {
opts: T, opts: T,
logger?: Logger, logger?: Logger,
): Promise<any> { ): Promise<any> {
const Bluebird = await import('bluebird');
const _ = await import('lodash'); const _ = await import('lodash');
type ObjectWithUrl = { url?: string }; interface ObjectWithUrl {
url?: string;
}
if (logger != null) { if (logger != null) {
let url: string | null = null; let url: string | null = null;

View File

@ -28,15 +28,15 @@ import {
import * as semver from 'resin-semver'; import * as semver from 'resin-semver';
import { Readable } from 'stream'; import { Readable } from 'stream';
import Logger = require('../logger');
import { displayBuildLog } from './logs';
import { makeBuildTasks } from '../compose_ts'; import { makeBuildTasks } from '../compose_ts';
import Logger = require('../logger');
import { DeviceInfo } from './api'; import { DeviceInfo } from './api';
import * as LocalPushErrors from './errors'; import * as LocalPushErrors from './errors';
import { displayBuildLog } from './logs';
// Define the logger here so the debug output // Define the logger here so the debug output
// can be used everywhere // can be used everywhere
const logger = new Logger(); const globalLogger = new Logger();
export interface DeviceDeployOptions { export interface DeviceDeployOptions {
source: string; source: string;
@ -61,7 +61,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
exitWithExpectedError(`Could not access source directory: ${opts.source}`); exitWithExpectedError(`Could not access source directory: ${opts.source}`);
} }
const api = new DeviceAPI(logger, opts.deviceHost); const api = new DeviceAPI(globalLogger, opts.deviceHost);
// First check that we can access the device with a ping // First check that we can access the device with a ping
try { try {
@ -88,9 +88,9 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
exitWithExpectedError(versionError); exitWithExpectedError(versionError);
} }
logger.logInfo(`Starting build on device ${opts.deviceHost}`); globalLogger.logInfo(`Starting build on device ${opts.deviceHost}`);
const project = await loadProject(logger, opts.source, 'local'); const project = await loadProject(globalLogger, opts.source, 'local');
// Attempt to attach to the device's docker daemon // Attempt to attach to the device's docker daemon
const docker = connectToDocker( const docker = connectToDocker(
@ -108,11 +108,11 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
tarStream, tarStream,
docker, docker,
deviceInfo, deviceInfo,
logger, globalLogger,
opts, opts,
); );
logger.logDebug('Setting device state...'); globalLogger.logDebug('Setting device state...');
// Now set the target state on the device // Now set the target state on the device
const currentTargetState = await api.getTargetState(); const currentTargetState = await api.getTargetState();
@ -121,18 +121,18 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
currentTargetState, currentTargetState,
project.composition, project.composition,
); );
logger.logDebug(`Sending target state: ${JSON.stringify(targetState)}`); globalLogger.logDebug(`Sending target state: ${JSON.stringify(targetState)}`);
await api.setTargetState(targetState); await api.setTargetState(targetState);
// Print an empty newline to seperate the build output // Print an empty newline to separate the build output
// from the device output // from the device output
console.log(); console.log();
logger.logInfo('Streaming device logs...'); globalLogger.logInfo('Streaming device logs...');
// Now all we need to do is stream back the logs // Now all we need to do is stream back the logs
const logStream = await api.getLogStream(); const logStream = await api.getLogStream();
await displayDeviceLogs(logStream, logger); await displayDeviceLogs(logStream, globalLogger);
} }
function connectToDocker(host: string, port: number): Docker { function connectToDocker(host: string, port: number): Docker {
@ -226,7 +226,7 @@ async function assignDockerBuildOpts(
// that we can use all of them for cache // that we can use all of them for cache
const images = await getDeviceDockerImages(docker); const images = await getDeviceDockerImages(docker);
logger.logDebug(`Using ${images.length} on-device images for cache...`); globalLogger.logDebug(`Using ${images.length} on-device images for cache...`);
await Bluebird.map(buildTasks, async (task: BuildTask) => { await Bluebird.map(buildTasks, async (task: BuildTask) => {
task.dockerOpts = { task.dockerOpts = {

View File

@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import os = require('os');
import Bluebird = require('bluebird');
import _ = require('lodash');
import chalk from 'chalk';
import rindle = require('rindle');
import visuals = require('resin-cli-visuals');
import BalenaSdk = require('balena-sdk'); import BalenaSdk = require('balena-sdk');
import Bluebird = require('bluebird');
import chalk from 'chalk';
import _ = require('lodash');
import os = require('os');
import visuals = require('resin-cli-visuals');
import rindle = require('rindle');
import { InitializeEmitter, OperationState } from 'balena-device-init'; import { InitializeEmitter, OperationState } from 'balena-device-init';
@ -29,7 +29,7 @@ const waitStreamAsync = Bluebird.promisify(rindle.wait);
const balena = BalenaSdk.fromSharedOptions(); const balena = BalenaSdk.fromSharedOptions();
export function getGroupDefaults(group: { export function getGroupDefaults(group: {
options: { name: string; default?: string }[]; options: Array<{ name: string; default?: string }>;
}): { [name: string]: string | undefined } { }): { [name: string]: string | undefined } {
return _.chain(group) return _.chain(group)
.get('options') .get('options')

View File

@ -120,7 +120,7 @@ export class FileIgnorer {
}); });
return !_.some(ignoreTypes, ({ handle }) => handle.ignores(relFile)); return !_.some(ignoreTypes, ({ handle }) => handle.ignores(relFile));
}; }; // tslint:disable-line:semicolon
private addEntry( private addEntry(
pattern: string, pattern: string,

View File

@ -1,3 +1,19 @@
/**
* @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.
*/
import chalk from 'chalk'; import chalk from 'chalk';
import _ = require('lodash'); import _ = require('lodash');
import { EOL as eol } from 'os'; import { EOL as eol } from 'os';
@ -45,31 +61,31 @@ class Logger {
this.formatMessage = logger.formatWithPrefix.bind(logger); this.formatMessage = logger.formatWithPrefix.bind(logger);
} }
logInfo(msg: string) { public logInfo(msg: string) {
return this.streams.info.write(msg + eol); return this.streams.info.write(msg + eol);
} }
logDebug(msg: string) { public logDebug(msg: string) {
return this.streams.debug.write(msg + eol); return this.streams.debug.write(msg + eol);
} }
logSuccess(msg: string) { public logSuccess(msg: string) {
return this.streams.success.write(msg + eol); return this.streams.success.write(msg + eol);
} }
logWarn(msg: string) { public logWarn(msg: string) {
return this.streams.warn.write(msg + eol); return this.streams.warn.write(msg + eol);
} }
logError(msg: string) { public logError(msg: string) {
return this.streams.error.write(msg + eol); return this.streams.error.write(msg + eol);
} }
logBuild(msg: string) { public logBuild(msg: string) {
return this.streams.build.write(msg + eol); return this.streams.build.write(msg + eol);
} }
logLogs(msg: string) { public logLogs(msg: string) {
return this.streams.logs.write(msg + eol); return this.streams.logs.write(msg + eol);
} }
} }

View File

@ -13,15 +13,15 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import BalenaSdk = require('balena-sdk');
import Promise = require('bluebird');
import chalk from 'chalk';
import _ = require('lodash');
import _form = require('resin-cli-form'); import _form = require('resin-cli-form');
import _visuals = require('resin-cli-visuals'); import _visuals = require('resin-cli-visuals');
import _ = require('lodash');
import Promise = require('bluebird');
import BalenaSdk = require('balena-sdk');
import chalk from 'chalk';
import validation = require('./validation');
import messages = require('./messages'); import messages = require('./messages');
import validation = require('./validation');
const getBalenaSdk = _.once(() => BalenaSdk.fromSharedOptions()); const getBalenaSdk = _.once(() => BalenaSdk.fromSharedOptions());
@ -173,7 +173,9 @@ export function selectOrCreateApplication() {
return balena.models.application return balena.models.application
.hasAny() .hasAny()
.then(hasAnyApplications => { .then(hasAnyApplications => {
if (!hasAnyApplications) return; if (!hasAnyApplications) {
return;
}
return balena.models.application.getAll().then(applications => { return balena.models.application.getAll().then(applications => {
const appOptions = _.map< const appOptions = _.map<

View File

@ -1,9 +1,24 @@
import { stripIndent } from 'common-tags'; /**
* @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.
*/
import * as BalenaSdk from 'balena-sdk'; import * as BalenaSdk from 'balena-sdk';
import { stripIndent } from 'common-tags';
import Logger = require('./logger');
import { runCommand } from './helpers'; import { runCommand } from './helpers';
import Logger = require('./logger');
import { exec, execBuffered } from './ssh'; import { exec, execBuffered } from './ssh';
const MIN_BALENAOS_VERSION = 'v2.14.0'; const MIN_BALENAOS_VERSION = 'v2.14.0';
@ -34,7 +49,7 @@ export async function join(
logger.logDebug('Determining application...'); logger.logDebug('Determining application...');
const app = await getOrSelectApplication(sdk, deviceType, appName); const app = await getOrSelectApplication(sdk, deviceType, appName);
logger.logDebug(`Using application: ${app.app_name} (${app.device_type})`); logger.logDebug(`Using application: ${app.app_name} (${app.device_type})`);
if (app.device_type != deviceType) { if (app.device_type !== deviceType) {
logger.logDebug(`Forcing device type to: ${deviceType}`); logger.logDebug(`Forcing device type to: ${deviceType}`);
app.device_type = deviceType; app.device_type = deviceType;
} }
@ -206,28 +221,12 @@ async function getOrSelectApplication(
.value(); .value();
if (!appName) { if (!appName) {
const options = { return createOrSelectAppOrExit(
$filter: { device_type: { $in: compatibleDeviceTypes } }, form,
}; sdk,
compatibleDeviceTypes,
// No application specified, show a list to select one. deviceType,
const applications = await sdk.models.application.getAll(options); );
if (applications.length === 0) {
const shouldCreateApp = await form.ask({
message:
'You have no applications this device can join.\n' +
'Would you like to create one now?',
type: 'confirm',
default: true,
});
if (shouldCreateApp) {
return createApplication(sdk, deviceType);
}
process.exit(1);
}
return selectAppFromList(applications);
} }
const options: BalenaSdk.PineOptionsFor<BalenaSdk.Application> = {}; const options: BalenaSdk.PineOptionsFor<BalenaSdk.Application> = {};
@ -279,6 +278,39 @@ async function getOrSelectApplication(
return selectAppFromList(applications); return selectAppFromList(applications);
} }
// TODO: revisit this function's purpose. It was refactored out of
// `getOrSelectApplication` above in order to satisfy some resin-lint v3
// rules, but it looks like there's a fair amount of duplicate logic.
async function createOrSelectAppOrExit(
form: any,
sdk: BalenaSdk.BalenaSDK,
compatibleDeviceTypes: string[],
deviceType: string,
) {
const options = {
$filter: { device_type: { $in: compatibleDeviceTypes } },
};
// No application specified, show a list to select one.
const applications = await sdk.models.application.getAll(options);
if (applications.length === 0) {
const shouldCreateApp = await form.ask({
message:
'You have no applications this device can join.\n' +
'Would you like to create one now?',
type: 'confirm',
default: true,
});
if (shouldCreateApp) {
return createApplication(sdk, deviceType);
}
process.exit(1);
}
return selectAppFromList(applications);
}
async function createApplication( async function createApplication(
sdk: BalenaSdk.BalenaSDK, sdk: BalenaSdk.BalenaSDK,
deviceType: string, deviceType: string,
@ -294,7 +326,7 @@ async function createApplication(
} }
username = username.toLowerCase(); username = username.toLowerCase();
const appName = await new Promise<string>(async (resolve, reject) => { const applicationName = await new Promise<string>(async (resolve, reject) => {
while (true) { while (true) {
try { try {
const appName = await form.ask({ const appName = await form.ask({
@ -327,7 +359,7 @@ async function createApplication(
}); });
return sdk.models.application.create({ return sdk.models.application.create({
name: appName, name: applicationName,
deviceType, deviceType,
}); });
} }

View File

@ -13,14 +13,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { BalenaSDK } from 'balena-sdk';
import * as Bluebird from 'bluebird'; import * as Bluebird from 'bluebird';
import * as JSONStream from 'JSONStream'; import * as JSONStream from 'JSONStream';
import * as readline from 'readline'; import * as readline from 'readline';
import * as request from 'request'; import * as request from 'request';
import * as Stream from 'stream';
import { BalenaSDK } from 'balena-sdk';
import { Pack } from 'tar-stream';
import { RegistrySecrets } from 'resin-multibuild'; import { RegistrySecrets } from 'resin-multibuild';
import * as Stream from 'stream';
import { Pack } from 'tar-stream';
import { TypedError } from 'typed-error'; import { TypedError } from 'typed-error';
import { exitWithExpectedError } from '../utils/patterns'; import { exitWithExpectedError } from '../utils/patterns';
@ -278,7 +278,7 @@ function createRemoteBuildRequest(
); );
} }
} else { } else {
let msgArr = [ const msgArr = [
'Remote builder responded with HTTP error:', 'Remote builder responded with HTTP error:',
`${response.statusCode} ${response.statusMessage}`, `${response.statusCode} ${response.statusMessage}`,
]; ];

View File

@ -1,5 +1,21 @@
import { spawn } from 'child_process'; /**
* @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.
*/
import * as Bluebird from 'bluebird'; import * as Bluebird from 'bluebird';
import { spawn } from 'child_process';
import { TypedError } from 'typed-error'; import { TypedError } from 'typed-error';
import { getSubShellCommand } from './helpers'; import { getSubShellCommand } from './helpers';
@ -41,7 +57,7 @@ export async function exec(
ps.stdout.pipe(stdout); ps.stdout.pipe(stdout);
} }
}); });
if (exitCode != 0) { if (exitCode !== 0) {
throw new ExecError(cmd, exitCode); throw new ExecError(cmd, exitCode);
} }
} }

View File

@ -1,3 +1,19 @@
/**
* @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.
*/
import Promise = require('bluebird'); import Promise = require('bluebird');
import fs = require('fs'); import fs = require('fs');
@ -15,9 +31,9 @@ export function buffer(
}).then( }).then(
() => () =>
new Promise(function(resolve, reject) { new Promise(function(resolve, reject) {
const stream = fs.createReadStream(bufferFile); const fstream = fs.createReadStream(bufferFile);
stream.on('open', () => resolve(stream)).on('error', reject); fstream.on('open', () => resolve(fstream)).on('error', reject);
}), }),
); );
} }

View File

@ -13,16 +13,16 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import * as Bluebird from 'bluebird';
import { BalenaSDK } from 'balena-sdk'; import { BalenaSDK } from 'balena-sdk';
import * as Bluebird from 'bluebird';
import { Socket } from 'net'; import { Socket } from 'net';
import { TypedError } from 'typed-error'; import { TypedError } from 'typed-error';
const PROXY_CONNECT_TIMEOUT_MS = 10000; const PROXY_CONNECT_TIMEOUT_MS = 10000;
class UnableToConnectError extends TypedError { class UnableToConnectError extends TypedError {
status: string; public status: string;
statusCode: string; public statusCode: string;
constructor(statusCode: string, status: string) { constructor(statusCode: string, status: string) {
super(`Unable to connect: ${statusCode} ${status}`); super(`Unable to connect: ${statusCode} ${status}`);
this.status = status; this.status = status;
@ -31,7 +31,7 @@ class UnableToConnectError extends TypedError {
} }
class RemoteSocketNotListening extends TypedError { class RemoteSocketNotListening extends TypedError {
port: number; public port: number;
constructor(port: number) { constructor(port: number) {
super(`Device is not listening on port ${port}`); super(`Device is not listening on port ${port}`);
} }
@ -104,7 +104,7 @@ const openPortThroughProxy = (
const [httpStatus] = data.toString('utf8').split('\r\n'); const [httpStatus] = data.toString('utf8').split('\r\n');
const [, httpStatusCode, ...httpMessage] = httpStatus.split(' '); const [, httpStatusCode, ...httpMessage] = httpStatus.split(' ');
if (parseInt(httpStatusCode) === 200) { if (parseInt(httpStatusCode, 10) === 200) {
proxyTunnel.setTimeout(0); proxyTunnel.setTimeout(0);
resolve(proxyTunnel); resolve(proxyTunnel);
} else { } else {

View File

@ -14,8 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import * as UpdateNotifier from 'update-notifier';
import isRoot = require('is-root'); import isRoot = require('is-root');
import * as UpdateNotifier from 'update-notifier';
import packageJSON = require('../../package.json'); import packageJSON = require('../../package.json');
// Check for an update once a day. 1 day granularity should be // Check for an update once a day. 1 day granularity should be

View File

@ -1,3 +1,19 @@
/**
* @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.
*/
import DynamicList = require('inquirer-dynamic-list'); import DynamicList = require('inquirer-dynamic-list');
export abstract class CustomDynamicList<T> extends DynamicList { export abstract class CustomDynamicList<T> extends DynamicList {
@ -9,7 +25,7 @@ export abstract class CustomDynamicList<T> extends DynamicList {
protected abstract format(thing: T): string; protected abstract format(thing: T): string;
refresh(): void { public refresh(): void {
this.opt.choices.choices = []; this.opt.choices.choices = [];
this.opt.choices.realChoices = []; this.opt.choices.realChoices = [];
for (const thing of this.getThings()) { for (const thing of this.getThings()) {
@ -18,7 +34,7 @@ export abstract class CustomDynamicList<T> extends DynamicList {
this.render(); this.render();
} }
async run(): Promise<T> { public async run(): Promise<T> {
this.refresh(); this.refresh();
return await super.run(); return await super.run();
} }

View File

@ -66,14 +66,16 @@
"@types/archiver": "2.1.2", "@types/archiver": "2.1.2",
"@types/bluebird": "3.5.21", "@types/bluebird": "3.5.21",
"@types/common-tags": "1.4.0", "@types/common-tags": "1.4.0",
"@types/dockerode": "2.5.5",
"@types/es6-promise": "0.0.32", "@types/es6-promise": "0.0.32",
"@types/fs-extra": "5.0.4", "@types/fs-extra": "5.0.4",
"@types/is-root": "1.0.0", "@types/is-root": "1.0.0",
"@types/lodash": "4.14.103", "@types/lodash": "4.14.112",
"@types/mkdirp": "0.5.2", "@types/mkdirp": "0.5.2",
"@types/node": "6.14.2", "@types/node": "6.14.2",
"@types/prettyjson": "0.0.28", "@types/prettyjson": "0.0.28",
"@types/raven": "2.5.1", "@types/raven": "2.5.1",
"@types/tar-stream": "1.6.0",
"catch-uncommitted": "^1.0.0", "catch-uncommitted": "^1.0.0",
"ent": "^2.2.0", "ent": "^2.2.0",
"filehound": "^1.16.2", "filehound": "^1.16.2",
@ -85,10 +87,10 @@
"gulp-shell": "^0.5.2", "gulp-shell": "^0.5.2",
"mochainon": "^2.0.0", "mochainon": "^2.0.0",
"pkg": "^4.3.0-beta.1", "pkg": "^4.3.0-beta.1",
"prettier": "^1.14.2", "prettier": "^1.15.3",
"publish-release": "^1.3.3", "publish-release": "^1.3.3",
"require-npm4-to-publish": "^1.0.0", "require-npm4-to-publish": "^1.0.0",
"resin-lint": "^2.0.1", "resin-lint": "^3.0.1",
"rewire": "^3.0.2", "rewire": "^3.0.2",
"ts-node": "^4.0.1", "ts-node": "^4.0.1",
"typescript": "2.8.1" "typescript": "2.8.1"
@ -113,7 +115,7 @@
"balena-settings-client": "^4.0.0", "balena-settings-client": "^4.0.0",
"balena-sync": "^10.0.2", "balena-sync": "^10.0.2",
"bash": "0.0.1", "bash": "0.0.1",
"bluebird": "^3.3.3", "bluebird": "^3.5.3",
"body-parser": "^1.14.1", "body-parser": "^1.14.1",
"capitano": "^1.9.0", "capitano": "^1.9.0",
"chalk": "^2.3.0", "chalk": "^2.3.0",
@ -123,9 +125,9 @@
"columnify": "^1.5.2", "columnify": "^1.5.2",
"common-tags": "^1.7.2", "common-tags": "^1.7.2",
"denymount": "^2.2.0", "denymount": "^2.2.0",
"docker-progress": "^3.0.4", "docker-progress": "^3.0.5",
"docker-qemu-transpose": "^0.5.3", "docker-qemu-transpose": "^0.5.3",
"docker-toolbelt": "^3.3.5", "docker-toolbelt": "^3.3.7",
"dockerode": "^2.5.5", "dockerode": "^2.5.5",
"dockerode-options": "^0.2.1", "dockerode-options": "^0.2.1",
"ejs": "^2.5.7", "ejs": "^2.5.7",
@ -157,10 +159,10 @@
"request": "^2.81.0", "request": "^2.81.0",
"resin-cli-form": "^2.0.1", "resin-cli-form": "^2.0.1",
"resin-cli-visuals": "^1.4.0", "resin-cli-visuals": "^1.4.0",
"resin-compose-parse": "^2.0.0", "resin-compose-parse": "^2.0.3",
"resin-doodles": "0.0.1", "resin-doodles": "0.0.1",
"resin-image-fs": "^5.0.2", "resin-image-fs": "^5.0.2",
"resin-multibuild": "^2.1.2", "resin-multibuild": "^2.1.4",
"resin-release": "^1.2.0", "resin-release": "^1.2.0",
"resin-semver": "^1.4.0", "resin-semver": "^1.4.0",
"resin-stream-logger": "^0.1.2", "resin-stream-logger": "^0.1.2",

View File

@ -1,3 +1,20 @@
/**
* @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.
*/
// These are the DefinitelyTyped typings for JSONStream, but because of this // These are the DefinitelyTyped typings for JSONStream, but because of this
// mismatch in case of jsonstream and JSONStream, it is necessary to include // mismatch in case of jsonstream and JSONStream, it is necessary to include
// them this way, with an upper case module declaration. They have also // them this way, with an upper case module declaration. They have also
@ -15,22 +32,21 @@ declare module 'JSONStream' {
recurse: boolean; recurse: boolean;
} }
export function parse(pattern: any): NodeJS.ReadWriteStream; export function parse(pattern: any | any[]): NodeJS.ReadWriteStream;
export function parse(patterns: any[]): NodeJS.ReadWriteStream;
type NewlineOnlyIndicator = false;
/** /**
* Create a writable stream. * Create a writable stream.
* you may pass in custom open, close, and seperator strings. But, by default, * you may pass in custom open, close, and seperator strings. But, by default,
* JSONStream.stringify() will create an array, * JSONStream.stringify() will create an array,
* (with default options open='[\n', sep='\n,\n', close='\n]\n') * (with default options open='[\n', sep='\n,\n', close='\n]\n')
*
* If you call JSONStream.stringify(false) the elements will only be separated by a newline.
*/ */
export function stringify(): NodeJS.ReadWriteStream;
/** If you call JSONStream.stringify(false) the elements will only be seperated by a newline. */
export function stringify( export function stringify(
newlineOnly: NewlineOnlyIndicator, newlineOnly?: NewlineOnlyIndicator,
): NodeJS.ReadWriteStream; ): NodeJS.ReadWriteStream;
type NewlineOnlyIndicator = false;
/** /**
* Create a writable stream. * Create a writable stream.

View File

@ -1,7 +1,23 @@
/**
* @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.
*/
declare module 'balena-device-init' { declare module 'balena-device-init' {
import { DeviceType } from 'balena-sdk';
import * as Promise from 'bluebird'; import * as Promise from 'bluebird';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { DeviceType } from 'balena-sdk';
interface OperationState { interface OperationState {
operation: operation:
@ -55,8 +71,7 @@ declare module 'balena-device-init' {
} }
interface InitializeEmitter { interface InitializeEmitter {
on(event: 'stdout', callback: (msg: string) => void): void; on(event: 'stdout' | 'stderr', callback: (msg: string) => void): void;
on(event: 'stderr', callback: (msg: string) => void): void;
on(event: 'state', callback: (state: OperationState) => void): void; on(event: 'state', callback: (state: OperationState) => void): void;
on(event: 'burn', callback: (state: BurnProgress) => void): void; on(event: 'burn', callback: (state: BurnProgress) => void): void;
} }

View File

@ -1,11 +1,27 @@
/**
* @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.
*/
declare module 'color-hash' { declare module 'color-hash' {
interface Hasher { interface Hasher {
hex(text: string): string; hex(text: string): string;
} }
class ColorHash { class ColorHash {
hex(text: string): string; public hex(text: string): string;
rgb(text: string): [number, number, number]; public rgb(text: string): [number, number, number];
} }
export = ColorHash; export = ColorHash;

View File

@ -1,3 +1,19 @@
/**
* @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.
*/
declare module 'inquirer-dynamic-list' { declare module 'inquirer-dynamic-list' {
interface Choice { interface Choice {
name: string; name: string;
@ -5,7 +21,7 @@ declare module 'inquirer-dynamic-list' {
} }
class DynamicList { class DynamicList {
opt: { public opt: {
choices: { choices: {
choices: Choice[]; choices: Choice[];
realChoices: Choice[]; realChoices: Choice[];
@ -17,9 +33,9 @@ declare module 'inquirer-dynamic-list' {
emptyMessage?: string; emptyMessage?: string;
choices: Choice[]; choices: Choice[];
}); });
addChoice(choice: Choice): void; public addChoice(choice: Choice): void;
render(): void; public render(): void;
run(): Promise<any>; public run(): Promise<any>;
} }
export = DynamicList; export = DynamicList;

18
typings/nplugm.d.ts vendored
View File

@ -1,4 +1,20 @@
/**
* @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.
*/
declare module 'nplugm' { declare module 'nplugm' {
import Promise = require('bluebird'); import Promise = require('bluebird');
export function list(regexp: RegExp): Promise<Array<string>>; export function list(regexp: RegExp): Promise<string[]>;
} }

18
typings/rindle.d.ts vendored
View File

@ -1,3 +1,19 @@
/**
* @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.
*/
declare module 'rindle' { declare module 'rindle' {
export function extract( export function extract(
stream: NodeJS.ReadableStream, stream: NodeJS.ReadableStream,
@ -6,7 +22,7 @@ declare module 'rindle' {
export function wait( export function wait(
stream: { stream: {
on(event: string, callback: Function): void; on(event: string, callback: (...args: any[]) => void): void;
}, },
callback: (error: Error, data: string) => void, callback: (error: Error, data: string) => void,
): void; ): void;

View File

@ -1,4 +1,22 @@
// Based on the official types at https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/update-notifier/index.d.ts /**
* @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.
*/
// Based on the official types at:
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/update-notifier/index.d.ts
// but fixed to handle options correctly // but fixed to handle options correctly
declare module 'update-notifier' { declare module 'update-notifier' {
@ -12,10 +30,10 @@ declare module 'update-notifier' {
class UpdateNotifier { class UpdateNotifier {
constructor(settings?: Settings); constructor(settings?: Settings);
update: UpdateInfo; public update: UpdateInfo;
check(): void; public check(): void;
checkNpm(): void; public checkNpm(): void;
notify(customMessage?: NotifyOptions): void; public notify(customMessage?: NotifyOptions): void;
} }
interface Settings { interface Settings {