Enforce and improve lazy loading of resin-cli-form

Change-type: patch
This commit is contained in:
Pagan Gazzard 2020-07-08 18:03:10 +01:00
parent 0bd27bd7ac
commit eea8c83bff
14 changed files with 60 additions and 79 deletions

View File

@ -19,7 +19,7 @@ import { flags } from '@oclif/command';
import type { IArg } from '@oclif/parser/lib/args'; import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command'; import Command from '../../command';
import * as cf from '../../utils/common-flags'; import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy'; import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation'; import { tryAsInteger } from '../../utils/validation';
import type { Device } from 'balena-sdk'; import type { Device } from 'balena-sdk';
import { ExpectedError } from '../../errors'; import { ExpectedError } from '../../errors';
@ -78,7 +78,6 @@ export default class DeviceOsUpdateCmd extends Command {
const sdk = getBalenaSdk(); const sdk = getBalenaSdk();
const patterns = await import('../../utils/patterns'); const patterns = await import('../../utils/patterns');
const form = await import('resin-cli-form');
// Get device info // Get device info
const { const {
@ -121,7 +120,7 @@ export default class DeviceOsUpdateCmd extends Command {
); );
} }
} else { } else {
targetOsVersion = await form.ask({ targetOsVersion = await getCliForm().ask({
message: 'Target OS version', message: 'Target OS version',
type: 'list', type: 'list',
choices: hupVersionInfo.versions.map((version) => ({ choices: hupVersionInfo.versions.map((version) => ({

View File

@ -19,7 +19,7 @@ import { flags } from '@oclif/command';
import type { IArg } from '@oclif/parser/lib/args'; import type { IArg } from '@oclif/parser/lib/args';
import Command from '../../command'; import Command from '../../command';
import * as cf from '../../utils/common-flags'; import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy'; import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { tryAsInteger } from '../../utils/validation'; import { tryAsInteger } from '../../utils/validation';
interface FlagsDef { interface FlagsDef {
@ -69,11 +69,10 @@ export default class DeviceRenameCmd extends Command {
const { args: params } = this.parse<FlagsDef, ArgsDef>(DeviceRenameCmd); const { args: params } = this.parse<FlagsDef, ArgsDef>(DeviceRenameCmd);
const balena = getBalenaSdk(); const balena = getBalenaSdk();
const form = await import('resin-cli-form');
const newName = const newName =
params.newName || params.newName ||
(await form.ask({ (await getCliForm().ask({
message: 'How do you want to name this device?', message: 'How do you want to name this device?',
type: 'input', type: 'input',
})) || })) ||

View File

@ -18,7 +18,7 @@
import { flags } from '@oclif/command'; import { flags } from '@oclif/command';
import Command from '../command'; import Command from '../command';
import * as cf from '../utils/common-flags'; import * as cf from '../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../utils/lazy'; import { getBalenaSdk, stripIndent, getCliForm } from '../utils/lazy';
import { ExpectedError } from '../errors'; import { ExpectedError } from '../errors';
interface FlagsDef { interface FlagsDef {
@ -147,8 +147,7 @@ ${messages.reachingOut}`);
// Token // Token
if (loginOptions.token) { if (loginOptions.token) {
if (!token) { if (!token) {
const form = await import('resin-cli-form'); token = await getCliForm().ask({
token = await form.ask({
message: 'Session token or API key from the preferences page', message: 'Session token or API key from the preferences page',
name: 'token', name: 'token',
type: 'input', type: 'input',

View File

@ -23,7 +23,7 @@ import Command from '../../command';
import { ExpectedError } from '../../errors'; import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags'; import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy'; import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { CommandHelp } from '../../utils/oclif-utils'; import { CommandHelp } from '../../utils/oclif-utils';
const BOOT_PARTITION = 1; const BOOT_PARTITION = 1;
@ -396,7 +396,6 @@ async function askQuestionsForDeviceType(
options: FlagsDef, options: FlagsDef,
configJson?: import('../../utils/config').ImgConfig, configJson?: import('../../utils/config').ImgConfig,
): Promise<Answers> { ): Promise<Answers> {
const form = await import('resin-cli-form');
const helpers = await import('../../utils/helpers'); const helpers = await import('../../utils/helpers');
const answerSources: any[] = [camelifyConfigOptions(options)]; const answerSources: any[] = [camelifyConfigOptions(options)];
const defaultAnswers: Partial<Answers> = {}; const defaultAnswers: Partial<Answers> = {};
@ -436,7 +435,7 @@ async function askQuestionsForDeviceType(
extraOpts = { override: defaultAnswers }; extraOpts = { override: defaultAnswers };
} }
return form.run(questions, extraOpts); return getCliForm().run(questions, extraOpts);
} }
/** /**

View File

@ -17,7 +17,7 @@ limitations under the License.
import * as commandOptions from './command-options'; import * as commandOptions from './command-options';
import { normalizeUuidProp } from '../utils/normalization'; import { normalizeUuidProp } from '../utils/normalization';
import { getBalenaSdk, getVisuals } from '../utils/lazy'; import { getBalenaSdk, getVisuals, getCliForm } from '../utils/lazy';
import * as _ from 'lodash'; import * as _ from 'lodash';
const getUmountAsync = async () => { const getUmountAsync = async () => {
@ -303,7 +303,6 @@ Examples:
normalizeUuidProp(options, 'device'); normalizeUuidProp(options, 'device');
const Bluebird = require('bluebird'); const Bluebird = require('bluebird');
const balena = getBalenaSdk(); const balena = getBalenaSdk();
const form = require('resin-cli-form');
const prettyjson = require('prettyjson'); const prettyjson = require('prettyjson');
const { const {
@ -378,7 +377,7 @@ See the help page for examples:
formOptions, // Pass params as an override: if there is any param with exactly the same name as a formOptions, // Pass params as an override: if there is any param with exactly the same name as a
) => ) =>
// required option, that value is used (and the corresponding question is not asked) // required option, that value is used (and the corresponding question is not asked)
form.run(formOptions, { override: options }), getCliForm().run(formOptions, { override: options }),
) )
.then(function (answers) { .then(function (answers) {
answers.version = options.version; answers.version = options.version;

View File

@ -2,7 +2,7 @@ import * as Bluebird from 'bluebird';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as dockerUtils from '../../utils/docker'; import * as dockerUtils from '../../utils/docker';
import { exitWithExpectedError } from '../../errors'; import { exitWithExpectedError } from '../../errors';
import { getChalk } from '../../utils/lazy'; import { getChalk, getCliForm } from '../../utils/lazy';
export const dockerPort = 2375; export const dockerPort = 2375;
export const dockerTimeout = 2000; export const dockerTimeout = 2000;
@ -26,7 +26,6 @@ export const selectContainerFromDevice = Bluebird.method(function (
if (filterSupervisor == null) { if (filterSupervisor == null) {
filterSupervisor = false; filterSupervisor = false;
} }
const form = require('resin-cli-form');
const docker = dockerUtils.createClient({ const docker = dockerUtils.createClient({
host: deviceIp, host: deviceIp,
port: dockerPort, port: dockerPort,
@ -45,7 +44,7 @@ export const selectContainerFromDevice = Bluebird.method(function (
exitWithExpectedError(`No containers found in ${deviceIp}`); exitWithExpectedError(`No containers found in ${deviceIp}`);
} }
return form.ask({ return getCliForm().ask({
message: 'Select a container', message: 'Select a container',
type: 'list', type: 'list',
choices: _.map(containers, function (container) { choices: _.map(containers, function (container) {

View File

@ -17,7 +17,12 @@ limitations under the License.
import type { CommandDefinition } from 'capitano'; import type { CommandDefinition } from 'capitano';
import type * as SDK from 'etcher-sdk'; import type * as SDK from 'etcher-sdk';
import { getChalk, getVisuals, stripIndent } from '../../utils/lazy'; import {
getChalk,
getVisuals,
stripIndent,
getCliForm,
} from '../../utils/lazy';
import { ExpectedError } from '../../errors'; import { ExpectedError } from '../../errors';
async function getDrive(options: { async function getDrive(options: {
@ -71,14 +76,13 @@ export const flash: CommandDefinition<
}, },
], ],
async action(params, options) { async action(params, options) {
const form = await import('resin-cli-form');
const { sourceDestination, multiWrite } = await import('etcher-sdk'); const { sourceDestination, multiWrite } = await import('etcher-sdk');
const drive = await getDrive(options); const drive = await getDrive(options);
const yes = const yes =
options.yes || options.yes ||
(await form.ask({ (await getCliForm().ask({
message: 'This will erase the selected drive. Are you sure?', message: 'This will erase the selected drive. Are you sure?',
type: 'confirm', type: 'confirm',
name: 'yes', name: 'yes',

View File

@ -17,7 +17,7 @@ limitations under the License.
import * as commandOptions from './command-options'; import * as commandOptions from './command-options';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { getBalenaSdk, getVisuals } from '../utils/lazy'; import { getBalenaSdk, getVisuals, getCliForm } from '../utils/lazy';
const formatVersion = function (v, isRecommended) { const formatVersion = function (v, isRecommended) {
let result = `v${v}`; let result = `v${v}`;
@ -35,7 +35,6 @@ const resolveVersion = function (deviceType, version) {
return Promise.resolve(version); return Promise.resolve(version);
} }
const form = require('resin-cli-form');
const balena = getBalenaSdk(); const balena = getBalenaSdk();
return balena.models.os return balena.models.os
@ -46,7 +45,7 @@ const resolveVersion = function (deviceType, version) {
name: formatVersion(v, v === recommended), name: formatVersion(v, v === recommended),
})); }));
return form.ask({ return getCliForm().ask({
message: 'Select the OS version:', message: 'Select the OS version:',
type: 'list', type: 'list',
choices, choices,
@ -185,7 +184,6 @@ const buildConfigForDeviceType = function (deviceType, advanced) {
if (advanced == null) { if (advanced == null) {
advanced = false; advanced = false;
} }
const form = require('resin-cli-form');
const helpers = require('../utils/helpers'); const helpers = require('../utils/helpers');
let override; let override;
@ -201,7 +199,7 @@ const buildConfigForDeviceType = function (deviceType, advanced) {
} }
} }
return form.run(questions, { override }); return getCliForm().run(questions, { override });
}; };
const $buildConfig = function (image, deviceTypeSlug, advanced) { const $buildConfig = function (image, deviceTypeSlug, advanced) {
@ -287,7 +285,6 @@ Examples:
action(params, options) { action(params, options) {
const Bluebird = require('bluebird'); const Bluebird = require('bluebird');
const umountAsync = Bluebird.promisify(require('umount').umount); const umountAsync = Bluebird.promisify(require('umount').umount);
const form = require('resin-cli-form');
const patterns = require('../utils/patterns'); const patterns = require('../utils/patterns');
const helpers = require('../utils/helpers'); const helpers = require('../utils/helpers');
@ -298,7 +295,7 @@ ${INIT_WARNING_MESSAGE}\
`); `);
return Bluebird.resolve(helpers.getManifest(params.image, options.type)) return Bluebird.resolve(helpers.getManifest(params.image, options.type))
.then((manifest) => .then((manifest) =>
form.run(manifest.initialization?.options, { getCliForm().run(manifest.initialization?.options, {
override: { override: {
drive: options.drive, drive: options.drive,
}, },

View File

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import * as _ from 'lodash'; import * as _ from 'lodash';
import { getBalenaSdk, getVisuals } from '../utils/lazy'; import { getBalenaSdk, getVisuals, getCliForm } from '../utils/lazy';
import * as dockerUtils from '../utils/docker'; import * as dockerUtils from '../utils/docker';
const isCurrent = (commit) => commit === 'latest' || commit === 'current'; const isCurrent = (commit) => commit === 'latest' || commit === 'current';
@ -83,7 +83,6 @@ const getApplicationsWithSuccessfulBuilds = function (deviceType) {
const selectApplication = function (deviceType) { const selectApplication = function (deviceType) {
const visuals = getVisuals(); const visuals = getVisuals();
const form = require('resin-cli-form');
const { exitWithExpectedError } = require('../errors'); const { exitWithExpectedError } = require('../errors');
const applicationInfoSpinner = new visuals.Spinner( const applicationInfoSpinner = new visuals.Spinner(
@ -100,7 +99,7 @@ const selectApplication = function (deviceType) {
`You have no apps with successful releases for a '${deviceType}' device type.`, `You have no apps with successful releases for a '${deviceType}' device type.`,
); );
} }
return form.ask({ return getCliForm().ask({
message: 'Select an application', message: 'Select an application',
type: 'list', type: 'list',
choices: applications.map((app) => ({ choices: applications.map((app) => ({
@ -112,7 +111,6 @@ const selectApplication = function (deviceType) {
}; };
const selectApplicationCommit = function (releases) { const selectApplicationCommit = function (releases) {
const form = require('resin-cli-form');
const { exitWithExpectedError } = require('../errors'); const { exitWithExpectedError } = require('../errors');
if (releases.length === 0) { if (releases.length === 0) {
@ -125,7 +123,7 @@ const selectApplicationCommit = function (releases) {
value: release.commit, value: release.commit,
})), })),
); );
return form.ask({ return getCliForm().ask({
message: 'Select a release', message: 'Select a release',
type: 'list', type: 'list',
default: 'current', default: 'current',
@ -140,7 +138,6 @@ const offerToDisableAutomaticUpdates = function (
) { ) {
const Bluebird = require('bluebird'); const Bluebird = require('bluebird');
const balena = getBalenaSdk(); const balena = getBalenaSdk();
const form = require('resin-cli-form');
if ( if (
isCurrent(commit) || isCurrent(commit) ||
@ -162,7 +159,7 @@ see https://balena.io/docs/reference/api/resources/device/#set-device-to-release
Alternatively you can pass the --pin-device-to-release flag to pin only this device to the selected release.\ Alternatively you can pass the --pin-device-to-release flag to pin only this device to the selected release.\
`; `;
return form return getCliForm()
.ask({ .ask({
message, message,
type: 'confirm', type: 'confirm',

View File

@ -19,6 +19,7 @@ limitations under the License.
import type * as BalenaSdk from 'balena-sdk'; import type * as BalenaSdk from 'balena-sdk';
import type { Chalk } from 'chalk'; import type { Chalk } from 'chalk';
import type * as visuals from 'resin-cli-visuals'; import type * as visuals from 'resin-cli-visuals';
import type * as CliForm from 'resin-cli-form';
import type { stripIndent as StripIndent } from 'common-tags'; import type { stripIndent as StripIndent } from 'common-tags';
// Equivalent of _.once but avoiding the need to import lodash for lazy deps // Equivalent of _.once but avoiding the need to import lodash for lazy deps
@ -52,6 +53,10 @@ export const getVisuals = once(
export const getChalk = once(() => require('chalk') as Chalk); export const getChalk = once(() => require('chalk') as Chalk);
export const getCliForm = once(
() => require('resin-cli-form') as typeof CliForm,
);
// Directly export stripIndent as we always use it immediately, but importing just `stripIndent` reduces startup time // Directly export stripIndent as we always use it immediately, but importing just `stripIndent` reduces startup time
// tslint:disable-next-line:no-var-requires // tslint:disable-next-line:no-var-requires
export const stripIndent = require('common-tags/lib/stripIndent') as typeof StripIndent; export const stripIndent = require('common-tags/lib/stripIndent') as typeof StripIndent;

View File

@ -16,7 +16,6 @@ limitations under the License.
import { BalenaApplicationNotFound } from 'balena-errors'; import { BalenaApplicationNotFound } from 'balena-errors';
import type * as BalenaSdk from 'balena-sdk'; import type * as BalenaSdk from 'balena-sdk';
import _ = require('lodash'); import _ = require('lodash');
import _form = require('resin-cli-form');
import { import {
exitWithExpectedError, exitWithExpectedError,
@ -24,15 +23,13 @@ import {
NotLoggedInError, NotLoggedInError,
ExpectedError, ExpectedError,
} from '../errors'; } from '../errors';
import { getBalenaSdk, getVisuals, stripIndent } from './lazy'; import { getBalenaSdk, getVisuals, stripIndent, getCliForm } from './lazy';
import validation = require('./validation'); import validation = require('./validation');
import { delay } from './helpers'; import { delay } from './helpers';
const getForm = _.once((): typeof _form => require('resin-cli-form'));
export function authenticate(options: {}): Promise<void> { export function authenticate(options: {}): Promise<void> {
const balena = getBalenaSdk(); const balena = getBalenaSdk();
return getForm() return getCliForm()
.run( .run(
[ [
{ {
@ -56,7 +53,7 @@ export function authenticate(options: {}): Promise<void> {
return; return;
} }
return getForm() return getCliForm()
.ask({ .ask({
message: 'Two factor auth challenge:', message: 'Two factor auth challenge:',
name: 'code', name: 'code',
@ -91,7 +88,7 @@ export async function checkLoggedIn(): Promise<void> {
} }
export function askLoginType() { export function askLoginType() {
return getForm().ask<'web' | 'credentials' | 'token' | 'register'>({ return getCliForm().ask<'web' | 'credentials' | 'token' | 'register'>({
message: 'How would you like to login?', message: 'How would you like to login?',
name: 'loginType', name: 'loginType',
type: 'list', type: 'list',
@ -123,7 +120,7 @@ export function selectDeviceType() {
deviceTypes = _.sortBy(deviceTypes, 'name').filter( deviceTypes = _.sortBy(deviceTypes, 'name').filter(
(dt) => dt.state !== 'DISCONTINUED', (dt) => dt.state !== 'DISCONTINUED',
); );
return getForm().ask({ return getCliForm().ask({
message: 'Device Type', message: 'Device Type',
type: 'list', type: 'list',
choices: _.map(deviceTypes, ({ slug: value, name }) => ({ choices: _.map(deviceTypes, ({ slug: value, name }) => ({
@ -147,7 +144,7 @@ export async function confirm(
return; return;
} }
const confirmed = await getForm().ask<boolean>({ const confirmed = await getCliForm().ask<boolean>({
message, message,
type: 'confirm', type: 'confirm',
default: false, default: false,
@ -177,7 +174,7 @@ export function selectApplication(
}) })
.filter(filter || _.constant(true)) .filter(filter || _.constant(true))
.then((applications) => { .then((applications) => {
return getForm().ask({ return getCliForm().ask({
message: 'Select an application', message: 'Select an application',
type: 'list', type: 'list',
choices: _.map(applications, (application) => ({ choices: _.map(applications, (application) => ({
@ -212,7 +209,7 @@ export function selectOrCreateApplication() {
value: null, value: null,
}); });
return getForm().ask({ return getCliForm().ask({
message: 'Select an application', message: 'Select an application',
type: 'list', type: 'list',
choices: appOptions, choices: appOptions,
@ -224,7 +221,7 @@ export function selectOrCreateApplication() {
return application; return application;
} }
return getForm().ask({ return getCliForm().ask({
message: 'Choose a Name for your new application', message: 'Choose a Name for your new application',
type: 'input', type: 'input',
validate: validation.validateApplicationName, validate: validation.validateApplicationName,
@ -324,7 +321,7 @@ export function inferOrSelectDevice(preferredUuid: string) {
? preferredUuid ? preferredUuid
: onlineDevices[0].uuid; : onlineDevices[0].uuid;
return getForm().ask({ return getCliForm().ask({
message: 'Select a device', message: 'Select a device',
type: 'list', type: 'list',
default: defaultUuid, default: defaultUuid,
@ -381,7 +378,7 @@ export async function getOnlineTargetUuid(
throw new ExpectedError('No accessible devices are online'); throw new ExpectedError('No accessible devices are online');
} }
return await getForm().ask({ return await getCliForm().ask({
message: 'Select a device', message: 'Select a device',
type: 'list', type: 'list',
default: devices[0].uuid, default: devices[0].uuid,
@ -416,7 +413,7 @@ export function selectFromList<T>(
message: string, message: string,
choices: Array<T & { name: string }>, choices: Array<T & { name: string }>,
): Promise<T> { ): Promise<T> {
return getForm().ask<T>({ return getCliForm().ask<T>({
message, message,
type: 'list', type: 'list',
choices: _.map(choices, (s) => ({ choices: _.map(choices, (s) => ({

View File

@ -17,7 +17,7 @@
import type * as BalenaSdk from 'balena-sdk'; import type * as BalenaSdk from 'balena-sdk';
import { ExpectedError, printErrorMessage } from '../errors'; import { ExpectedError, printErrorMessage } from '../errors';
import { getVisuals, stripIndent } from './lazy'; import { getVisuals, stripIndent, getCliForm } from './lazy';
import Logger = require('./logger'); import Logger = require('./logger');
import { exec, execBuffered, getDeviceOsRelease } from './ssh'; import { exec, execBuffered, getDeviceOsRelease } from './ssh';
@ -206,7 +206,6 @@ async function getOrSelectApplication(
appName?: string, appName?: string,
): Promise<BalenaSdk.Application> { ): Promise<BalenaSdk.Application> {
const _ = await import('lodash'); const _ = await import('lodash');
const form = await import('resin-cli-form');
const allDeviceTypes = await sdk.models.config.getDeviceTypes(); const allDeviceTypes = await sdk.models.config.getDeviceTypes();
const deviceTypeManifest = _.find(allDeviceTypes, { slug: deviceType }); const deviceTypeManifest = _.find(allDeviceTypes, { slug: deviceType });
@ -227,12 +226,7 @@ async function getOrSelectApplication(
.value(); .value();
if (!appName) { if (!appName) {
return createOrSelectAppOrExit( return createOrSelectAppOrExit(sdk, compatibleDeviceTypes, deviceType);
form,
sdk,
compatibleDeviceTypes,
deviceType,
);
} }
const options: BalenaSdk.PineOptionsFor<BalenaSdk.Application> = {}; const options: BalenaSdk.PineOptionsFor<BalenaSdk.Application> = {};
@ -254,7 +248,7 @@ async function getOrSelectApplication(
const applications = await sdk.models.application.getAll(options); const applications = await sdk.models.application.getAll(options);
if (applications.length === 0) { if (applications.length === 0) {
const shouldCreateApp = await form.ask({ const shouldCreateApp = await getCliForm().ask({
message: message:
`No application found with name "${appName}".\n` + `No application found with name "${appName}".\n` +
'Would you like to create it now?', 'Would you like to create it now?',
@ -288,7 +282,6 @@ async function getOrSelectApplication(
// `getOrSelectApplication` above in order to satisfy some resin-lint v3 // `getOrSelectApplication` above in order to satisfy some resin-lint v3
// rules, but it looks like there's a fair amount of duplicate logic. // rules, but it looks like there's a fair amount of duplicate logic.
async function createOrSelectAppOrExit( async function createOrSelectAppOrExit(
form: any,
sdk: BalenaSdk.BalenaSDK, sdk: BalenaSdk.BalenaSDK,
compatibleDeviceTypes: string[], compatibleDeviceTypes: string[],
deviceType: string, deviceType: string,
@ -301,7 +294,7 @@ async function createOrSelectAppOrExit(
const applications = await sdk.models.application.getAll(options); const applications = await sdk.models.application.getAll(options);
if (applications.length === 0) { if (applications.length === 0) {
const shouldCreateApp = await form.ask({ const shouldCreateApp = await getCliForm().ask({
message: message:
'You have no applications this device can join.\n' + 'You have no applications this device can join.\n' +
'Would you like to create one now?', 'Would you like to create one now?',
@ -322,7 +315,6 @@ async function createApplication(
deviceType: string, deviceType: string,
name?: string, name?: string,
): Promise<BalenaSdk.Application> { ): Promise<BalenaSdk.Application> {
const form = await import('resin-cli-form');
const validation = await import('./validation'); const validation = await import('./validation');
let username = await sdk.auth.whoami(); let username = await sdk.auth.whoami();
@ -334,7 +326,7 @@ async function createApplication(
const applicationName = 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 getCliForm().ask({
message: 'Enter a name for your new application:', message: 'Enter a name for your new application:',
type: 'input', type: 'input',
default: name, default: name,
@ -376,7 +368,6 @@ async function generateApplicationConfig(
app: BalenaSdk.Application, app: BalenaSdk.Application,
options: { version: string }, options: { version: string },
) { ) {
const form = await import('resin-cli-form');
const { generateApplicationConfig: configGen } = await import('./config'); const { generateApplicationConfig: configGen } = await import('./config');
const manifest = await sdk.models.device.getManifestBySlug(app.device_type); const manifest = await sdk.models.device.getManifestBySlug(app.device_type);
@ -384,7 +375,7 @@ async function generateApplicationConfig(
manifest.options && manifest.options &&
manifest.options.filter((opt) => opt.name !== 'network'); manifest.options.filter((opt) => opt.name !== 'network');
const values = { const values = {
...(opts ? await form.run(opts) : {}), ...(opts ? await getCliForm().run(opts) : {}),
...options, ...options,
}; };

View File

@ -2,6 +2,6 @@
"extends": "./node_modules/@balena/lint/config/tslint-prettier.json", "extends": "./node_modules/@balena/lint/config/tslint-prettier.json",
"rules": { "rules": {
"ignoreDefinitionFiles": false, "ignoreDefinitionFiles": false,
"import-blacklist": [true, "resin-cli-visuals", "chalk", "common-tags"] "import-blacklist": [true, "resin-cli-visuals", "chalk", "common-tags", "resin-cli-form"]
} }
} }

View File

@ -18,13 +18,13 @@
declare module 'resin-cli-form' { declare module 'resin-cli-form' {
import Bluebird = require('bluebird'); import Bluebird = require('bluebird');
type TypeOrPromiseLike<T> = T | PromiseLike<T>; export type TypeOrPromiseLike<T> = T | PromiseLike<T>;
type Validate = ( export type Validate = (
input: any, input: any,
) => TypeOrPromiseLike<boolean | string | undefined>; ) => TypeOrPromiseLike<boolean | string | undefined>;
interface AskOptions<T> { export interface AskOptions<T> {
message: string; message: string;
type?: string; type?: string;
name?: string; name?: string;
@ -36,20 +36,16 @@ declare module 'resin-cli-form' {
validate?: Validate; validate?: Validate;
} }
interface RunQuestion { export interface RunQuestion {
message: string; message: string;
name: string; name: string;
type?: string; type?: string;
validate?: Validate; validate?: Validate;
} }
const form: { export const ask: <T = string>(options: AskOptions<T>) => Bluebird<T>;
ask: <T = string>(options: AskOptions<T>) => Bluebird<T>; export const run: <T = any>(
run: <T = any>( questions?: RunQuestion[],
questions?: RunQuestion[], extraOptions?: { override?: object },
extraOptions?: { override?: object }, ) => Bluebird<T>;
) => Bluebird<T>;
};
export = form;
} }