diff --git a/automation/build-bin.ts b/automation/build-bin.ts index 520f5f39..76fc8f81 100644 --- a/automation/build-bin.ts +++ b/automation/build-bin.ts @@ -18,15 +18,15 @@ import type { JsonVersions } from '../lib/commands/version/index'; import { run as oclifRun } from '@oclif/core'; -import * as archiver from 'archiver'; -import * as Bluebird from 'bluebird'; +import archiver from 'archiver'; +import Bluebird from 'bluebird'; import { exec, execFile } from 'child_process'; import * as filehound from 'filehound'; import type { Stats } from 'fs'; import * as fs from 'fs-extra'; -import * as klaw from 'klaw'; +import klaw from 'klaw'; import * as path from 'path'; -import * as rimraf from 'rimraf'; +import rimraf from 'rimraf'; import * as semver from 'semver'; import { promisify } from 'util'; import { notarize } from '@electron/notarize'; @@ -87,7 +87,7 @@ export const finalReleaseAssets: { [platform: string]: string[] } = { * Throw an error if the diff is not empty. */ async function diffPkgOutput(pkgOut: string) { - const { monochrome } = await import('../tests/helpers'); + const { monochrome } = await import('../tests/helpers.js'); const relSavedPath = path.join( 'tests', 'test-data', @@ -263,7 +263,7 @@ async function testPkg() { 'version', '-j', ]); - const { filterCliOutputForTests } = await import('../tests/helpers'); + const { filterCliOutputForTests } = await import('../tests/helpers.js'); const filtered = filterCliOutputForTests({ err: stderr.split(/\r?\n/), out: stdout.split(/\r?\n/), diff --git a/automation/utils.ts b/automation/utils.ts index 77c97b2b..5b9f5ef5 100644 --- a/automation/utils.ts +++ b/automation/utils.ts @@ -97,7 +97,7 @@ export function loadPackageJson() { * @returns The program's full path, e.g. 'C:\WINDOWS\System32\OpenSSH\ssh.EXE' */ export async function which(program: string): Promise { - const whichMod = await import('which'); + const { default: whichMod } = await import('which'); let programPath: string; try { programPath = await whichMod(program); diff --git a/lib/app.ts b/lib/app.ts index 8b9359ea..98065ea5 100644 --- a/lib/app.ts +++ b/lib/app.ts @@ -31,7 +31,7 @@ import { run as mainRun, settings } from '@oclif/core'; * @see https://docs.sentry.io/error-reporting/quickstart/?platform=node */ export const setupSentry = onceAsync(async () => { - const config = await import('./config'); + const config = await import('./config.js'); const Sentry = await import('@sentry/node'); Sentry.init({ autoSessionTracking: false, @@ -51,7 +51,7 @@ export const setupSentry = onceAsync(async () => { async function checkNodeVersion() { const validNodeVersions = packageJSON.engines.node; if (!(await import('semver')).satisfies(process.version, validNodeVersions)) { - const { getNodeEngineVersionWarn } = await import('./utils/messages'); + const { getNodeEngineVersionWarn } = await import('./utils/messages.js'); console.warn(getNodeEngineVersionWarn(process.version, validNodeVersions)); } } @@ -89,13 +89,13 @@ async function init() { const settings = new CliSettings(); // Proxy setup should be done early on, before loading balena-sdk - await (await import('./utils/proxy')).setupGlobalHttpProxy(settings); + await (await import('./utils/proxy.js')).setupGlobalHttpProxy(settings); setupBalenaSdkSharedOptions(settings); // check for CLI updates once a day if (!process.env.BALENARC_OFFLINE_MODE) { - (await import('./utils/update')).notify(); + (await import('./utils/update.js')).notify(); } } @@ -106,7 +106,7 @@ async function oclifRun(command: string[], options: AppOptions) { if (unsupportedFlag || process.env.BALENARC_UNSUPPORTED) { deprecationPromise = Promise.resolve(); } else { - const { DeprecationChecker } = await import('./deprecation'); + const { DeprecationChecker } = await import('./deprecation.js'); const deprecationChecker = new DeprecationChecker(packageJSON.version); // warnAndAbortIfDeprecated uses previously cached data only await deprecationChecker.warnAndAbortIfDeprecated(); @@ -137,7 +137,8 @@ async function oclifRun(command: string[], options: AppOptions) { } } if (shouldFlush) { - await import('@oclif/core/flush'); + const { default: flush } = await import('@oclif/core/flush.js'); + await flush(); } // TODO: figure out why we need to call fast-boot stop() here, in // addition to calling it in the main `run()` function in this file. @@ -148,11 +149,11 @@ async function oclifRun(command: string[], options: AppOptions) { // the try/catch block above, execution does not get past the // Promise.all() call below, but I don't understand why. if (isEEXIT) { - (await import('./fast-boot')).stop(); + (await import('./fast-boot.js')).stop(); } })(!options.noFlush); - const { trackPromise } = await import('./hooks/prerun/track'); + const { trackPromise } = await import('./hooks/prerun/track.js'); await Promise.all([trackPromise, deprecationPromise, runPromise]); } @@ -161,7 +162,7 @@ async function oclifRun(command: string[], options: AppOptions) { export async function run(cliArgs = process.argv, options: AppOptions) { try { const { setOfflineModeEnvVars, normalizeEnvVars, pkgExec } = await import( - './utils/bootstrap' + './utils/bootstrap.js' ); setOfflineModeEnvVars(); normalizeEnvVars(); @@ -180,10 +181,10 @@ export async function run(cliArgs = process.argv, options: AppOptions) { const args = await preparseArgs(cliArgs); await oclifRun(args, options); } catch (err) { - await (await import('./errors')).handleError(err); + await (await import('./errors.js')).handleError(err); } finally { try { - (await import('./fast-boot')).stop(); + (await import('./fast-boot.js')).stop(); } catch (e) { if (process.env.DEBUG) { console.error(`[debug] Stopping fast-boot: ${e}`); diff --git a/lib/auth/index.ts b/lib/auth/index.ts index 2089eaad..7c48867c 100644 --- a/lib/auth/index.ts +++ b/lib/auth/index.ts @@ -42,7 +42,7 @@ import { LoginServer } from './server'; * console.log("My session token is: #{sessionToken}") */ export async function login({ host = '127.0.0.1', port = 0 }) { - const utils = await import('./utils'); + const utils = await import('./utils.js'); const loginServer = new LoginServer(); const { @@ -55,7 +55,7 @@ export async function login({ host = '127.0.0.1', port = 0 }) { const loginUrl = await utils.getDashboardLoginURL(callbackUrl); console.info(`Opening web browser for URL:\n${loginUrl}`); - const open = await import('open'); + const { default: open } = await import('open'); await open(loginUrl, { wait: false }); const balena = getBalenaSdk(); diff --git a/lib/auth/server.ts b/lib/auth/server.ts index df7880d4..c24388fd 100644 --- a/lib/auth/server.ts +++ b/lib/auth/server.ts @@ -16,7 +16,7 @@ limitations under the License. import * as bodyParser from 'body-parser'; import { EventEmitter } from 'events'; -import * as express from 'express'; +import express from 'express'; import type { Socket } from 'net'; import * as path from 'path'; diff --git a/lib/command.ts b/lib/command.ts index 1b260a35..83c8c445 100644 --- a/lib/command.ts +++ b/lib/command.ts @@ -71,7 +71,7 @@ export default abstract class BalenaCommand extends Command { * - other code needs to execute before check */ protected static async checkElevatedPrivileges() { - const isElevated = await (await import('is-elevated'))(); + const isElevated = await (await import('is-elevated')).default(); if (!isElevated) { throw new InsufficientPrivilegesError( 'You need root/admin privileges to run this command', @@ -94,7 +94,7 @@ export default abstract class BalenaCommand extends Command { * @throws {NotLoggedInError} */ public static async checkLoggedIn() { - await (await import('./utils/patterns')).checkLoggedIn(); + await (await import('./utils/patterns.js')).checkLoggedIn(); } /** @@ -139,14 +139,16 @@ export default abstract class BalenaCommand extends Command { * values from stdin based in configuration, minimising command implementation. */ protected async getStdin() { - this.stdin = await (await import('get-stdin'))(); + const { default: getStdin } = await import('get-stdin'); + this.stdin = await getStdin(); } /** * Get a logger instance. */ protected static async getLogger() { - return (await import('./utils/logger')).getLogger(); + const { default: logger } = await import('./utils/logger.js'); + return logger.getLogger(); } protected async init() { diff --git a/lib/commands/api-keys/index.ts b/lib/commands/api-keys/index.ts index cadf144e..d0ceb50f 100644 --- a/lib/commands/api-keys/index.ts +++ b/lib/commands/api-keys/index.ts @@ -46,7 +46,7 @@ export default class ApiKeysCmd extends Command { public async run() { const { flags: options } = await this.parse(ApiKeysCmd); - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); const actorId = options.fleet ? ( await getApplication(getBalenaSdk(), options.fleet, { diff --git a/lib/commands/app/create.ts b/lib/commands/app/create.ts index 5d82e33c..1e888504 100644 --- a/lib/commands/app/create.ts +++ b/lib/commands/app/create.ts @@ -77,7 +77,7 @@ export default class AppCreateCmd extends Command { const { args: params, flags: options } = await this.parse(AppCreateCmd); await ( - await import('../../utils/application-create') + await import('../../utils/application-create.js') ).applicationCreateBase('app', options, params); } } diff --git a/lib/commands/block/create.ts b/lib/commands/block/create.ts index efb5ced7..e6dd7b56 100644 --- a/lib/commands/block/create.ts +++ b/lib/commands/block/create.ts @@ -77,7 +77,7 @@ export default class BlockCreateCmd extends Command { const { args: params, flags: options } = await this.parse(BlockCreateCmd); await ( - await import('../../utils/application-create') + await import('../../utils/application-create.js') ).applicationCreateBase('block', options, params); } } diff --git a/lib/commands/build/index.ts b/lib/commands/build/index.ts index 906f3489..0bcef8eb 100644 --- a/lib/commands/build/index.ts +++ b/lib/commands/build/index.ts @@ -36,6 +36,7 @@ import type { ComposeCliFlags, ComposeOpts } from '../../utils/compose-types'; import { buildProject, composeCliFlags } from '../../utils/compose_ts'; import type { BuildOpts, DockerCliFlags } from '../../utils/docker'; import { dockerCliFlags } from '../../utils/docker'; +import type Dockerode from 'dockerode'; // TODO: For this special one we can't use Interfaces.InferredFlags/InferredArgs // because of the 'registry-secrets' type which is defined in the actual code @@ -157,14 +158,16 @@ ${dockerignoreHelp} (opts.fleet == null && (opts.arch == null || opts.deviceType == null)) || (opts.fleet != null && (opts.arch != null || opts.deviceType != null)) ) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); throw new ExpectedError( 'You must specify either a fleet (-f), or the device type (-d) and optionally the architecture (-A)', ); } // Validate project directory - const { validateProjectDirectory } = await import('../../utils/compose_ts'); + const { validateProjectDirectory } = await import( + '../../utils/compose_ts.js' + ); const { dockerfilePath, registrySecrets } = await validateProjectDirectory( sdk, { @@ -197,7 +200,7 @@ ${dockerignoreHelp} )) as PineTypedResult ).is_of__cpu_architecture[0].slug; } catch (err) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); if (err instanceof sdk.errors.BalenaInvalidDeviceType) { let message = err.message; if (!(await sdk.auth.isLoggedIn())) { @@ -214,7 +217,7 @@ ${dockerignoreHelp} protected async getAppAndResolveArch(opts: FlagsDef) { if (opts.fleet) { - const { getAppWithArch } = await import('../../utils/helpers'); + const { getAppWithArch } = await import('../../utils/helpers.js'); const app = await getAppWithArch(opts.fleet); opts.arch = app.arch; opts.deviceType = app.is_for__device_type[0].slug; @@ -222,8 +225,14 @@ ${dockerignoreHelp} } } - protected async prepareBuild(options: FlagsDef) { - const { getDocker, generateBuildOpts } = await import('../../utils/docker'); + protected async prepareBuild(options: FlagsDef): Promise<{ + docker: Dockerode; + buildOpts: BuildOpts; + composeOpts: ComposeOpts; + }> { + const { getDocker, generateBuildOpts } = await import( + '../../utils/docker.js' + ); const [docker, buildOpts, composeOpts] = await Promise.all([ getDocker(options), generateBuildOpts(options), @@ -261,7 +270,7 @@ ${dockerignoreHelp} buildOpts: BuildOpts; }, ) { - const { loadProject } = await import('../../utils/compose_ts'); + const { loadProject } = await import('../../utils/compose_ts.js'); const project = await loadProject( logger, diff --git a/lib/commands/config/generate.ts b/lib/commands/config/generate.ts index 2788b3c6..b5a7210a 100644 --- a/lib/commands/config/generate.ts +++ b/lib/commands/config/generate.ts @@ -126,7 +126,7 @@ export default class ConfigGenerateCmd extends Command { public static authenticated = true; public async getApplication(balena: BalenaSDK, fleet: string) { - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); return await getApplication(balena, fleet, { $select: 'slug', $expand: { @@ -152,7 +152,7 @@ export default class ConfigGenerateCmd extends Command { $expand: { is_of__device_type: { $select: 'slug' } }, }); if (!rawDevice.belongs_to__application) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); throw new ExpectedError(stripIndent` Device ${options.device} does not appear to belong to an accessible fleet. Try with a different device, or use '--fleet' instead of '--device'.`); @@ -171,14 +171,14 @@ export default class ConfigGenerateCmd extends Command { // Check compatibility if application and deviceType provided if (options.fleet && options.deviceType) { - const helpers = await import('../../utils/helpers'); + const helpers = await import('../../utils/helpers.js'); if ( !(await helpers.areDeviceTypesCompatible( resourceDeviceType, deviceType, )) ) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); throw new ExpectedError( `Device type ${options.deviceType} is incompatible with fleet ${options.fleet}`, ); @@ -189,7 +189,7 @@ export default class ConfigGenerateCmd extends Command { await balena.models.config.getDeviceTypeManifestBySlug(deviceType); const { validateSecureBootOptionAndWarn } = await import( - '../../utils/config' + '../../utils/config.js' ); await validateSecureBootOptionAndWarn( options.secureBoot, @@ -211,7 +211,7 @@ export default class ConfigGenerateCmd extends Command { // Generate config const { generateDeviceConfig, generateApplicationConfig } = await import( - '../../utils/config' + '../../utils/config.js' ); let config; @@ -250,7 +250,7 @@ export default class ConfigGenerateCmd extends Command { protected async validateOptions( options: Interfaces.InferredFlags, ) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); if (options.device == null && options.fleet == null) { throw new ExpectedError(this.missingDeviceOrAppMessage); @@ -259,9 +259,9 @@ export default class ConfigGenerateCmd extends Command { if (!options.fleet && options.deviceType) { throw new ExpectedError(this.deviceTypeNotAllowedMessage); } - const { normalizeOsVersion } = await import('../../utils/normalization'); + const { normalizeOsVersion } = await import('../../utils/normalization.js'); options.version = normalizeOsVersion(options.version); - const { validateDevOptionAndWarn } = await import('../../utils/config'); + const { validateDevOptionAndWarn } = await import('../../utils/config.js'); await validateDevOptionAndWarn(options.dev, options.version); } } diff --git a/lib/commands/config/inject.ts b/lib/commands/config/inject.ts index 6e344f70..a9034e0d 100644 --- a/lib/commands/config/inject.ts +++ b/lib/commands/config/inject.ts @@ -56,7 +56,7 @@ export default class ConfigInjectCmd extends Command { public async run() { const { args: params, flags: options } = await this.parse(ConfigInjectCmd); - const { safeUmount } = await import('../../utils/umount'); + const { safeUmount } = await import('../../utils/umount.js'); const drive = options.drive || (await getVisuals().drive('Select the device/OS drive')); diff --git a/lib/commands/config/read.ts b/lib/commands/config/read.ts index 333fea87..9830e5a6 100644 --- a/lib/commands/config/read.ts +++ b/lib/commands/config/read.ts @@ -50,7 +50,7 @@ export default class ConfigReadCmd extends Command { public async run() { const { flags: options } = await this.parse(ConfigReadCmd); - const { safeUmount } = await import('../../utils/umount'); + const { safeUmount } = await import('../../utils/umount.js'); const drive = options.drive || (await getVisuals().drive('Select the device drive')); diff --git a/lib/commands/config/reconfigure.ts b/lib/commands/config/reconfigure.ts index be9ab466..8dd9a2b1 100644 --- a/lib/commands/config/reconfigure.ts +++ b/lib/commands/config/reconfigure.ts @@ -59,7 +59,7 @@ export default class ConfigReconfigureCmd extends Command { public async run() { const { flags: options } = await this.parse(ConfigReconfigureCmd); - const { safeUmount } = await import('../../utils/umount'); + const { safeUmount } = await import('../../utils/umount.js'); const drive = options.drive || (await getVisuals().drive('Select the device drive')); @@ -70,7 +70,7 @@ export default class ConfigReconfigureCmd extends Command { await safeUmount(drive); if (!uuid) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); throw new ExpectedError( `Error: UUID not found in 'config.json' file for '${drive}'`, ); @@ -84,7 +84,7 @@ export default class ConfigReconfigureCmd extends Command { configureCommand.push('--advanced'); } - const { runCommand } = await import('../../utils/helpers'); + const { runCommand } = await import('../../utils/helpers.js'); await runCommand(configureCommand); console.info('Done'); diff --git a/lib/commands/config/write.ts b/lib/commands/config/write.ts index e1323f5f..dd922da1 100644 --- a/lib/commands/config/write.ts +++ b/lib/commands/config/write.ts @@ -61,7 +61,7 @@ export default class ConfigWriteCmd extends Command { public async run() { const { args: params, flags: options } = await this.parse(ConfigWriteCmd); - const { denyMount, safeUmount } = await import('../../utils/umount'); + const { denyMount, safeUmount } = await import('../../utils/umount.js'); const drive = options.drive || (await getVisuals().drive('Select the device drive')); diff --git a/lib/commands/deploy/index.ts b/lib/commands/deploy/index.ts index 1fa0232c..e11e72fa 100644 --- a/lib/commands/deploy/index.ts +++ b/lib/commands/deploy/index.ts @@ -175,7 +175,7 @@ ${dockerignoreHelp} const sdk = getBalenaSdk(); const { getRegistrySecrets, validateProjectDirectory } = await import( - '../../utils/compose_ts' + '../../utils/compose_ts.js' ); const { releaseTagKeys, releaseTagValues } = parseReleaseTagKeysAndValues( @@ -199,10 +199,10 @@ ${dockerignoreHelp} (options as FlagsDef)['registry-secrets'] = registrySecrets; } - const helpers = await import('../../utils/helpers'); + const helpers = await import('../../utils/helpers.js'); const app = await helpers.getAppWithArch(fleet); - const dockerUtils = await import('../../utils/docker'); + const dockerUtils = await import('../../utils/docker.js'); const [docker, buildOpts, composeOpts] = await Promise.all([ dockerUtils.getDocker(options), dockerUtils.generateBuildOpts(options as FlagsDef), @@ -250,7 +250,7 @@ ${dockerignoreHelp} const doodles = await import('resin-doodles'); const sdk = getBalenaSdk(); const { deployProject: $deployProject, loadProject } = await import( - '../../utils/compose_ts' + '../../utils/compose_ts.js' ); const appType = opts.app.application_type[0]; diff --git a/lib/commands/device/deactivate.ts b/lib/commands/device/deactivate.ts index 43afcc8e..c22d2653 100644 --- a/lib/commands/device/deactivate.ts +++ b/lib/commands/device/deactivate.ts @@ -55,7 +55,7 @@ export default class DeviceDeactivateCmd extends Command { await this.parse(DeviceDeactivateCmd); const balena = getBalenaSdk(); - const patterns = await import('../../utils/patterns'); + const patterns = await import('../../utils/patterns.js'); const uuid = params.uuid; const deactivationWarning = ` diff --git a/lib/commands/device/index.ts b/lib/commands/device/index.ts index 71dbef74..3dc318ca 100644 --- a/lib/commands/device/index.ts +++ b/lib/commands/device/index.ts @@ -122,7 +122,7 @@ export default class DeviceCmd extends Command { )) as ExtendedDevice; if (options.view) { - const open = await import('open'); + const { default: open } = await import('open'); const dashboardUrl = balena.models.device.getDashboardUrl(device.uuid); await open(dashboardUrl, { wait: false }); return; diff --git a/lib/commands/device/init.ts b/lib/commands/device/init.ts index 3fc45e4b..2a4b45c1 100644 --- a/lib/commands/device/init.ts +++ b/lib/commands/device/init.ts @@ -113,12 +113,12 @@ export default class DeviceInitCmd extends Command { // Imports const { promisify } = await import('util'); - const rimraf = promisify(await import('rimraf')); + const rimraf = promisify((await import('rimraf')).default); const tmp = await import('tmp'); const tmpNameAsync = promisify(tmp.tmpName); tmp.setGracefulCleanup(); - const { downloadOSImage } = await import('../../utils/cloud'); - const { getApplication } = await import('../../utils/sdk'); + const { downloadOSImage } = await import('../../utils/cloud.js'); + const { getApplication } = await import('../../utils/sdk.js'); const logger = await Command.getLogger(); const balena = getBalenaSdk(); @@ -133,7 +133,7 @@ export default class DeviceInitCmd extends Command { }, }, }) - : await (await import('../../utils/patterns')).selectApplication(); + : await (await import('../../utils/patterns.js')).selectApplication(); // Register new device const deviceUuid = balena.models.device.generateUniqueKey(); diff --git a/lib/commands/device/move.ts b/lib/commands/device/move.ts index 20e4c9af..bff8f949 100644 --- a/lib/commands/device/move.ts +++ b/lib/commands/device/move.ts @@ -101,7 +101,7 @@ export default class DeviceMoveCmd extends Command { const devices = await this.getDevices(balena, deviceUuids); // Disambiguate application - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); // Get destination application const application = options.fleet @@ -151,7 +151,7 @@ export default class DeviceMoveCmd extends Command { }) .map((deviceType) => deviceType.id); - const patterns = await import('../../utils/patterns'); + const patterns = await import('../../utils/patterns.js'); try { const application = await patterns.selectApplication( { diff --git a/lib/commands/device/os-update.ts b/lib/commands/device/os-update.ts index bb5b3226..c7883ae0 100644 --- a/lib/commands/device/os-update.ts +++ b/lib/commands/device/os-update.ts @@ -122,7 +122,9 @@ export default class DeviceOsUpdateCmd extends Command { // Get target OS version let targetOsVersion = options.version; if (targetOsVersion != null) { - const { normalizeOsVersion } = await import('../../utils/normalization'); + const { normalizeOsVersion } = await import( + '../../utils/normalization.js' + ); targetOsVersion = normalizeOsVersion(targetOsVersion); if (!hupVersionInfo.versions.includes(targetOsVersion)) { throw new ExpectedError( @@ -143,7 +145,7 @@ export default class DeviceOsUpdateCmd extends Command { }); } - const patterns = await import('../../utils/patterns'); + const patterns = await import('../../utils/patterns.js'); // Confirm and start update await patterns.confirm( options.yes || false, diff --git a/lib/commands/device/register.ts b/lib/commands/device/register.ts index 7a9d10b5..6a366267 100644 --- a/lib/commands/device/register.ts +++ b/lib/commands/device/register.ts @@ -64,7 +64,7 @@ export default class DeviceRegisterCmd extends Command { const { args: params, flags: options } = await this.parse(DeviceRegisterCmd); - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); const balena = getBalenaSdk(); diff --git a/lib/commands/device/restart.ts b/lib/commands/device/restart.ts index 71f35f7b..8b71c101 100644 --- a/lib/commands/device/restart.ts +++ b/lib/commands/device/restart.ts @@ -94,8 +94,8 @@ export default class DeviceRestartCmd extends Command { deviceUuid: string, serviceNames: string[], ) { - const { ExpectedError, instanceOf } = await import('../../errors'); - const { getExpandedProp } = await import('../../utils/pine'); + const { ExpectedError, instanceOf } = await import('../../errors.js'); + const { getExpandedProp } = await import('../../utils/pine.js'); // Get device let device: DeviceWithServiceDetails; @@ -161,7 +161,7 @@ export default class DeviceRestartCmd extends Command { // Note: device.restartApplication throws `BalenaDeviceNotFound: Device not found` if device not online. // Need to use device.get first to distinguish between non-existant and offline devices. // Remove this workaround when SDK issue resolved: https://github.com/balena-io/balena-sdk/issues/649 - const { instanceOf, ExpectedError } = await import('../../errors'); + const { instanceOf, ExpectedError } = await import('../../errors.js'); try { const device = await balena.models.device.get(deviceUuid); if (!device.is_online) { diff --git a/lib/commands/device/rm.ts b/lib/commands/device/rm.ts index 6f3cc482..9f7e8206 100644 --- a/lib/commands/device/rm.ts +++ b/lib/commands/device/rm.ts @@ -56,7 +56,7 @@ export default class DeviceRmCmd extends Command { const { args: params, flags: options } = await this.parse(DeviceRmCmd); const balena = getBalenaSdk(); - const patterns = await import('../../utils/patterns'); + const patterns = await import('../../utils/patterns.js'); // Confirm const uuids = params.uuid.split(','); diff --git a/lib/commands/device/start-service.ts b/lib/commands/device/start-service.ts index 4637f221..460f5e3f 100644 --- a/lib/commands/device/start-service.ts +++ b/lib/commands/device/start-service.ts @@ -78,8 +78,8 @@ export default class DeviceStartServiceCmd extends Command { deviceUuid: string, serviceNames: string[], ) { - const { ExpectedError } = await import('../../errors'); - const { getExpandedProp } = await import('../../utils/pine'); + const { ExpectedError } = await import('../../errors.js'); + const { getExpandedProp } = await import('../../utils/pine.js'); // Get device const device = await balena.models.device.getWithServiceDetails( diff --git a/lib/commands/device/stop-service.ts b/lib/commands/device/stop-service.ts index b7aa53dc..1ae793ff 100644 --- a/lib/commands/device/stop-service.ts +++ b/lib/commands/device/stop-service.ts @@ -78,8 +78,8 @@ export default class DeviceStopServiceCmd extends Command { deviceUuid: string, serviceNames: string[], ) { - const { ExpectedError } = await import('../../errors'); - const { getExpandedProp } = await import('../../utils/pine'); + const { ExpectedError } = await import('../../errors.js'); + const { getExpandedProp } = await import('../../utils/pine.js'); // Get device const device = await balena.models.device.getWithServiceDetails( diff --git a/lib/commands/devices/index.ts b/lib/commands/devices/index.ts index e7196c42..70991a3a 100644 --- a/lib/commands/devices/index.ts +++ b/lib/commands/devices/index.ts @@ -78,7 +78,7 @@ export default class DevicesCmd extends Command { const devices = ( await (async () => { if (options.fleet != null) { - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); const application = await getApplication(balena, options.fleet, { $select: 'slug', $expand: { @@ -115,7 +115,7 @@ export default class DevicesCmd extends Command { ]; if (options.json) { - const { pickAndRename } = await import('../../utils/helpers'); + const { pickAndRename } = await import('../../utils/helpers.js'); const mapped = devices.map((device) => pickAndRename(device, fields)); console.log(JSON.stringify(mapped, null, 4)); } else { diff --git a/lib/commands/env/add.ts b/lib/commands/env/add.ts index 479e03c4..77c58fc5 100644 --- a/lib/commands/env/add.ts +++ b/lib/commands/env/add.ts @@ -185,7 +185,7 @@ async function resolveFleetSlugs( fleetOption: string, ) { const fleetSlugs: string[] = []; - const { getFleetSlug } = await import('../../utils/sdk'); + const { getFleetSlug } = await import('../../utils/sdk.js'); for (const appNameOrSlug of fleetOption.split(',')) { try { fleetSlugs.push(await getFleetSlug(balena, appNameOrSlug)); @@ -222,7 +222,7 @@ async function setServiceVars( } } } else if (options.device) { - const { getDeviceAndAppFromUUID } = await import('../../utils/cloud'); + const { getDeviceAndAppFromUUID } = await import('../../utils/cloud.js'); for (const uuid of options.device.split(',')) { let device; let app; diff --git a/lib/commands/env/rm.ts b/lib/commands/env/rm.ts index d3589001..1af607eb 100644 --- a/lib/commands/env/rm.ts +++ b/lib/commands/env/rm.ts @@ -71,7 +71,7 @@ export default class EnvRmCmd extends Command { await Command.checkLoggedIn(); - const { confirm } = await import('../../utils/patterns'); + const { confirm } = await import('../../utils/patterns.js'); await confirm( opt.yes || false, 'Are you sure you want to delete the environment variable?', diff --git a/lib/commands/envs/index.ts b/lib/commands/envs/index.ts index 310d9cca..d0719d81 100644 --- a/lib/commands/envs/index.ts +++ b/lib/commands/envs/index.ts @@ -125,14 +125,14 @@ export default class EnvsCmd extends Command { let fleetSlug: string | undefined = options.fleet ? await ( - await import('../../utils/sdk') + await import('../../utils/sdk.js') ).getFleetSlug(balena, options.fleet) : undefined; let fullUUID: string | undefined; // as oppposed to the short, 7-char UUID if (options.device) { const { getDeviceAndMaybeAppFromUUID } = await import( - '../../utils/cloud' + '../../utils/cloud.js' ); const [device, app] = await getDeviceAndMaybeAppFromUUID( balena, @@ -186,7 +186,7 @@ export default class EnvsCmd extends Command { } if (options.json) { - const { pickAndRename } = await import('../../utils/helpers'); + const { pickAndRename } = await import('../../utils/helpers.js'); const mapped = varArray.map((o) => pickAndRename(o, fields)); this.log(JSON.stringify(mapped, null, 4)); } else { diff --git a/lib/commands/fleet/create.ts b/lib/commands/fleet/create.ts index 2d10c221..a4f11a2a 100644 --- a/lib/commands/fleet/create.ts +++ b/lib/commands/fleet/create.ts @@ -77,7 +77,7 @@ export default class FleetCreateCmd extends Command { const { args: params, flags: options } = await this.parse(FleetCreateCmd); await ( - await import('../../utils/application-create') + await import('../../utils/application-create.js') ).applicationCreateBase('fleet', options, params); } } diff --git a/lib/commands/fleet/index.ts b/lib/commands/fleet/index.ts index b59c135a..81849e88 100644 --- a/lib/commands/fleet/index.ts +++ b/lib/commands/fleet/index.ts @@ -58,7 +58,7 @@ export default class FleetCmd extends Command { public async run() { const { args: params, flags: options } = await this.parse(FleetCmd); - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); const balena = getBalenaSdk(); @@ -70,7 +70,7 @@ export default class FleetCmd extends Command { }); if (options.view) { - const open = await import('open'); + const { default: open } = await import('open'); const dashboardUrl = balena.models.application.getDashboardUrl( application.id, ); diff --git a/lib/commands/fleet/purge.ts b/lib/commands/fleet/purge.ts index 5456ea0a..4ecbd85c 100644 --- a/lib/commands/fleet/purge.ts +++ b/lib/commands/fleet/purge.ts @@ -51,7 +51,7 @@ export default class FleetPurgeCmd extends Command { public async run() { const { args: params } = await this.parse(FleetPurgeCmd); - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); const balena = getBalenaSdk(); diff --git a/lib/commands/fleet/rename.ts b/lib/commands/fleet/rename.ts index 9214d2e6..f8569aa1 100644 --- a/lib/commands/fleet/rename.ts +++ b/lib/commands/fleet/rename.ts @@ -59,13 +59,15 @@ export default class FleetRenameCmd extends Command { public async run() { const { args: params } = await this.parse(FleetRenameCmd); - const { validateApplicationName } = await import('../../utils/validation'); - const { ExpectedError } = await import('../../errors'); + const { validateApplicationName } = await import( + '../../utils/validation.js' + ); + const { ExpectedError } = await import('../../errors.js'); const balena = getBalenaSdk(); // Disambiguate target application (if params.params is a number, it could either be an ID or a numerical name) - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); const application = await getApplication(balena, params.fleet, { $select: ['id', 'app_name', 'slug'], $expand: { diff --git a/lib/commands/fleet/restart.ts b/lib/commands/fleet/restart.ts index f9a8c4b6..6d22b657 100644 --- a/lib/commands/fleet/restart.ts +++ b/lib/commands/fleet/restart.ts @@ -50,7 +50,7 @@ export default class FleetRestartCmd extends Command { public async run() { const { args: params } = await this.parse(FleetRestartCmd); - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); const balena = getBalenaSdk(); diff --git a/lib/commands/fleet/rm.ts b/lib/commands/fleet/rm.ts index e75d1c04..25dab03f 100644 --- a/lib/commands/fleet/rm.ts +++ b/lib/commands/fleet/rm.ts @@ -54,8 +54,8 @@ export default class FleetRmCmd extends Command { public async run() { const { args: params, flags: options } = await this.parse(FleetRmCmd); - const { confirm } = await import('../../utils/patterns'); - const { getApplication } = await import('../../utils/sdk'); + const { confirm } = await import('../../utils/patterns.js'); + const { getApplication } = await import('../../utils/sdk.js'); const balena = getBalenaSdk(); // Confirm diff --git a/lib/commands/internal/osinit.ts b/lib/commands/internal/osinit.ts index 8bc12992..9bc184b0 100644 --- a/lib/commands/internal/osinit.ts +++ b/lib/commands/internal/osinit.ts @@ -63,7 +63,7 @@ export default class OsinitCmd extends Command { const config = JSON.parse(params.config); const { getManifest, osProgressHandler } = await import( - '../../utils/helpers' + '../../utils/helpers.js' ); const manifest = await getManifest(params.image, params.type); diff --git a/lib/commands/join/index.ts b/lib/commands/join/index.ts index 152381b3..a61efb1e 100644 --- a/lib/commands/join/index.ts +++ b/lib/commands/join/index.ts @@ -78,7 +78,7 @@ export default class JoinCmd extends Command { public async run() { const { args: params, flags: options } = await this.parse(JoinCmd); - const promote = await import('../../utils/promote'); + const promote = await import('../../utils/promote.js'); const sdk = getBalenaSdk(); const logger = await Command.getLogger(); return promote.join( diff --git a/lib/commands/key/rm.ts b/lib/commands/key/rm.ts index 5e0ad100..f9523efe 100644 --- a/lib/commands/key/rm.ts +++ b/lib/commands/key/rm.ts @@ -52,7 +52,7 @@ export default class KeyRmCmd extends Command { public async run() { const { args: params, flags: options } = await this.parse(KeyRmCmd); - const patterns = await import('../../utils/patterns'); + const patterns = await import('../../utils/patterns.js'); await patterns.confirm( options.yes ?? false, diff --git a/lib/commands/leave/index.ts b/lib/commands/leave/index.ts index 2365d007..d30cf2ce 100644 --- a/lib/commands/leave/index.ts +++ b/lib/commands/leave/index.ts @@ -62,7 +62,7 @@ export default class LeaveCmd extends Command { public async run() { const { args: params } = await this.parse(LeaveCmd); - const promote = await import('../../utils/promote'); + const promote = await import('../../utils/promote.js'); const logger = await Command.getLogger(); return promote.leave(logger, params.deviceIpOrHostname); } diff --git a/lib/commands/local/configure.ts b/lib/commands/local/configure.ts index 53aa170d..220d1288 100644 --- a/lib/commands/local/configure.ts +++ b/lib/commands/local/configure.ts @@ -53,8 +53,8 @@ export default class LocalConfigureCmd extends Command { const { args: params } = await this.parse(LocalConfigureCmd); const reconfix = await import('reconfix'); - const { denyMount, safeUmount } = await import('../../utils/umount'); - const Logger = await import('../../utils/logger'); + const { denyMount, safeUmount } = await import('../../utils/umount.js'); + const { default: Logger } = await import('../../utils/logger.js'); const logger = Logger.getLogger(); diff --git a/lib/commands/local/flash.ts b/lib/commands/local/flash.ts index e2301718..c0293605 100644 --- a/lib/commands/local/flash.ts +++ b/lib/commands/local/flash.ts @@ -79,7 +79,7 @@ export default class LocalFlashCmd extends Command { const drive = await this.getDrive(options); - const { confirm } = await import('../../utils/patterns'); + const { confirm } = await import('../../utils/patterns.js'); await confirm( options.yes, 'This will erase the selected drive. Are you sure?', diff --git a/lib/commands/login/index.ts b/lib/commands/login/index.ts index 70d6c1c6..fb140488 100644 --- a/lib/commands/login/index.ts +++ b/lib/commands/login/index.ts @@ -123,7 +123,7 @@ export default class LoginCmd extends Command { const { flags: options, args: params } = await this.parse(LoginCmd); const balena = getBalenaSdk(); - const messages = await import('../../utils/messages'); + const messages = await import('../../utils/messages.js'); const balenaUrl = await balena.settings.get('balenaUrl'); // Consolidate user/email options @@ -202,20 +202,20 @@ ${messages.reachingOut}`); } // Credentials else if (loginOptions.credentials) { - const patterns = await import('../../utils/patterns'); + const patterns = await import('../../utils/patterns.js'); return patterns.authenticate(loginOptions); } // Web else if (loginOptions.web) { - const auth = await import('../../auth'); + const auth = await import('../../auth/index.js'); await auth.login({ port: loginOptions.port }); return; } else { - const patterns = await import('../../utils/patterns'); + const patterns = await import('../../utils/patterns.js'); // User had not selected login preference, prompt interactively const loginType = await patterns.askLoginType(); if (loginType === 'register') { - const open = await import('open'); + const { default: open } = await import('open'); const signupUrl = `https://dashboard.${balenaUrl}/signup`; await open(signupUrl, { wait: false }); throw new ExpectedError(`Please sign up at ${signupUrl}`); diff --git a/lib/commands/logs/index.ts b/lib/commands/logs/index.ts index 1ca17e72..5b8b49ce 100644 --- a/lib/commands/logs/index.ts +++ b/lib/commands/logs/index.ts @@ -96,14 +96,14 @@ export default class LogsCmd extends Command { const { args: params, flags: options } = await this.parse(LogsCmd); const balena = getBalenaSdk(); - const { serviceIdToName } = await import('../../utils/cloud'); + const { serviceIdToName } = await import('../../utils/cloud.js'); const { connectAndDisplayDeviceLogs, displayLogObject } = await import( - '../../utils/device/logs' + '../../utils/device/logs.js' ); const { validateIPAddress, validateDotLocalUrl } = await import( - '../../utils/validation' + '../../utils/validation.js' ); - const Logger = await import('../../utils/logger'); + const { default: Logger } = await import('../../utils/logger.js'); const logger = Logger.getLogger(); @@ -132,13 +132,13 @@ export default class LogsCmd extends Command { validateDotLocalUrl(params.device) ) { // Logs from local device - const { DeviceAPI } = await import('../../utils/device/api'); + const { DeviceAPI } = await import('../../utils/device/api.js'); const deviceApi = new DeviceAPI(logger, params.device); logger.logDebug('Checking we can access device'); try { await deviceApi.ping(); } catch (e) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); throw new ExpectedError( `Cannot access device at address ${params.device}. Device may not be in local mode.`, ); diff --git a/lib/commands/orgs/index.ts b/lib/commands/orgs/index.ts index f50604f8..28deb7f9 100644 --- a/lib/commands/orgs/index.ts +++ b/lib/commands/orgs/index.ts @@ -38,7 +38,7 @@ export default class OrgsCmd extends Command { public async run() { await this.parse(OrgsCmd); - const { getOwnOrganizations } = await import('../../utils/sdk'); + const { getOwnOrganizations } = await import('../../utils/sdk.js'); // Get organizations const organizations = await getOwnOrganizations(getBalenaSdk(), { diff --git a/lib/commands/os/build-config.ts b/lib/commands/os/build-config.ts index 0b6d954a..fe5c8323 100644 --- a/lib/commands/os/build-config.ts +++ b/lib/commands/os/build-config.ts @@ -82,7 +82,7 @@ export default class OsBuildConfigCmd extends Command { async buildConfig(image: string, deviceTypeSlug: string, advanced: boolean) { advanced = advanced || false; - const { getManifest } = await import('../../utils/helpers'); + const { getManifest } = await import('../../utils/helpers.js'); const deviceTypeManifest = await getManifest(image, deviceTypeSlug); return this.buildConfigForDeviceType(deviceTypeManifest, advanced); @@ -103,7 +103,7 @@ export default class OsBuildConfigCmd extends Command { }); if (advancedGroup != null) { - const { getGroupDefaults } = await import('../../utils/helpers'); + const { getGroupDefaults } = await import('../../utils/helpers.js'); override = getGroupDefaults(advancedGroup); } } diff --git a/lib/commands/os/configure.ts b/lib/commands/os/configure.ts index d25f8ce2..01a8b638 100644 --- a/lib/commands/os/configure.ts +++ b/lib/commands/os/configure.ts @@ -170,10 +170,10 @@ export default class OsConfigureCmd extends Command { const devInit = await import('balena-device-init'); const { promises: fs } = await import('fs'); const { generateDeviceConfig, generateApplicationConfig } = await import( - '../../utils/config' + '../../utils/config.js' ); - const helpers = await import('../../utils/helpers'); - const { getApplication } = await import('../../utils/sdk'); + const helpers = await import('../../utils/helpers.js'); + const { getApplication } = await import('../../utils/sdk.js'); let app: ApplicationWithDeviceTypeSlug | undefined; let device; @@ -211,7 +211,7 @@ export default class OsConfigureCmd extends Command { configJson = JSON.parse(rawConfig); } - const { normalizeOsVersion } = await import('../../utils/normalization'); + const { normalizeOsVersion } = await import('../../utils/normalization.js'); const osVersion = normalizeOsVersion( options.version || (await getOsVersionFromImage( @@ -221,11 +221,11 @@ export default class OsConfigureCmd extends Command { )), ); - const { validateDevOptionAndWarn } = await import('../../utils/config'); + const { validateDevOptionAndWarn } = await import('../../utils/config.js'); await validateDevOptionAndWarn(options.dev, osVersion); const { validateSecureBootOptionAndWarn } = await import( - '../../utils/config' + '../../utils/config.js' ); await validateSecureBootOptionAndWarn( options.secureBoot, @@ -363,7 +363,7 @@ async function checkDeviceTypeCompatibility( }, ) { if (options['device-type']) { - const helpers = await import('../../utils/helpers'); + const helpers = await import('../../utils/helpers.js'); if ( !(await helpers.areDeviceTypesCompatible( app.is_for__device_type[0].slug, @@ -417,7 +417,7 @@ async function askQuestionsForDeviceType( isGroup: true, }); if (!_.isEmpty(advancedGroup)) { - const helpers = await import('../../utils/helpers'); + const helpers = await import('../../utils/helpers.js'); answerSources.push(helpers.getGroupDefaults(advancedGroup)); } } diff --git a/lib/commands/os/download.ts b/lib/commands/os/download.ts index e7ef1bda..66664b81 100644 --- a/lib/commands/os/download.ts +++ b/lib/commands/os/download.ts @@ -95,7 +95,7 @@ export default class OsDownloadCmd extends Command { await OsDownloadCmd.checkLoggedIn(); } catch (e) { const { ExpectedError, NotLoggedInError } = await import( - '../../errors' + '../../errors.js' ); if (e instanceof NotLoggedInError) { throw new ExpectedError(stripIndent` @@ -107,7 +107,7 @@ export default class OsDownloadCmd extends Command { } } - const { downloadOSImage } = await import('../../utils/cloud'); + const { downloadOSImage } = await import('../../utils/cloud.js'); try { await downloadOSImage(params.type, options.output, options.version); diff --git a/lib/commands/os/initialize.ts b/lib/commands/os/initialize.ts index 322c1ab8..ca574483 100644 --- a/lib/commands/os/initialize.ts +++ b/lib/commands/os/initialize.ts @@ -62,7 +62,7 @@ export default class OsInitializeCmd extends Command { public async run() { const { args: params, flags: options } = await this.parse(OsInitializeCmd); - const { getManifest, sudo } = await import('../../utils/helpers'); + const { getManifest, sudo } = await import('../../utils/helpers.js'); console.info(`Initializing device ${INIT_WARNING_MESSAGE}`); @@ -75,13 +75,13 @@ export default class OsInitializeCmd extends Command { }); if (answers.drive != null) { - const { confirm } = await import('../../utils/patterns'); + const { confirm } = await import('../../utils/patterns.js'); await confirm( options.yes, `This will erase ${answers.drive}. Are you sure?`, `Going to erase ${answers.drive}.`, ); - const { safeUmount } = await import('../../utils/umount'); + const { safeUmount } = await import('../../utils/umount.js'); await safeUmount(answers.drive); } @@ -94,7 +94,7 @@ export default class OsInitializeCmd extends Command { ]); if (answers.drive != null) { - const { safeUmount } = await import('../../utils/umount'); + const { safeUmount } = await import('../../utils/umount.js'); await safeUmount(answers.drive); console.info(`You can safely remove ${answers.drive} now`); } diff --git a/lib/commands/os/versions.ts b/lib/commands/os/versions.ts index 9ba22a6b..79cd8049 100644 --- a/lib/commands/os/versions.ts +++ b/lib/commands/os/versions.ts @@ -58,7 +58,7 @@ export default class OsVersionsCmd extends Command { const { args: params, flags: options } = await this.parse(OsVersionsCmd); if (options['include-draft']) { - const { warnify } = await import('../../utils/messages'); + const { warnify } = await import('../../utils/messages.js'); console.error( warnify(stripIndent` Using pre-release balenaOS versions is only supported for OS updates @@ -68,7 +68,7 @@ export default class OsVersionsCmd extends Command { } const { formatOsVersion, getOsVersions } = await import( - '../../utils/cloud' + '../../utils/cloud.js' ); const vs = await getOsVersions( params.type, diff --git a/lib/commands/preload/index.ts b/lib/commands/preload/index.ts index 7df4fc46..6966d1ad 100644 --- a/lib/commands/preload/index.ts +++ b/lib/commands/preload/index.ts @@ -39,6 +39,7 @@ import type { Release, } from 'balena-sdk'; import type { Preloader } from 'balena-preload'; +import type { EventEmitter } from 'events'; export default class PreloadCmd extends Command { public static description = stripIndent` @@ -145,10 +146,10 @@ Can be repeated to add multiple certificates.\ const { args: params, flags: options } = await this.parse(PreloadCmd); const balena = getBalenaSdk(); - const balenaPreload = await import('balena-preload'); + const { default: balenaPreload } = await import('balena-preload'); const visuals = getVisuals(); - const nodeCleanup = await import('node-cleanup'); - const { instanceOf } = await import('../../errors'); + const { default: nodeCleanup } = await import('node-cleanup'); + const { instanceOf } = await import('../../errors.js'); // Check image file exists try { @@ -172,7 +173,7 @@ Can be repeated to add multiple certificates.\ // Load app here, and use app slug from hereon const fleetSlug: string | undefined = options.fleet ? await ( - await import('../../utils/sdk') + await import('../../utils/sdk.js') ).getFleetSlug(balena, options.fleet) : undefined; @@ -229,7 +230,7 @@ Can be repeated to add multiple certificates.\ } // Get a configured dockerode instance - const dockerUtils = await import('../../utils/docker'); + const dockerUtils = await import('../../utils/docker.js'); const docker = await dockerUtils.getDocker(options); const preloader = new balenaPreload.Preloader( undefined, @@ -243,7 +244,7 @@ Can be repeated to add multiple certificates.\ pinDevice ?? false, certificates, additionalSpace, - ); + ) as Preloader & EventEmitter; let gotSignal = false; @@ -481,7 +482,7 @@ Would you like to disable automatic updates for this fleet now?\ } async getAppWithReleases(balenaSdk: BalenaSDK, slug: string) { - const { getApplication } = await import('../../utils/sdk'); + const { getApplication } = await import('../../utils/sdk.js'); return await getApplication(balenaSdk, slug, { $expand: this.applicationExpandOptions, diff --git a/lib/commands/push/index.ts b/lib/commands/push/index.ts index 7693f7c4..6560c263 100644 --- a/lib/commands/push/index.ts +++ b/lib/commands/push/index.ts @@ -233,7 +233,9 @@ export default class PushCmd extends Command { logger.logDebug(`Using build source directory: ${options.source} `); const sdk = getBalenaSdk(); - const { validateProjectDirectory } = await import('../../utils/compose_ts'); + const { validateProjectDirectory } = await import( + '../../utils/compose_ts.js' + ); const { dockerfilePath, registrySecrets } = await validateProjectDirectory( sdk, { @@ -276,8 +278,8 @@ export default class PushCmd extends Command { dockerfilePath: string, registrySecrets: RegistrySecrets, ) { - const remote = await import('../../utils/remote-build'); - const { getApplication } = await import('../../utils/sdk'); + const remote = await import('../../utils/remote-build.js'); + const { getApplication } = await import('../../utils/sdk.js'); // Check for invalid options const localOnlyOptions: Array = [ @@ -356,7 +358,7 @@ export default class PushCmd extends Command { 'is only valid when pushing to a fleet', ); - const deviceDeploy = await import('../../utils/device/deploy'); + const deviceDeploy = await import('../../utils/device/deploy.js'); try { await deviceDeploy.deployToDevice({ @@ -376,7 +378,7 @@ export default class PushCmd extends Command { convertEol: !options['noconvert-eol'], }); } catch (e) { - const { BuildError } = await import('../../utils/device/errors'); + const { BuildError } = await import('../../utils/device/errors.js'); if (instanceOf(e, BuildError)) { throw new ExpectedError(e.toString()); } else { @@ -387,7 +389,7 @@ export default class PushCmd extends Command { protected async getBuildTarget(appOrDevice: string): Promise { const { validateLocalHostnameOrIp } = await import( - '../../utils/validation' + '../../utils/validation.js' ); return validateLocalHostnameOrIp(appOrDevice) diff --git a/lib/commands/releases/index.ts b/lib/commands/releases/index.ts index 49bf3897..72ef9e0b 100644 --- a/lib/commands/releases/index.ts +++ b/lib/commands/releases/index.ts @@ -67,7 +67,7 @@ export default class ReleasesCmd extends Command { ]; const balena = getBalenaSdk(); - const { getFleetSlug } = await import('../../utils/sdk'); + const { getFleetSlug } = await import('../../utils/sdk.js'); const releases = await balena.models.release.getAllByApplication( await getFleetSlug(balena, params.fleet), diff --git a/lib/commands/scan/index.ts b/lib/commands/scan/index.ts index fd6fdcc2..181ef3c5 100644 --- a/lib/commands/scan/index.ts +++ b/lib/commands/scan/index.ts @@ -65,10 +65,10 @@ export default class ScanCmd extends Command { public async run() { const _ = await import('lodash'); const { discoverLocalBalenaOsDevices } = await import( - '../../utils/discover' + '../../utils/discover.js' ); const prettyjson = await import('prettyjson'); - const dockerUtils = await import('../../utils/docker'); + const dockerUtils = await import('../../utils/docker.js'); const dockerPort = 2375; const dockerTimeout = 2000; diff --git a/lib/commands/ssh/index.ts b/lib/commands/ssh/index.ts index 477736ff..c469d90d 100644 --- a/lib/commands/ssh/index.ts +++ b/lib/commands/ssh/index.ts @@ -111,7 +111,9 @@ export default class SshCmd extends Command { // Local connection if (validateLocalHostnameOrIp(params.fleetOrDevice)) { - const { performLocalDeviceSSH } = await import('../../utils/device/ssh'); + const { performLocalDeviceSSH } = await import( + '../../utils/device/ssh.js' + ); return await performLocalDeviceSSH({ hostname: params.fleetOrDevice, port: options.port || 'local', @@ -122,8 +124,10 @@ export default class SshCmd extends Command { } // Remote connection - const { getProxyConfig } = await import('../../utils/helpers'); - const { getOnlineTargetDeviceUuid } = await import('../../utils/patterns'); + const { getProxyConfig } = await import('../../utils/helpers.js'); + const { getOnlineTargetDeviceUuid } = await import( + '../../utils/patterns.js' + ); const sdk = getBalenaSdk(); const proxyConfig = getProxyConfig(); @@ -137,7 +141,7 @@ export default class SshCmd extends Command { params.fleetOrDevice, ); - const { which } = await import('../../utils/which'); + const { which } = await import('../../utils/which.js'); const [whichProxytunnel, { username }, proxyUrl] = await Promise.all([ useProxy ? which('proxytunnel', false) : undefined, @@ -189,7 +193,7 @@ export default class SshCmd extends Command { let containerId: string | undefined; if (params.service != null) { const { getContainerIdForService } = await import( - '../../utils/device/ssh' + '../../utils/device/ssh.js' ); containerId = await getContainerIdForService({ deviceUuid, @@ -207,7 +211,7 @@ export default class SshCmd extends Command { } else { accessCommand = `host ${deviceUuid}`; } - const { runRemoteCommand } = await import('../../utils/ssh'); + const { runRemoteCommand } = await import('../../utils/ssh.js'); await runRemoteCommand({ cmd: accessCommand, hostname: `ssh.${proxyUrl}`, diff --git a/lib/commands/support/index.ts b/lib/commands/support/index.ts index 84af6f4c..22030c13 100644 --- a/lib/commands/support/index.ts +++ b/lib/commands/support/index.ts @@ -116,7 +116,7 @@ export default class SupportCmd extends Command { ux.action.stop(); } - const { getFleetSlug } = await import('../../utils/sdk'); + const { getFleetSlug } = await import('../../utils/sdk.js'); // Process applications for (const appName of appNames) { diff --git a/lib/commands/tag/rm.ts b/lib/commands/tag/rm.ts index 057418f4..1eaaa6fc 100644 --- a/lib/commands/tag/rm.ts +++ b/lib/commands/tag/rm.ts @@ -72,12 +72,12 @@ export default class TagRmCmd extends Command { // Check user has specified one of application/device/release if (!options.fleet && !options.device && !options.release) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); throw new ExpectedError(TagRmCmd.missingResourceMessage); } if (options.fleet) { - const { getFleetSlug } = await import('../../utils/sdk'); + const { getFleetSlug } = await import('../../utils/sdk.js'); return balena.models.application.tags.remove( await getFleetSlug(balena, options.fleet), params.tagKey, @@ -88,7 +88,7 @@ export default class TagRmCmd extends Command { } if (options.release) { const { disambiguateReleaseParam } = await import( - '../../utils/normalization' + '../../utils/normalization.js' ); const releaseParam = await disambiguateReleaseParam( balena, diff --git a/lib/commands/tag/set.ts b/lib/commands/tag/set.ts index d77e4190..77d9bec7 100644 --- a/lib/commands/tag/set.ts +++ b/lib/commands/tag/set.ts @@ -85,14 +85,14 @@ export default class TagSetCmd extends Command { // Check user has specified one of application/device/release if (!options.fleet && !options.device && !options.release) { - const { ExpectedError } = await import('../../errors'); + const { ExpectedError } = await import('../../errors.js'); throw new ExpectedError(TagSetCmd.missingResourceMessage); } params.value ??= ''; if (options.fleet) { - const { getFleetSlug } = await import('../../utils/sdk'); + const { getFleetSlug } = await import('../../utils/sdk.js'); return balena.models.application.tags.set( await getFleetSlug(balena, options.fleet), params.tagKey, @@ -108,7 +108,7 @@ export default class TagSetCmd extends Command { } if (options.release) { const { disambiguateReleaseParam } = await import( - '../../utils/normalization' + '../../utils/normalization.js' ); const releaseParam = await disambiguateReleaseParam( balena, diff --git a/lib/commands/tags/index.ts b/lib/commands/tags/index.ts index 9653c396..a7a7cbc5 100644 --- a/lib/commands/tags/index.ts +++ b/lib/commands/tags/index.ts @@ -71,7 +71,7 @@ export default class TagsCmd extends Command { let tags; if (options.fleet) { - const { getFleetSlug } = await import('../../utils/sdk'); + const { getFleetSlug } = await import('../../utils/sdk.js'); tags = await balena.models.application.tags.getAllByApplication( await getFleetSlug(balena, options.fleet), ); @@ -81,7 +81,7 @@ export default class TagsCmd extends Command { } if (options.release) { const { disambiguateReleaseParam } = await import( - '../../utils/normalization' + '../../utils/normalization.js' ); const releaseParam = await disambiguateReleaseParam( balena, diff --git a/lib/commands/tunnel/index.ts b/lib/commands/tunnel/index.ts index 91be2fe6..bac32073 100644 --- a/lib/commands/tunnel/index.ts +++ b/lib/commands/tunnel/index.ts @@ -122,7 +122,9 @@ export default class TunnelCmd extends Command { } // Ascertain device uuid - const { getOnlineTargetDeviceUuid } = await import('../../utils/patterns'); + const { getOnlineTargetDeviceUuid } = await import( + '../../utils/patterns.js' + ); const uuid = await getOnlineTargetDeviceUuid(sdk, params.deviceOrFleet); logger.logInfo(`Opening a tunnel to ${uuid}...`); @@ -134,7 +136,7 @@ export default class TunnelCmd extends Command { .map(async ({ localPort, localAddress, remotePort }) => { try { const { tunnelConnectionToDevice } = await import( - '../../utils/tunnel' + '../../utils/tunnel.js' ); const handler = await tunnelConnectionToDevice(uuid, remotePort, sdk); diff --git a/lib/commands/version/index.ts b/lib/commands/version/index.ts index 9c59a8cc..1fa1c2e2 100644 --- a/lib/commands/version/index.ts +++ b/lib/commands/version/index.ts @@ -72,7 +72,7 @@ export default class VersionCmd extends Command { public async run() { const { flags: options } = await this.parse(VersionCmd); const versions: JsonVersions = { - 'balena-cli': (await import('../../../package.json')).version, + 'balena-cli': (await import('../../../package.json')).default.version, 'Node.js': process.version && process.version.startsWith('v') ? process.version.slice(1) diff --git a/lib/deprecation.ts b/lib/deprecation.ts index 7a8762bb..c55f74cc 100644 --- a/lib/deprecation.ts +++ b/lib/deprecation.ts @@ -102,7 +102,7 @@ export class DeprecationChecker { protected async fetchPublishedTimestampForVersion( version: string, ): Promise { - const { default: got } = await import('got'); + const { default: got } = (await import('got')).default; const url = this.getNpmUrl(version); let response: import('got').Response> | undefined; try { @@ -198,7 +198,7 @@ or release date not available`); const nextMajorDate = new Date(nextMajorDateStr).getTime(); const daysElapsed = Math.trunc((this.now - nextMajorDate) / this.msInDay); if (daysElapsed > this.expiryDays) { - const { ExpectedError } = await import('./errors'); + const { ExpectedError } = await import('./errors.js'); throw new ExpectedError(this.getExpiryMsg(daysElapsed)); } else if (daysElapsed > this.deprecationDays && process.stderr.isTTY) { console.error(this.getDeprecationMsg(daysElapsed)); diff --git a/lib/events.ts b/lib/events.ts index fd0f74f6..fef266bf 100644 --- a/lib/events.ts +++ b/lib/events.ts @@ -44,7 +44,7 @@ export async function trackCommand(commandSignature: string) { scope.setExtra('command', commandSignature); }); } - const { getCachedUsername } = await import('./utils/bootstrap'); + const { getCachedUsername } = await import('./utils/bootstrap.js'); let username: string | undefined; try { username = (await getCachedUsername())?.username; @@ -79,7 +79,7 @@ const TIMEOUT = 4000; * Make the event tracking HTTPS request to balenaCloud's '/mixpanel' endpoint. */ async function sendEvent(balenaUrl: string, event: string, username?: string) { - const { default: got } = await import('got'); + const { default: got } = (await import('got')).default; const trackData = { api_key: 'balena-main', events: [ diff --git a/lib/fast-boot.ts b/lib/fast-boot.ts index d66dd499..fd2718f9 100644 --- a/lib/fast-boot.ts +++ b/lib/fast-boot.ts @@ -74,7 +74,7 @@ async function $start() { stat(path.join(root, 'npm-shrinkwrap.json'), { bigint: true }), ]); // Include timestamps to account for dev-time changes to node_modules - const cacheKiller = `${pJson.version}-${pStat.mtimeMs}-${nStat.mtimeMs}`; + const cacheKiller = `${pJson.default.version}-${pStat.mtimeMs}-${nStat.mtimeMs}`; require('fast-boot2').start({ cacheFile, cacheKiller, diff --git a/lib/help.ts b/lib/help.ts index e9644fee..39796bc5 100644 --- a/lib/help.ts +++ b/lib/help.ts @@ -15,7 +15,7 @@ * limitations under the License. */ import { Help } from '@oclif/core'; -import * as indent from 'indent-string'; +import indent from 'indent-string'; import { getChalk } from './utils/lazy'; // Partially overrides standard implementation of help plugin diff --git a/lib/hooks/prerun/track.ts b/lib/hooks/prerun/track.ts index c57061aa..434ff534 100644 --- a/lib/hooks/prerun/track.ts +++ b/lib/hooks/prerun/track.ts @@ -33,7 +33,7 @@ export const trackPromise = new Promise((resolve) => { * literally so: 'NAME' and 'VALUE' are NOT replaced with actual values. */ const hook: Hook<'prerun'> = async function (options) { - const events = await import('../../events'); + const events = await import('../../events.js'); const usage: string | string[] | undefined = options.Command.usage; const cmdSignature = usage == null ? '*' : typeof usage === 'string' ? usage : usage.join(' '); diff --git a/lib/preparser.ts b/lib/preparser.ts index b09418a8..35161fb6 100644 --- a/lib/preparser.ts +++ b/lib/preparser.ts @@ -68,7 +68,7 @@ export async function preparseArgs(argv: string[]): Promise { process.env.BLUEBIRD_LONG_STACK_TRACES = '1'; } - const Logger = await import('./utils/logger'); + const Logger = await import('./utils/logger.js'); Logger.command = cmdSlice[0]; let args = cmdSlice; @@ -157,7 +157,7 @@ Please use "balena ${alternative}" instead.`); // Check if this is a space separated 'topic command' style command subcommand (e.g. `end add`) // by comparing with oclif style colon-separated subcommand list (e.g. `env:add`) export async function isSubcommand(args: string[]) { - const { getCommandIdsFromManifest } = await import('./utils/oclif-utils'); + const { getCommandIdsFromManifest } = await import('./utils/oclif-utils.js'); const commandIds = await getCommandIdsFromManifest(); return commandIds.includes(`${args[0] || ''}:${args[1] || ''}`); } diff --git a/lib/utils/application-create.ts b/lib/utils/application-create.ts index 072b561c..74ae562e 100644 --- a/lib/utils/application-create.ts +++ b/lib/utils/application-create.ts @@ -18,12 +18,12 @@ export async function applicationCreateBase( ) { // Ascertain device type const deviceType = - options.type || (await (await import('./patterns')).selectDeviceType()); + options.type || (await (await import('./patterns.js')).selectDeviceType()); // Ascertain organization const organization = options.organization?.toLowerCase() || - (await (await import('./patterns')).getAndSelectOrganization()); + (await (await import('./patterns.js')).getAndSelectOrganization()); // Create application try { diff --git a/lib/utils/bootstrap.ts b/lib/utils/bootstrap.ts index bcf5c587..21e7ee61 100644 --- a/lib/utils/bootstrap.ts +++ b/lib/utils/bootstrap.ts @@ -139,7 +139,7 @@ export async function getCachedUsername(): Promise { return cachedUsername; } const [{ getBalenaSdk }, { getStorage }, settings] = await Promise.all([ - import('./lazy'), + import('./lazy.js'), import('balena-settings-storage'), import('balena-settings-client'), ]); diff --git a/lib/utils/cloud.ts b/lib/utils/cloud.ts index 1546441d..536f11a2 100644 --- a/lib/utils/cloud.ts +++ b/lib/utils/cloud.ts @@ -206,7 +206,7 @@ async function resolveOSVersion( false, ); } - const { normalizeOsVersion } = await import('./normalization'); + const { normalizeOsVersion } = await import('./normalization.js'); version = normalizeOsVersion(version); return version; } diff --git a/lib/utils/compose.ts b/lib/utils/compose.ts index a9f8d09c..5543115e 100644 --- a/lib/utils/compose.ts +++ b/lib/utils/compose.ts @@ -479,10 +479,8 @@ export class BuildProgressUI implements Renderer { } _renderStatus(end = false) { - const moment = require('moment') as typeof import('moment'); - ( - require('moment-duration-format') as typeof import('moment-duration-format') - )(moment); + const moment = require('moment'); + require('moment-duration-format')(moment); this._tty.clearLine(); this._tty.write(this._prefix); @@ -577,10 +575,8 @@ export class BuildProgressInline implements Renderer { } end(summary?: Dictionary) { - const moment = require('moment') as typeof import('moment'); - ( - require('moment-duration-format') as typeof import('moment-duration-format') - )(moment); + const moment = require('moment'); + require('moment-duration-format')(moment); if (this._ended) { return; diff --git a/lib/utils/compose_ts.ts b/lib/utils/compose_ts.ts index 8cb9ae5b..21eabf09 100644 --- a/lib/utils/compose_ts.ts +++ b/lib/utils/compose_ts.ts @@ -117,7 +117,7 @@ export async function loadProject( imageTag?: string, ): Promise { const compose = await import('@balena/compose/dist/parse'); - const { createProject } = await import('./compose'); + const { createProject } = await import('./compose.js'); let composeName: string; let composeStr: string; @@ -265,7 +265,7 @@ export async function buildProject( const renderer = await startRenderer({ imageDescriptors, ...opts }); let buildSummaryByService: Dictionary | undefined; try { - const { awaitInterruptibleTask } = await import('./helpers'); + const { awaitInterruptibleTask } = await import('./helpers.js'); const [images, summaryMsgByService] = await awaitInterruptibleTask( $buildProject, imageDescriptors, @@ -330,7 +330,7 @@ async function $buildProject( logger.logDebug('Prepared tasks; building...'); - const { BALENA_ENGINE_TMP_PATH } = await import('../config'); + const { BALENA_ENGINE_TMP_PATH } = await import('../config.js'); const builder = await import('@balena/compose/dist/multibuild'); const builtImages = await builder.performBuilds( @@ -358,13 +358,14 @@ async function startRenderer({ }): Promise { let renderer: Renderer; if (inlineLogs) { - renderer = new (await import('./compose')).BuildProgressInline( + renderer = new (await import('./compose.js')).BuildProgressInline( logger.streams['build'], imageDescriptors, ); } else { - const tty = (await import('./tty'))(process.stdout); - renderer = new (await import('./compose')).BuildProgressUI( + const { default: $tty } = await import('./tty.js'); + const tty = $tty(process.stdout); + renderer = new (await import('./compose.js')).BuildProgressUI( tty, imageDescriptors, ); @@ -388,7 +389,7 @@ async function installQemuIfNeeded({ logger: Logger; projectPath: string; }): Promise { - const qemu = await import('./qemu'); + const qemu = await import('./qemu.js'); const needsQemu = await qemu.installQemuIfNeeded( emulated, logger, @@ -471,7 +472,7 @@ async function qemuTransposeBuildStream({ dockerfilePath?: string; projectPath: string; }): Promise { - const qemu = await import('./qemu'); + const qemu = await import('./qemu.js'); const binPath = qemu.qemuPathInContext( path.join(projectPath, task.context ?? ''), ); @@ -681,7 +682,7 @@ export async function getServiceDirsFromComposition( sourceDir: string, composition?: Composition, ): Promise> { - const { createProject } = await import('./compose'); + const { createProject } = await import('./compose.js'); const serviceDirs: Dictionary = {}; if (!composition) { const [, composeStr] = await resolveProject( @@ -757,7 +758,7 @@ export async function tarDirectory( preFinalizeCallback, }: TarDirectoryOptions, ): Promise { - const { filterFilesWithDockerignore } = await import('./ignore'); + const { filterFilesWithDockerignore } = await import('./ignore.js'); const { toPosixPath } = (await import('@balena/compose/dist/multibuild')) .PathUtils; @@ -891,7 +892,7 @@ export async function checkBuildSecretsRequirements( ) { const [metaObj, metaFilename] = await loadBuildMetatada(sourceDir); if (metaObj && !_.isEmpty(metaObj['build-secrets'])) { - const dockerUtils = await import('./docker'); + const dockerUtils = await import('./docker.js'); const isBalenaEngine = await dockerUtils.isBalenaEngine(docker); if (!isBalenaEngine) { throw new ExpectedError(stripIndent` @@ -1222,7 +1223,7 @@ async function getTokenForPreviousRepos( taggedImages: TaggedImage[], ): Promise { logger.logDebug('Authorizing push...'); - const { authorizePush, getPreviousRepos } = await import('./compose'); + const { authorizePush, getPreviousRepos } = await import('./compose.js'); const sdk = getBalenaSdk(); const previousRepos = await getPreviousRepos(sdk, logger, appId); @@ -1246,9 +1247,10 @@ async function pushAndUpdateServiceImages( ) => Promise, ) { const { DockerProgress } = await import('docker-progress'); - const { retry } = await import('./helpers'); - const { pushProgressRenderer } = await import('./compose'); - const tty = (await import('./tty'))(process.stdout); + const { retry } = await import('./helpers.js'); + const { pushProgressRenderer } = await import('./compose.js'); + const { default: $tty } = await import('./tty.js'); + const tty = $tty(process.stdout); const opts = { authconfig: { registrytoken: token } }; const progress = new DockerProgress({ docker }); const renderer = pushProgressRenderer( @@ -1361,8 +1363,9 @@ export async function deployProject( isDraft: boolean, ): Promise { const releaseMod = await import('@balena/compose/dist/release'); - const { createRelease, tagServiceImages } = await import('./compose'); - const tty = (await import('./tty'))(process.stdout); + const { createRelease, tagServiceImages } = await import('./compose.js'); + const { default: $tty } = await import('./tty.js'); + const tty = $tty(process.stdout); const prefix = getChalk().cyan('[Info]') + ' '; const spinner = createSpinner(); @@ -1397,7 +1400,7 @@ export async function deployProject( logger.logDebug('Tagging images...'); const taggedImages = await tagServiceImages(docker, images, serviceImages); try { - const { awaitInterruptibleTask } = await import('./helpers'); + const { awaitInterruptibleTask } = await import('./helpers.js'); // awaitInterruptibleTask throws SIGINTError on CTRL-C, // causing the release status to be set to 'failed' await awaitInterruptibleTask(async () => { diff --git a/lib/utils/config.ts b/lib/utils/config.ts index 51948225..3275c726 100644 --- a/lib/utils/config.ts +++ b/lib/utils/config.ts @@ -161,13 +161,13 @@ export async function validateDevOptionAndWarn( return; } if (version && /\bprod\b/.test(version)) { - const { ExpectedError } = await import('../errors'); + const { ExpectedError } = await import('../errors.js'); throw new ExpectedError( `Error: The '--dev' option conflicts with production balenaOS version '${version}'`, ); } if (!logger) { - const Logger = await import('./logger'); + const { default: Logger } = await import('./logger.js'); logger = Logger.getLogger(); } logger.logInfo(stripIndent` @@ -192,7 +192,7 @@ export async function validateSecureBootOptionAndWarn( if (!secureBoot) { return; } - const { ExpectedError } = await import('../errors'); + const { ExpectedError } = await import('../errors.js'); if (!version) { throw new ExpectedError(`Error: No version provided`); } @@ -215,7 +215,7 @@ export async function validateSecureBootOptionAndWarn( }) ) { if (!logger) { - const Logger = await import('./logger'); + const { default: Logger } = await import('./logger.js'); logger = Logger.getLogger(); } logger.logInfo(stripIndent` diff --git a/lib/utils/device/api.ts b/lib/utils/device/api.ts index 7687ed25..62f2b67b 100644 --- a/lib/utils/device/api.ts +++ b/lib/utils/device/api.ts @@ -15,7 +15,7 @@ * limitations under the License. */ import * as _ from 'lodash'; -import * as request from 'request'; +import request from 'request'; import type * as Stream from 'stream'; import { retry } from '../helpers'; diff --git a/lib/utils/device/deploy.ts b/lib/utils/device/deploy.ts index 018467e8..9c5e64ae 100644 --- a/lib/utils/device/deploy.ts +++ b/lib/utils/device/deploy.ts @@ -16,7 +16,7 @@ */ import * as semver from 'balena-semver'; -import * as Docker from 'dockerode'; +import Docker from 'dockerode'; import * as _ from 'lodash'; import type { Composition } from '@balena/compose/dist/parse'; import type { @@ -215,7 +215,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise { imageIds = {}; } - const { awaitInterruptibleTask } = await import('../helpers'); + const { awaitInterruptibleTask } = await import('../helpers.js'); const buildTasks = await awaitInterruptibleTask( performBuilds, project.composition, @@ -295,7 +295,7 @@ async function streamDeviceLogs( return; } globalLogger.logInfo('Streaming device logs...'); - const { connectAndDisplayDeviceLogs } = await import('./logs'); + const { connectAndDisplayDeviceLogs } = await import('./logs.js'); return connectAndDisplayDeviceLogs({ deviceApi, logger: globalLogger, diff --git a/lib/utils/device/live.ts b/lib/utils/device/live.ts index 81758127..667b31fe 100644 --- a/lib/utils/device/live.ts +++ b/lib/utils/device/live.ts @@ -108,8 +108,8 @@ export class LivepushManager { this.logger.logLivepush('Device state settled'); // Prepare dockerignore data for file watcher - const { getDockerignoreByService } = await import('../ignore'); - const { getServiceDirsFromComposition } = await import('../compose_ts'); + const { getDockerignoreByService } = await import('../ignore.js'); + const { getServiceDirsFromComposition } = await import('../compose_ts.js'); const rootContext = path.resolve(this.buildContext); const serviceDirsByService = await getServiceDirsFromComposition( this.deployOpts.source, diff --git a/lib/utils/device/logs.ts b/lib/utils/device/logs.ts index 267ba1f4..2786600c 100644 --- a/lib/utils/device/logs.ts +++ b/lib/utils/device/logs.ts @@ -62,7 +62,7 @@ async function displayDeviceLogs( system: boolean, filterServices?: string[], ): Promise { - const { addSIGINTHandler } = await import('../helpers'); + const { addSIGINTHandler } = await import('../helpers.js'); const { parse: ndjsonParse } = await import('ndjson'); let gotSignal = false; const handleSignal = () => { @@ -125,7 +125,7 @@ export async function connectAndDisplayDeviceLogs({ return displayDeviceLogs(logStream, logger, system, filterServices); } - const { retry } = await import('../../utils/helpers'); + const { retry } = await import('../../utils/helpers.js'); try { await retry({ func: connectAndDisplay, diff --git a/lib/utils/discover.ts b/lib/utils/discover.ts index 76945582..25e1c309 100644 --- a/lib/utils/discover.ts +++ b/lib/utils/discover.ts @@ -21,7 +21,7 @@ export async function discoverLocalBalenaOsDevices( ): Promise { const services = await new Promise((resolve) => { const bonjour = new Bonjour({}, async (err: string | Error) => { - await (await import('../errors')).handleError(err); + await (await import('../errors.js')).handleError(err); }); const resinSshServices: Service[] = []; const browser = bonjour.find(avahiBalenaSshConfig, (service) => diff --git a/lib/utils/docker.ts b/lib/utils/docker.ts index f93ecf03..58b414c1 100644 --- a/lib/utils/docker.ts +++ b/lib/utils/docker.ts @@ -186,7 +186,7 @@ export async function getDocker( export async function createClient( opts: dockerode.DockerOptions, ): Promise { - const Docker = await import('dockerode'); + const { default: Docker } = await import('dockerode'); return new Docker(opts); } diff --git a/lib/utils/helpers.ts b/lib/utils/helpers.ts index 8d040383..f29cd68a 100644 --- a/lib/utils/helpers.ts +++ b/lib/utils/helpers.ts @@ -77,7 +77,7 @@ export async function sudo( isCLIcmd, }: { stderr?: NodeJS.WritableStream; msg?: string; isCLIcmd?: boolean } = {}, ) { - const { executeWithPrivileges } = await import('./sudo'); + const { executeWithPrivileges } = await import('./sudo.js'); if (process.platform !== 'win32') { console.log( @@ -115,7 +115,7 @@ export async function getManifest( manifest.slug !== deviceType && manifest.slug !== (await sdk.models.deviceType.get(deviceType)).slug ) { - const { ExpectedError } = await import('../errors'); + const { ExpectedError } = await import('../errors.js'); throw new ExpectedError( `The device type of the provided OS image ${manifest.slug}, does not match the expected device type ${deviceType}`, ); @@ -182,7 +182,7 @@ export async function osProgressHandler(step: InitializeEmitter) { } export async function getAppWithArch(applicationName: string) { - const { getApplication } = await import('./sdk'); + const { getApplication } = await import('./sdk.js'); const balena = getBalenaSdk(); const app = await getApplication(balena, applicationName, { $expand: { @@ -239,7 +239,7 @@ export async function retry({ backoffScaler?: number; maxSingleDelayMs?: number; }): Promise { - const { SIGINTError } = await import('../errors'); + const { SIGINTError } = await import('../errors.js'); let delayMs = initialDelayMs; for (let count = 0; count < maxAttempts - 1; count++) { const lastAttemptMs = Date.now(); diff --git a/lib/utils/ignore.ts b/lib/utils/ignore.ts index dcc8d5a3..a9be2275 100644 --- a/lib/utils/ignore.ts +++ b/lib/utils/ignore.ts @@ -104,7 +104,7 @@ export async function getDockerIgnoreInstance( ): Promise { const dockerIgnoreStr = await readDockerIgnoreFile(directory); const $dockerIgnore = (await import('@balena/dockerignore')).default; - const ig = $dockerIgnore({ ignorecase: false }); + const ig = $dockerIgnore.default({ ignorecase: false }); ig.add(['**/.git']); if (dockerIgnoreStr) { diff --git a/lib/utils/patterns.ts b/lib/utils/patterns.ts index ebae0aa6..18e6a1f3 100644 --- a/lib/utils/patterns.ts +++ b/lib/utils/patterns.ts @@ -28,8 +28,9 @@ import { instanceOf, NotLoggedInError, ExpectedError } from '../errors'; import { getBalenaSdk, getVisuals, stripIndent, getCliForm } from './lazy'; import validation = require('./validation'); import { delay } from './helpers'; +import type Bluebird from 'bluebird'; -export function authenticate(options: object): Promise { +export function authenticate(options: object): Bluebird { const balena = getBalenaSdk(); return getCliForm() .run( @@ -229,7 +230,7 @@ export async function selectOrganization( } export async function getAndSelectOrganization() { - const { getOwnOrganizations } = await import('./sdk'); + const { getOwnOrganizations } = await import('./sdk.js'); const organizations = await getOwnOrganizations(getBalenaSdk(), { $select: ['name', 'handle'], }); @@ -304,7 +305,8 @@ export async function getOnlineTargetDeviceUuid( sdk: BalenaSDK, fleetOrDevice: string, ) { - const logger = (await import('../utils/logger')).getLogger(); + const { default: Logger } = await import('../utils/logger.js'); + const logger = Logger.getLogger(); // If looks like UUID, probably device if (validation.validateUuid(fleetOrDevice)) { @@ -337,7 +339,7 @@ export async function getOnlineTargetDeviceUuid( const application = await (async () => { try { logger.logDebug(`Fetching fleet ${fleetOrDevice}`); - const { getApplication } = await import('./sdk'); + const { getApplication } = await import('./sdk.js'); return await getApplication(sdk, fleetOrDevice, { $select: ['id', 'slug'], $expand: { @@ -382,7 +384,7 @@ export async function getOnlineTargetDeviceUuid( export function selectFromList( message: string, choices: Array, -): Promise { +): Bluebird { return getCliForm().ask({ message, type: 'list', diff --git a/lib/utils/promote.ts b/lib/utils/promote.ts index 805dc259..e7f8165d 100644 --- a/lib/utils/promote.ts +++ b/lib/utils/promote.ts @@ -167,7 +167,7 @@ const dockerPort = 2375; const dockerTimeout = 2000; async function selectLocalBalenaOsDevice(timeout = 4000): Promise { - const { discoverLocalBalenaOsDevices } = await import('../utils/discover'); + const { discoverLocalBalenaOsDevices } = await import('../utils/discover.js'); const { SpinnerPromise } = getVisuals(); const devices = await new SpinnerPromise({ promise: discoverLocalBalenaOsDevices(timeout), @@ -176,7 +176,7 @@ async function selectLocalBalenaOsDevice(timeout = 4000): Promise { }); const responsiveDevices: typeof devices = []; - const Docker = await import('dockerode'); + const { default: Docker } = await import('dockerode'); await Promise.all( devices.map(async function (device) { const address = device?.address; @@ -231,7 +231,7 @@ async function selectAppFromList( applications: ApplicationWithDeviceTypeSlug[], ): Promise { const _ = await import('lodash'); - const { selectFromList } = await import('../utils/patterns'); + const { selectFromList } = await import('../utils/patterns.js'); // Present a list to the user which shows the fully qualified fleet // name (user/fleetname) and allows them to select. @@ -384,7 +384,7 @@ async function createApplication( deviceType: string, name?: string, ): Promise { - const validation = await import('./validation'); + const validation = await import('./validation.js'); let username: string; try { @@ -447,7 +447,7 @@ async function generateApplicationConfig( appUpdatePollInterval?: number; }, ) { - const { generateApplicationConfig: configGen } = await import('./config'); + const { generateApplicationConfig: configGen } = await import('./config.js'); const manifest = await sdk.models.config.getDeviceTypeManifestBySlug( app.is_for__device_type[0].slug, diff --git a/lib/utils/qemu.ts b/lib/utils/qemu.ts index a9e379dc..ed54254f 100644 --- a/lib/utils/qemu.ts +++ b/lib/utils/qemu.ts @@ -94,7 +94,7 @@ async function installQemu(arch: string, qemuPath: string) { const urlVersion = encodeURIComponent(QEMU_VERSION); const qemuUrl = `https://github.com/balena-io/qemu/releases/download/${urlVersion}/${urlFile}`; - const request = await import('request'); + const { default: request } = await import('request'); const fs = await import('fs'); const zlib = await import('zlib'); const tar = await import('tar-stream'); diff --git a/lib/utils/remote-build.ts b/lib/utils/remote-build.ts index 353b653d..1887fc9f 100644 --- a/lib/utils/remote-build.ts +++ b/lib/utils/remote-build.ts @@ -126,7 +126,7 @@ export async function startRemoteBuild( } }; - const { addSIGINTHandler } = await import('./helpers'); + const { addSIGINTHandler } = await import('./helpers.js'); addSIGINTHandler(sigintHandler); try { diff --git a/lib/utils/sdk.ts b/lib/utils/sdk.ts index 0df612df..4e95833f 100644 --- a/lib/utils/sdk.ts +++ b/lib/utils/sdk.ts @@ -42,7 +42,7 @@ export async function getApplication( nameOrSlugOrId: string | number, options?: PineOptions, ): Promise { - const { looksLikeFleetSlug } = await import('./validation'); + const { looksLikeFleetSlug } = await import('./validation.js'); const whoamiResult = await sdk.auth.whoami(); const isDeviceActor = whoamiResult?.actorType === 'device'; @@ -97,7 +97,7 @@ export async function getFleetSlug( sdk: BalenaSDK, nameOrSlug: string, ): Promise { - const { looksLikeFleetSlug } = await import('./validation'); + const { looksLikeFleetSlug } = await import('./validation.js'); if (!looksLikeFleetSlug(nameOrSlug)) { // Not a slug: must be an app name. // TODO: revisit this logic when we add support for fleet UUIDs. diff --git a/lib/utils/ssh.ts b/lib/utils/ssh.ts index 6613b2cf..3e8527d9 100644 --- a/lib/utils/ssh.ts +++ b/lib/utils/ssh.ts @@ -127,7 +127,7 @@ export async function runRemoteCommand({ } else { ignoreStdin = false; } - const { which } = await import('./which'); + const { which } = await import('./which.js'); const program = await which('ssh'); const args = sshArgsForRemoteCommand({ cmd, @@ -140,7 +140,7 @@ export async function runRemoteCommand({ }); if (process.env.DEBUG) { - const logger = (await import('./logger')).getLogger(); + const logger = (await import('./logger.js')).default.getLogger(); logger.logDebug(`Executing [${program},${args}]`); } @@ -296,11 +296,11 @@ export const findBestUsernameForDevice = _.memoize( if (await isRootUserGood(hostname, port)) { username = 'root'; } else { - const { getCachedUsername } = await import('./bootstrap'); + const { getCachedUsername } = await import('./bootstrap.js'); username = (await getCachedUsername())?.username; } if (!username) { - const { stripIndent } = await import('./lazy'); + const { stripIndent } = await import('./lazy.js'); throw new ExpectedError(stripIndent` SSH authentication failed for 'root@${hostname}'. Please login with 'balena login' for alternative authentication.`); diff --git a/lib/utils/sudo.ts b/lib/utils/sudo.ts index 603b89af..3e8953dd 100644 --- a/lib/utils/sudo.ts +++ b/lib/utils/sudo.ts @@ -43,8 +43,8 @@ export async function executeWithPrivileges( isCLIcmd = true, ): Promise { // whether the CLI is already running with admin / super user privileges - const isElevated = await (await import('is-elevated'))(); - const { shellEscape } = await import('./helpers'); + const isElevated = await (await import('is-elevated')).default(); + const { shellEscape } = await import('./helpers.js'); const opts: SpawnOptions = { env: process.env, stdio: ['inherit', 'inherit', stderr ? 'pipe' : 'inherit'], diff --git a/lib/utils/umount.ts b/lib/utils/umount.ts index 335a9536..37ab045e 100644 --- a/lib/utils/umount.ts +++ b/lib/utils/umount.ts @@ -39,7 +39,7 @@ export async function umount(device: string): Promise { if (process.platform === 'win32') { return; } - const { sanitizePath, whichBin } = await import('./which'); + const { sanitizePath, whichBin } = await import('./which.js'); // sanitize user's input (regular expression attacks ?) device = sanitizePath(device); const cmd: string[] = []; @@ -48,7 +48,7 @@ export async function umount(device: string): Promise { cmd.push('/usr/sbin/diskutil', 'unmountDisk', 'force', device); } else { // Linux - const glob = promisify(await import('glob')); + const glob = promisify((await import('glob')).default); // '?*' expands a base device path like '/dev/sdb' to an array of paths // like '/dev/sdb1', '/dev/sdb2', ..., '/dev/sdb11', ... (partitions) // that exist for balenaOS images and are needed as arguments to 'umount' @@ -75,7 +75,7 @@ export async function umount(device: string): Promise { } return; } - const { ExpectedError } = await import('../errors'); + const { ExpectedError } = await import('../errors.js'); throw new ExpectedError(msg.join('\n')); } } @@ -92,7 +92,7 @@ export async function isMounted(device: string): Promise { if (!device) { return false; } - const { whichBin } = await import('./which'); + const { whichBin } = await import('./which.js'); const mountCmd = await whichBin('mount'); let stdout = ''; let stderr = ''; @@ -101,7 +101,7 @@ export async function isMounted(device: string): Promise { stdout = proc.stdout; stderr = proc.stderr; } catch (err) { - const { ExpectedError } = await import('../errors'); + const { ExpectedError } = await import('../errors.js'); throw new ExpectedError( `Error executing "${mountCmd}":\n${stderr}\n${err.message}`, ); @@ -131,7 +131,7 @@ export async function denyMount( handler: () => any, opts: { autoMountOnSuccess?: boolean; executablePath?: string } = {}, ) { - const denymount = promisify(await import('denymount')); + const denymount = promisify((await import('denymount')).default); if (process.pkg) { // when running in a standalone pkg install, the 'denymount' // executable is placed on the same folder as process.execPath diff --git a/lib/utils/update.ts b/lib/utils/update.ts index caf1ca2e..918acc92 100644 --- a/lib/utils/update.ts +++ b/lib/utils/update.ts @@ -15,7 +15,7 @@ limitations under the License. */ import isRoot = require('is-root'); -import * as UpdateNotifier from 'update-notifier'; +import UpdateNotifier from 'update-notifier'; import packageJSON = require('../../package.json'); diff --git a/lib/utils/which.ts b/lib/utils/which.ts index d35b72bb..af7cafe6 100644 --- a/lib/utils/which.ts +++ b/lib/utils/which.ts @@ -76,14 +76,14 @@ export async function which( program: string, rejectOnMissing = true, ): Promise { - const whichMod = await import('which'); + const { default: whichMod } = await import('which'); let programPath: string; try { programPath = await whichMod(program); } catch (err) { if (err.code === 'ENOENT') { if (rejectOnMissing) { - const { ExpectedError } = await import('../errors'); + const { ExpectedError } = await import('../errors.js'); throw new ExpectedError( `'${program}' program not found. Is it installed?`, ); diff --git a/tests/auth/utils.spec.ts b/tests/auth/utils.spec.ts index ad1e8285..793ff498 100644 --- a/tests/auth/utils.spec.ts +++ b/tests/auth/utils.spec.ts @@ -1,4 +1,4 @@ -import * as Bluebird from 'bluebird'; +import Bluebird from 'bluebird'; import { expect } from 'chai'; import rewire = require('rewire'); import * as sinon from 'sinon'; diff --git a/tests/commands/build.spec.ts b/tests/commands/build.spec.ts index d402f551..3184edd9 100644 --- a/tests/commands/build.spec.ts +++ b/tests/commands/build.spec.ts @@ -17,7 +17,7 @@ import { expect } from 'chai'; import * as _ from 'lodash'; -import * as mock from 'mock-require'; +import mock from 'mock-require'; import { promises as fs } from 'fs'; import * as path from 'path'; diff --git a/tests/commands/ssh.spec.ts b/tests/commands/ssh.spec.ts index 4e67b7e4..22f7e8e9 100644 --- a/tests/commands/ssh.spec.ts +++ b/tests/commands/ssh.spec.ts @@ -16,7 +16,7 @@ */ import { expect } from 'chai'; -import mock = require('mock-require'); +import mock from 'mock-require'; import type { Server } from 'net'; import { createServer } from 'net'; @@ -149,7 +149,7 @@ describe('balena ssh', function () { /** Check whether the 'ssh' tool (executable) exists in the PATH */ async function checkSsh(): Promise { - const { which } = await import('../../build/utils/which'); + const { which } = await import('../../build/utils/which.js'); const sshPath = await which('ssh', false); if ((sshPath || '').includes('\\Windows\\System32\\OpenSSH\\ssh')) { // don't use Windows' built-in ssh tool for these test cases diff --git a/tests/helpers.ts b/tests/helpers.ts index dddf112e..fd701da5 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -90,8 +90,8 @@ export function filterCliOutputForTests({ * @param cmd Command to execute, e.g. `push myApp` (without 'balena' prefix) */ async function runCommandInProcess(cmd: string): Promise { - const balenaCLI = await import('../build/app'); - const intercept = await import('intercept-stdout'); + const balenaCLI = await import('../build/app.js'); + const { default: intercept } = await import('intercept-stdout'); const preArgs = [process.argv[0], path.join(process.cwd(), 'bin', 'balena')]; @@ -236,7 +236,7 @@ export async function runCommand(cmd: string): Promise { } catch { throw new Error(`Standalone executable not found: "${standalonePath}"`); } - const proxy = await import('./nock/proxy-server'); + const proxy = await import('./nock/proxy-server.js'); const [proxyPort] = await proxy.createProxyServerOnce(); return runCommandInSubprocess(cmd, proxyPort); } else { @@ -353,7 +353,7 @@ export function deepJsonParse(data: any): any { export async function switchSentry( enabled: boolean | undefined, ): Promise { - const balenaCLI = await import('../build/app'); + const balenaCLI = await import('../build/app.js'); const sentryOpts = (await balenaCLI.setupSentry()).getClient()?.getOptions(); if (sentryOpts) { const sentryStatus = sentryOpts.enabled; diff --git a/tests/nock/nock-mock.ts b/tests/nock/nock-mock.ts index 04ce0d6d..2b2ce10c 100644 --- a/tests/nock/nock-mock.ts +++ b/tests/nock/nock-mock.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import * as nock from 'nock'; +import nock from 'nock'; import * as fs from 'fs'; export interface ScopeOpts { diff --git a/tests/utils/device/live.spec.ts b/tests/utils/device/live.spec.ts index 844c01d2..5baf2fe0 100644 --- a/tests/utils/device/live.spec.ts +++ b/tests/utils/device/live.spec.ts @@ -83,10 +83,10 @@ describeSS('LivepushManager::setupFilesystemWatcher', function () { changedPathHandler: (serviceName: string, changedPath: string) => void, ): Promise> { const { getServiceDirsFromComposition } = await import( - '../../../build/utils/compose_ts' + '../../../build/utils/compose_ts.js' ); const { getDockerignoreByService } = await import( - '../../../build/utils/ignore' + '../../../build/utils/ignore.js' ); const rootContext = path.resolve(projectPath); diff --git a/tests/utils/qemu.spec.ts b/tests/utils/qemu.spec.ts index fc38de3c..87d1b8b4 100644 --- a/tests/utils/qemu.spec.ts +++ b/tests/utils/qemu.spec.ts @@ -22,7 +22,7 @@ describe('@balena/compose/multibuild consistency', function () { const { QEMU_BIN_NAME: MQEMU_BIN_NAME } = await import( '@balena/compose/dist/multibuild' ); - const { QEMU_BIN_NAME } = await import('../../build/utils/qemu'); + const { QEMU_BIN_NAME } = await import('../../build/utils/qemu.js'); expect(QEMU_BIN_NAME).to.equal(MQEMU_BIN_NAME); }); }); diff --git a/tests/utils/update.spec.ts b/tests/utils/update.spec.ts index c726b3b3..f9813da4 100644 --- a/tests/utils/update.spec.ts +++ b/tests/utils/update.spec.ts @@ -16,7 +16,7 @@ */ import { expect } from 'chai'; -import * as stripIndent from 'common-tags/lib/stripIndent'; +import stripIndent from 'common-tags/lib/stripIndent'; import { getNotifierMessage } from '../../build/utils/update'; diff --git a/tsconfig.json b/tsconfig.json index bfe183cb..f335e82f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { "declaration": true, - "module": "commonjs", - "target": "es2018", + "module": "Node16", + "target": "es2022", "outDir": "build", "strict": true, "strictPropertyInitialization": false,