mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-18 21:27:51 +00:00
Refactor initialization code (delete app-oclif.ts and app-common.ts)
Change-type: patch
This commit is contained in:
parent
cf376316bc
commit
d0e4fa0e59
@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright 2019 Balena Ltd.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Main } from '@oclif/command';
|
|
||||||
|
|
||||||
import { trackPromise } from './hooks/prerun/track';
|
|
||||||
|
|
||||||
class CustomMain extends Main {
|
|
||||||
protected _helpOverride(): boolean {
|
|
||||||
// Disable oclif's default handler for the 'version' command
|
|
||||||
if (['-v', '--version', 'version'].includes(this.argv[0])) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return super._helpOverride();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
import type { AppOptions } from './preparser';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* oclif CLI entrypoint
|
|
||||||
*/
|
|
||||||
export async function run(command: string[], options: AppOptions) {
|
|
||||||
const runPromise = CustomMain.run(command).then(
|
|
||||||
() => {
|
|
||||||
if (!options.noFlush) {
|
|
||||||
return require('@oclif/command/flush');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
// oclif sometimes exits with ExitError code 0 (not an error)
|
|
||||||
// (Avoid `error instanceof ExitError` here for the reasons explained
|
|
||||||
// in the CONTRIBUTING.md file regarding the `instanceof` operator.)
|
|
||||||
if (error.oclif?.exit === 0) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
await Promise.all([trackPromise, runPromise]);
|
|
||||||
} catch (err) {
|
|
||||||
await (await import('./errors')).handleError(err);
|
|
||||||
}
|
|
||||||
}
|
|
185
lib/app.ts
185
lib/app.ts
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @license
|
* @license
|
||||||
* Copyright 2019 Balena Ltd.
|
* Copyright 2019-2020 Balena Ltd.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -15,73 +15,138 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import * as packageJSON from '../package.json';
|
||||||
|
import { CliSettings } from './utils/bootstrap';
|
||||||
|
import { onceAsync, stripIndent } from './utils/lazy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CLI entrypoint, but see also `bin/balena` and `bin/balena-dev` which
|
* Sentry.io setup
|
||||||
* call this function.
|
* @see https://docs.sentry.io/error-reporting/quickstart/?platform=node
|
||||||
*/
|
*/
|
||||||
|
export const setupSentry = onceAsync(async () => {
|
||||||
|
const config = await import('./config');
|
||||||
|
const Sentry = await import('@sentry/node');
|
||||||
|
Sentry.init({
|
||||||
|
dsn: config.sentryDsn,
|
||||||
|
release: packageJSON.version,
|
||||||
|
});
|
||||||
|
Sentry.configureScope((scope) => {
|
||||||
|
scope.setExtras({
|
||||||
|
is_pkg: !!(process as any).pkg,
|
||||||
|
node_version: process.version,
|
||||||
|
platform: process.platform,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return Sentry.getCurrentHub();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function checkNodeVersion() {
|
||||||
|
const validNodeVersions = packageJSON.engines.node;
|
||||||
|
if (!(await import('semver')).satisfies(process.version, validNodeVersions)) {
|
||||||
|
console.warn(stripIndent`
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
Warning: Node version "${process.version}" does not match required versions "${validNodeVersions}".
|
||||||
|
This may cause unexpected behavior. To upgrade Node, visit:
|
||||||
|
https://nodejs.org/en/download/
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Setup balena-sdk options that are shared with imported packages */
|
||||||
|
function setupBalenaSdkSharedOptions(settings: CliSettings) {
|
||||||
|
const BalenaSdk = require('balena-sdk') as typeof import('balena-sdk');
|
||||||
|
BalenaSdk.setSharedOptions({
|
||||||
|
apiUrl: settings.get<string>('apiUrl'),
|
||||||
|
dataDirectory: settings.get<string>('dataDirectory'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addresses the console warning:
|
||||||
|
* (node:49500) MaxListenersExceededWarning: Possible EventEmitter memory
|
||||||
|
* leak detected. 11 error listeners added. Use emitter.setMaxListeners() to
|
||||||
|
* increase limit
|
||||||
|
*/
|
||||||
|
export function setMaxListeners(maxListeners: number) {
|
||||||
|
require('events').EventEmitter.defaultMaxListeners = maxListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Selected CLI initialization steps */
|
||||||
|
async function init() {
|
||||||
|
if (process.env.BALENARC_NO_SENTRY) {
|
||||||
|
console.error(`WARN: disabling Sentry.io error reporting`);
|
||||||
|
} else {
|
||||||
|
await setupSentry();
|
||||||
|
}
|
||||||
|
checkNodeVersion();
|
||||||
|
|
||||||
|
const settings = new CliSettings();
|
||||||
|
|
||||||
|
// Proxy setup should be done early on, before loading balena-sdk
|
||||||
|
await (await import('./utils/proxy')).setupGlobalHttpProxy(settings);
|
||||||
|
|
||||||
|
setupBalenaSdkSharedOptions(settings);
|
||||||
|
|
||||||
|
// check for CLI updates once a day
|
||||||
|
(await import('./utils/update')).notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Execute the oclif parser and the CLI command. */
|
||||||
|
async function oclifRun(
|
||||||
|
command: string[],
|
||||||
|
options: import('./preparser').AppOptions,
|
||||||
|
) {
|
||||||
|
const { CustomMain } = await import('./utils/oclif-utils');
|
||||||
|
const runPromise = CustomMain.run(command).then(
|
||||||
|
() => {
|
||||||
|
if (!options.noFlush) {
|
||||||
|
return require('@oclif/command/flush');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
// oclif sometimes exits with ExitError code 0 (not an error)
|
||||||
|
// (Avoid `error instanceof ExitError` here for the reasons explained
|
||||||
|
// in the CONTRIBUTING.md file regarding the `instanceof` operator.)
|
||||||
|
if (error.oclif?.exit === 0) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const { trackPromise } = await import('./hooks/prerun/track');
|
||||||
|
await Promise.all([trackPromise, runPromise]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** CLI entrypoint. Called by the `bin/balena` and `bin/balena-dev` scripts. */
|
||||||
export async function run(
|
export async function run(
|
||||||
cliArgs = process.argv,
|
cliArgs = process.argv,
|
||||||
options: import('./preparser').AppOptions = {},
|
options: import('./preparser').AppOptions = {},
|
||||||
) {
|
) {
|
||||||
(await import('./utils/bootstrap')).normalizeEnvVar('DEBUG');
|
|
||||||
|
|
||||||
// The 'pkgExec' special/internal command provides a Node.js interpreter
|
|
||||||
// for use of the standalone zip package. See pkgExec function.
|
|
||||||
if (cliArgs.length > 3 && cliArgs[2] === 'pkgExec') {
|
|
||||||
return pkgExec(cliArgs[3], cliArgs.slice(4));
|
|
||||||
}
|
|
||||||
|
|
||||||
const { globalInit } = await import('./app-common');
|
|
||||||
const { preparseArgs, checkDeletedCommand } = await import('./preparser');
|
|
||||||
|
|
||||||
// globalInit() must be called very early on (before other imports) because
|
|
||||||
// it sets up Sentry error reporting, global HTTP proxy settings, balena-sdk
|
|
||||||
// shared options, and performs node version requirement checks.
|
|
||||||
await globalInit();
|
|
||||||
|
|
||||||
// Look for commands that have been removed and if so, exit with a notice
|
|
||||||
checkDeletedCommand(cliArgs.slice(2));
|
|
||||||
|
|
||||||
const args = await preparseArgs(cliArgs);
|
|
||||||
await (await import('./app-oclif')).run(args, options);
|
|
||||||
|
|
||||||
// Windows fix: reading from stdin prevents the process from exiting
|
|
||||||
process.stdin.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements the 'pkgExec' command, used as a way to provide a Node.js
|
|
||||||
* interpreter for child_process.spawn()-like operations when the CLI is
|
|
||||||
* executing as a standalone zip package (built-in Node interpreter) and
|
|
||||||
* the system may not have a separate Node.js installation. A present use
|
|
||||||
* case is a patched version of the 'windosu' package that requires a
|
|
||||||
* Node.js interpreter to spawn a privileged child process.
|
|
||||||
*
|
|
||||||
* @param modFunc Path to a JS module that will be executed via require().
|
|
||||||
* The modFunc argument may optionally contain a function name separated
|
|
||||||
* by '::', for example '::main' in:
|
|
||||||
* 'C:\\snapshot\\balena-cli\\node_modules\\windosu\\lib\\pipe.js::main'
|
|
||||||
* in which case that function is executed in the require'd module.
|
|
||||||
* @param args Optional arguments to passed through process.argv and as
|
|
||||||
* arguments to the function specified via modFunc.
|
|
||||||
*/
|
|
||||||
async function pkgExec(modFunc: string, args: string[]) {
|
|
||||||
const [modPath, funcName] = modFunc.split('::');
|
|
||||||
let replacedModPath = modPath;
|
|
||||||
const match = modPath
|
|
||||||
.replace(/\\/g, '/')
|
|
||||||
.match(/\/snapshot\/balena-cli\/(.+)/);
|
|
||||||
if (match) {
|
|
||||||
replacedModPath = `../${match[1]}`;
|
|
||||||
}
|
|
||||||
process.argv = [process.argv[0], process.argv[1], ...args];
|
|
||||||
try {
|
try {
|
||||||
const mod: any = await import(replacedModPath);
|
const { normalizeEnvVars, pkgExec } = await import('./utils/bootstrap');
|
||||||
if (funcName) {
|
normalizeEnvVars();
|
||||||
await mod[funcName](...args);
|
|
||||||
|
// The 'pkgExec' special/internal command provides a Node.js interpreter
|
||||||
|
// for use of the standalone zip package. See pkgExec function.
|
||||||
|
if (cliArgs.length > 3 && cliArgs[2] === 'pkgExec') {
|
||||||
|
return pkgExec(cliArgs[3], cliArgs.slice(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await init();
|
||||||
|
|
||||||
|
const { preparseArgs, checkDeletedCommand } = await import('./preparser');
|
||||||
|
|
||||||
|
// Look for commands that have been removed and if so, exit with a notice
|
||||||
|
checkDeletedCommand(cliArgs.slice(2));
|
||||||
|
|
||||||
|
const args = await preparseArgs(cliArgs);
|
||||||
|
await oclifRun(args, options);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Error executing pkgExec "${modFunc}" [${args.join()}]`);
|
await (await import('./errors')).handleError(err);
|
||||||
console.error(err);
|
} finally {
|
||||||
|
// Windows fix: reading from stdin prevents the process from exiting
|
||||||
|
process.stdin.pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @license
|
* @license
|
||||||
* Copyright 2020 Balena Ltd.
|
* Copyright 2019-2020 Balena Ltd.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,6 +22,31 @@
|
|||||||
* like Sentry error reporting, preparser, oclif parser and the like.
|
* like Sentry error reporting, preparser, oclif parser and the like.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export class CliSettings {
|
||||||
|
public readonly settings: any;
|
||||||
|
constructor() {
|
||||||
|
this.settings = require('balena-settings-client') as typeof import('balena-settings-client');
|
||||||
|
}
|
||||||
|
|
||||||
|
public get<T>(name: string): T {
|
||||||
|
return this.settings.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like settings.get(), but return `undefined` instead of throwing an
|
||||||
|
* error if the setting is not found / not defined.
|
||||||
|
*/
|
||||||
|
public getCatch<T>(name: string): T | undefined {
|
||||||
|
try {
|
||||||
|
return this.settings.get(name);
|
||||||
|
} catch (err) {
|
||||||
|
if (!/Setting not found/i.test(err.message)) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function parseBoolEnvVar(varName: string): boolean {
|
export function parseBoolEnvVar(varName: string): boolean {
|
||||||
return !['0', 'no', 'false', '', undefined].includes(
|
return !['0', 'no', 'false', '', undefined].includes(
|
||||||
process.env[varName]?.toLowerCase(),
|
process.env[varName]?.toLowerCase(),
|
||||||
@ -31,3 +56,48 @@ export function parseBoolEnvVar(varName: string): boolean {
|
|||||||
export function normalizeEnvVar(varName: string) {
|
export function normalizeEnvVar(varName: string) {
|
||||||
process.env[varName] = parseBoolEnvVar(varName) ? '1' : '';
|
process.env[varName] = parseBoolEnvVar(varName) ? '1' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bootstrapVars = ['DEBUG', 'BALENARC_NO_SENTRY'];
|
||||||
|
|
||||||
|
export function normalizeEnvVars(varNames: string[] = bootstrapVars) {
|
||||||
|
for (const varName of varNames) {
|
||||||
|
normalizeEnvVar(varName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the 'pkgExec' command, used as a way to provide a Node.js
|
||||||
|
* interpreter for child_process.spawn()-like operations when the CLI is
|
||||||
|
* executing as a standalone zip package (built-in Node interpreter) and
|
||||||
|
* the system may not have a separate Node.js installation. A present use
|
||||||
|
* case is a patched version of the 'windosu' package that requires a
|
||||||
|
* Node.js interpreter to spawn a privileged child process.
|
||||||
|
*
|
||||||
|
* @param modFunc Path to a JS module that will be executed via require().
|
||||||
|
* The modFunc argument may optionally contain a function name separated
|
||||||
|
* by '::', for example '::main' in:
|
||||||
|
* 'C:\\snapshot\\balena-cli\\node_modules\\windosu\\lib\\pipe.js::main'
|
||||||
|
* in which case that function is executed in the require'd module.
|
||||||
|
* @param args Optional arguments to passed through process.argv and as
|
||||||
|
* arguments to the function specified via modFunc.
|
||||||
|
*/
|
||||||
|
export async function pkgExec(modFunc: string, args: string[]) {
|
||||||
|
const [modPath, funcName] = modFunc.split('::');
|
||||||
|
let replacedModPath = modPath;
|
||||||
|
const match = modPath
|
||||||
|
.replace(/\\/g, '/')
|
||||||
|
.match(/\/snapshot\/balena-cli\/(.+)/);
|
||||||
|
if (match) {
|
||||||
|
replacedModPath = `../${match[1]}`;
|
||||||
|
}
|
||||||
|
process.argv = [process.argv[0], process.argv[1], ...args];
|
||||||
|
try {
|
||||||
|
const mod: any = await import(replacedModPath);
|
||||||
|
if (funcName) {
|
||||||
|
await mod[funcName](...args);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error executing pkgExec "${modFunc}" [${args.join()}]`);
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Main } from '@oclif/command';
|
||||||
import type * as Config from '@oclif/config';
|
import type * as Config from '@oclif/config';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,6 +49,17 @@ export class CommandHelp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class CustomMain extends Main {
|
||||||
|
protected _helpOverride(): boolean {
|
||||||
|
// Disable oclif's default handler for the 'version' command
|
||||||
|
if (['-v', '--version', 'version'].includes(this.argv[0])) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return super._helpOverride();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Convert e.g. 'env add NAME [VALUE]' to 'env add <name> [value]' */
|
/** Convert e.g. 'env add NAME [VALUE]' to 'env add <name> [value]' */
|
||||||
export function capitanoizeOclifUsage(
|
export function capitanoizeOclifUsage(
|
||||||
oclifUsage: string | string[] | undefined,
|
oclifUsage: string | string[] | undefined,
|
||||||
|
@ -15,71 +15,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as packageJSON from '../package.json';
|
|
||||||
import { onceAsync, stripIndent } from './utils/lazy';
|
|
||||||
|
|
||||||
class CliSettings {
|
|
||||||
public readonly settings: any;
|
|
||||||
constructor() {
|
|
||||||
this.settings = require('balena-settings-client') as typeof import('balena-settings-client');
|
|
||||||
}
|
|
||||||
|
|
||||||
public get<T>(name: string): T {
|
|
||||||
return this.settings.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Like settings.get(), but return `undefined` instead of throwing an
|
|
||||||
* error if the setting is not found / not defined.
|
|
||||||
*/
|
|
||||||
public getCatch<T>(name: string): T | undefined {
|
|
||||||
try {
|
|
||||||
return this.settings.get(name);
|
|
||||||
} catch (err) {
|
|
||||||
if (!/Setting not found/i.test(err.message)) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sentry.io setup
|
|
||||||
* @see https://docs.sentry.io/error-reporting/quickstart/?platform=node
|
|
||||||
*/
|
|
||||||
export const setupSentry = onceAsync(async () => {
|
|
||||||
const config = await import('./config');
|
|
||||||
const Sentry = await import('@sentry/node');
|
|
||||||
Sentry.init({
|
|
||||||
dsn: config.sentryDsn,
|
|
||||||
release: packageJSON.version,
|
|
||||||
});
|
|
||||||
Sentry.configureScope((scope) => {
|
|
||||||
scope.setExtras({
|
|
||||||
is_pkg: !!(process as any).pkg,
|
|
||||||
node_version: process.version,
|
|
||||||
platform: process.platform,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return Sentry.getCurrentHub();
|
|
||||||
});
|
|
||||||
|
|
||||||
async function checkNodeVersion() {
|
|
||||||
const validNodeVersions = packageJSON.engines.node;
|
|
||||||
if (!(await import('semver')).satisfies(process.version, validNodeVersions)) {
|
|
||||||
console.warn(stripIndent`
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Warning: Node version "${process.version}" does not match required versions "${validNodeVersions}".
|
|
||||||
This may cause unexpected behavior. To upgrade Node, visit:
|
|
||||||
https://nodejs.org/en/download/
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
import type { Options as GlobalTunnelNgConfig } from 'global-tunnel-ng';
|
import type { Options as GlobalTunnelNgConfig } from 'global-tunnel-ng';
|
||||||
export type { GlobalTunnelNgConfig };
|
export type { GlobalTunnelNgConfig };
|
||||||
|
|
||||||
|
import { CliSettings } from './bootstrap';
|
||||||
|
|
||||||
type ProxyConfig = string | GlobalTunnelNgConfig;
|
type ProxyConfig = string | GlobalTunnelNgConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +44,7 @@ type ProxyConfig = string | GlobalTunnelNgConfig;
|
|||||||
* 'localhost' and '127.0.0.1' are always excluded. If NO_PROXY is not defined,
|
* 'localhost' and '127.0.0.1' are always excluded. If NO_PROXY is not defined,
|
||||||
* default exclusion patterns are added for all private IPv4 address ranges.
|
* default exclusion patterns are added for all private IPv4 address ranges.
|
||||||
*/
|
*/
|
||||||
async function setupGlobalHttpProxy(settings: CliSettings) {
|
export async function setupGlobalHttpProxy(settings: CliSettings) {
|
||||||
// `global-tunnel-ng` accepts lowercase variables with higher precedence
|
// `global-tunnel-ng` accepts lowercase variables with higher precedence
|
||||||
// than uppercase variables, but `global-agent` does not accept lowercase.
|
// than uppercase variables, but `global-agent` does not accept lowercase.
|
||||||
// Set uppercase versions for backwards compatibility.
|
// Set uppercase versions for backwards compatibility.
|
||||||
@ -207,42 +147,3 @@ export function makeUrlFromTunnelNgConfig(cfg: GlobalTunnelNgConfig): string {
|
|||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupBalenaSdkSharedOptions(settings: CliSettings) {
|
|
||||||
// We don't yet use balena-sdk directly everywhere, but we set up shared
|
|
||||||
// options correctly so we can do safely in submodules
|
|
||||||
const BalenaSdk = require('balena-sdk') as typeof import('balena-sdk');
|
|
||||||
BalenaSdk.setSharedOptions({
|
|
||||||
apiUrl: settings.get<string>('apiUrl'),
|
|
||||||
dataDirectory: settings.get<string>('dataDirectory'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Addresses the console warning:
|
|
||||||
* (node:49500) MaxListenersExceededWarning: Possible EventEmitter memory
|
|
||||||
* leak detected. 11 error listeners added. Use emitter.setMaxListeners() to
|
|
||||||
* increase limit
|
|
||||||
*/
|
|
||||||
export function setMaxListeners(maxListeners: number) {
|
|
||||||
require('events').EventEmitter.defaultMaxListeners = maxListeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function globalInit() {
|
|
||||||
(await import('./utils/bootstrap')).normalizeEnvVar('BALENARC_NO_SENTRY');
|
|
||||||
if (process.env.BALENARC_NO_SENTRY) {
|
|
||||||
console.error(`WARN: disabling Sentry.io error reporting`);
|
|
||||||
} else {
|
|
||||||
await setupSentry();
|
|
||||||
}
|
|
||||||
checkNodeVersion();
|
|
||||||
|
|
||||||
const settings = new CliSettings();
|
|
||||||
|
|
||||||
// Proxy setup should be done early on, before loading balena-sdk
|
|
||||||
await setupGlobalHttpProxy(settings);
|
|
||||||
setupBalenaSdkSharedOptions(settings);
|
|
||||||
|
|
||||||
// check for CLI updates once a day
|
|
||||||
(await import('./utils/update')).notify();
|
|
||||||
}
|
|
@ -23,7 +23,6 @@ import * as nock from 'nock';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
import * as balenaCLI from '../build/app';
|
import * as balenaCLI from '../build/app';
|
||||||
import { setupSentry } from '../build/app-common';
|
|
||||||
|
|
||||||
const balenaExe = process.platform === 'win32' ? 'balena.exe' : 'balena';
|
const balenaExe = process.platform === 'win32' ? 'balena.exe' : 'balena';
|
||||||
const standalonePath = path.resolve(__dirname, '..', 'build-bin', balenaExe);
|
const standalonePath = path.resolve(__dirname, '..', 'build-bin', balenaExe);
|
||||||
@ -287,7 +286,7 @@ export function fillTemplateArray(
|
|||||||
export async function switchSentry(
|
export async function switchSentry(
|
||||||
enabled: boolean | undefined,
|
enabled: boolean | undefined,
|
||||||
): Promise<boolean | undefined> {
|
): Promise<boolean | undefined> {
|
||||||
const sentryOpts = (await setupSentry()).getClient()?.getOptions();
|
const sentryOpts = (await balenaCLI.setupSentry()).getClient()?.getOptions();
|
||||||
if (sentryOpts) {
|
if (sentryOpts) {
|
||||||
const sentryStatus = sentryOpts.enabled;
|
const sentryStatus = sentryOpts.enabled;
|
||||||
sentryOpts.enabled = enabled;
|
sentryOpts.enabled = enabled;
|
||||||
|
@ -20,7 +20,7 @@ import { expect } from 'chai';
|
|||||||
import {
|
import {
|
||||||
GlobalTunnelNgConfig,
|
GlobalTunnelNgConfig,
|
||||||
makeUrlFromTunnelNgConfig,
|
makeUrlFromTunnelNgConfig,
|
||||||
} from '../build/app-common';
|
} from '../build/utils/proxy';
|
||||||
|
|
||||||
describe('makeUrlFromTunnelNgConfig() function', function () {
|
describe('makeUrlFromTunnelNgConfig() function', function () {
|
||||||
it('should return a URL given a GlobalTunnelNgConfig object', () => {
|
it('should return a URL given a GlobalTunnelNgConfig object', () => {
|
Loading…
Reference in New Issue
Block a user