mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-20 22:23:07 +00:00
Convert lib/utils/compose to typescript
Change-type: patch
This commit is contained in:
parent
a80f676804
commit
bd021c0a2d
9
lib/utils/compose-types.d.ts
vendored
9
lib/utils/compose-types.d.ts
vendored
@ -15,6 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { ImageModel, ReleaseModel } from 'balena-release/build/models';
|
||||||
import type { Composition, ImageDescriptor } from 'resin-compose-parse';
|
import type { Composition, ImageDescriptor } from 'resin-compose-parse';
|
||||||
import type { Pack } from 'tar-stream';
|
import type { Pack } from 'tar-stream';
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ export interface ComposeOpts {
|
|||||||
inlineLogs?: boolean;
|
inlineLogs?: boolean;
|
||||||
multiDockerignore: boolean;
|
multiDockerignore: boolean;
|
||||||
noParentCheck: boolean;
|
noParentCheck: boolean;
|
||||||
projectName: string;
|
projectName?: string;
|
||||||
projectPath: string;
|
projectPath: string;
|
||||||
isLocal?: boolean;
|
isLocal?: boolean;
|
||||||
}
|
}
|
||||||
@ -79,7 +80,7 @@ export interface ComposeProject {
|
|||||||
export interface Release {
|
export interface Release {
|
||||||
client: ReturnType<typeof import('balena-release').createClient>;
|
client: ReturnType<typeof import('balena-release').createClient>;
|
||||||
release: Pick<
|
release: Pick<
|
||||||
import('balena-release/build/models').ReleaseModel,
|
ReleaseModel,
|
||||||
| 'id'
|
| 'id'
|
||||||
| 'status'
|
| 'status'
|
||||||
| 'commit'
|
| 'commit'
|
||||||
@ -91,7 +92,9 @@ export interface Release {
|
|||||||
| 'start_timestamp'
|
| 'start_timestamp'
|
||||||
| 'end_timestamp'
|
| 'end_timestamp'
|
||||||
>;
|
>;
|
||||||
serviceImages: Partial<import('balena-release/build/models').ImageModel>;
|
serviceImages: Dictionary<
|
||||||
|
Omit<ImageModel, 'created_at' | 'is_a_build_of__service' | '__metadata'>
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TarDirectoryOptions {
|
interface TarDirectoryOptions {
|
||||||
|
@ -15,14 +15,32 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { Renderer } from './compose_ts';
|
||||||
|
import type * as SDK from 'balena-sdk';
|
||||||
|
import type Dockerode = require('dockerode');
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import type { Composition, ImageDescriptor } from 'resin-compose-parse';
|
||||||
|
import type {
|
||||||
|
BuiltImage,
|
||||||
|
ComposeOpts,
|
||||||
|
ComposeProject,
|
||||||
|
Release,
|
||||||
|
TaggedImage,
|
||||||
|
} from './compose-types';
|
||||||
import { getChalk } from './lazy';
|
import { getChalk } from './lazy';
|
||||||
|
import Logger = require('./logger');
|
||||||
|
import { ProgressCallback } from 'docker-progress';
|
||||||
|
|
||||||
/**
|
export function generateOpts(options: {
|
||||||
* @returns Promise<{import('./compose-types').ComposeOpts}>
|
source?: string;
|
||||||
*/
|
projectName?: string;
|
||||||
export function generateOpts(options) {
|
nologs: boolean;
|
||||||
const { promises: fs } = require('fs');
|
'noconvert-eol': boolean;
|
||||||
|
dockerfile?: string;
|
||||||
|
'multi-dockerignore': boolean;
|
||||||
|
'noparent-check': boolean;
|
||||||
|
}): Promise<ComposeOpts> {
|
||||||
|
const { promises: fs } = require('fs') as typeof import('fs');
|
||||||
return fs.realpath(options.source || '.').then((projectPath) => ({
|
return fs.realpath(options.source || '.').then((projectPath) => ({
|
||||||
projectName: options.projectName,
|
projectName: options.projectName,
|
||||||
projectPath,
|
projectPath,
|
||||||
@ -34,24 +52,19 @@ export function generateOpts(options) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the given composition and return a structure with info. Input is:
|
/** Parse the given composition and return a structure with info. Input is:
|
||||||
// - composePath: the *absolute* path to the directory containing the compose file
|
* - composePath: the *absolute* path to the directory containing the compose file
|
||||||
// - composeStr: the contents of the compose file, as a string
|
* - composeStr: the contents of the compose file, as a string
|
||||||
/**
|
|
||||||
* @param {string} composePath
|
|
||||||
* @param {string} composeStr
|
|
||||||
* @param {string | undefined} projectName The --projectName flag (build, deploy)
|
|
||||||
* @param {string | undefined} imageTag The --tag flag (build, deploy)
|
|
||||||
* @returns {import('./compose-types').ComposeProject}
|
|
||||||
*/
|
*/
|
||||||
export function createProject(
|
export function createProject(
|
||||||
composePath,
|
composePath: string,
|
||||||
composeStr,
|
composeStr: string,
|
||||||
projectName = '',
|
projectName = '',
|
||||||
imageTag = '',
|
imageTag = '',
|
||||||
) {
|
): ComposeProject {
|
||||||
const yml = require('js-yaml');
|
const yml = require('js-yaml') as typeof import('js-yaml');
|
||||||
const compose = require('resin-compose-parse');
|
const compose =
|
||||||
|
require('resin-compose-parse') as typeof import('resin-compose-parse');
|
||||||
|
|
||||||
// both methods below may throw.
|
// both methods below may throw.
|
||||||
const rawComposition = yml.load(composeStr);
|
const rawComposition = yml.load(composeStr);
|
||||||
@ -67,7 +80,8 @@ export function createProject(
|
|||||||
descr.image.context != null &&
|
descr.image.context != null &&
|
||||||
descr.image.tag == null
|
descr.image.tag == null
|
||||||
) {
|
) {
|
||||||
const { makeImageName } = require('./compose_ts');
|
const { makeImageName } =
|
||||||
|
require('./compose_ts') as typeof import('./compose_ts');
|
||||||
descr.image.tag = makeImageName(projectName, descr.serviceName, imageTag);
|
descr.image.tag = makeImageName(projectName, descr.serviceName, imageTag);
|
||||||
}
|
}
|
||||||
return descr;
|
return descr;
|
||||||
@ -80,30 +94,20 @@ export function createProject(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} apiEndpoint
|
|
||||||
* @param {string} auth
|
|
||||||
* @param {number} userId
|
|
||||||
* @param {number} appId
|
|
||||||
* @param {import('resin-compose-parse').Composition} composition
|
|
||||||
* @param {boolean} draft
|
|
||||||
* @param {string|undefined} semver
|
|
||||||
* @param {string|undefined} contract
|
|
||||||
* @returns {Promise<import('./compose-types').Release>}
|
|
||||||
*/
|
|
||||||
export const createRelease = async function (
|
export const createRelease = async function (
|
||||||
apiEndpoint,
|
apiEndpoint: string,
|
||||||
auth,
|
auth: string,
|
||||||
userId,
|
userId: number,
|
||||||
appId,
|
appId: number,
|
||||||
composition,
|
composition: Composition,
|
||||||
draft,
|
draft: boolean,
|
||||||
semver,
|
semver?: string,
|
||||||
contract,
|
contract?: string,
|
||||||
) {
|
): Promise<Release> {
|
||||||
const _ = require('lodash');
|
const _ = require('lodash') as typeof import('lodash');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto') as typeof import('crypto');
|
||||||
const releaseMod = require('balena-release');
|
const releaseMod =
|
||||||
|
require('balena-release') as typeof import('balena-release');
|
||||||
|
|
||||||
const client = releaseMod.createClient({ apiEndpoint, auth });
|
const client = releaseMod.createClient({ apiEndpoint, auth });
|
||||||
|
|
||||||
@ -133,24 +137,26 @@ export const createRelease = async function (
|
|||||||
'start_timestamp',
|
'start_timestamp',
|
||||||
'end_timestamp',
|
'end_timestamp',
|
||||||
]),
|
]),
|
||||||
serviceImages: _.mapValues(serviceImages, (serviceImage) =>
|
serviceImages: _.mapValues(
|
||||||
_.omit(serviceImage, [
|
serviceImages,
|
||||||
'created_at',
|
(serviceImage) =>
|
||||||
'is_a_build_of__service',
|
_.omit(serviceImage, [
|
||||||
'__metadata',
|
'created_at',
|
||||||
]),
|
'is_a_build_of__service',
|
||||||
|
'__metadata',
|
||||||
|
]) as Omit<
|
||||||
|
typeof serviceImage,
|
||||||
|
'created_at' | 'is_a_build_of__service' | '__metadata'
|
||||||
|
>,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export const tagServiceImages = (
|
||||||
*
|
docker: Dockerode,
|
||||||
* @param {import('dockerode')} docker
|
images: BuiltImage[],
|
||||||
* @param {Array<import('./compose-types').BuiltImage>} images
|
serviceImages: Release['serviceImages'],
|
||||||
* @param {Partial<import('balena-release/build/models').ImageModel>} serviceImages
|
): Promise<TaggedImage[]> =>
|
||||||
* @returns {Promise<Array<import('./compose-types').TaggedImage>>}
|
|
||||||
*/
|
|
||||||
export const tagServiceImages = (docker, images, serviceImages) =>
|
|
||||||
Promise.all(
|
Promise.all(
|
||||||
images.map(function (d) {
|
images.map(function (d) {
|
||||||
const serviceImage = serviceImages[d.serviceName];
|
const serviceImage = serviceImages[d.serviceName];
|
||||||
@ -177,25 +183,24 @@ export const tagServiceImages = (docker, images, serviceImages) =>
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
export const getPreviousRepos = (
|
||||||
* @param {*} sdk
|
sdk: SDK.BalenaSDK,
|
||||||
* @param {import('./logger')} logger
|
logger: Logger,
|
||||||
* @param {number} appID
|
appID: number,
|
||||||
* @returns {Promise<string[]>}
|
): Promise<string[]> =>
|
||||||
*/
|
|
||||||
export const getPreviousRepos = (sdk, logger, appID) =>
|
|
||||||
sdk.pine
|
sdk.pine
|
||||||
.get({
|
.get<SDK.Release>({
|
||||||
resource: 'release',
|
resource: 'release',
|
||||||
options: {
|
options: {
|
||||||
|
$select: 'id',
|
||||||
$filter: {
|
$filter: {
|
||||||
belongs_to__application: appID,
|
belongs_to__application: appID,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
},
|
},
|
||||||
$select: ['id'],
|
|
||||||
$expand: {
|
$expand: {
|
||||||
contains__image: {
|
contains__image: {
|
||||||
$expand: 'image',
|
$select: 'image',
|
||||||
|
$expand: { image: { $select: 'is_stored_at__image_location' } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
$orderby: 'id desc',
|
$orderby: 'id desc',
|
||||||
@ -205,8 +210,11 @@ export const getPreviousRepos = (sdk, logger, appID) =>
|
|||||||
.then(function (release) {
|
.then(function (release) {
|
||||||
// grab all images from the latest release, return all image locations in the registry
|
// grab all images from the latest release, return all image locations in the registry
|
||||||
if (release.length > 0) {
|
if (release.length > 0) {
|
||||||
const images = release[0].contains__image;
|
const images = release[0].contains__image as Array<{
|
||||||
const { getRegistryAndName } = require('resin-multibuild');
|
image: [SDK.Image];
|
||||||
|
}>;
|
||||||
|
const { getRegistryAndName } =
|
||||||
|
require('resin-multibuild') as typeof import('resin-multibuild');
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
images.map(function (d) {
|
images.map(function (d) {
|
||||||
const imageName = d.image[0].is_stored_at__image_location || '';
|
const imageName = d.image[0].is_stored_at__image_location || '';
|
||||||
@ -226,21 +234,13 @@ export const getPreviousRepos = (sdk, logger, appID) =>
|
|||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {*} sdk
|
|
||||||
* @param {string} tokenAuthEndpoint
|
|
||||||
* @param {string} registry
|
|
||||||
* @param {string[]} images
|
|
||||||
* @param {string[]} previousRepos
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
export const authorizePush = function (
|
export const authorizePush = function (
|
||||||
sdk,
|
sdk: SDK.BalenaSDK,
|
||||||
tokenAuthEndpoint,
|
tokenAuthEndpoint: string,
|
||||||
registry,
|
registry: string,
|
||||||
images,
|
images: string[],
|
||||||
previousRepos,
|
previousRepos: string[],
|
||||||
) {
|
): Promise<string> {
|
||||||
if (!Array.isArray(images)) {
|
if (!Array.isArray(images)) {
|
||||||
images = [images];
|
images = [images];
|
||||||
}
|
}
|
||||||
@ -261,17 +261,20 @@ export const authorizePush = function (
|
|||||||
|
|
||||||
// utilities
|
// utilities
|
||||||
|
|
||||||
const renderProgressBar = function (percentage, stepCount) {
|
const renderProgressBar = function (percentage: number, stepCount: number) {
|
||||||
const _ = require('lodash');
|
const _ = require('lodash') as typeof import('lodash');
|
||||||
percentage = _.clamp(percentage, 0, 100);
|
percentage = _.clamp(percentage, 0, 100);
|
||||||
const barCount = Math.floor((stepCount * percentage) / 100);
|
const barCount = Math.floor((stepCount * percentage) / 100);
|
||||||
const spaceCount = stepCount - barCount;
|
const spaceCount = stepCount - barCount;
|
||||||
const bar = `[${_.repeat('=', barCount)}>${_.repeat(' ', spaceCount)}]`;
|
const bar = `[${_.repeat('=', barCount)}>${_.repeat(' ', spaceCount)}]`;
|
||||||
return `${bar} ${_.padStart(percentage, 3)}%`;
|
return `${bar} ${_.padStart(`${percentage}`, 3)}%`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const pushProgressRenderer = function (tty, prefix) {
|
export const pushProgressRenderer = function (
|
||||||
const fn = function (e) {
|
tty: ReturnType<typeof import('./tty')>,
|
||||||
|
prefix: string,
|
||||||
|
): ProgressCallback & { end: () => void } {
|
||||||
|
const fn: ProgressCallback & { end: () => void } = function (e) {
|
||||||
const { error, percentage } = e;
|
const { error, percentage } = e;
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
@ -285,14 +288,39 @@ export const pushProgressRenderer = function (tty, prefix) {
|
|||||||
return fn;
|
return fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class BuildProgressUI {
|
export class BuildProgressUI implements Renderer {
|
||||||
constructor(tty, descriptors) {
|
public streams;
|
||||||
|
private _prefix;
|
||||||
|
private _prefixWidth;
|
||||||
|
private _tty;
|
||||||
|
private _services;
|
||||||
|
private _startTime: undefined | number;
|
||||||
|
private _ended;
|
||||||
|
private _serviceToDataMap: Dictionary<{
|
||||||
|
status?: string;
|
||||||
|
progress?: number;
|
||||||
|
error?: Error;
|
||||||
|
}> = {};
|
||||||
|
private _cancelled;
|
||||||
|
private _spinner;
|
||||||
|
private _runloop:
|
||||||
|
| undefined
|
||||||
|
| ReturnType<typeof import('./compose_ts').createRunLoop>;
|
||||||
|
|
||||||
|
// these are to handle window wrapping
|
||||||
|
private _maxLineWidth: undefined | number;
|
||||||
|
private _lineWidths: number[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
tty: ReturnType<typeof import('./tty')>,
|
||||||
|
descriptors: ImageDescriptor[],
|
||||||
|
) {
|
||||||
this._handleEvent = this._handleEvent.bind(this);
|
this._handleEvent = this._handleEvent.bind(this);
|
||||||
this.start = this.start.bind(this);
|
this.start = this.start.bind(this);
|
||||||
this.end = this.end.bind(this);
|
this.end = this.end.bind(this);
|
||||||
this._display = this._display.bind(this);
|
this._display = this._display.bind(this);
|
||||||
const _ = require('lodash');
|
const _ = require('lodash') as typeof import('lodash');
|
||||||
const through = require('through2');
|
const through = require('through2') as typeof import('through2');
|
||||||
|
|
||||||
const eventHandler = this._handleEvent;
|
const eventHandler = this._handleEvent;
|
||||||
const services = _.map(descriptors, 'serviceName');
|
const services = _.map(descriptors, 'serviceName');
|
||||||
@ -310,7 +338,6 @@ export class BuildProgressUI {
|
|||||||
.value();
|
.value();
|
||||||
|
|
||||||
this._tty = tty;
|
this._tty = tty;
|
||||||
this._serviceToDataMap = {};
|
|
||||||
this._services = services;
|
this._services = services;
|
||||||
|
|
||||||
// Logger magically prefixes the log line with [Build] etc., but it doesn't
|
// Logger magically prefixes the log line with [Build] etc., but it doesn't
|
||||||
@ -320,22 +347,22 @@ export class BuildProgressUI {
|
|||||||
|
|
||||||
const offset = 10; // account for escape sequences inserted for colouring
|
const offset = 10; // account for escape sequences inserted for colouring
|
||||||
this._prefixWidth =
|
this._prefixWidth =
|
||||||
offset + prefix.length + _.max(_.map(services, 'length'));
|
offset + prefix.length + _.max(_.map(services, (s) => s.length))!;
|
||||||
this._prefix = prefix;
|
this._prefix = prefix;
|
||||||
|
|
||||||
// these are to handle window wrapping
|
|
||||||
this._maxLineWidth = null;
|
|
||||||
this._lineWidths = [];
|
|
||||||
|
|
||||||
this._startTime = null;
|
|
||||||
this._ended = false;
|
this._ended = false;
|
||||||
this._cancelled = false;
|
this._cancelled = false;
|
||||||
this._spinner = require('./compose_ts').createSpinner();
|
this._spinner = (
|
||||||
|
require('./compose_ts') as typeof import('./compose_ts')
|
||||||
|
).createSpinner();
|
||||||
|
|
||||||
this.streams = streams;
|
this.streams = streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleEvent(service, event) {
|
_handleEvent(
|
||||||
|
service: string,
|
||||||
|
event: { status?: string; progress?: number; error?: Error },
|
||||||
|
) {
|
||||||
this._serviceToDataMap[service] = event;
|
this._serviceToDataMap[service] = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,20 +371,19 @@ export class BuildProgressUI {
|
|||||||
this._services.forEach((service) => {
|
this._services.forEach((service) => {
|
||||||
this.streams[service].write({ status: 'Preparing...' });
|
this.streams[service].write({ status: 'Preparing...' });
|
||||||
});
|
});
|
||||||
this._runloop = require('./compose_ts').createRunLoop(this._display);
|
this._runloop = (
|
||||||
|
require('./compose_ts') as typeof import('./compose_ts')
|
||||||
|
).createRunLoop(this._display);
|
||||||
this._startTime = Date.now();
|
this._startTime = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
end(summary?: Dictionary<string>) {
|
||||||
* @param {Dictionary<string> | undefined} summary
|
|
||||||
*/
|
|
||||||
end(summary) {
|
|
||||||
if (this._ended) {
|
if (this._ended) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._ended = true;
|
this._ended = true;
|
||||||
this._runloop?.end();
|
this._runloop?.end();
|
||||||
this._runloop = null;
|
this._runloop = undefined;
|
||||||
|
|
||||||
this._clear();
|
this._clear();
|
||||||
this._renderStatus(true);
|
this._renderStatus(true);
|
||||||
@ -378,7 +404,7 @@ export class BuildProgressUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getServiceSummary() {
|
_getServiceSummary() {
|
||||||
const _ = require('lodash');
|
const _ = require('lodash') as typeof import('lodash');
|
||||||
|
|
||||||
const services = this._services;
|
const services = this._services;
|
||||||
const serviceToDataMap = this._serviceToDataMap;
|
const serviceToDataMap = this._serviceToDataMap;
|
||||||
@ -405,11 +431,11 @@ export class BuildProgressUI {
|
|||||||
.value();
|
.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderStatus(end) {
|
_renderStatus(end = false) {
|
||||||
end ??= false;
|
const moment = require('moment') as typeof import('moment');
|
||||||
|
(
|
||||||
const moment = require('moment');
|
require('moment-duration-format') as typeof import('moment-duration-format')
|
||||||
require('moment-duration-format')(moment);
|
)(moment);
|
||||||
|
|
||||||
this._tty.clearLine();
|
this._tty.clearLine();
|
||||||
this._tty.write(this._prefix);
|
this._tty.write(this._prefix);
|
||||||
@ -434,11 +460,11 @@ export class BuildProgressUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderSummary(serviceToStrMap) {
|
_renderSummary(serviceToStrMap: Dictionary<string>) {
|
||||||
const _ = require('lodash');
|
const _ = require('lodash') as typeof import('lodash');
|
||||||
const chalk = getChalk();
|
const chalk = getChalk();
|
||||||
const truncate = require('cli-truncate');
|
const truncate = require('cli-truncate') as typeof import('cli-truncate');
|
||||||
const strlen = require('string-width');
|
const strlen = require('string-width') as typeof import('string-width');
|
||||||
|
|
||||||
this._services.forEach((service, index) => {
|
this._services.forEach((service, index) => {
|
||||||
let str = _.padEnd(this._prefix + chalk.bold(service), this._prefixWidth);
|
let str = _.padEnd(this._prefix + chalk.bold(service), this._prefixWidth);
|
||||||
@ -454,13 +480,23 @@ export class BuildProgressUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BuildProgressInline {
|
export class BuildProgressInline implements Renderer {
|
||||||
constructor(outStream, descriptors) {
|
public streams;
|
||||||
|
private _prefixWidth;
|
||||||
|
private _outStream;
|
||||||
|
private _services;
|
||||||
|
private _startTime: number | undefined;
|
||||||
|
private _ended;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
outStream: NodeJS.ReadWriteStream,
|
||||||
|
descriptors: Array<{ serviceName: string }>,
|
||||||
|
) {
|
||||||
this.start = this.start.bind(this);
|
this.start = this.start.bind(this);
|
||||||
this.end = this.end.bind(this);
|
this.end = this.end.bind(this);
|
||||||
this._renderEvent = this._renderEvent.bind(this);
|
this._renderEvent = this._renderEvent.bind(this);
|
||||||
const _ = require('lodash');
|
const _ = require('lodash') as typeof import('lodash');
|
||||||
const through = require('through2');
|
const through = require('through2') as typeof import('through2');
|
||||||
|
|
||||||
const services = _.map(descriptors, 'serviceName');
|
const services = _.map(descriptors, 'serviceName');
|
||||||
const eventHandler = this._renderEvent;
|
const eventHandler = this._renderEvent;
|
||||||
@ -477,10 +513,9 @@ export class BuildProgressInline {
|
|||||||
.value();
|
.value();
|
||||||
|
|
||||||
const offset = 10; // account for escape sequences inserted for colouring
|
const offset = 10; // account for escape sequences inserted for colouring
|
||||||
this._prefixWidth = offset + _.max(_.map(services, 'length'));
|
this._prefixWidth = offset + _.max(_.map(services, (s) => s.length))!;
|
||||||
this._outStream = outStream;
|
this._outStream = outStream;
|
||||||
this._services = services;
|
this._services = services;
|
||||||
this._startTime = null;
|
|
||||||
this._ended = false;
|
this._ended = false;
|
||||||
|
|
||||||
this.streams = streams;
|
this.streams = streams;
|
||||||
@ -494,12 +529,11 @@ export class BuildProgressInline {
|
|||||||
this._startTime = Date.now();
|
this._startTime = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
end(summary?: Dictionary<string>) {
|
||||||
* @param {Dictionary<string> | undefined} summary
|
const moment = require('moment') as typeof import('moment');
|
||||||
*/
|
(
|
||||||
end(summary) {
|
require('moment-duration-format') as typeof import('moment-duration-format')
|
||||||
const moment = require('moment');
|
)(moment);
|
||||||
require('moment-duration-format')(moment);
|
|
||||||
|
|
||||||
if (this._ended) {
|
if (this._ended) {
|
||||||
return;
|
return;
|
||||||
@ -527,8 +561,8 @@ export class BuildProgressInline {
|
|||||||
this._outStream.write(`Built ${serviceStr} in ${durationStr}\n`);
|
this._outStream.write(`Built ${serviceStr} in ${durationStr}\n`);
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderEvent(service, event) {
|
_renderEvent(service: string, event: { status?: string; error?: Error }) {
|
||||||
const _ = require('lodash');
|
const _ = require('lodash') as typeof import('lodash');
|
||||||
|
|
||||||
const str = (function () {
|
const str = (function () {
|
||||||
const { status, error } = event;
|
const { status, error } = event;
|
@ -235,7 +235,7 @@ interface BuildTaskPlus extends MultiBuild.BuildTask {
|
|||||||
logBuffer?: string[];
|
logBuffer?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Renderer {
|
export interface Renderer {
|
||||||
start: () => void;
|
start: () => void;
|
||||||
end: (buildSummaryByService?: Dictionary<string>) => void;
|
end: (buildSummaryByService?: Dictionary<string>) => void;
|
||||||
streams: Dictionary<NodeJS.ReadWriteStream>;
|
streams: Dictionary<NodeJS.ReadWriteStream>;
|
||||||
|
Loading…
Reference in New Issue
Block a user