@ms-cloudpack/cli 0.77.44 → 0.77.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cloudpack.js +1 -1
- package/lib/types/CommandAction.d.ts +6 -6
- package/lib/types/CommandAction.js.map +1 -1
- package/lib/utilities/CloudpackCommand.d.ts.map +1 -1
- package/lib/utilities/CloudpackCommand.js +6 -0
- package/lib/utilities/CloudpackCommand.js.map +1 -1
- package/lib/utilities/CommandExecutor.d.ts +32 -4
- package/lib/utilities/CommandExecutor.d.ts.map +1 -1
- package/lib/utilities/CommandExecutor.js +108 -29
- package/lib/utilities/CommandExecutor.js.map +1 -1
- package/package.json +11 -11
package/bin/cloudpack.js
CHANGED
|
@@ -74,12 +74,12 @@ export interface CommandActionParams<TOptions extends object> extends AppCommand
|
|
|
74
74
|
* be exported from each command's `src/commands/<name>/execute.ts` module and is called by
|
|
75
75
|
* `CommandExecutor` against each app.
|
|
76
76
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* -
|
|
81
|
-
*
|
|
82
|
-
*
|
|
77
|
+
* The function should return a promise of an exit options object:
|
|
78
|
+
* - For most commands, this should be the result of running the command.
|
|
79
|
+
* - Interrupts will be handled automatically (use `setInterruptMessageHandler` for a custom message).
|
|
80
|
+
* - For commands such as `start` which run continuously, it's okay if the promise doesn't resolve.
|
|
81
|
+
* If a restart is needed, return `{ restart: true, ... }`.
|
|
82
|
+
* - For multi-app, if there's a failure in one app, the command will continue running for others.
|
|
83
83
|
*/
|
|
84
84
|
export type CommandAction<TOptions> = (params: CommandActionParams<TOptions & SharedOptions>) => Promise<CommandExitParams>;
|
|
85
85
|
export type CommandActionModule<TOptions> = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandAction.js","sourceRoot":"","sources":["../../src/types/CommandAction.ts"],"names":[],"mappings":"AAkBA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AACtC,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC","sourcesContent":["import type { CreateApiContextOptions } from '@ms-cloudpack/api-server';\nimport type { AutoDispose } from './AutoDispose.js';\nimport type { SharedOptions } from './SharedOptions.js';\nimport type { Span } from '@ms-cloudpack/telemetry';\nimport type { ProgramOptions } from './ProgramOptions.js';\n\n/**\n * Context for running a command in a specific app (after initialization).\n * For convenience, this can be passed/spread directly to `createApiContext`.\n */\nexport interface AppCommandContext extends Pick<\n CreateApiContextOptions,\n 'cachePath' | 'config' | 'reporter' | 'taskRunner' | 'telemetryClient'\n> {\n /** App path (CWD for most operations). */\n appPath: string;\n}\n\nexport const ExitCodeSuccessful = 0;\nexport const ExitCodeGenericError = 1;\nexport const ExitCodeAuthenticationError = 2;\nexport type ExitCode = typeof ExitCodeSuccessful | typeof ExitCodeGenericError | typeof ExitCodeAuthenticationError;\n\nexport interface CommandExitParams {\n /**\n * Message to show on exit.\n * If `isInterrupted` is true, use an empty string (it will show a default interrupt message).\n */\n message: string;\n /** Whether there are errors. By default, checks the reporter for failed tasks. */\n hasErrors?: boolean;\n /** Exit code to use. Defaults to 1 if there are errors, 0 if not. */\n exitCode?: ExitCode;\n /** True if the user interrupted an operation (ctrl+C). Sets the message automatically. */\n isInterrupted?: boolean;\n /** Whether to restart the command after it exits. */\n restart?: boolean;\n}\n\nexport interface CommandActionParams<TOptions extends object>\n extends AppCommandContext, Pick<ProgramOptions, 'commandEvents'> {\n /**\n * Command-specific options, parsed from `process.argv`.\n * Types are generally defined in each command's `src/commands/<name>/types/<Name>Types.ts` module.\n * The command line options are defined in each command's `src/commands/<name>/index.ts` module.\n */\n options: TOptions;\n\n /**\n * Command-specific arguments. Arguments in commander are positional arguments that are not options.\n * For example, in `echo somestring`, `somestring` is an argument.\n */\n args: string[];\n\n /**\n * Whether the command is being run for multiple apps. (It only runs on one app at a time, but\n * multi-app may impact formatting choices or other behaviors.)\n *\n * Note that this will only ever be true for commands initialized with `discoverAppPaths: 'multi'`.\n */\n isMultiApp: boolean;\n\n /**\n * Parent span for the command.\n */\n span: Span;\n\n /**\n * Function that can be called with any `Disposable`s that should be cleaned up automatically\n * when the program exits. (See `AutoDisposableList.add` for implementation.)\n */\n autoDispose: AutoDispose;\n\n /**\n * Set a callback to get the message to display if ctrl+C is pressed.\n */\n setInterruptMessageHandler: (getMessage: () => string) => void;\n\n /**\n * Indicates whether this command execution is a restart of a previous execution.\n * When true, the command is being run again due to a restart trigger (e.g., config changes).\n * This can be used to modify behavior on restart, such as skipping browser opening.\n */\n isRestart: boolean;\n}\n\n/**\n * Command action function (executor). This is the type of the `execute` function which should\n * be exported from each command's `src/commands/<name>/execute.ts` module and is called by\n * `CommandExecutor` against each app.\n *\n *
|
|
1
|
+
{"version":3,"file":"CommandAction.js","sourceRoot":"","sources":["../../src/types/CommandAction.ts"],"names":[],"mappings":"AAkBA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AACtC,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC","sourcesContent":["import type { CreateApiContextOptions } from '@ms-cloudpack/api-server';\nimport type { AutoDispose } from './AutoDispose.js';\nimport type { SharedOptions } from './SharedOptions.js';\nimport type { Span } from '@ms-cloudpack/telemetry';\nimport type { ProgramOptions } from './ProgramOptions.js';\n\n/**\n * Context for running a command in a specific app (after initialization).\n * For convenience, this can be passed/spread directly to `createApiContext`.\n */\nexport interface AppCommandContext extends Pick<\n CreateApiContextOptions,\n 'cachePath' | 'config' | 'reporter' | 'taskRunner' | 'telemetryClient'\n> {\n /** App path (CWD for most operations). */\n appPath: string;\n}\n\nexport const ExitCodeSuccessful = 0;\nexport const ExitCodeGenericError = 1;\nexport const ExitCodeAuthenticationError = 2;\nexport type ExitCode = typeof ExitCodeSuccessful | typeof ExitCodeGenericError | typeof ExitCodeAuthenticationError;\n\nexport interface CommandExitParams {\n /**\n * Message to show on exit.\n * If `isInterrupted` is true, use an empty string (it will show a default interrupt message).\n */\n message: string;\n /** Whether there are errors. By default, checks the reporter for failed tasks. */\n hasErrors?: boolean;\n /** Exit code to use. Defaults to 1 if there are errors, 0 if not. */\n exitCode?: ExitCode;\n /** True if the user interrupted an operation (ctrl+C). Sets the message automatically. */\n isInterrupted?: boolean;\n /** Whether to restart the command after it exits. */\n restart?: boolean;\n}\n\nexport interface CommandActionParams<TOptions extends object>\n extends AppCommandContext, Pick<ProgramOptions, 'commandEvents'> {\n /**\n * Command-specific options, parsed from `process.argv`.\n * Types are generally defined in each command's `src/commands/<name>/types/<Name>Types.ts` module.\n * The command line options are defined in each command's `src/commands/<name>/index.ts` module.\n */\n options: TOptions;\n\n /**\n * Command-specific arguments. Arguments in commander are positional arguments that are not options.\n * For example, in `echo somestring`, `somestring` is an argument.\n */\n args: string[];\n\n /**\n * Whether the command is being run for multiple apps. (It only runs on one app at a time, but\n * multi-app may impact formatting choices or other behaviors.)\n *\n * Note that this will only ever be true for commands initialized with `discoverAppPaths: 'multi'`.\n */\n isMultiApp: boolean;\n\n /**\n * Parent span for the command.\n */\n span: Span;\n\n /**\n * Function that can be called with any `Disposable`s that should be cleaned up automatically\n * when the program exits. (See `AutoDisposableList.add` for implementation.)\n */\n autoDispose: AutoDispose;\n\n /**\n * Set a callback to get the message to display if ctrl+C is pressed.\n */\n setInterruptMessageHandler: (getMessage: () => string) => void;\n\n /**\n * Indicates whether this command execution is a restart of a previous execution.\n * When true, the command is being run again due to a restart trigger (e.g., config changes).\n * This can be used to modify behavior on restart, such as skipping browser opening.\n */\n isRestart: boolean;\n}\n\n/**\n * Command action function (executor). This is the type of the `execute` function which should\n * be exported from each command's `src/commands/<name>/execute.ts` module and is called by\n * `CommandExecutor` against each app.\n *\n * The function should return a promise of an exit options object:\n * - For most commands, this should be the result of running the command.\n * - Interrupts will be handled automatically (use `setInterruptMessageHandler` for a custom message).\n * - For commands such as `start` which run continuously, it's okay if the promise doesn't resolve.\n * If a restart is needed, return `{ restart: true, ... }`.\n * - For multi-app, if there's a failure in one app, the command will continue running for others.\n */\nexport type CommandAction<TOptions> = (\n params: CommandActionParams<TOptions & SharedOptions>,\n) => Promise<CommandExitParams>;\n\nexport type CommandActionModule<TOptions> = {\n execute: CommandAction<TOptions>;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudpackCommand.d.ts","sourceRoot":"","sources":["../../src/utilities/CloudpackCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,mBAAmB,EAAE,KAAK,QAAQ,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMnF;;;GAGG;AACH,MAAM,WAAW,sBAAsB,CAAC,QAAQ,SAAS,MAAM,EAAE,UAAU,SAAS,MAAM,CAAE,SAAQ,OAAO,CACzG,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,sBAAsB,CAAC,CACnF;IACC,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IAEb,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAEpD,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,UAAU,EAAE,QAAQ,CAAC,CAAC;IAE1C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE3D,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,yDAAyD;IACzD,WAAW,CAAC,EAAE;QACZ;;;WAGG;QACH,QAAQ,EAAE,mBAAmB,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IAEF,mDAAmD;IACnD,aAAa,CAAC,EAAE,mBAAmB,CAAC;IAEpC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,MAAM,aAAa,CAAC,GAAG,IAAI,CAAC;CACvD;AAED;;;;;;;GAOG;AACH,qBAAa,gBAAgB,CAAC,QAAQ,SAAS,MAAM,EAAE,UAAU,SAAS,MAAM;IAC9E,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,gBAAgB,CAGtB;IAEF;;;OAGG;gBAGD,MAAM,EAAE,sBAAsB,CAAC,QAAQ,EAAE,UAAU,CAAC,GAClD,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,GAAG;QACxD,+DAA+D;QAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB;
|
|
1
|
+
{"version":3,"file":"CloudpackCommand.d.ts","sourceRoot":"","sources":["../../src/utilities/CloudpackCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,mBAAmB,EAAE,KAAK,QAAQ,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMnF;;;GAGG;AACH,MAAM,WAAW,sBAAsB,CAAC,QAAQ,SAAS,MAAM,EAAE,UAAU,SAAS,MAAM,CAAE,SAAQ,OAAO,CACzG,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,sBAAsB,CAAC,CACnF;IACC,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IAEb,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAEpD,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,UAAU,EAAE,QAAQ,CAAC,CAAC;IAE1C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE3D,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,yDAAyD;IACzD,WAAW,CAAC,EAAE;QACZ;;;WAGG;QACH,QAAQ,EAAE,mBAAmB,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IAEF,mDAAmD;IACnD,aAAa,CAAC,EAAE,mBAAmB,CAAC;IAEpC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,MAAM,aAAa,CAAC,GAAG,IAAI,CAAC;CACvD;AAED;;;;;;;GAOG;AACH,qBAAa,gBAAgB,CAAC,QAAQ,SAAS,MAAM,EAAE,UAAU,SAAS,MAAM;IAC9E,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,gBAAgB,CAGtB;IAEF;;;OAGG;gBAGD,MAAM,EAAE,sBAAsB,CAAC,QAAQ,EAAE,UAAU,CAAC,GAClD,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,GAAG;QACxD,+DAA+D;QAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB;IAkFL,8BAA8B;IACvB,aAAa,CAAC,aAAa,SAAS,MAAM,EAAE,eAAe,SAAS,MAAM,GAAG,KAAK,EACvF,MAAM,EAAE,sBAAsB,CAAC,aAAa,EAAE,eAAe,CAAC,GAC7D,gBAAgB,CAAC,aAAa,EAAE,eAAe,CAAC;IAQnD,qEAAqE;IACxD,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAWjC,qGAAqG;IACrG,OAAO,CAAC,aAAa;IAMrB,iGAAiG;IACjG,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,UAAU;CAsCnB"}
|
|
@@ -33,6 +33,12 @@ export class CloudpackCommand {
|
|
|
33
33
|
command.description(params.description);
|
|
34
34
|
command.allowExcessArguments(false);
|
|
35
35
|
const isTopLevel = !params.parent;
|
|
36
|
+
if (isTopLevel && environmentInfo.isJest) {
|
|
37
|
+
// In tests, throw instead of exiting the process on invalid args
|
|
38
|
+
command.exitOverride((err) => {
|
|
39
|
+
throw new Error(`Process exited with code ${err.exitCode} due to arg parsing error`);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
36
42
|
command.createHelp = () => new CloudpackHelp({ isTopLevel });
|
|
37
43
|
// set the default help group for options
|
|
38
44
|
command.optionsGroup(optionGroups.default);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudpackCommand.js","sourceRoot":"","sources":["../../src/utilities/CloudpackCommand.ts"],"names":[],"mappings":"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","sourcesContent":["import { Command, Option, type AddHelpTextPosition, type Argument, type OutputConfiguration } from 'commander';\nimport type { CommandActionModule } from '../types/CommandAction.js';\nimport type { SharedOptions } from '../types/SharedOptions.js';\nimport { CommandExecutor, type CommandExecutorParams } from './CommandExecutor.js';\nimport { environmentInfo } from '@ms-cloudpack/environment';\nimport { parseFeature } from './parseFeature.js';\nimport { parseDefine } from './parseDefine.js';\nimport { CloudpackHelp, optionGroups } from './CloudpackHelp.js';\n\n/**\n * Parameters for creating a command.\n * `TOptions` should be the command-specific options (if any), e.g. `StartOptions`.\n */\nexport interface CloudpackCommandParams<TOptions extends object, TArguments extends object> extends Partial<\n Pick<CommandExecutorParams<TOptions>, 'discoverAppPaths' | 'applyOptionsToConfig'>\n> {\n /** Command name */\n name: string;\n\n /** Command description */\n description: string;\n\n /**\n * Options specific to this command. The record ensures that all options are available in the CLI.\n * Allow multiple options for the same key since commander supports it with negatable options.\n */\n options?: Record<keyof TOptions, Option | Option[]>; //\n\n /** Arguments specific to this command. Key order determines the arg order. */\n args?: Record<keyof TArguments, Argument>;\n\n /**\n * Function returning an async import of the command's `src/commands/<name>/execute.ts` module.\n * Importing only on demand makes Cloudpack start up faster since it doesn't have to parse\n * every command's dependencies (many of which may be unrelated to the command being run).\n *\n * This can be undefined for a command that only has sub-commands.\n */\n getExecutor?: () => Promise<CommandActionModule<TOptions>>;\n\n /** Usage message override */\n usage?: string;\n\n /** Alternative name for the command */\n alias?: string;\n\n /** Extra text to be displayed with the built-in help. */\n addHelpText?: {\n /**\n * `'before'` or `'after'` to affect just this command.\n * `'beforeAll'` or `'afterAll'` to affect this command and all its subcommands.\n */\n position: AddHelpTextPosition;\n text: string;\n };\n\n /** Output options override (mainly for testing) */\n outputOptions?: OutputConfiguration;\n\n /**\n * The shared options are relevant for most commands, but this allows omitting them from help\n * where they're not relevant. `true` hides all shared options, or an array hides specific ones.\n */\n hideSharedOptions?: Array<keyof SharedOptions> | true;\n}\n\n/**\n * This wraps the `Command` class from [`commander`](https://www.npmjs.com/package/commander) with\n * Cloudpack-specific functionality and simpler APIs.\n *\n * Similar to the pattern from `commander`, this class represents both the program and its sub-commands.\n * - The top-level \"program\" command should be created with `new CloudpackCommand()`.\n * - Sub-commands should be created with the `.addSubCommand` method on the parent.\n */\nexport class CloudpackCommand<TOptions extends object, TArguments extends object> {\n private _command: Command;\n private _executorOptions: Pick<\n CommandExecutorParams<TOptions>,\n 'programOptions' | 'discoverAppPaths' | 'applyOptionsToConfig'\n >;\n\n /**\n * This should only be used directly (outside this class) to create the top-level `program` command.\n * To add sub-commands, use `.addSubCommand` instead.\n */\n constructor(\n // The extra options here shouldn't be exposed to the `createSubCommand` API\n params: CloudpackCommandParams<TOptions, TArguments> &\n Pick<CommandExecutorParams<TOptions>, 'programOptions'> & {\n /** This must be undefined for the top-level program command */\n parent?: Command;\n },\n ) {\n this._executorOptions = {\n programOptions: params.programOptions,\n discoverAppPaths: params.discoverAppPaths,\n applyOptionsToConfig: params.applyOptionsToConfig,\n };\n\n const command = params.parent?.command(params.name) || new Command(params.name);\n this._command = command;\n\n command.version(params.programOptions.version);\n command.description(params.description);\n command.allowExcessArguments(false);\n\n const isTopLevel = !params.parent;\n command.createHelp = () => new CloudpackHelp({ isTopLevel });\n // set the default help group for options\n command.optionsGroup(optionGroups.default);\n\n params.usage && command.usage(params.usage);\n params.alias && command.alias(params.alias);\n params.addHelpText && command.addHelpText(params.addHelpText.position, params.addHelpText.text);\n params.outputOptions && command.configureOutput(params.outputOptions);\n params.getExecutor && this._addAction(params.getExecutor);\n\n if (params.args) {\n this._addArguments<TArguments>(params.args);\n }\n\n if (params.options) {\n // Add the command-specific options first so they show up first in help\n this._addOptions<TOptions>(params.options);\n }\n\n // Add shared options. These must be manually added to the program command and each sub-command\n // because commander doesn't natively support inheriting options.\n this._addOptions<SharedOptions>(\n {\n verbose: new Option('-v, --verbose', 'Show additional details in logging.').helpGroup(optionGroups.logging),\n debug: new Option('-d, --debug', 'Show debug information (superset of --verbose).')\n .conflicts('verbose')\n .helpGroup(optionGroups.logging),\n quiet: new Option('-q, --quiet', 'Disable non-essential logging.')\n .conflicts('verbose')\n .conflicts('debug')\n .helpGroup(optionGroups.logging),\n color:\n // In the parsed options, this will be a boolean `color` with default value true, except in tests, CI, or environments without a TTY (e.g., concurrently).\n new Option('-n, --no-color', 'Disable colors in the output.')\n .helpGroup(optionGroups.logging)\n .default(\n !environmentInfo.isJest && !environmentInfo.isLage && !environmentInfo.isCI && !!process.stdout.isTTY,\n ),\n logFile: new Option('--log-file', 'Write a log file with all console output.').helpGroup(optionGroups.logging),\n cachePath: new Option(\n '--cache-path <path>',\n 'Custom cache folder. To change the default, run `cloudpack config set cachePath <path>`.',\n ).helpGroup(optionGroups.common),\n config: new Option(\n '-c, --config <filename>',\n 'Custom config file name to use instead of cloudpack.config.json.',\n ).helpGroup(optionGroups.common),\n define: new Option('--define <key=value>', 'Define a global variable. Can be specified multiple times.')\n .helpGroup(optionGroups.common)\n .argParser(parseDefine),\n features: new Option('--features <featureNames...>', 'Enable experimental features.')\n .helpGroup(optionGroups.common)\n .argParser(parseFeature),\n },\n params.hideSharedOptions,\n );\n }\n\n /** Create a child command. */\n public addSubCommand<TChildOptions extends object, TChildArguments extends object = never>(\n params: CloudpackCommandParams<TChildOptions, TChildArguments>,\n ): CloudpackCommand<TChildOptions, TChildArguments> {\n return new CloudpackCommand<TChildOptions, TChildArguments>({\n ...params,\n programOptions: this._executorOptions.programOptions,\n parent: this._command,\n });\n }\n\n /** Run the program (only works on the top-level program command). */\n public async run(): Promise<void> {\n if (this._command.parent) {\n throw new Error('Only the top-level program command can be run directly.');\n }\n\n await this._command.parseAsync(this._executorOptions.programOptions.argv);\n if (this._command.args.length === 0) {\n this._command.help();\n }\n }\n\n /** Add arguments. The generic enforces that argument objects are included for all keys of a type. */\n private _addArguments<TAddArguments extends object>(args: Record<keyof TAddArguments, Argument>): void {\n for (const argument of Object.values(args)) {\n this._command.addArgument(argument as Argument);\n }\n }\n\n /** Add options. The generic enforces that option objects are included for all keys of a type. */\n private _addOptions<TAddOptions extends object>(\n options: Record<keyof TAddOptions, Option | Option[]>,\n hideOptions?: Array<keyof TAddOptions> | true,\n ): void {\n for (const [name, optionOrOptions] of Object.entries(options) as [keyof TAddOptions, Option | Option[]][]) {\n const optionArray = Array.isArray(optionOrOptions) ? optionOrOptions : [optionOrOptions];\n for (const option of optionArray) {\n if (hideOptions === true || hideOptions?.includes(name)) {\n option.hideHelp();\n }\n this._command.addOption(option);\n }\n }\n }\n\n private _addAction(getExecutor: NonNullable<CloudpackCommandParams<TOptions, TArguments>['getExecutor']>): void {\n const command = this._command;\n // The action function receives parsed options as its first parameter, but we ignore those\n // because they only contain options *specific to this command*, not shared options like `debug`.\n command.action(async () => {\n // Commander has support for custom parsers that parse arguments.\n // Use processedArgs instead of args to get the parsed arguments.\n const processedArgs = command.processedArgs as string[];\n\n // Get the shared options too, not just the ones for this command.\n // (In `cloudpackCommand`, we added the shared options to each command object so that they show up\n // in help, but commander still seems to respect options only at the first command where they're\n // encountered, which for shared options will always be the program command.)\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n const options = command.optsWithGlobals<TOptions & SharedOptions>();\n\n // Usually `command` will be a sub-command (e.g. \"bundle\"), but it could also be a sub-sub-command\n // (e.g. \"cache clean\").\n const verb = command.parent?.parent ? `${command.parent.name()} ${command.name()}` : command.name();\n\n // Dynamically import the execute function\n const { execute } = await getExecutor();\n if (typeof execute !== 'function') {\n // throw instead of exiting politely, since this is a major developer error\n throw new Error(`No execute function was exported from the command module for ${verb}.`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n const commandExecutor = new CommandExecutor<TOptions & SharedOptions>({\n args: processedArgs,\n options,\n execute,\n verb,\n ...this._executorOptions,\n });\n await commandExecutor.execute();\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CloudpackCommand.js","sourceRoot":"","sources":["../../src/utilities/CloudpackCommand.ts"],"names":[],"mappings":"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","sourcesContent":["import { Command, Option, type AddHelpTextPosition, type Argument, type OutputConfiguration } from 'commander';\nimport type { CommandActionModule } from '../types/CommandAction.js';\nimport type { SharedOptions } from '../types/SharedOptions.js';\nimport { CommandExecutor, type CommandExecutorParams } from './CommandExecutor.js';\nimport { environmentInfo } from '@ms-cloudpack/environment';\nimport { parseFeature } from './parseFeature.js';\nimport { parseDefine } from './parseDefine.js';\nimport { CloudpackHelp, optionGroups } from './CloudpackHelp.js';\n\n/**\n * Parameters for creating a command.\n * `TOptions` should be the command-specific options (if any), e.g. `StartOptions`.\n */\nexport interface CloudpackCommandParams<TOptions extends object, TArguments extends object> extends Partial<\n Pick<CommandExecutorParams<TOptions>, 'discoverAppPaths' | 'applyOptionsToConfig'>\n> {\n /** Command name */\n name: string;\n\n /** Command description */\n description: string;\n\n /**\n * Options specific to this command. The record ensures that all options are available in the CLI.\n * Allow multiple options for the same key since commander supports it with negatable options.\n */\n options?: Record<keyof TOptions, Option | Option[]>; //\n\n /** Arguments specific to this command. Key order determines the arg order. */\n args?: Record<keyof TArguments, Argument>;\n\n /**\n * Function returning an async import of the command's `src/commands/<name>/execute.ts` module.\n * Importing only on demand makes Cloudpack start up faster since it doesn't have to parse\n * every command's dependencies (many of which may be unrelated to the command being run).\n *\n * This can be undefined for a command that only has sub-commands.\n */\n getExecutor?: () => Promise<CommandActionModule<TOptions>>;\n\n /** Usage message override */\n usage?: string;\n\n /** Alternative name for the command */\n alias?: string;\n\n /** Extra text to be displayed with the built-in help. */\n addHelpText?: {\n /**\n * `'before'` or `'after'` to affect just this command.\n * `'beforeAll'` or `'afterAll'` to affect this command and all its subcommands.\n */\n position: AddHelpTextPosition;\n text: string;\n };\n\n /** Output options override (mainly for testing) */\n outputOptions?: OutputConfiguration;\n\n /**\n * The shared options are relevant for most commands, but this allows omitting them from help\n * where they're not relevant. `true` hides all shared options, or an array hides specific ones.\n */\n hideSharedOptions?: Array<keyof SharedOptions> | true;\n}\n\n/**\n * This wraps the `Command` class from [`commander`](https://www.npmjs.com/package/commander) with\n * Cloudpack-specific functionality and simpler APIs.\n *\n * Similar to the pattern from `commander`, this class represents both the program and its sub-commands.\n * - The top-level \"program\" command should be created with `new CloudpackCommand()`.\n * - Sub-commands should be created with the `.addSubCommand` method on the parent.\n */\nexport class CloudpackCommand<TOptions extends object, TArguments extends object> {\n private _command: Command;\n private _executorOptions: Pick<\n CommandExecutorParams<TOptions>,\n 'programOptions' | 'discoverAppPaths' | 'applyOptionsToConfig'\n >;\n\n /**\n * This should only be used directly (outside this class) to create the top-level `program` command.\n * To add sub-commands, use `.addSubCommand` instead.\n */\n constructor(\n // The extra options here shouldn't be exposed to the `createSubCommand` API\n params: CloudpackCommandParams<TOptions, TArguments> &\n Pick<CommandExecutorParams<TOptions>, 'programOptions'> & {\n /** This must be undefined for the top-level program command */\n parent?: Command;\n },\n ) {\n this._executorOptions = {\n programOptions: params.programOptions,\n discoverAppPaths: params.discoverAppPaths,\n applyOptionsToConfig: params.applyOptionsToConfig,\n };\n\n const command = params.parent?.command(params.name) || new Command(params.name);\n this._command = command;\n\n command.version(params.programOptions.version);\n command.description(params.description);\n command.allowExcessArguments(false);\n\n const isTopLevel = !params.parent;\n\n if (isTopLevel && environmentInfo.isJest) {\n // In tests, throw instead of exiting the process on invalid args\n command.exitOverride((err) => {\n throw new Error(`Process exited with code ${err.exitCode} due to arg parsing error`);\n });\n }\n\n command.createHelp = () => new CloudpackHelp({ isTopLevel });\n // set the default help group for options\n command.optionsGroup(optionGroups.default);\n\n params.usage && command.usage(params.usage);\n params.alias && command.alias(params.alias);\n params.addHelpText && command.addHelpText(params.addHelpText.position, params.addHelpText.text);\n params.outputOptions && command.configureOutput(params.outputOptions);\n params.getExecutor && this._addAction(params.getExecutor);\n\n if (params.args) {\n this._addArguments<TArguments>(params.args);\n }\n\n if (params.options) {\n // Add the command-specific options first so they show up first in help\n this._addOptions<TOptions>(params.options);\n }\n\n // Add shared options. These must be manually added to the program command and each sub-command\n // because commander doesn't natively support inheriting options.\n this._addOptions<SharedOptions>(\n {\n verbose: new Option('-v, --verbose', 'Show additional details in logging.').helpGroup(optionGroups.logging),\n debug: new Option('-d, --debug', 'Show debug information (superset of --verbose).')\n .conflicts('verbose')\n .helpGroup(optionGroups.logging),\n quiet: new Option('-q, --quiet', 'Disable non-essential logging.')\n .conflicts('verbose')\n .conflicts('debug')\n .helpGroup(optionGroups.logging),\n color:\n // In the parsed options, this will be a boolean `color` with default value true, except in tests, CI, or environments without a TTY (e.g., concurrently).\n new Option('-n, --no-color', 'Disable colors in the output.')\n .helpGroup(optionGroups.logging)\n .default(\n !environmentInfo.isJest && !environmentInfo.isLage && !environmentInfo.isCI && !!process.stdout.isTTY,\n ),\n logFile: new Option('--log-file', 'Write a log file with all console output.').helpGroup(optionGroups.logging),\n cachePath: new Option(\n '--cache-path <path>',\n 'Custom cache folder. To change the default, run `cloudpack config set cachePath <path>`.',\n ).helpGroup(optionGroups.common),\n config: new Option(\n '-c, --config <filename>',\n 'Custom config file name to use instead of cloudpack.config.json.',\n ).helpGroup(optionGroups.common),\n define: new Option('--define <key=value>', 'Define a global variable. Can be specified multiple times.')\n .helpGroup(optionGroups.common)\n .argParser(parseDefine),\n features: new Option('--features <featureNames...>', 'Enable experimental features.')\n .helpGroup(optionGroups.common)\n .argParser(parseFeature),\n },\n params.hideSharedOptions,\n );\n }\n\n /** Create a child command. */\n public addSubCommand<TChildOptions extends object, TChildArguments extends object = never>(\n params: CloudpackCommandParams<TChildOptions, TChildArguments>,\n ): CloudpackCommand<TChildOptions, TChildArguments> {\n return new CloudpackCommand<TChildOptions, TChildArguments>({\n ...params,\n programOptions: this._executorOptions.programOptions,\n parent: this._command,\n });\n }\n\n /** Run the program (only works on the top-level program command). */\n public async run(): Promise<void> {\n if (this._command.parent) {\n throw new Error('Only the top-level program command can be run directly.');\n }\n\n await this._command.parseAsync(this._executorOptions.programOptions.argv);\n if (this._command.args.length === 0) {\n this._command.help();\n }\n }\n\n /** Add arguments. The generic enforces that argument objects are included for all keys of a type. */\n private _addArguments<TAddArguments extends object>(args: Record<keyof TAddArguments, Argument>): void {\n for (const argument of Object.values(args)) {\n this._command.addArgument(argument as Argument);\n }\n }\n\n /** Add options. The generic enforces that option objects are included for all keys of a type. */\n private _addOptions<TAddOptions extends object>(\n options: Record<keyof TAddOptions, Option | Option[]>,\n hideOptions?: Array<keyof TAddOptions> | true,\n ): void {\n for (const [name, optionOrOptions] of Object.entries(options) as [keyof TAddOptions, Option | Option[]][]) {\n const optionArray = Array.isArray(optionOrOptions) ? optionOrOptions : [optionOrOptions];\n for (const option of optionArray) {\n if (hideOptions === true || hideOptions?.includes(name)) {\n option.hideHelp();\n }\n this._command.addOption(option);\n }\n }\n }\n\n private _addAction(getExecutor: NonNullable<CloudpackCommandParams<TOptions, TArguments>['getExecutor']>): void {\n const command = this._command;\n // The action function receives parsed options as its first parameter, but we ignore those\n // because they only contain options *specific to this command*, not shared options like `debug`.\n command.action(async () => {\n // Commander has support for custom parsers that parse arguments.\n // Use processedArgs instead of args to get the parsed arguments.\n const processedArgs = command.processedArgs as string[];\n\n // Get the shared options too, not just the ones for this command.\n // (In `cloudpackCommand`, we added the shared options to each command object so that they show up\n // in help, but commander still seems to respect options only at the first command where they're\n // encountered, which for shared options will always be the program command.)\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n const options = command.optsWithGlobals<TOptions & SharedOptions>();\n\n // Usually `command` will be a sub-command (e.g. \"bundle\"), but it could also be a sub-sub-command\n // (e.g. \"cache clean\").\n const verb = command.parent?.parent ? `${command.parent.name()} ${command.name()}` : command.name();\n\n // Dynamically import the execute function\n const { execute } = await getExecutor();\n if (typeof execute !== 'function') {\n // throw instead of exiting politely, since this is a major developer error\n throw new Error(`No execute function was exported from the command module for ${verb}.`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n const commandExecutor = new CommandExecutor<TOptions & SharedOptions>({\n args: processedArgs,\n options,\n execute,\n verb,\n ...this._executorOptions,\n });\n await commandExecutor.execute();\n });\n }\n}\n"]}
|
|
@@ -42,21 +42,42 @@ export declare class CommandExecutor<TOptions extends SharedOptions> {
|
|
|
42
42
|
private _discoverAppPaths;
|
|
43
43
|
private _applyOptionsToConfig;
|
|
44
44
|
private _reporter;
|
|
45
|
+
/** Items which should be disposed before a restart, as well as at process exit */
|
|
45
46
|
private _autoDisposableList;
|
|
47
|
+
/** Items which should be disposed before exit only */
|
|
48
|
+
private _finalDisposableList;
|
|
46
49
|
private _hasCalledExit;
|
|
47
50
|
private _args;
|
|
48
51
|
private _sigintCount;
|
|
49
52
|
private _onInterrupt?;
|
|
50
53
|
private _getMessageOnInterrupt?;
|
|
54
|
+
/** Active `CommandExecutor` instances. In tests, there may be more than one. */
|
|
51
55
|
private static _activeInstances;
|
|
52
|
-
|
|
56
|
+
/** Mock implementation of `process.exit` for testing purposes. */
|
|
57
|
+
private static _mockProcessExit;
|
|
58
|
+
/**
|
|
59
|
+
* Set a mock `process.exit()` implementation for tests, to handle cases where the command would
|
|
60
|
+
* call `process.exit()`.
|
|
61
|
+
*/
|
|
62
|
+
static mockProcessExitForTests(mockImpl: typeof process.exit | undefined): void;
|
|
63
|
+
/**
|
|
64
|
+
* For testing use only: end all active CommandExecutor instances and call `process.exit()`
|
|
65
|
+
* (which should be mocked by the test).
|
|
66
|
+
*/
|
|
67
|
+
static exitAllForTests(params: CommandExitParams): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Get a list of the commands that are running, including their arguments.
|
|
70
|
+
*/
|
|
71
|
+
static getRunningCommands(): string[];
|
|
53
72
|
constructor(params: CommandExecutorParams<TOptions>);
|
|
54
73
|
/**
|
|
55
|
-
* Run the command, including handling for restarts.
|
|
74
|
+
* Run the command, including handling for restarts. This should only be called once per instance,
|
|
75
|
+
* immediately after the constructor (since constructors can't be async).
|
|
56
76
|
*/
|
|
57
77
|
execute(): Promise<void>;
|
|
58
78
|
/**
|
|
59
79
|
* Execute a single iteration of the command.
|
|
80
|
+
* @returns true if a restart is needed
|
|
60
81
|
*/
|
|
61
82
|
private _executeOnce;
|
|
62
83
|
/**
|
|
@@ -67,11 +88,18 @@ export declare class CommandExecutor<TOptions extends SharedOptions> {
|
|
|
67
88
|
/** Translate certain CLI options into options for `readConfig()`. */
|
|
68
89
|
private _getConfigOptionsFromCliOptions;
|
|
69
90
|
private _initTelemetry;
|
|
70
|
-
|
|
91
|
+
private _sigintHandler;
|
|
92
|
+
private _uncaughtExceptionHandler;
|
|
93
|
+
private _unexpectedErrorHandler;
|
|
71
94
|
/**
|
|
72
95
|
* Exit function called with the result returned by the command's execute function,
|
|
73
96
|
* or manually via `CommandExecutor.exitAll()` in tests.
|
|
97
|
+
*
|
|
98
|
+
* Except in tests, execution can be assumed to have stopped after this is called.
|
|
99
|
+
* (In tests, `process.exit` is probably mocked to throw.)
|
|
74
100
|
*/
|
|
75
|
-
|
|
101
|
+
private _exit;
|
|
102
|
+
/** Call the mocked or real `process.exit()` function */
|
|
103
|
+
private _callProcessExit;
|
|
76
104
|
}
|
|
77
105
|
//# sourceMappingURL=CommandExecutor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandExecutor.d.ts","sourceRoot":"","sources":["../../src/utilities/CommandExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAe9D,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAqB,MAAM,2BAA2B,CAAC;AACrG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAQ7E,MAAM,WAAW,qBAAqB,CAAC,QAAQ,SAAS,aAAa;IACnE,iCAAiC;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf,2CAA2C;IAC3C,OAAO,EAAE,QAAQ,CAAC;IAElB,uCAAuC;IACvC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEjC,0CAA0C;IAC1C,cAAc,EAAE,cAAc,CAAC;IAE/B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;;OAQG;IACH,gBAAgB,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAEnD;;;OAGG;IACH,oBAAoB,EAChB,CAAC,CACC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC,CAAC,KAC3D,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,GAAG,SAAS,CAAC,GAC9D,SAAS,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"CommandExecutor.d.ts","sourceRoot":"","sources":["../../src/utilities/CommandExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAe9D,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAqB,MAAM,2BAA2B,CAAC;AACrG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAI/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAQ7E,MAAM,WAAW,qBAAqB,CAAC,QAAQ,SAAS,aAAa;IACnE,iCAAiC;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf,2CAA2C;IAC3C,OAAO,EAAE,QAAQ,CAAC;IAElB,uCAAuC;IACvC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEjC,0CAA0C;IAC1C,cAAc,EAAE,cAAc,CAAC;IAE/B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;;OAQG;IACH,gBAAgB,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAEnD;;;OAGG;IACH,oBAAoB,EAChB,CAAC,CACC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC,CAAC,KAC3D,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,GAAG,SAAS,CAAC,GAC9D,SAAS,CAAC;CACf;AAUD;;GAEG;AACH,qBAAa,eAAe,CAAC,QAAQ,SAAS,aAAa;IACzD,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,iBAAiB,CAAmC;IAC5D,OAAO,CAAC,qBAAqB,CAA0D;IACvF,OAAO,CAAC,SAAS,CAAe;IAChC,kFAAkF;IAClF,OAAO,CAAC,mBAAmB,CAAqB;IAChD,sDAAsD;IACtD,OAAO,CAAC,oBAAoB,CAAqB;IACjD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,sBAAsB,CAAC,CAAe;IAE9C,gFAAgF;IAEhF,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAmC;IAClE,kEAAkE;IAClE,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAkC;IAEjE;;;OAGG;WACW,uBAAuB,CAAC,QAAQ,EAAE,OAAO,OAAO,CAAC,IAAI,GAAG,SAAS,GAAG,IAAI;IAItF;;;OAGG;WACiB,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7E;;OAEG;WACW,kBAAkB,IAAI,MAAM,EAAE;gBAMhC,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC;IA0DnD;;;OAGG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBrC;;;OAGG;YACW,YAAY;IA4E1B;;;OAGG;YACW,mBAAmB;IAoGjC,qEAAqE;IACrE,OAAO,CAAC,+BAA+B;YAgBzB,cAAc;IAkD5B,OAAO,CAAC,cAAc,CAgBpB;IAEF,OAAO,CAAC,yBAAyB,CAO/B;IAEF,OAAO,CAAC,uBAAuB,CAI7B;IAEF;;;;;;OAMG;YACW,KAAK;IA6BnB,wDAAwD;IACxD,OAAO,CAAC,gBAAgB;CAGzB"}
|
|
@@ -11,10 +11,11 @@ import { TaskRunner } from '@ms-cloudpack/api-server';
|
|
|
11
11
|
import { readLocalConfigs } from './readLocalConfigs.js';
|
|
12
12
|
import { readRemoteConfigs } from './readRemoteConfigs.js';
|
|
13
13
|
import { getCliStartTime } from './getCliStartTime.js';
|
|
14
|
+
// eslint-disable-next-line no-restricted-properties -- this is the central handler
|
|
15
|
+
const realProcessExit = process.exit.bind(process);
|
|
14
16
|
/**
|
|
15
17
|
* This class manages orchestration and shared state while executing a command.
|
|
16
18
|
*/
|
|
17
|
-
// 'app' is an optional reused option
|
|
18
19
|
export class CommandExecutor {
|
|
19
20
|
_options;
|
|
20
21
|
_execute;
|
|
@@ -23,22 +24,43 @@ export class CommandExecutor {
|
|
|
23
24
|
_discoverAppPaths;
|
|
24
25
|
_applyOptionsToConfig;
|
|
25
26
|
_reporter;
|
|
27
|
+
/** Items which should be disposed before a restart, as well as at process exit */
|
|
26
28
|
_autoDisposableList;
|
|
29
|
+
/** Items which should be disposed before exit only */
|
|
30
|
+
_finalDisposableList;
|
|
27
31
|
_hasCalledExit = false;
|
|
28
32
|
_args;
|
|
29
33
|
_sigintCount = 0;
|
|
30
34
|
_onInterrupt;
|
|
31
35
|
_getMessageOnInterrupt;
|
|
36
|
+
/** Active `CommandExecutor` instances. In tests, there may be more than one. */
|
|
32
37
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- options type isn't used
|
|
33
38
|
static _activeInstances = new Set();
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
/** Mock implementation of `process.exit` for testing purposes. */
|
|
40
|
+
static _mockProcessExit;
|
|
41
|
+
/**
|
|
42
|
+
* Set a mock `process.exit()` implementation for tests, to handle cases where the command would
|
|
43
|
+
* call `process.exit()`.
|
|
44
|
+
*/
|
|
45
|
+
static mockProcessExitForTests(mockImpl) {
|
|
46
|
+
CommandExecutor._mockProcessExit = mockImpl;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* For testing use only: end all active CommandExecutor instances and call `process.exit()`
|
|
50
|
+
* (which should be mocked by the test).
|
|
51
|
+
*/
|
|
52
|
+
static async exitAllForTests(params) {
|
|
36
53
|
for (const instance of CommandExecutor._activeInstances) {
|
|
37
54
|
await instance._exit(params);
|
|
38
|
-
process.off('SIGINT', instance._sigintHandler);
|
|
39
55
|
}
|
|
40
56
|
CommandExecutor._activeInstances = new Set();
|
|
41
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Get a list of the commands that are running, including their arguments.
|
|
60
|
+
*/
|
|
61
|
+
static getRunningCommands() {
|
|
62
|
+
return Array.from(CommandExecutor._activeInstances).map((instance) => [instance._verb, ...instance._args].join(' '));
|
|
63
|
+
}
|
|
42
64
|
constructor(params) {
|
|
43
65
|
this._args = params.args;
|
|
44
66
|
this._options = params.options;
|
|
@@ -47,19 +69,54 @@ export class CommandExecutor {
|
|
|
47
69
|
this._verb = params.verb;
|
|
48
70
|
this._discoverAppPaths = params.discoverAppPaths;
|
|
49
71
|
this._applyOptionsToConfig = params.applyOptionsToConfig;
|
|
50
|
-
this._reporter = new TaskReporter();
|
|
51
72
|
this._autoDisposableList = new AutoDisposableList();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// This has to be a separate method because constructors can't be async.
|
|
57
|
-
async execute() {
|
|
73
|
+
this._finalDisposableList = new AutoDisposableList();
|
|
74
|
+
this._finalDisposableList.add(this._autoDisposableList);
|
|
75
|
+
this._reporter = new TaskReporter();
|
|
76
|
+
this._finalDisposableList.add(this._reporter);
|
|
58
77
|
CommandExecutor._activeInstances.add(this);
|
|
59
|
-
|
|
78
|
+
this._finalDisposableList.add({
|
|
79
|
+
dispose: () => {
|
|
80
|
+
CommandExecutor._activeInstances.delete(this);
|
|
81
|
+
// Command event listeners are currently only removed on final disposal since the start tests rely on
|
|
82
|
+
// a 'ready' event listener carrying over across restarts.
|
|
83
|
+
this._programOptions.commandEvents.removeAllListeners();
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
// Handle SIGINT (Ctrl+C) and unhandled errors. These must be removed in _exit.
|
|
87
|
+
// (Skip in tests to avoid interfering with test framework handling.)
|
|
60
88
|
if (!environmentInfo.isJest) {
|
|
61
89
|
process.on('SIGINT', this._sigintHandler);
|
|
90
|
+
// This should also catch unhandled promise rejections
|
|
91
|
+
process.on('uncaughtException', this._uncaughtExceptionHandler);
|
|
92
|
+
process.on('error', this._unexpectedErrorHandler);
|
|
93
|
+
// Also override process.exit in case some code calls it directly.
|
|
94
|
+
// eslint-disable-next-line no-restricted-properties -- central handling code
|
|
95
|
+
process.exit = ((code) => {
|
|
96
|
+
// Get the call stack to display
|
|
97
|
+
const error = new Error(`Unexpected process.exit(${code ?? ''}) call`);
|
|
98
|
+
void this._exit({
|
|
99
|
+
message: error.stack || '',
|
|
100
|
+
hasErrors: true,
|
|
101
|
+
exitCode: 1,
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
this._finalDisposableList.add({
|
|
105
|
+
dispose: () => {
|
|
106
|
+
process.off('SIGINT', this._sigintHandler);
|
|
107
|
+
process.off('uncaughtException', this._uncaughtExceptionHandler);
|
|
108
|
+
process.off('error', this._unexpectedErrorHandler);
|
|
109
|
+
// eslint-disable-next-line no-restricted-properties
|
|
110
|
+
process.exit = realProcessExit;
|
|
111
|
+
},
|
|
112
|
+
});
|
|
62
113
|
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Run the command, including handling for restarts. This should only be called once per instance,
|
|
117
|
+
* immediately after the constructor (since constructors can't be async).
|
|
118
|
+
*/
|
|
119
|
+
async execute() {
|
|
63
120
|
try {
|
|
64
121
|
let shouldRestart = false;
|
|
65
122
|
do {
|
|
@@ -80,11 +137,13 @@ export class CommandExecutor {
|
|
|
80
137
|
}
|
|
81
138
|
/**
|
|
82
139
|
* Execute a single iteration of the command.
|
|
140
|
+
* @returns true if a restart is needed
|
|
83
141
|
*/
|
|
84
142
|
async _executeOnce(isRestart) {
|
|
85
143
|
const contexts = await this._initializeContexts();
|
|
86
144
|
if (!Array.isArray(contexts)) {
|
|
87
|
-
|
|
145
|
+
await this._exit(contexts);
|
|
146
|
+
return false;
|
|
88
147
|
}
|
|
89
148
|
const spanName = `${this._verb.toUpperCase().replace(/ /g, '_')}_EXECUTE`;
|
|
90
149
|
const results = [];
|
|
@@ -96,10 +155,15 @@ export class CommandExecutor {
|
|
|
96
155
|
span.setAttribute('isInterrupted', true);
|
|
97
156
|
span.end();
|
|
98
157
|
};
|
|
158
|
+
const isMultiApp = contexts.length > 1;
|
|
159
|
+
if (isMultiApp) {
|
|
160
|
+
console.log();
|
|
161
|
+
console.log(`==== Starting ${this._verb} for ${context.appName} ====`);
|
|
162
|
+
}
|
|
99
163
|
return this._execute({
|
|
100
164
|
...context,
|
|
101
165
|
span,
|
|
102
|
-
isMultiApp
|
|
166
|
+
isMultiApp,
|
|
103
167
|
args: this._args,
|
|
104
168
|
options: this._options,
|
|
105
169
|
commandEvents: this._programOptions.commandEvents,
|
|
@@ -111,7 +175,8 @@ export class CommandExecutor {
|
|
|
111
175
|
});
|
|
112
176
|
});
|
|
113
177
|
if (result?.isInterrupted) {
|
|
114
|
-
|
|
178
|
+
await this._exit(result);
|
|
179
|
+
return false;
|
|
115
180
|
}
|
|
116
181
|
if (result) {
|
|
117
182
|
results.push(result);
|
|
@@ -133,7 +198,7 @@ export class CommandExecutor {
|
|
|
133
198
|
}
|
|
134
199
|
else if (results.length) {
|
|
135
200
|
// If one or more apps returned a result, exit.
|
|
136
|
-
|
|
201
|
+
await this._exit({
|
|
137
202
|
message: results.map((r) => r.message).join('\n'),
|
|
138
203
|
hasErrors: results.some((r) => r.hasErrors),
|
|
139
204
|
// If any app returned a non-zero exit code, use that.
|
|
@@ -220,6 +285,7 @@ export class CommandExecutor {
|
|
|
220
285
|
const telemetryClient = await this._initTelemetry(name, config, telemetryApi);
|
|
221
286
|
contexts.push({
|
|
222
287
|
appPath,
|
|
288
|
+
appName: name,
|
|
223
289
|
cachePath: this._options.cachePath,
|
|
224
290
|
config,
|
|
225
291
|
reporter: this._reporter,
|
|
@@ -259,7 +325,7 @@ export class CommandExecutor {
|
|
|
259
325
|
.filter(([, value]) => value)
|
|
260
326
|
.map(([key]) => key);
|
|
261
327
|
if (enabledFeatureNames.length) {
|
|
262
|
-
console.log(`Enabled features: ${enabledFeatureNames.map((f) => yellow(f)).join(', ')}`);
|
|
328
|
+
console.log(`Enabled features for ${appName}: ${enabledFeatureNames.map((f) => yellow(f)).join(', ')}`);
|
|
263
329
|
}
|
|
264
330
|
const telemetryAttributes = {
|
|
265
331
|
verb: this._verb,
|
|
@@ -286,16 +352,31 @@ export class CommandExecutor {
|
|
|
286
352
|
console.debug('Forcing exit');
|
|
287
353
|
// We are forcing the process to exit.
|
|
288
354
|
// No clean-up is needed because user pressed Ctrl+C twice.
|
|
289
|
-
|
|
290
|
-
|
|
355
|
+
this._callProcessExit(1);
|
|
356
|
+
return;
|
|
291
357
|
}
|
|
292
358
|
this._onInterrupt?.();
|
|
293
359
|
// We are trying to exit gracefully.
|
|
294
360
|
void this._exit({ isInterrupted: true, message: '' });
|
|
295
361
|
};
|
|
362
|
+
_uncaughtExceptionHandler = (error, reason) => {
|
|
363
|
+
const errorType = reason === 'uncaughtException' ? 'Uncaught exception' : 'Unhandled promise rejection';
|
|
364
|
+
const message = `${errorType}: ${error.stack || error.message || String(error)}`;
|
|
365
|
+
// Go ahead and log the message in case the process exits before cleanup is complete
|
|
366
|
+
console.error(message);
|
|
367
|
+
void this._exit({ message, hasErrors: true, exitCode: 1 });
|
|
368
|
+
};
|
|
369
|
+
_unexpectedErrorHandler = (...args) => {
|
|
370
|
+
const err = new Error('Unexpected process error');
|
|
371
|
+
console.error(err.stack);
|
|
372
|
+
console.error('Error details:', ...args);
|
|
373
|
+
};
|
|
296
374
|
/**
|
|
297
375
|
* Exit function called with the result returned by the command's execute function,
|
|
298
376
|
* or manually via `CommandExecutor.exitAll()` in tests.
|
|
377
|
+
*
|
|
378
|
+
* Except in tests, execution can be assumed to have stopped after this is called.
|
|
379
|
+
* (In tests, `process.exit` is probably mocked to throw.)
|
|
299
380
|
*/
|
|
300
381
|
async _exit(params) {
|
|
301
382
|
const { hasErrors = this._reporter.hasErrors(), exitCode = hasErrors ? 1 : 0 } = params;
|
|
@@ -312,21 +393,19 @@ export class CommandExecutor {
|
|
|
312
393
|
}
|
|
313
394
|
else {
|
|
314
395
|
this._hasCalledExit = true;
|
|
315
|
-
// Dispose all registered disposables.
|
|
316
|
-
await this._autoDisposableList.dispose();
|
|
317
|
-
// Remove all event listeners. Currently this is only done on final disposal because one of
|
|
318
|
-
// the start tests relies on a 'ready' event listener carrying over across restarts.
|
|
319
|
-
this._programOptions.commandEvents.removeAllListeners();
|
|
320
396
|
// Show the summary message (this will throw if called twice).
|
|
321
|
-
|
|
397
|
+
this._reporter.complete({
|
|
322
398
|
summary: hasErrors ? red(message) : message,
|
|
323
399
|
showHelp: exitCode !== 0,
|
|
324
400
|
});
|
|
401
|
+
// Dispose all resources
|
|
402
|
+
await this._finalDisposableList.dispose();
|
|
325
403
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
404
|
+
this._callProcessExit(exitCode);
|
|
405
|
+
}
|
|
406
|
+
/** Call the mocked or real `process.exit()` function */
|
|
407
|
+
_callProcessExit(exitCode) {
|
|
408
|
+
(CommandExecutor._mockProcessExit || realProcessExit)(exitCode);
|
|
330
409
|
}
|
|
331
410
|
}
|
|
332
411
|
//# sourceMappingURL=CommandExecutor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandExecutor.js","sourceRoot":"","sources":["../../src/utilities/CommandExecutor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,IAAI,EACJ,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,GAAG,EACH,oBAAoB,EACpB,MAAM,GACP,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAA2C,MAAM,yBAAyB,CAAC;AAClG,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAoC,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAwCvD;;GAEG;AACH,qCAAqC;AACrC,MAAM,OAAO,eAAe;IAClB,QAAQ,CAAW;IACnB,QAAQ,CAA0B;IAClC,eAAe,CAAiB;IAChC,KAAK,CAAS;IACd,iBAAiB,CAAmC;IACpD,qBAAqB,CAA0D;IAC/E,SAAS,CAAe;IACxB,mBAAmB,CAAqB;IACxC,cAAc,GAAG,KAAK,CAAC;IACvB,KAAK,CAAW;IAChB,YAAY,GAAG,CAAC,CAAC;IACjB,YAAY,CAAc;IAC1B,sBAAsB,CAAgB;IAC9C,yFAAyF;IACjF,MAAM,CAAC,gBAAgB,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE3D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAyB;QACnD,4FAA4F;QAC5F,KAAK,MAAM,QAAQ,IAAI,eAAe,CAAC,gBAAgB,EAAE,CAAC;YACxD,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;QACjD,CAAC;QACD,eAAe,CAAC,gBAAgB,GAAG,IAAI,GAAG,EAAE,CAAC;IAC/C,CAAC;IAED,YAAY,MAAuC;QACjD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,gBAAgB,CAAC;QACjD,IAAI,CAAC,qBAAqB,GAAG,MAAM,CAAC,oBAAoB,CAAC;QACzD,IAAI,CAAC,SAAS,GAAG,IAAI,YAAY,EAAE,CAAC;QACpC,IAAI,CAAC,mBAAmB,GAAG,IAAI,kBAAkB,EAAE,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,wEAAwE;IACjE,KAAK,CAAC,OAAO;QAClB,eAAe,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,qCAAqC;QACrC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;YAC5B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC;YACH,IAAI,aAAa,GAAG,KAAK,CAAC;YAC1B,GAAG,CAAC;gBACF,aAAa,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;YACzD,CAAC,QAAQ,aAAa,EAAE;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kEAAkE;YAClE,MAAM,GAAG,GAAG,KAAoC,CAAC;YACjD,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU;gBAC5B,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,wCAAwC;gBACtD,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,wCAAwC;YAEvF,MAAM,IAAI,CAAC,KAAK,CAAC;gBACf,SAAS,EAAE,IAAI;gBACf,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CAAC,SAAkB;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAElD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC;QAC1E,MAAM,OAAO,GAAwB,EAAE,CAAC;QAExC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,4DAA4D;YAC5D,gEAAgE;YAChE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAC3F,IAAI,CAAC,YAAY,GAAG,GAAG,EAAE;oBACvB,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;oBACzC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACb,CAAC,CAAC;gBAEF,OAAO,IAAI,CAAC,QAAQ,CAAC;oBACnB,GAAG,OAAO;oBACV,IAAI;oBACJ,UAAU,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC;oBAC/B,IAAI,EAAE,IAAI,CAAC,KAAK;oBAChB,OAAO,EAAE,IAAI,CAAC,QAAQ;oBACtB,aAAa,EAAE,IAAI,CAAC,eAAe,CAAC,aAAa;oBACjD,SAAS;oBACT,WAAW,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC;oBACrE,0BAA0B,EAAE,CAAC,UAAU,EAAE,EAAE;wBACzC,IAAI,CAAC,sBAAsB,GAAG,UAAU,CAAC;oBAC3C,CAAC;iBACF,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YACH,IAAI,MAAM,EAAE,aAAa,EAAE,CAAC;gBAC1B,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,gFAAgF;gBAChF,sDAAsD;gBACtD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAChC,CAAC;QAED,qEAAqE;QACrE,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAErD,IAAI,aAAa,EAAE,CAAC;YAClB,sCAAsC;YACtC,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC;YACzC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAE9C,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1B,+CAA+C;YAC/C,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC;gBACtB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBACjD,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC3C,sDAAsD;gBACtD,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,QAAQ;aAC/D,CAAC,CAAC;QACL,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,mBAAmB;QAC/B,IAAI,QAAkB,CAAC;QAEvB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,4DAA4D;YAC5D,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,QAA2D,CAAC;YACxF,MAAM,cAAc,GAClB,IAAI,CAAC,iBAAiB,KAAK,QAAQ;gBACjC,CAAC,CAAC,MAAM,sBAAsB,CAAC;oBAC3B,OAAO,EAAE;wBACP,KAAK;wBACL,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS;wBAClC,UAAU,EAAE,GAAG;qBAChB;oBACD,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE;iBACtC,CAAC;gBACJ,CAAC,CAAC,MAAM,qBAAqB,CAAC;oBAC1B,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG;oBAC7B,QAAQ,EAAE,IAAI,CAAC,iBAAiB;oBAChC,UAAU,EAAE,GAAG;iBAChB,CAAC,CAAC;YACT,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnC,iFAAiF;gBACjF,OAAO,cAAc,CAAC;YACxB,CAAC;YACD,QAAQ,GAAG,cAAc,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,mBAAmB;YACnB,QAAQ,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QACxC,CAAC;QAED,6FAA6F;QAC7F,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;QAEpC,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,KAAK,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAC9F,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE;YACzC,GAAG,IAAI,CAAC,+BAA+B,EAAE;YACzC,qBAAqB,EAAE,IAAI;SAC5B,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,IAAI,GAAG,CAC1B,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;aACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;aAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAa,CACzC,CAAC;QAEF,yDAAyD;QACzD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;YACxB,WAAW,EAAE,WAAW;YACxB,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,OAAO;YACrC,WAAW,EAAE,GAAG,EAAE,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG;YACpF,WAAW,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YACzC,aAAa,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK;YACnC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO;YAChC,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG;YAC7B,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK;gBACrB,CAAC,CAAC,kBAAkB;gBACpB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO;oBACrB,CAAC,CAAC,oBAAoB;oBACtB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK;wBACnB,CAAC,CAAC,eAAe;wBACjB,CAAC,CAAC,oBAAoB,CAAC;SAC9B,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/F,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,YAAY,GAAG,cAAc,CAAC;YAClC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;YAC3C,QAAQ;YACR,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;QAEH,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAEzE,MAAM,QAAQ,GAAwB,EAAE,CAAC;QAEzC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YAChC,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAc,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;YACnF,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,GAAG,UAAU,IAAI,EAAE,CAAC;YAE3D,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;YAE9E,QAAQ,CAAC,IAAI,CAAC;gBACZ,OAAO;gBACP,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS;gBAClC,MAAM;gBACN,QAAQ,EAAE,IAAI,CAAC,SAAS;gBACxB,eAAe;gBACf,UAAU;aACX,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,qEAAqE;IAC7D,+BAA+B;QACrC,+DAA+D;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAkD,CAAC;QACxE,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,cAAc,EAAE,OAAO,CAAC,MAAM;YAC9B,yFAAyF;YACzF,oEAAoE;YACpE,oBAAoB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;YAC9F,aAAa,EAAE,OAAO,CAAC,QAAQ;YAC/B,gBAAgB,EAAE,OAAO,CAAC,MAAM;YAChC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;SACvD,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,cAAc,CAC1B,OAA2B,EAC3B,MAAuB,EACvB,YAA0B;QAE1B,qCAAqC;QACrC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAEpC,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC;QAE5C,MAAM,gBAAgB,GACpB,IAAI,CAAC,eAAe,CAAC,gBAAgB,IAAI,eAAe,CAAC,MAAM;YAC7D,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,gBAAgB,IAAI,eAAe,CAAC,SAAS,CAAC,yBAAyB,CAAC;QAEhG,MAAM,eAAe,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAE1E,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;QAEtF,MAAM,eAAe,CAAC,MAAM,CAAC,eAAe,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;YACrF,MAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;iBAC9D,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC;iBAC5B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;YAEvB,IAAI,mBAAmB,CAAC,MAAM,EAAE,CAAC;gBAC/B,OAAO,CAAC,GAAG,CAAC,qBAAqB,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC3F,CAAC;YAED,MAAM,mBAAmB,GAAG;gBAC1B,IAAI,EAAE,IAAI,CAAC,KAAK;gBAChB,SAAS,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;gBACjD,WAAW,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO;gBAChG,OAAO,EAAE,OAAO,IAAI,WAAW;gBAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,QAAQ,EAAE,mBAAmB;gBAC7B,qBAAqB,EAAE,eAAe,CAAC,SAAS,CAAC,8BAA8B;gBAC/E,gCAAgC;gBAChC,GAAG,eAAe,CAAC,GAAG;aACvB,CAAC;YAEF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBAC/D,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,eAAe,CAAC;IACzB,CAAC;IAES,cAAc,GAAG,GAAS,EAAE;QACpC,IAAI,CAAC,YAAY,EAAE,CAAC;QAEpB,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAE9B,sCAAsC;YACtC,2DAA2D;YAC3D,yEAAyE;YACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QAEtB,oCAAoC;QACpC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC;IAEF;;;OAGG;IACO,KAAK,CAAC,KAAK,CAAC,MAAyB;QAC7C,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC;QACxF,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,IAAI,qBAAqB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QAEjH,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,mEAAmE;YACnE,8FAA8F;YAC9F,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;qBACxC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,GAAG,CAAC;qBAC1C,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,0DAA0D,YAAY,GAAG,CAAC,CAAC;YAC1F,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAE3B,sCAAsC;YACtC,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC;YAEzC,2FAA2F;YAC3F,oFAAoF;YACpF,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,kBAAkB,EAAE,CAAC;YAExD,8DAA8D;YAC9D,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;gBAC5B,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;gBAC3C,QAAQ,EAAE,QAAQ,KAAK,CAAC;aACzB,CAAC,CAAC;QACL,CAAC;QAED,eAAe,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAE3C,yEAAyE;QACzE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC","sourcesContent":["import type { ReadConfigOptions } from '@ms-cloudpack/config';\nimport type { CloudpackConfig, PackageJson } from '@ms-cloudpack/common-types';\nimport { readJson } from '@ms-cloudpack/json-utilities';\nimport {\n TaskReporter,\n bold,\n debugLoggingConfig,\n defaultLoggingConfig,\n noLoggingConfig,\n red,\n verboseLoggingConfig,\n yellow,\n} from '@ms-cloudpack/task-reporter';\nimport { startTelemetry, type TelemetryApi, type TelemetryClient } from '@ms-cloudpack/telemetry';\nimport path from 'path';\nimport type { CommandAction, CommandExitParams, AppCommandContext } from '../types/CommandAction.js';\nimport type { ProgramOptions } from '../types/ProgramOptions.js';\nimport type { SharedOptions } from '../types/SharedOptions.js';\nimport { AutoDisposableList } from './AutoDisposableList.js';\nimport { getVersion } from '@ms-cloudpack/package-utilities';\nimport { environmentInfo } from '@ms-cloudpack/environment';\nimport type { ReusedOptions } from '../types/ReusedOptions.js';\nimport type { AppPathDiscoveryMode } from '../types/AppPathDiscoveryMode.js';\nimport { discoverRemoteAppPaths } from './discoverRemoteAppPaths.js';\nimport { discoverLocalAppPaths } from './discoverLocalAppPaths.js';\nimport { TaskRunner } from '@ms-cloudpack/api-server';\nimport { readLocalConfigs, type InvalidCloudpackConfigError } from './readLocalConfigs.js';\nimport { readRemoteConfigs } from './readRemoteConfigs.js';\nimport { getCliStartTime } from './getCliStartTime.js';\n\nexport interface CommandExecutorParams<TOptions extends SharedOptions> {\n /** Command-specific arguments */\n args: string[];\n\n /** Command-specific and shared options. */\n options: TOptions;\n\n /** Function to execute the command. */\n execute: CommandAction<TOptions>;\n\n /** Shared program-level configuration. */\n programOptions: ProgramOptions;\n\n /** Verb being run, e.g. `bundle` or `cache clean`. */\n verb: string;\n\n /**\n * By default, the command will run against `cwd` (usually `process.cwd()`).\n * If this option is set, attempt to discover app path(s) instead.\n * (`cwd` will still be preferred if it has a `cloudpack.config.json`.)\n * See {@link AppPathDiscoveryMode} for details.\n *\n * Note that `isMultiApp` elsewhere will only be true if this is set to `'multi'` and\n * multiple apps are found.\n */\n discoverAppPaths: AppPathDiscoveryMode | undefined;\n\n /**\n * Apply any command-specific CLI options that need to be passed through to `readConfig`.\n * (Shared and reused options are applied automatically.)\n */\n applyOptionsToConfig:\n | ((\n options: Omit<TOptions, keyof (SharedOptions & ReusedOptions)>,\n ) => Pick<ReadConfigOptions, 'extraServerConfig'> | undefined)\n | undefined;\n}\n\n/**\n * This class manages orchestration and shared state while executing a command.\n */\n// 'app' is an optional reused option\nexport class CommandExecutor<TOptions extends SharedOptions> {\n private _options: TOptions;\n private _execute: CommandAction<TOptions>;\n private _programOptions: ProgramOptions;\n private _verb: string;\n private _discoverAppPaths: AppPathDiscoveryMode | undefined;\n private _applyOptionsToConfig: CommandExecutorParams<TOptions>['applyOptionsToConfig'];\n private _reporter: TaskReporter;\n private _autoDisposableList: AutoDisposableList;\n private _hasCalledExit = false;\n private _args: string[];\n private _sigintCount = 0;\n private _onInterrupt?: () => void;\n private _getMessageOnInterrupt?: () => string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- options type isn't used\n private static _activeInstances = new Set<CommandExecutor<any>>();\n\n public static async exitAll(params: CommandExitParams): Promise<void> {\n // There should only be one instance at a time, but we assume multiple instances for safety.\n for (const instance of CommandExecutor._activeInstances) {\n await instance._exit(params);\n process.off('SIGINT', instance._sigintHandler);\n }\n CommandExecutor._activeInstances = new Set();\n }\n\n constructor(params: CommandExecutorParams<TOptions>) {\n this._args = params.args;\n this._options = params.options;\n this._execute = params.execute;\n this._programOptions = params.programOptions;\n this._verb = params.verb;\n this._discoverAppPaths = params.discoverAppPaths;\n this._applyOptionsToConfig = params.applyOptionsToConfig;\n this._reporter = new TaskReporter();\n this._autoDisposableList = new AutoDisposableList();\n }\n\n /**\n * Run the command, including handling for restarts.\n */\n // This has to be a separate method because constructors can't be async.\n public async execute(): Promise<void> {\n CommandExecutor._activeInstances.add(this);\n // Handle SIGINT (Ctrl+C) gracefully.\n if (!environmentInfo.isJest) {\n process.on('SIGINT', this._sigintHandler);\n }\n\n try {\n let shouldRestart = false;\n do {\n shouldRestart = await this._executeOnce(shouldRestart);\n } while (shouldRestart);\n } catch (error) {\n // If an error occurs, exit the process with a non-zero exit code.\n const err = error as InvalidCloudpackConfigError;\n const message = err.isExpected\n ? err.message // Only show message for expected errors\n : err.stack || err.message || String(error); // Show full stack for unexpected errors\n\n await this._exit({\n hasErrors: true,\n message,\n });\n }\n }\n\n /**\n * Execute a single iteration of the command.\n */\n private async _executeOnce(isRestart: boolean): Promise<boolean> {\n const contexts = await this._initializeContexts();\n\n if (!Array.isArray(contexts)) {\n return await this._exit(contexts);\n }\n\n const spanName = `${this._verb.toUpperCase().replace(/ /g, '_')}_EXECUTE`;\n const results: CommandExitParams[] = [];\n\n for (const context of contexts) {\n // Call the execute function which is the real command logic\n // (ie: real init command logic, real start command logic, etc.)\n const result = await context.telemetryClient.tracer.startActiveSpan(spanName, async (span) => {\n this._onInterrupt = () => {\n span.setAttribute('isInterrupted', true);\n span.end();\n };\n\n return this._execute({\n ...context,\n span,\n isMultiApp: contexts.length > 1,\n args: this._args,\n options: this._options,\n commandEvents: this._programOptions.commandEvents,\n isRestart,\n autoDispose: (disposable) => this._autoDisposableList.add(disposable),\n setInterruptMessageHandler: (getMessage) => {\n this._getMessageOnInterrupt = getMessage;\n },\n });\n });\n if (result?.isInterrupted) {\n return await this._exit(result);\n }\n if (result) {\n results.push(result);\n } else {\n // If the command returned null, this means it should keep running (e.g. start).\n // We disallow returning undefined to avoid accidents.\n throw new Error('Command executor must return exit options or null');\n }\n this._onInterrupt = undefined;\n }\n\n // Determine whether a command requested a restart in this iteration.\n const shouldRestart = results.some((r) => r.restart);\n\n if (shouldRestart) {\n // Dispose all registered disposables.\n await this._autoDisposableList.dispose();\n this._reporter.reset(true /* clearOutputs */);\n\n console.warn(results.map((r) => r.message).join('\\n'));\n } else if (results.length) {\n // If one or more apps returned a result, exit.\n return await this._exit({\n message: results.map((r) => r.message).join('\\n'),\n hasErrors: results.some((r) => r.hasErrors),\n // If any app returned a non-zero exit code, use that.\n exitCode: results.find(({ exitCode }) => !!exitCode)?.exitCode,\n });\n }\n\n return shouldRestart;\n }\n\n /**\n * Determine the app paths and initialize the context for each app.\n * @returns Context(s), or an exit options object if there was an error. (might also throw on error)\n */\n private async _initializeContexts(): Promise<AppCommandContext[] | CommandExitParams> {\n let appPaths: string[];\n\n if (this._discoverAppPaths) {\n // Search for cloudpack configs to determine the app path(s)\n const { app, login } = this._options as unknown as Pick<ReusedOptions, 'app' | 'login'>;\n const appPathsResult =\n this._discoverAppPaths === 'remote'\n ? await discoverRemoteAppPaths({\n options: {\n login,\n cachePath: this._options.cachePath,\n desiredApp: app,\n },\n context: { reporter: this._reporter },\n })\n : await discoverLocalAppPaths({\n cwd: this._programOptions.cwd,\n discover: this._discoverAppPaths,\n desiredApp: app,\n });\n if (!Array.isArray(appPathsResult)) {\n // This means there was an error (or the user cancelled) while getting app paths.\n return appPathsResult;\n }\n appPaths = appPathsResult;\n } else {\n // Just use the cwd\n appPaths = [this._programOptions.cwd];\n }\n\n // The task runner is shared between all apps so that task results can potentially be reused.\n const taskRunner = new TaskRunner();\n\n const readConfig = this._discoverAppPaths === 'remote' ? readRemoteConfigs : readLocalConfigs;\n const configs = await readConfig(appPaths, {\n ...this._getConfigOptionsFromCliOptions(),\n enableDefaultFeatures: true,\n });\n\n const helpMessages = new Set<string>(\n Object.values(configs)\n .filter((c) => c.helpMessage)\n .map((c) => c.helpMessage) as string[],\n );\n\n // Set reporter options and print the product info header\n this._reporter.setOptions({\n productName: 'Cloudpack',\n version: this._programOptions.version,\n description: () => `Running \"${bold(this._programOptions.argv.slice(2).join(' '))}\"`,\n helpMessage: [...helpMessages].join('\\n'),\n plainTextMode: !this._options.color,\n logFile: !!this._options.logFile,\n cwd: this._programOptions.cwd,\n ...(this._options.debug\n ? debugLoggingConfig\n : this._options.verbose\n ? verboseLoggingConfig\n : this._options.quiet\n ? noLoggingConfig\n : defaultLoggingConfig),\n });\n\n const logLevel = this._options.verbose ? 'VERBOSE' : this._options.debug ? 'DEBUG' : undefined;\n if (!this._options.debug) {\n this._reporter.ignoreLogMessage('ApplicationInsights:');\n }\n\n const telemetryApi = startTelemetry({\n productVersion: getVersion(import.meta.url),\n logLevel,\n serviceName: 'cli',\n });\n\n this._autoDisposableList.add({ dispose: () => telemetryApi.shutdown() });\n\n const contexts: AppCommandContext[] = [];\n\n for (const appPath of Object.keys(configs)) {\n const config = configs[appPath];\n const definition = await readJson<PackageJson>(path.join(appPath, 'package.json'));\n const { name = path.basename(appPath) } = definition || {};\n\n const telemetryClient = await this._initTelemetry(name, config, telemetryApi);\n\n contexts.push({\n appPath,\n cachePath: this._options.cachePath,\n config,\n reporter: this._reporter,\n telemetryClient,\n taskRunner,\n });\n }\n\n return contexts;\n }\n\n /** Translate certain CLI options into options for `readConfig()`. */\n private _getConfigOptionsFromCliOptions(): ReadConfigOptions {\n // These options don't exist for all commands, but that's fine.\n const options = this._options as Partial<ReusedOptions & SharedOptions>;\n return {\n mode: options.mode,\n logBundleInfo: options.logBundleInfo,\n configFileName: options.config,\n // Handle --bundler by passing it as a universal package override, which will be appended\n // to any user-provided packageSettings so that it takes precedence.\n extraPackageSettings: options.bundler ? [{ match: '*', bundler: options.bundler }] : undefined,\n extraFeatures: options.features,\n extraDefineFlags: options.define,\n ...(this._applyOptionsToConfig?.(this._options) || {}),\n };\n }\n\n private async _initTelemetry(\n appName: string | undefined,\n config: CloudpackConfig,\n telemetryApi: TelemetryApi,\n ): Promise<TelemetryClient> {\n // Mark the start time for telemetry.\n const startTime = performance.now();\n\n const programOptions = this._programOptions;\n\n const connectionString =\n this._programOptions.disableTelemetry || environmentInfo.isJest\n ? undefined\n : config.telemetry?.connectionString || environmentInfo.cloudpack.telemetryConnectionString;\n\n const telemetryClient = await telemetryApi.createClient(connectionString);\n\n telemetryClient.tracer.startSpan('CLI_ENTRY', { startTime: getCliStartTime() }).end();\n\n await telemetryClient.tracer.startActiveSpan('INIT_TELEMETRY', { startTime }, (span) => {\n const enabledFeatureNames = Object.entries(config.features || {})\n .filter(([, value]) => value)\n .map(([key]) => key);\n\n if (enabledFeatureNames.length) {\n console.log(`Enabled features: ${enabledFeatureNames.map((f) => yellow(f)).join(', ')}`);\n }\n\n const telemetryAttributes = {\n verb: this._verb,\n arguments: programOptions.argv.slice(3).join(' '),\n environment: environmentInfo.isCI ? 'ci' : environmentInfo.isCodespaces ? 'codespaces' : 'local',\n appName: appName || '<unknown>',\n mode: config.mode,\n features: enabledFeatureNames,\n externalCorrelationId: environmentInfo.cloudpack.telemetryExternalCorrelationId,\n // Azure DevOps build attributes\n ...environmentInfo.ado,\n };\n\n for (const [key, value] of Object.entries(telemetryAttributes)) {\n if (value) {\n span.setAttribute(key, value);\n }\n }\n });\n\n return telemetryClient;\n }\n\n protected _sigintHandler = (): void => {\n this._sigintCount++;\n\n if (this._sigintCount > 1) {\n console.debug('Forcing exit');\n\n // We are forcing the process to exit.\n // No clean-up is needed because user pressed Ctrl+C twice.\n // eslint-disable-next-line no-restricted-properties -- top-level cleanup\n process.exit(1);\n }\n\n this._onInterrupt?.();\n\n // We are trying to exit gracefully.\n void this._exit({ isInterrupted: true, message: '' });\n };\n\n /**\n * Exit function called with the result returned by the command's execute function,\n * or manually via `CommandExecutor.exitAll()` in tests.\n */\n protected async _exit(params: CommandExitParams): Promise<never> {\n const { hasErrors = this._reporter.hasErrors(), exitCode = hasErrors ? 1 : 0 } = params;\n const message = params.isInterrupted ? this._getMessageOnInterrupt?.() || 'Interrupted by user' : params.message;\n\n if (this._hasCalledExit) {\n // Skip most of the operations if exit() was called multiple times.\n // But only use the error message if not in a test, due to the way we're mocking process.exit.\n if (!environmentInfo.isJest) {\n const prettyParams = Object.entries(params)\n .map(([key, value]) => `${key}=\"${value}\"`)\n .join(', ');\n console.warn(`exit() was called multiple times. This call's options: ${prettyParams}.`);\n }\n } else {\n this._hasCalledExit = true;\n\n // Dispose all registered disposables.\n await this._autoDisposableList.dispose();\n\n // Remove all event listeners. Currently this is only done on final disposal because one of\n // the start tests relies on a 'ready' event listener carrying over across restarts.\n this._programOptions.commandEvents.removeAllListeners();\n\n // Show the summary message (this will throw if called twice).\n await this._reporter.complete({\n summary: hasErrors ? red(message) : message,\n showHelp: exitCode !== 0,\n });\n }\n\n CommandExecutor._activeInstances.delete(this);\n process.off('SIGINT', this._sigintHandler);\n\n // eslint-disable-next-line no-restricted-properties -- top-level cleanup\n process.exit(exitCode);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CommandExecutor.js","sourceRoot":"","sources":["../../src/utilities/CommandExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReadConfigOptions } from '@ms-cloudpack/config';\nimport type { CloudpackConfig, PackageJson } from '@ms-cloudpack/common-types';\nimport { readJson } from '@ms-cloudpack/json-utilities';\nimport {\n TaskReporter,\n bold,\n debugLoggingConfig,\n defaultLoggingConfig,\n noLoggingConfig,\n red,\n verboseLoggingConfig,\n yellow,\n} from '@ms-cloudpack/task-reporter';\nimport { startTelemetry, type TelemetryApi, type TelemetryClient } from '@ms-cloudpack/telemetry';\nimport path from 'path';\nimport type { CommandAction, CommandExitParams, AppCommandContext } from '../types/CommandAction.js';\nimport type { ProgramOptions } from '../types/ProgramOptions.js';\nimport type { SharedOptions } from '../types/SharedOptions.js';\nimport { AutoDisposableList } from './AutoDisposableList.js';\nimport { getVersion } from '@ms-cloudpack/package-utilities';\nimport { environmentInfo } from '@ms-cloudpack/environment';\nimport type { ReusedOptions } from '../types/ReusedOptions.js';\nimport type { AppPathDiscoveryMode } from '../types/AppPathDiscoveryMode.js';\nimport { discoverRemoteAppPaths } from './discoverRemoteAppPaths.js';\nimport { discoverLocalAppPaths } from './discoverLocalAppPaths.js';\nimport { TaskRunner } from '@ms-cloudpack/api-server';\nimport { readLocalConfigs, type InvalidCloudpackConfigError } from './readLocalConfigs.js';\nimport { readRemoteConfigs } from './readRemoteConfigs.js';\nimport { getCliStartTime } from './getCliStartTime.js';\n\nexport interface CommandExecutorParams<TOptions extends SharedOptions> {\n /** Command-specific arguments */\n args: string[];\n\n /** Command-specific and shared options. */\n options: TOptions;\n\n /** Function to execute the command. */\n execute: CommandAction<TOptions>;\n\n /** Shared program-level configuration. */\n programOptions: ProgramOptions;\n\n /** Verb being run, e.g. `bundle` or `cache clean`. */\n verb: string;\n\n /**\n * By default, the command will run against `cwd` (usually `process.cwd()`).\n * If this option is set, attempt to discover app path(s) instead.\n * (`cwd` will still be preferred if it has a `cloudpack.config.json`.)\n * See {@link AppPathDiscoveryMode} for details.\n *\n * Note that `isMultiApp` elsewhere will only be true if this is set to `'multi'` and\n * multiple apps are found.\n */\n discoverAppPaths: AppPathDiscoveryMode | undefined;\n\n /**\n * Apply any command-specific CLI options that need to be passed through to `readConfig`.\n * (Shared and reused options are applied automatically.)\n */\n applyOptionsToConfig:\n | ((\n options: Omit<TOptions, keyof (SharedOptions & ReusedOptions)>,\n ) => Pick<ReadConfigOptions, 'extraServerConfig'> | undefined)\n | undefined;\n}\n\ninterface ExtendedAppCommandContext extends AppCommandContext {\n /** Name of the app package */\n appName: string;\n}\n\n// eslint-disable-next-line no-restricted-properties -- this is the central handler\nconst realProcessExit = process.exit.bind(process);\n\n/**\n * This class manages orchestration and shared state while executing a command.\n */\nexport class CommandExecutor<TOptions extends SharedOptions> {\n private _options: TOptions;\n private _execute: CommandAction<TOptions>;\n private _programOptions: ProgramOptions;\n private _verb: string;\n private _discoverAppPaths: AppPathDiscoveryMode | undefined;\n private _applyOptionsToConfig: CommandExecutorParams<TOptions>['applyOptionsToConfig'];\n private _reporter: TaskReporter;\n /** Items which should be disposed before a restart, as well as at process exit */\n private _autoDisposableList: AutoDisposableList;\n /** Items which should be disposed before exit only */\n private _finalDisposableList: AutoDisposableList;\n private _hasCalledExit = false;\n private _args: string[];\n private _sigintCount = 0;\n private _onInterrupt?: () => void;\n private _getMessageOnInterrupt?: () => string;\n\n /** Active `CommandExecutor` instances. In tests, there may be more than one. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- options type isn't used\n private static _activeInstances = new Set<CommandExecutor<any>>();\n /** Mock implementation of `process.exit` for testing purposes. */\n private static _mockProcessExit: typeof process.exit | undefined;\n\n /**\n * Set a mock `process.exit()` implementation for tests, to handle cases where the command would\n * call `process.exit()`.\n */\n public static mockProcessExitForTests(mockImpl: typeof process.exit | undefined): void {\n CommandExecutor._mockProcessExit = mockImpl;\n }\n\n /**\n * For testing use only: end all active CommandExecutor instances and call `process.exit()`\n * (which should be mocked by the test).\n */\n public static async exitAllForTests(params: CommandExitParams): Promise<void> {\n for (const instance of CommandExecutor._activeInstances) {\n await instance._exit(params);\n }\n CommandExecutor._activeInstances = new Set();\n }\n\n /**\n * Get a list of the commands that are running, including their arguments.\n */\n public static getRunningCommands(): string[] {\n return Array.from(CommandExecutor._activeInstances).map((instance) =>\n [instance._verb, ...instance._args].join(' '),\n );\n }\n\n constructor(params: CommandExecutorParams<TOptions>) {\n this._args = params.args;\n this._options = params.options;\n this._execute = params.execute;\n this._programOptions = params.programOptions;\n this._verb = params.verb;\n this._discoverAppPaths = params.discoverAppPaths;\n this._applyOptionsToConfig = params.applyOptionsToConfig;\n\n this._autoDisposableList = new AutoDisposableList();\n this._finalDisposableList = new AutoDisposableList();\n this._finalDisposableList.add(this._autoDisposableList);\n\n this._reporter = new TaskReporter();\n this._finalDisposableList.add(this._reporter);\n\n CommandExecutor._activeInstances.add(this);\n this._finalDisposableList.add({\n dispose: () => {\n CommandExecutor._activeInstances.delete(this);\n\n // Command event listeners are currently only removed on final disposal since the start tests rely on\n // a 'ready' event listener carrying over across restarts.\n this._programOptions.commandEvents.removeAllListeners();\n },\n });\n\n // Handle SIGINT (Ctrl+C) and unhandled errors. These must be removed in _exit.\n // (Skip in tests to avoid interfering with test framework handling.)\n if (!environmentInfo.isJest) {\n process.on('SIGINT', this._sigintHandler);\n // This should also catch unhandled promise rejections\n process.on('uncaughtException', this._uncaughtExceptionHandler);\n process.on('error', this._unexpectedErrorHandler);\n // Also override process.exit in case some code calls it directly.\n // eslint-disable-next-line no-restricted-properties -- central handling code\n process.exit = ((code) => {\n // Get the call stack to display\n const error = new Error(`Unexpected process.exit(${code ?? ''}) call`);\n void this._exit({\n message: error.stack || '',\n hasErrors: true,\n exitCode: 1,\n });\n }) as typeof process.exit;\n\n this._finalDisposableList.add({\n dispose: () => {\n process.off('SIGINT', this._sigintHandler);\n process.off('uncaughtException', this._uncaughtExceptionHandler);\n process.off('error', this._unexpectedErrorHandler);\n // eslint-disable-next-line no-restricted-properties\n process.exit = realProcessExit;\n },\n });\n }\n }\n\n /**\n * Run the command, including handling for restarts. This should only be called once per instance,\n * immediately after the constructor (since constructors can't be async).\n */\n public async execute(): Promise<void> {\n try {\n let shouldRestart = false;\n do {\n shouldRestart = await this._executeOnce(shouldRestart);\n } while (shouldRestart);\n } catch (error) {\n // If an error occurs, exit the process with a non-zero exit code.\n const err = error as InvalidCloudpackConfigError;\n const message = err.isExpected\n ? err.message // Only show message for expected errors\n : err.stack || err.message || String(error); // Show full stack for unexpected errors\n\n await this._exit({\n hasErrors: true,\n message,\n });\n }\n }\n\n /**\n * Execute a single iteration of the command.\n * @returns true if a restart is needed\n */\n private async _executeOnce(isRestart: boolean): Promise<boolean> {\n const contexts = await this._initializeContexts();\n\n if (!Array.isArray(contexts)) {\n await this._exit(contexts);\n return false;\n }\n\n const spanName = `${this._verb.toUpperCase().replace(/ /g, '_')}_EXECUTE`;\n const results: CommandExitParams[] = [];\n\n for (const context of contexts) {\n // Call the execute function which is the real command logic\n // (ie: real init command logic, real start command logic, etc.)\n const result = await context.telemetryClient.tracer.startActiveSpan(spanName, async (span) => {\n this._onInterrupt = () => {\n span.setAttribute('isInterrupted', true);\n span.end();\n };\n\n const isMultiApp = contexts.length > 1;\n if (isMultiApp) {\n console.log();\n console.log(`==== Starting ${this._verb} for ${context.appName} ====`);\n }\n\n return this._execute({\n ...context,\n span,\n isMultiApp,\n args: this._args,\n options: this._options,\n commandEvents: this._programOptions.commandEvents,\n isRestart,\n autoDispose: (disposable) => this._autoDisposableList.add(disposable),\n setInterruptMessageHandler: (getMessage) => {\n this._getMessageOnInterrupt = getMessage;\n },\n });\n });\n if (result?.isInterrupted) {\n await this._exit(result);\n return false;\n }\n if (result) {\n results.push(result);\n } else {\n // If the command returned null, this means it should keep running (e.g. start).\n // We disallow returning undefined to avoid accidents.\n throw new Error('Command executor must return exit options or null');\n }\n this._onInterrupt = undefined;\n }\n\n // Determine whether a command requested a restart in this iteration.\n const shouldRestart = results.some((r) => r.restart);\n\n if (shouldRestart) {\n // Dispose all registered disposables.\n await this._autoDisposableList.dispose();\n this._reporter.reset(true /* clearOutputs */);\n\n console.warn(results.map((r) => r.message).join('\\n'));\n } else if (results.length) {\n // If one or more apps returned a result, exit.\n await this._exit({\n message: results.map((r) => r.message).join('\\n'),\n hasErrors: results.some((r) => r.hasErrors),\n // If any app returned a non-zero exit code, use that.\n exitCode: results.find(({ exitCode }) => !!exitCode)?.exitCode,\n });\n }\n\n return shouldRestart;\n }\n\n /**\n * Determine the app paths and initialize the context for each app.\n * @returns Context(s), or an exit options object if there was an error. (might also throw on error)\n */\n private async _initializeContexts(): Promise<ExtendedAppCommandContext[] | CommandExitParams> {\n let appPaths: string[];\n\n if (this._discoverAppPaths) {\n // Search for cloudpack configs to determine the app path(s)\n const { app, login } = this._options as unknown as Pick<ReusedOptions, 'app' | 'login'>;\n const appPathsResult =\n this._discoverAppPaths === 'remote'\n ? await discoverRemoteAppPaths({\n options: {\n login,\n cachePath: this._options.cachePath,\n desiredApp: app,\n },\n context: { reporter: this._reporter },\n })\n : await discoverLocalAppPaths({\n cwd: this._programOptions.cwd,\n discover: this._discoverAppPaths,\n desiredApp: app,\n });\n if (!Array.isArray(appPathsResult)) {\n // This means there was an error (or the user cancelled) while getting app paths.\n return appPathsResult;\n }\n appPaths = appPathsResult;\n } else {\n // Just use the cwd\n appPaths = [this._programOptions.cwd];\n }\n\n // The task runner is shared between all apps so that task results can potentially be reused.\n const taskRunner = new TaskRunner();\n\n const readConfig = this._discoverAppPaths === 'remote' ? readRemoteConfigs : readLocalConfigs;\n const configs = await readConfig(appPaths, {\n ...this._getConfigOptionsFromCliOptions(),\n enableDefaultFeatures: true,\n });\n\n const helpMessages = new Set<string>(\n Object.values(configs)\n .filter((c) => c.helpMessage)\n .map((c) => c.helpMessage) as string[],\n );\n\n // Set reporter options and print the product info header\n this._reporter.setOptions({\n productName: 'Cloudpack',\n version: this._programOptions.version,\n description: () => `Running \"${bold(this._programOptions.argv.slice(2).join(' '))}\"`,\n helpMessage: [...helpMessages].join('\\n'),\n plainTextMode: !this._options.color,\n logFile: !!this._options.logFile,\n cwd: this._programOptions.cwd,\n ...(this._options.debug\n ? debugLoggingConfig\n : this._options.verbose\n ? verboseLoggingConfig\n : this._options.quiet\n ? noLoggingConfig\n : defaultLoggingConfig),\n });\n\n const logLevel = this._options.verbose ? 'VERBOSE' : this._options.debug ? 'DEBUG' : undefined;\n if (!this._options.debug) {\n this._reporter.ignoreLogMessage('ApplicationInsights:');\n }\n\n const telemetryApi = startTelemetry({\n productVersion: getVersion(import.meta.url),\n logLevel,\n serviceName: 'cli',\n });\n\n this._autoDisposableList.add({ dispose: () => telemetryApi.shutdown() });\n\n const contexts: ExtendedAppCommandContext[] = [];\n\n for (const appPath of Object.keys(configs)) {\n const config = configs[appPath];\n const definition = await readJson<PackageJson>(path.join(appPath, 'package.json'));\n const { name = path.basename(appPath) } = definition || {};\n\n const telemetryClient = await this._initTelemetry(name, config, telemetryApi);\n\n contexts.push({\n appPath,\n appName: name,\n cachePath: this._options.cachePath,\n config,\n reporter: this._reporter,\n telemetryClient,\n taskRunner,\n });\n }\n\n return contexts;\n }\n\n /** Translate certain CLI options into options for `readConfig()`. */\n private _getConfigOptionsFromCliOptions(): ReadConfigOptions {\n // These options don't exist for all commands, but that's fine.\n const options = this._options as Partial<ReusedOptions & SharedOptions>;\n return {\n mode: options.mode,\n logBundleInfo: options.logBundleInfo,\n configFileName: options.config,\n // Handle --bundler by passing it as a universal package override, which will be appended\n // to any user-provided packageSettings so that it takes precedence.\n extraPackageSettings: options.bundler ? [{ match: '*', bundler: options.bundler }] : undefined,\n extraFeatures: options.features,\n extraDefineFlags: options.define,\n ...(this._applyOptionsToConfig?.(this._options) || {}),\n };\n }\n\n private async _initTelemetry(\n appName: string | undefined,\n config: CloudpackConfig,\n telemetryApi: TelemetryApi,\n ): Promise<TelemetryClient> {\n // Mark the start time for telemetry.\n const startTime = performance.now();\n\n const programOptions = this._programOptions;\n\n const connectionString =\n this._programOptions.disableTelemetry || environmentInfo.isJest\n ? undefined\n : config.telemetry?.connectionString || environmentInfo.cloudpack.telemetryConnectionString;\n\n const telemetryClient = await telemetryApi.createClient(connectionString);\n\n telemetryClient.tracer.startSpan('CLI_ENTRY', { startTime: getCliStartTime() }).end();\n\n await telemetryClient.tracer.startActiveSpan('INIT_TELEMETRY', { startTime }, (span) => {\n const enabledFeatureNames = Object.entries(config.features || {})\n .filter(([, value]) => value)\n .map(([key]) => key);\n\n if (enabledFeatureNames.length) {\n console.log(`Enabled features for ${appName}: ${enabledFeatureNames.map((f) => yellow(f)).join(', ')}`);\n }\n\n const telemetryAttributes = {\n verb: this._verb,\n arguments: programOptions.argv.slice(3).join(' '),\n environment: environmentInfo.isCI ? 'ci' : environmentInfo.isCodespaces ? 'codespaces' : 'local',\n appName: appName || '<unknown>',\n mode: config.mode,\n features: enabledFeatureNames,\n externalCorrelationId: environmentInfo.cloudpack.telemetryExternalCorrelationId,\n // Azure DevOps build attributes\n ...environmentInfo.ado,\n };\n\n for (const [key, value] of Object.entries(telemetryAttributes)) {\n if (value) {\n span.setAttribute(key, value);\n }\n }\n });\n\n return telemetryClient;\n }\n\n private _sigintHandler = (): void => {\n this._sigintCount++;\n\n if (this._sigintCount > 1) {\n console.debug('Forcing exit');\n\n // We are forcing the process to exit.\n // No clean-up is needed because user pressed Ctrl+C twice.\n this._callProcessExit(1);\n return;\n }\n\n this._onInterrupt?.();\n\n // We are trying to exit gracefully.\n void this._exit({ isInterrupted: true, message: '' });\n };\n\n private _uncaughtExceptionHandler: NodeJS.UncaughtExceptionListener = (error, reason) => {\n const errorType = reason === 'uncaughtException' ? 'Uncaught exception' : 'Unhandled promise rejection';\n const message = `${errorType}: ${error.stack || error.message || String(error)}`;\n // Go ahead and log the message in case the process exits before cleanup is complete\n console.error(message);\n\n void this._exit({ message, hasErrors: true, exitCode: 1 });\n };\n\n private _unexpectedErrorHandler = (...args: unknown[]): void => {\n const err = new Error('Unexpected process error');\n console.error(err.stack);\n console.error('Error details:', ...args);\n };\n\n /**\n * Exit function called with the result returned by the command's execute function,\n * or manually via `CommandExecutor.exitAll()` in tests.\n *\n * Except in tests, execution can be assumed to have stopped after this is called.\n * (In tests, `process.exit` is probably mocked to throw.)\n */\n private async _exit(params: CommandExitParams): Promise<void> {\n const { hasErrors = this._reporter.hasErrors(), exitCode = hasErrors ? 1 : 0 } = params;\n const message = params.isInterrupted ? this._getMessageOnInterrupt?.() || 'Interrupted by user' : params.message;\n\n if (this._hasCalledExit) {\n // Skip most of the operations if exit() was called multiple times.\n // But only use the error message if not in a test, due to the way we're mocking process.exit.\n if (!environmentInfo.isJest) {\n const prettyParams = Object.entries(params)\n .map(([key, value]) => `${key}=\"${value}\"`)\n .join(', ');\n console.warn(`exit() was called multiple times. This call's options: ${prettyParams}.`);\n }\n } else {\n this._hasCalledExit = true;\n\n // Show the summary message (this will throw if called twice).\n this._reporter.complete({\n summary: hasErrors ? red(message) : message,\n showHelp: exitCode !== 0,\n });\n\n // Dispose all resources\n await this._finalDisposableList.dispose();\n }\n\n this._callProcessExit(exitCode);\n }\n\n /** Call the mocked or real `process.exit()` function */\n private _callProcessExit(exitCode: number): void {\n (CommandExecutor._mockProcessExit || realProcessExit)(exitCode);\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ms-cloudpack/cli",
|
|
3
|
-
"version": "0.77.
|
|
3
|
+
"version": "0.77.46",
|
|
4
4
|
"description": "The Cloudpack command line interface - a tool for managing fast inner and outer looping in web apps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,25 +30,25 @@
|
|
|
30
30
|
"test": "cloudpack-scripts test"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@ms-cloudpack/api-server": "^0.66.
|
|
34
|
-
"@ms-cloudpack/app-server": "^0.20.
|
|
35
|
-
"@ms-cloudpack/bundler": "^0.27.
|
|
33
|
+
"@ms-cloudpack/api-server": "^0.66.12",
|
|
34
|
+
"@ms-cloudpack/app-server": "^0.20.51",
|
|
35
|
+
"@ms-cloudpack/bundler": "^0.27.15",
|
|
36
36
|
"@ms-cloudpack/bundler-capabilities": "^0.5.1",
|
|
37
37
|
"@ms-cloudpack/common-types": "^0.33.2",
|
|
38
|
-
"@ms-cloudpack/config": "^0.38.
|
|
38
|
+
"@ms-cloudpack/config": "^0.38.30",
|
|
39
39
|
"@ms-cloudpack/create-express-app": "^1.10.69",
|
|
40
40
|
"@ms-cloudpack/environment": "^0.1.1",
|
|
41
41
|
"@ms-cloudpack/file-watcher": "^0.4.28",
|
|
42
42
|
"@ms-cloudpack/json-utilities": "^0.1.11",
|
|
43
|
-
"@ms-cloudpack/link-proxy": "^0.2.
|
|
44
|
-
"@ms-cloudpack/overlay": "^0.19.
|
|
45
|
-
"@ms-cloudpack/package-utilities": "^13.3.
|
|
43
|
+
"@ms-cloudpack/link-proxy": "^0.2.73",
|
|
44
|
+
"@ms-cloudpack/overlay": "^0.19.69",
|
|
45
|
+
"@ms-cloudpack/package-utilities": "^13.3.6",
|
|
46
46
|
"@ms-cloudpack/path-string-parsing": "^1.3.0",
|
|
47
47
|
"@ms-cloudpack/path-utilities": "^3.2.5",
|
|
48
|
-
"@ms-cloudpack/remote-cache": "^0.11.
|
|
48
|
+
"@ms-cloudpack/remote-cache": "^0.11.65",
|
|
49
49
|
"@ms-cloudpack/setup-utilities": "^0.5.56",
|
|
50
|
-
"@ms-cloudpack/task-reporter": "^0.
|
|
51
|
-
"@ms-cloudpack/telemetry": "^0.11.
|
|
50
|
+
"@ms-cloudpack/task-reporter": "^0.19.0",
|
|
51
|
+
"@ms-cloudpack/telemetry": "^0.11.65",
|
|
52
52
|
"@yarnpkg/lockfile": "^1.1.0",
|
|
53
53
|
"commander": "^14.0.0",
|
|
54
54
|
"cross-spawn": "^7.0.3",
|