Be lazier with imports in oclif actions

Change-type: patch
This commit is contained in:
Pagan Gazzard 2020-07-08 18:21:37 +01:00
parent 463f3f40ca
commit d6f1328238
15 changed files with 52 additions and 50 deletions

View File

@ -20,6 +20,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 } from '../../utils/lazy';
import type * as BalenaSDK from 'balena-sdk';
interface FlagsDef { interface FlagsDef {
type?: string; // application device type type?: string; // application device type
@ -75,11 +76,12 @@ export default class AppCreateCmd extends Command {
); );
const balena = getBalenaSdk(); const balena = getBalenaSdk();
const patterns = await import('../../utils/patterns');
// Create application // Create application
const deviceType = options.type || (await patterns.selectDeviceType()); const deviceType =
let application: import('balena-sdk').Application; options.type ||
(await (await import('../../utils/patterns')).selectDeviceType());
let application: BalenaSDK.Application;
try { try {
application = await balena.models.application.create({ application = await balena.models.application.create({
name: params.name, name: params.name,

View File

@ -61,7 +61,6 @@ export default class AppsCmd extends Command {
public async run() { public async run() {
const { flags: options } = this.parse<FlagsDef, {}>(AppsCmd); const { flags: options } = this.parse<FlagsDef, {}>(AppsCmd);
const _ = await import('lodash');
const balena = getBalenaSdk(); const balena = getBalenaSdk();
// Get applications // Get applications
@ -72,6 +71,7 @@ export default class AppsCmd extends Command {
}, },
); );
const _ = await import('lodash');
// Add extended properties // Add extended properties
applications.forEach((application) => { applications.forEach((application) => {
application.device_count = application.owns__device?.length ?? 0; application.device_count = application.owns__device?.length ?? 0;

View File

@ -92,7 +92,6 @@ export default class DeviceInitCmd extends Command {
const tmpNameAsync = promisify(tmp.tmpName); const tmpNameAsync = promisify(tmp.tmpName);
tmp.setGracefulCleanup(); tmp.setGracefulCleanup();
const balena = getBalenaSdk(); const balena = getBalenaSdk();
const patterns = await import('../../utils/patterns');
const Logger = await import('../../utils/logger'); const Logger = await import('../../utils/logger');
const logger = Logger.getLogger(); const logger = Logger.getLogger();
@ -103,7 +102,8 @@ export default class DeviceInitCmd extends Command {
// Get application and // Get application and
const application = await balena.models.application.get( const application = await balena.models.application.get(
options['application'] || (await patterns.selectApplication()), options['application'] ||
(await (await import('../../utils/patterns')).selectApplication()),
); );
// Register new device // Register new device

View File

@ -77,7 +77,6 @@ export default class DeviceMoveCmd extends Command {
); );
const balena = getBalenaSdk(); const balena = getBalenaSdk();
const patterns = await import('../../utils/patterns');
// Consolidate application options // Consolidate application options
options.application = options.application || options.app; options.application = options.application || options.app;
@ -113,6 +112,7 @@ export default class DeviceMoveCmd extends Command {
dt.state !== 'DISCONTINUED', dt.state !== 'DISCONTINUED',
); );
const patterns = await import('../../utils/patterns');
application = await patterns.selectApplication( application = await patterns.selectApplication(
(app: Application) => (app: Application) =>
compatibleDeviceTypes.some((dt) => dt.slug === app.device_type) && compatibleDeviceTypes.some((dt) => dt.slug === app.device_type) &&

View File

@ -77,7 +77,6 @@ export default class DeviceOsUpdateCmd extends Command {
); );
const sdk = getBalenaSdk(); const sdk = getBalenaSdk();
const patterns = await import('../../utils/patterns');
// Get device info // Get device info
const { const {
@ -133,6 +132,7 @@ export default class DeviceOsUpdateCmd extends Command {
}); });
} }
const patterns = await import('../../utils/patterns');
// Confirm and start update // Confirm and start update
await patterns.confirm( await patterns.confirm(
options.yes || false, options.yes || false,

View File

@ -87,11 +87,10 @@ export default class EnvRmCmd extends Command {
const { args: params, flags: opt } = this.parse<FlagsDef, ArgsDef>( const { args: params, flags: opt } = this.parse<FlagsDef, ArgsDef>(
EnvRmCmd, EnvRmCmd,
); );
const balena = getBalenaSdk();
const { confirm } = await import('../../utils/patterns');
await Command.checkLoggedIn(); await Command.checkLoggedIn();
const { confirm } = await import('../../utils/patterns');
await confirm( await confirm(
opt.yes || false, opt.yes || false,
'Are you sure you want to delete the environment variable?', 'Are you sure you want to delete the environment variable?',
@ -99,6 +98,7 @@ export default class EnvRmCmd extends Command {
true, true,
); );
const balena = getBalenaSdk();
await balena.pine.delete({ await balena.pine.delete({
resource: ec.getVarResourceName(opt.config, opt.device, opt.service), resource: ec.getVarResourceName(opt.config, opt.device, opt.service),
id: params.id, id: params.id,

View File

@ -201,12 +201,12 @@ export default class EnvsCmd extends Command {
} }
const balena = getBalenaSdk(); const balena = getBalenaSdk();
const { getDeviceAndMaybeAppFromUUID } = await import('../utils/cloud');
let appName = options.application; let appName = options.application;
let fullUUID: string | undefined; // as oppposed to the short, 7-char UUID let fullUUID: string | undefined; // as oppposed to the short, 7-char UUID
if (options.device) { if (options.device) {
const { getDeviceAndMaybeAppFromUUID } = await import('../utils/cloud');
const [device, app] = await getDeviceAndMaybeAppFromUUID( const [device, app] = await getDeviceAndMaybeAppFromUUID(
balena, balena,
options.device, options.device,

View File

@ -67,14 +67,14 @@ export default class OsinitCmd extends Command {
public async run() { public async run() {
const { args: params } = this.parse<{}, ArgsDef>(OsinitCmd); const { args: params } = this.parse<{}, ArgsDef>(OsinitCmd);
const { initialize } = await import('balena-device-init'); const config = JSON.parse(params.config);
const { getManifest, osProgressHandler } = await import( const { getManifest, osProgressHandler } = await import(
'../../utils/helpers' '../../utils/helpers'
); );
const config = JSON.parse(params.config);
const manifest = await getManifest(params.image, params.type); const manifest = await getManifest(params.image, params.type);
const { initialize } = await import('balena-device-init');
const initializeEmitter = await initialize(params.image, manifest, config); const initializeEmitter = await initialize(params.image, manifest, config);
await osProgressHandler(initializeEmitter); await osProgressHandler(initializeEmitter);
} }

View File

@ -123,6 +123,7 @@ export default class LoginCmd extends Command {
console.log(messages.balenaAsciiArt); console.log(messages.balenaAsciiArt);
console.log(`\nLogging in to ${balenaUrl}`); console.log(`\nLogging in to ${balenaUrl}`);
await this.doLogin(options, params.token); await this.doLogin(options, params.token);
const username = await balena.auth.whoami(); const username = await balena.auth.whoami();
console.info(`Successfully logged in as: ${username}`); console.info(`Successfully logged in as: ${username}`);
@ -141,9 +142,6 @@ ${messages.reachingOut}`);
} }
async doLogin(loginOptions: FlagsDef, token?: string): Promise<void> { async doLogin(loginOptions: FlagsDef, token?: string): Promise<void> {
const patterns = await import('../utils/patterns');
const balena = getBalenaSdk();
// Token // Token
if (loginOptions.token) { if (loginOptions.token) {
if (!token) { if (!token) {
@ -153,6 +151,7 @@ ${messages.reachingOut}`);
type: 'input', type: 'input',
}); });
} }
const balena = getBalenaSdk();
await balena.auth.loginWithToken(token!); await balena.auth.loginWithToken(token!);
if (!(await balena.auth.whoami())) { if (!(await balena.auth.whoami())) {
throw new ExpectedError('Token authentication failed'); throw new ExpectedError('Token authentication failed');
@ -161,6 +160,7 @@ ${messages.reachingOut}`);
} }
// Credentials // Credentials
else if (loginOptions.credentials) { else if (loginOptions.credentials) {
const patterns = await import('../utils/patterns');
return patterns.authenticate(loginOptions); return patterns.authenticate(loginOptions);
} }
// Web // Web
@ -168,8 +168,8 @@ ${messages.reachingOut}`);
const auth = await import('../auth'); const auth = await import('../auth');
await auth.login(); await auth.login();
return; return;
} } else {
const patterns = await import('../utils/patterns');
// User had not selected login preference, prompt interactively // User had not selected login preference, prompt interactively
const loginType = await patterns.askLoginType(); const loginType = await patterns.askLoginType();
if (loginType === 'register') { if (loginType === 'register') {
@ -183,4 +183,5 @@ ${messages.reachingOut}`);
loginOptions[loginType] = true; loginOptions[loginType] = true;
return this.doLogin(loginOptions); return this.doLogin(loginOptions);
} }
}
} }

View File

@ -102,7 +102,6 @@ export default class LogsCmd extends Command {
); );
const balena = getBalenaSdk(); const balena = getBalenaSdk();
const { ExpectedError } = await import('../errors');
const { serviceIdToName } = await import('../utils/cloud'); const { serviceIdToName } = await import('../utils/cloud');
const { displayDeviceLogs, displayLogObject } = await import( const { displayDeviceLogs, displayLogObject } = await import(
'../utils/device/logs' '../utils/device/logs'
@ -147,6 +146,7 @@ export default class LogsCmd extends Command {
try { try {
await deviceApi.ping(); await deviceApi.ping();
} catch (e) { } catch (e) {
const { ExpectedError } = await import('../errors');
throw new ExpectedError( throw new ExpectedError(
`Cannot access device at address ${params.device}. Device may not be in local mode.`, `Cannot access device at address ${params.device}. Device may not be in local mode.`,
); );

View File

@ -192,7 +192,6 @@ export default class OsConfigureCmd extends Command {
'../../utils/config' '../../utils/config'
); );
const helpers = await import('../../utils/helpers'); const helpers = await import('../../utils/helpers');
const imagefs = await require('resin-image-fs');
let app: BalenaSdk.Application | undefined; let app: BalenaSdk.Application | undefined;
let device: BalenaSdk.Device | undefined; let device: BalenaSdk.Device | undefined;
let deviceTypeSlug: string; let deviceTypeSlug: string;
@ -273,6 +272,7 @@ export default class OsConfigureCmd extends Command {
}; };
}), }),
); );
const imagefs = await import('resin-image-fs');
for (const { name, content } of files) { for (const { name, content } of files) {
await imagefs.writeFile( await imagefs.writeFile(
@ -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 helpers = await import('../../utils/helpers');
const answerSources: any[] = [camelifyConfigOptions(options)]; const answerSources: any[] = [camelifyConfigOptions(options)];
const defaultAnswers: Partial<Answers> = {}; const defaultAnswers: Partial<Answers> = {};
const questions: any = deviceType.options; const questions: any = deviceType.options;
@ -412,6 +411,7 @@ async function askQuestionsForDeviceType(
isGroup: true, isGroup: true,
}); });
if (!_.isEmpty(advancedGroup)) { if (!_.isEmpty(advancedGroup)) {
const helpers = await import('../../utils/helpers');
answerSources.push(helpers.getGroupDefaults(advancedGroup)); answerSources.push(helpers.getGroupDefaults(advancedGroup));
} }
} }

View File

@ -41,11 +41,9 @@ export default class SettingsCmd extends Command {
public async run() { public async run() {
this.parse<FlagsDef, {}>(SettingsCmd); this.parse<FlagsDef, {}>(SettingsCmd);
const prettyjson = await import('prettyjson'); const settings = await getBalenaSdk().settings.getAll();
return getBalenaSdk() const prettyjson = await import('prettyjson');
.settings.getAll() console.log(prettyjson.render(settings));
.then(prettyjson.render)
.then(console.log);
} }
} }

View File

@ -123,17 +123,6 @@ export default class NoteCmd extends Command {
NoteCmd, NoteCmd,
); );
const { ExpectedError } = await import('../errors');
const { getProxyConfig, which } = await import('../utils/helpers');
const { checkLoggedIn, getOnlineTargetUuid } = await import(
'../utils/patterns'
);
const { spawnSshAndThrowOnError } = await import('../utils/ssh');
const sdk = getBalenaSdk();
const proxyConfig = getProxyConfig();
const useProxy = !!proxyConfig && !options.noproxy;
// if we're doing a direct SSH connection locally... // if we're doing a direct SSH connection locally...
if ( if (
validateDotLocalUrl(params.applicationOrDevice) || validateDotLocalUrl(params.applicationOrDevice) ||
@ -149,6 +138,15 @@ export default class NoteCmd extends Command {
}); });
} }
const { getProxyConfig, which } = await import('../utils/helpers');
const { checkLoggedIn, getOnlineTargetUuid } = await import(
'../utils/patterns'
);
const sdk = getBalenaSdk();
const proxyConfig = getProxyConfig();
const useProxy = !!proxyConfig && !options.noproxy;
// this will be a tunnelled SSH connection... // this will be a tunnelled SSH connection...
await checkLoggedIn(); await checkLoggedIn();
const uuid = await getOnlineTargetUuid(sdk, params.applicationOrDevice); const uuid = await getOnlineTargetUuid(sdk, params.applicationOrDevice);
@ -207,6 +205,7 @@ export default class NoteCmd extends Command {
const proxyCommand = useProxy ? getSshProxyCommand() : undefined; const proxyCommand = useProxy ? getSshProxyCommand() : undefined;
if (username == null) { if (username == null) {
const { ExpectedError } = await import('../errors');
throw new ExpectedError( throw new ExpectedError(
`Opening an SSH connection to a remote device requires you to be logged in.`, `Opening an SSH connection to a remote device requires you to be logged in.`,
); );
@ -248,6 +247,7 @@ export default class NoteCmd extends Command {
username: username!, username: username!,
}); });
const { spawnSshAndThrowOnError } = await import('../utils/ssh');
return spawnSshAndThrowOnError(command); return spawnSshAndThrowOnError(command);
} }

View File

@ -13,7 +13,6 @@ 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 { BalenaApplicationNotFound } from 'balena-errors';
import type * as BalenaSdk from 'balena-sdk'; import type * as BalenaSdk from 'balena-sdk';
import _ = require('lodash'); import _ = require('lodash');
@ -391,6 +390,7 @@ export async function getOnlineTargetUuid(
})), })),
}); });
} catch (err) { } catch (err) {
const { BalenaApplicationNotFound } = await import('balena-errors');
if (!instanceOf(err, BalenaApplicationNotFound)) { if (!instanceOf(err, BalenaApplicationNotFound)) {
throw err; throw err;
} }

View File

@ -21,6 +21,7 @@
"allowJs": true "allowJs": true
}, },
"include": [ "include": [
"./lib/**/*" "./lib/**/*",
"./typings/**/*"
] ]
} }