@ms-cloudpack/cli 0.72.49 → 0.72.50

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.
Files changed (114) hide show
  1. package/lib/commands/bundle/execute.d.ts.map +1 -1
  2. package/lib/commands/bundle/execute.js +3 -7
  3. package/lib/commands/bundle/execute.js.map +1 -1
  4. package/lib/commands/bundle/index.d.ts.map +1 -1
  5. package/lib/commands/bundle/index.js +1 -2
  6. package/lib/commands/bundle/index.js.map +1 -1
  7. package/lib/commands/bundle/types/BundleOptions.d.ts +1 -8
  8. package/lib/commands/bundle/types/BundleOptions.d.ts.map +1 -1
  9. package/lib/commands/bundle/types/BundleOptions.js.map +1 -1
  10. package/lib/commands/cache/clean.d.ts.map +1 -1
  11. package/lib/commands/cache/clean.js +1 -2
  12. package/lib/commands/cache/clean.js.map +1 -1
  13. package/lib/commands/config/delete.d.ts.map +1 -1
  14. package/lib/commands/config/delete.js +1 -2
  15. package/lib/commands/config/delete.js.map +1 -1
  16. package/lib/commands/config/get.d.ts.map +1 -1
  17. package/lib/commands/config/get.js +1 -2
  18. package/lib/commands/config/get.js.map +1 -1
  19. package/lib/commands/config/list.d.ts.map +1 -1
  20. package/lib/commands/config/list.js +1 -3
  21. package/lib/commands/config/list.js.map +1 -1
  22. package/lib/commands/config/set.d.ts.map +1 -1
  23. package/lib/commands/config/set.js +1 -2
  24. package/lib/commands/config/set.js.map +1 -1
  25. package/lib/commands/info/lockFile/execute.d.ts.map +1 -1
  26. package/lib/commands/info/lockFile/execute.js +1 -2
  27. package/lib/commands/info/lockFile/execute.js.map +1 -1
  28. package/lib/commands/info/nonSemverDeps/execute.js +2 -2
  29. package/lib/commands/info/nonSemverDeps/execute.js.map +1 -1
  30. package/lib/commands/init/execute.d.ts.map +1 -1
  31. package/lib/commands/init/execute.js +1 -10
  32. package/lib/commands/init/execute.js.map +1 -1
  33. package/lib/commands/init/index.d.ts.map +1 -1
  34. package/lib/commands/init/index.js +3 -0
  35. package/lib/commands/init/index.js.map +1 -1
  36. package/lib/commands/init/init.d.ts.map +1 -1
  37. package/lib/commands/init/init.js +149 -148
  38. package/lib/commands/init/init.js.map +1 -1
  39. package/lib/commands/init/types/InitOptions.d.ts +1 -1
  40. package/lib/commands/init/types/InitOptions.d.ts.map +1 -1
  41. package/lib/commands/init/types/InitOptions.js.map +1 -1
  42. package/lib/commands/link/execute.d.ts.map +1 -1
  43. package/lib/commands/link/execute.js +2 -2
  44. package/lib/commands/link/execute.js.map +1 -1
  45. package/lib/commands/setup/execute.d.ts.map +1 -1
  46. package/lib/commands/setup/execute.js +1 -2
  47. package/lib/commands/setup/execute.js.map +1 -1
  48. package/lib/commands/start/execute.d.ts.map +1 -1
  49. package/lib/commands/start/execute.js +3 -10
  50. package/lib/commands/start/execute.js.map +1 -1
  51. package/lib/commands/start/index.js +5 -2
  52. package/lib/commands/start/index.js.map +1 -1
  53. package/lib/commands/start/types/StartOptions.d.ts +1 -3
  54. package/lib/commands/start/types/StartOptions.d.ts.map +1 -1
  55. package/lib/commands/start/types/StartOptions.js.map +1 -1
  56. package/lib/commands/sync/execute.d.ts.map +1 -1
  57. package/lib/commands/sync/execute.js +2 -2
  58. package/lib/commands/sync/execute.js.map +1 -1
  59. package/lib/commands/unlink/execute.js +2 -2
  60. package/lib/commands/unlink/execute.js.map +1 -1
  61. package/lib/types/AppPathDiscoveryMode.d.ts +14 -0
  62. package/lib/types/AppPathDiscoveryMode.d.ts.map +1 -0
  63. package/lib/types/AppPathDiscoveryMode.js +2 -0
  64. package/lib/types/AppPathDiscoveryMode.js.map +1 -0
  65. package/lib/types/CommandAction.d.ts +5 -25
  66. package/lib/types/CommandAction.d.ts.map +1 -1
  67. package/lib/types/CommandAction.js.map +1 -1
  68. package/lib/types/ReusedOptions.d.ts +9 -0
  69. package/lib/types/ReusedOptions.d.ts.map +1 -1
  70. package/lib/types/ReusedOptions.js.map +1 -1
  71. package/lib/types/SharedOptions.d.ts +2 -2
  72. package/lib/types/SharedOptions.d.ts.map +1 -1
  73. package/lib/types/SharedOptions.js.map +1 -1
  74. package/lib/utilities/CloudpackCommand.d.ts +3 -1
  75. package/lib/utilities/CloudpackCommand.d.ts.map +1 -1
  76. package/lib/utilities/CloudpackCommand.js +4 -1
  77. package/lib/utilities/CloudpackCommand.js.map +1 -1
  78. package/lib/utilities/CommandExecutor.d.ts +19 -7
  79. package/lib/utilities/CommandExecutor.d.ts.map +1 -1
  80. package/lib/utilities/CommandExecutor.js +48 -26
  81. package/lib/utilities/CommandExecutor.js.map +1 -1
  82. package/lib/utilities/discoverAppPaths.d.ts +28 -0
  83. package/lib/utilities/discoverAppPaths.d.ts.map +1 -0
  84. package/lib/utilities/discoverAppPaths.js +80 -0
  85. package/lib/utilities/discoverAppPaths.js.map +1 -0
  86. package/lib/utilities/parseFeature.d.ts +6 -0
  87. package/lib/utilities/parseFeature.d.ts.map +1 -0
  88. package/lib/utilities/parseFeature.js +42 -0
  89. package/lib/utilities/parseFeature.js.map +1 -0
  90. package/lib/utilities/reusedOptions.d.ts +8 -0
  91. package/lib/utilities/reusedOptions.d.ts.map +1 -1
  92. package/lib/utilities/reusedOptions.js +8 -0
  93. package/lib/utilities/reusedOptions.js.map +1 -1
  94. package/package.json +6 -6
  95. package/lib/commands/start/getStartingAppPath.d.ts +0 -12
  96. package/lib/commands/start/getStartingAppPath.d.ts.map +0 -1
  97. package/lib/commands/start/getStartingAppPath.js +0 -60
  98. package/lib/commands/start/getStartingAppPath.js.map +0 -1
  99. package/lib/utilities/checkFeatures.d.ts +0 -12
  100. package/lib/utilities/checkFeatures.d.ts.map +0 -1
  101. package/lib/utilities/checkFeatures.js +0 -24
  102. package/lib/utilities/checkFeatures.js.map +0 -1
  103. package/lib/utilities/findCloudpackAppPaths.d.ts +0 -7
  104. package/lib/utilities/findCloudpackAppPaths.d.ts.map +0 -1
  105. package/lib/utilities/findCloudpackAppPaths.js +0 -12
  106. package/lib/utilities/findCloudpackAppPaths.js.map +0 -1
  107. package/lib/utilities/getConfigOptionsFromCliOptions.d.ts +0 -8
  108. package/lib/utilities/getConfigOptionsFromCliOptions.d.ts.map +0 -1
  109. package/lib/utilities/getConfigOptionsFromCliOptions.js +0 -14
  110. package/lib/utilities/getConfigOptionsFromCliOptions.js.map +0 -1
  111. package/lib/utilities/mergeFeatures.d.ts +0 -8
  112. package/lib/utilities/mergeFeatures.d.ts.map +0 -1
  113. package/lib/utilities/mergeFeatures.js +0 -16
  114. package/lib/utilities/mergeFeatures.js.map +0 -1
@@ -4,14 +4,14 @@ import { TaskReporter, bold, debugLoggingConfig, defaultLoggingConfig, noLogging
4
4
  import { createTelemetryClient } from '@ms-cloudpack/telemetry';
5
5
  import path from 'path';
6
6
  import { AutoDisposableList } from './AutoDisposableList.js';
7
- import { checkFeatures } from './checkFeatures.js';
8
7
  import { getVersion } from '@ms-cloudpack/package-utilities';
9
- import { mergeFeatures } from './mergeFeatures.js';
10
8
  import { environmentInfo } from '@ms-cloudpack/environment';
11
9
  import { getCliStartTime } from './getCliStartTime.js';
10
+ import { discoverAppPaths } from './discoverAppPaths.js';
12
11
  /**
13
12
  * This class manages orchestration and shared state while executing a command.
14
13
  */
14
+ // 'app' is an optional reused option
15
15
  export class CommandExecutor {
16
16
  static async exitAll(params) {
17
17
  // There should only be one instance at a time, but we assume multiple instances for safety.
@@ -42,6 +42,7 @@ export class CommandExecutor {
42
42
  this._execute = params.execute;
43
43
  this._programOptions = params.programOptions;
44
44
  this._verb = params.verb;
45
+ this._discoverAppPaths = params.discoverAppPaths;
45
46
  this._reporter = new TaskReporter();
46
47
  this._abortController = new AbortController();
47
48
  this._autoDisposableList = new AutoDisposableList();
@@ -53,14 +54,18 @@ export class CommandExecutor {
53
54
  try {
54
55
  // Handle SIGINT (Ctrl+C) gracefully.
55
56
  process.on('SIGINT', this._sigintHandler);
57
+ const contexts = await this._initializeContexts();
58
+ if (!Array.isArray(contexts)) {
59
+ await this._exit(contexts);
60
+ return;
61
+ }
56
62
  // Call the execute function which is the real command logic
57
63
  // (ie: real init command logic, real start command logic, etc.)
58
64
  const result = await this._execute({
65
+ contexts,
59
66
  args: this._args,
60
67
  options: this._options,
61
- cwd: this._programOptions.cwd,
62
68
  reporter: this._reporter,
63
- initialize: this._initialize.bind(this),
64
69
  abortSignal: this._abortController.signal,
65
70
  autoDispose: (disposable) => this._autoDisposableList.add(disposable),
66
71
  setInterruptMessageHandler: (getMessage) => {
@@ -79,25 +84,40 @@ export class CommandExecutor {
79
84
  });
80
85
  }
81
86
  }
82
- async _initialize(initializeParams) {
83
- const { appPath: singleAppPath, configOptions } = initializeParams;
84
- let { appPaths } = initializeParams;
85
- if (singleAppPath && appPaths) {
86
- throw Error('appPath and appPaths cannot both be specified at the same time');
87
- }
88
- if (!singleAppPath && !appPaths) {
89
- throw Error('one of appPath or appPaths must be specified');
87
+ /**
88
+ * Determine the app paths and initialize the context for each app.
89
+ * @returns Context(s), or an exit options object if there was an error. (might also throw on error)
90
+ */
91
+ async _initializeContexts() {
92
+ let appPaths;
93
+ if (this._discoverAppPaths) {
94
+ // Search for cloudpack configs to determine the app path(s)
95
+ const appPathsResult = await discoverAppPaths({
96
+ cwd: this._programOptions.cwd,
97
+ discover: this._discoverAppPaths,
98
+ desiredApp: this._options.app,
99
+ });
100
+ if (!Array.isArray(appPathsResult)) {
101
+ // This means there was an error (or the user cancelled) while getting app paths.
102
+ return appPathsResult;
103
+ }
104
+ appPaths = appPathsResult;
90
105
  }
91
- if (!appPaths || appPaths.length === 0) {
92
- appPaths = singleAppPath ? [singleAppPath] : [];
106
+ else {
107
+ // Just use the cwd
108
+ appPaths = [this._programOptions.cwd];
93
109
  }
110
+ const configOptions = this._getConfigOptionsFromCliOptions();
94
111
  const contexts = [];
95
112
  const helpMessages = new Set();
96
113
  const configs = {};
97
114
  for (const appPath of appPaths) {
98
115
  let config;
99
116
  try {
100
- config = await readConfig(appPath, configOptions);
117
+ config = await readConfig(appPath, {
118
+ ...configOptions,
119
+ extraFeatures: this._options.features,
120
+ });
101
121
  }
102
122
  catch (err) {
103
123
  await this._exit({
@@ -136,16 +156,6 @@ export class CommandExecutor {
136
156
  this._autoDisposableList.add({
137
157
  dispose: () => telemetryClient.shutdown(),
138
158
  });
139
- // Merge in any additional features from the command line and remote feature flags.
140
- config.features = mergeFeatures({
141
- configFeatures: config.features,
142
- commandLineFeatures: this._options.features,
143
- });
144
- const featureErrors = checkFeatures({ configFeatures: config.features });
145
- // If there are any invalid features, warn the user and continue.
146
- if (featureErrors.length) {
147
- featureErrors.forEach((warning) => console.warn(warning));
148
- }
149
159
  contexts.push({
150
160
  appPath,
151
161
  cachePath: this._options.cachePath,
@@ -154,7 +164,19 @@ export class CommandExecutor {
154
164
  telemetryClient,
155
165
  });
156
166
  }
157
- return singleAppPath ? contexts[0] : contexts;
167
+ return contexts;
168
+ }
169
+ /** Translate certain CLI options into options for `readConfig()`. */
170
+ _getConfigOptionsFromCliOptions() {
171
+ // These options don't exist for all commands, but that's fine.
172
+ const options = this._options;
173
+ return {
174
+ mode: options.mode,
175
+ logBundleInfo: options.logBundleInfo,
176
+ // Handle --bundler by passing it as a universal package override, which will be appended
177
+ // to any user-provided packageSettings so that it takes precedence.
178
+ extraPackageSettings: options.bundler ? [{ match: '*', bundler: options.bundler }] : undefined,
179
+ };
158
180
  }
159
181
  async _initTelemetry(appName, config) {
160
182
  // Mark the start time for telemetry.
@@ -1 +1 @@
1
- {"version":3,"file":"CommandExecutor.js","sourceRoot":"","sources":["../../src/utilities/CommandExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import { readConfig } 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 { createTelemetryClient, type TelemetryClient } from '@ms-cloudpack/telemetry';\nimport path from 'path';\nimport type {\n CommandAction,\n CommandExitParams,\n AppCommandContext,\n CommandInitializeOptions,\n} from '../types/CommandAction.js';\nimport type { ProgramOptions } from '../types/ProgramOptions.js';\nimport type { SharedOptions } from '../types/SharedOptions.js';\nimport { AutoDisposableList } from './AutoDisposableList.js';\nimport { checkFeatures } from './checkFeatures.js';\nimport { getVersion } from '@ms-cloudpack/package-utilities';\nimport { mergeFeatures } from './mergeFeatures.js';\nimport { environmentInfo } from '@ms-cloudpack/environment';\nimport { getCliStartTime } from './getCliStartTime.js';\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 _reporter: TaskReporter;\n private _autoDisposableList: AutoDisposableList;\n private _abortController: AbortController;\n private _hasCalledExit = false;\n private _args: string[];\n private _sigintCount = 0;\n private _getMessageOnInterrupt = () => `Interrupted by user`;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- options type isn't used\n private static _activeInstances: 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 = [];\n }\n\n constructor(params: {\n /** Command-specific arguments */\n args: string[];\n /** Command-specific and shared options. */\n options: TOptions;\n /** Function to execute the command. */\n execute: CommandAction<TOptions>;\n /** Shared program-level configuration. */\n programOptions: ProgramOptions;\n /** Verb being run, e.g. `bundle` or `cache clean`. */\n verb: string;\n }) {\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._reporter = new TaskReporter();\n this._abortController = new AbortController();\n this._autoDisposableList = new AutoDisposableList();\n }\n\n /** Run the command. */\n // This has to be a separate method because constructors can't be async.\n public async execute(): Promise<void> {\n CommandExecutor._activeInstances.push(this);\n try {\n // Handle SIGINT (Ctrl+C) gracefully.\n process.on('SIGINT', this._sigintHandler);\n\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 this._execute({\n args: this._args,\n options: this._options,\n cwd: this._programOptions.cwd,\n reporter: this._reporter,\n initialize: this._initialize.bind(this),\n abortSignal: this._abortController.signal,\n autoDispose: (disposable) => this._autoDisposableList.add(disposable),\n setInterruptMessageHandler: (getMessage) => {\n this._getMessageOnInterrupt = getMessage;\n },\n });\n if (result) {\n await this._exit(result);\n }\n } catch (error) {\n // If an error occurs, exit the process with a non-zero exit code.\n await this._exit({\n hasErrors: true,\n message: error instanceof Error ? error.stack || error.message : String(error),\n });\n }\n }\n\n /**\n * This is the `initialize` function passed to the command's execute function.\n * This function uses `this` to references several class members, which is why\n * the `execute` method must use `.bind(this)`.\n * (An arrow function isn't possible here due to the overloaded method signature).\n */\n private async _initialize(\n initializeParams: CommandInitializeOptions & { appPath: string },\n ): Promise<AppCommandContext>;\n private async _initialize(\n initializeParams: CommandInitializeOptions & { appPaths: string[] },\n ): Promise<AppCommandContext[]>;\n private async _initialize(\n initializeParams: CommandInitializeOptions & {\n appPath?: string;\n appPaths?: string[];\n },\n ): Promise<AppCommandContext | AppCommandContext[]> {\n const { appPath: singleAppPath, configOptions } = initializeParams;\n let { appPaths } = initializeParams;\n\n if (singleAppPath && appPaths) {\n throw Error('appPath and appPaths cannot both be specified at the same time');\n }\n if (!singleAppPath && !appPaths) {\n throw Error('one of appPath or appPaths must be specified');\n }\n\n if (!appPaths || appPaths.length === 0) {\n appPaths = singleAppPath ? [singleAppPath] : [];\n }\n\n const contexts: AppCommandContext[] = [];\n\n const helpMessages = new Set<string>();\n\n const configs: Record<string, CloudpackConfig> = {};\n for (const appPath of appPaths) {\n let config: CloudpackConfig;\n\n try {\n config = await readConfig(appPath, configOptions);\n } catch (err) {\n await this._exit({\n message: `Invalid cloudpack config: ${(err as Error).message || err}`,\n hasErrors: true,\n });\n // eslint-disable-next-line no-restricted-properties -- this will never be reached, but TypeScript doesn't know that\n process.exit(1);\n }\n if (config.helpMessage) {\n helpMessages.add(config.helpMessage);\n }\n\n configs[appPath] = config;\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 ...(this._options.debug\n ? debugLoggingConfig\n : this._options.verbose\n ? verboseLoggingConfig\n : this._options.quiet\n ? noLoggingConfig\n : defaultLoggingConfig),\n });\n\n for (const appPath of appPaths) {\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);\n // Dispose the telemetry client when the app is closing\n this._autoDisposableList.add({\n dispose: () => telemetryClient.shutdown(),\n });\n\n // Merge in any additional features from the command line and remote feature flags.\n config.features = mergeFeatures({\n configFeatures: config.features,\n commandLineFeatures: this._options.features,\n });\n\n const featureErrors = checkFeatures({ configFeatures: config.features });\n\n // If there are any invalid features, warn the user and continue.\n if (featureErrors.length) {\n featureErrors.forEach((warning) => console.warn(warning));\n }\n\n contexts.push({\n appPath,\n cachePath: this._options.cachePath,\n config,\n reporter: this._reporter,\n telemetryClient,\n });\n }\n\n return singleAppPath ? contexts[0] : contexts;\n }\n\n private async _initTelemetry(appName: string | undefined, config: CloudpackConfig): Promise<TelemetryClient> {\n // Mark the start time for telemetry.\n const startTime = performance.now();\n\n const programOptions = this._programOptions;\n const options = this._options;\n\n const connectionString =\n programOptions.disableTelemetry || environmentInfo.isJest\n ? undefined\n : config.telemetry?.connectionString || environmentInfo.cloudpack.telemetryConnectionString;\n\n const logLevel = options.verbose ? 'VERBOSE' : options.debug ? 'DEBUG' : undefined;\n if (!options.debug) {\n this._reporter.ignoreLogMessage('ApplicationInsights:');\n }\n\n const telemetryClient = await createTelemetryClient({\n productVersion: getVersion(import.meta.url),\n connectionString,\n logLevel,\n serviceNamespace: 'cloudpack',\n serviceName: 'cli',\n });\n\n void telemetryClient.tracer.startActiveSpan('CLI_ENTRY', { startTime: getCliStartTime() }, () => {\n // Retrieve the current telemetry context\n const activeContext = telemetryClient.context.active();\n\n /**\n * Sets the current context as the root context. This ensures that all spans created during this CLI execution\n * will be children of this root span, even though the root span is closed immediately. This helps group all\n * spans under a single root span for better traceability.\n *\n * Typically, the root span should remain open until the CLI exits. However, in environments like Codespaces,\n * the CLI might run indefinitely, which could leave the root span open indefinitely.\n *\n * To prevent this, the root span is closed immediately after it is set as the root context.\n */\n telemetryClient.setRootContext(activeContext);\n });\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 || 'library',\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 // 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() : 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 // Let the execute function know that we are exiting.\n this._abortController.abort();\n\n // Dispose all registered disposables.\n await this._autoDisposableList.dispose();\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\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 { readConfig, 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 { createTelemetryClient, 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 { getCliStartTime } from './getCliStartTime.js';\nimport type { ReusedOptions } from '../types/ReusedOptions.js';\nimport type { AppPathDiscoveryMode } from '../types/AppPathDiscoveryMode.js';\nimport { discoverAppPaths } from './discoverAppPaths.js';\n\nexport interface CommandExecutorSharedParams {\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 discoverAppPaths?: AppPathDiscoveryMode;\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 & Pick<ReusedOptions, 'app'>> {\n private _options: TOptions;\n private _execute: CommandAction<TOptions>;\n private _programOptions: ProgramOptions;\n private _verb: string;\n private _discoverAppPaths: AppPathDiscoveryMode | undefined;\n private _reporter: TaskReporter;\n private _autoDisposableList: AutoDisposableList;\n private _abortController: AbortController;\n private _hasCalledExit = false;\n private _args: string[];\n private _sigintCount = 0;\n private _getMessageOnInterrupt = () => `Interrupted by user`;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- options type isn't used\n private static _activeInstances: 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 = [];\n }\n\n constructor(\n params: CommandExecutorSharedParams & {\n /** Command-specific arguments */\n args: string[];\n /** Command-specific and shared options. */\n options: TOptions;\n /** Function to execute the command. */\n execute: CommandAction<TOptions>;\n /** Shared program-level configuration. */\n programOptions: ProgramOptions;\n /** Verb being run, e.g. `bundle` or `cache clean`. */\n verb: string;\n },\n ) {\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._reporter = new TaskReporter();\n this._abortController = new AbortController();\n this._autoDisposableList = new AutoDisposableList();\n }\n\n /** Run the command. */\n // This has to be a separate method because constructors can't be async.\n public async execute(): Promise<void> {\n CommandExecutor._activeInstances.push(this);\n try {\n // Handle SIGINT (Ctrl+C) gracefully.\n process.on('SIGINT', this._sigintHandler);\n\n const contexts = await this._initializeContexts();\n\n if (!Array.isArray(contexts)) {\n await this._exit(contexts);\n return;\n }\n\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 this._execute({\n contexts,\n args: this._args,\n options: this._options,\n reporter: this._reporter,\n abortSignal: this._abortController.signal,\n autoDispose: (disposable) => this._autoDisposableList.add(disposable),\n setInterruptMessageHandler: (getMessage) => {\n this._getMessageOnInterrupt = getMessage;\n },\n });\n if (result) {\n await this._exit(result);\n }\n } catch (error) {\n // If an error occurs, exit the process with a non-zero exit code.\n await this._exit({\n hasErrors: true,\n message: error instanceof Error ? error.stack || error.message : String(error),\n });\n }\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 appPathsResult = await discoverAppPaths({\n cwd: this._programOptions.cwd,\n discover: this._discoverAppPaths,\n desiredApp: this._options.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 const configOptions = this._getConfigOptionsFromCliOptions();\n\n const contexts: AppCommandContext[] = [];\n\n const helpMessages = new Set<string>();\n\n const configs: Record<string, CloudpackConfig> = {};\n for (const appPath of appPaths) {\n let config: CloudpackConfig;\n\n try {\n config = await readConfig(appPath, {\n ...configOptions,\n extraFeatures: this._options.features,\n });\n } catch (err) {\n await this._exit({\n message: `Invalid cloudpack config: ${(err as Error).message || err}`,\n hasErrors: true,\n });\n // eslint-disable-next-line no-restricted-properties -- this will never be reached, but TypeScript doesn't know that\n process.exit(1);\n }\n if (config.helpMessage) {\n helpMessages.add(config.helpMessage);\n }\n\n configs[appPath] = config;\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 ...(this._options.debug\n ? debugLoggingConfig\n : this._options.verbose\n ? verboseLoggingConfig\n : this._options.quiet\n ? noLoggingConfig\n : defaultLoggingConfig),\n });\n\n for (const appPath of appPaths) {\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);\n // Dispose the telemetry client when the app is closing\n this._autoDisposableList.add({\n dispose: () => telemetryClient.shutdown(),\n });\n\n contexts.push({\n appPath,\n cachePath: this._options.cachePath,\n config,\n reporter: this._reporter,\n telemetryClient,\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 // 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 };\n }\n\n private async _initTelemetry(appName: string | undefined, config: CloudpackConfig): Promise<TelemetryClient> {\n // Mark the start time for telemetry.\n const startTime = performance.now();\n\n const programOptions = this._programOptions;\n const options = this._options;\n\n const connectionString =\n programOptions.disableTelemetry || environmentInfo.isJest\n ? undefined\n : config.telemetry?.connectionString || environmentInfo.cloudpack.telemetryConnectionString;\n\n const logLevel = options.verbose ? 'VERBOSE' : options.debug ? 'DEBUG' : undefined;\n if (!options.debug) {\n this._reporter.ignoreLogMessage('ApplicationInsights:');\n }\n\n const telemetryClient = await createTelemetryClient({\n productVersion: getVersion(import.meta.url),\n connectionString,\n logLevel,\n serviceNamespace: 'cloudpack',\n serviceName: 'cli',\n });\n\n void telemetryClient.tracer.startActiveSpan('CLI_ENTRY', { startTime: getCliStartTime() }, () => {\n // Retrieve the current telemetry context\n const activeContext = telemetryClient.context.active();\n\n /**\n * Sets the current context as the root context. This ensures that all spans created during this CLI execution\n * will be children of this root span, even though the root span is closed immediately. This helps group all\n * spans under a single root span for better traceability.\n *\n * Typically, the root span should remain open until the CLI exits. However, in environments like Codespaces,\n * the CLI might run indefinitely, which could leave the root span open indefinitely.\n *\n * To prevent this, the root span is closed immediately after it is set as the root context.\n */\n telemetryClient.setRootContext(activeContext);\n });\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 || 'library',\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 // 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() : 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 // Let the execute function know that we are exiting.\n this._abortController.abort();\n\n // Dispose all registered disposables.\n await this._autoDisposableList.dispose();\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\n // eslint-disable-next-line no-restricted-properties -- top-level cleanup\n process.exit(exitCode);\n }\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import type { CommandExitParams } from '../types/CommandAction.js';
2
+ import type { AppPathDiscoveryMode } from '../types/AppPathDiscoveryMode.js';
3
+ export type _AppPromptQuestionName = 'app';
4
+ /**
5
+ * Gets the appPath from which Cloudpack will run. If the CWD is a Cloudpack-enabled app,
6
+ * we'll use that; otherwise, we'll scan for Cloudpack-enabled app and present the user
7
+ * with a menu. If no apps are found, Cloudpack will just try to run in the CWD anyway.
8
+ *
9
+ * @returns App path(s) (just one unless `discover: 'multi'`), or an exit options object if
10
+ * there was an error.
11
+ */
12
+ export declare function discoverAppPaths(params: {
13
+ /** Working directory to start from. */
14
+ cwd: string;
15
+ /**
16
+ * How to determine the app path(s). (`--app` in the docs refers to `desiredApp` here.)
17
+ * @default 'single'
18
+ */
19
+ discover?: AppPathDiscoveryMode;
20
+ /**
21
+ * Desired app name or substring, from the `--app` option.
22
+ * - If there's an exact match, only that app will be returned.
23
+ * - If multiple apps match a substring, see `discover` for behavior.
24
+ * - If no match, it's an error.
25
+ */
26
+ desiredApp?: string;
27
+ }): Promise<string[] | CommandExitParams>;
28
+ //# sourceMappingURL=discoverAppPaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discoverAppPaths.d.ts","sourceRoot":"","sources":["../../src/utilities/discoverAppPaths.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAEhC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,iBAAiB,CAAC,CAiFxC"}
@@ -0,0 +1,80 @@
1
+ import { PackageDefinitions } from '@ms-cloudpack/package-utilities';
2
+ import glob from 'fast-glob';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import prompts from 'prompts';
6
+ import { appConfigFileName } from '@ms-cloudpack/config';
7
+ /**
8
+ * Gets the appPath from which Cloudpack will run. If the CWD is a Cloudpack-enabled app,
9
+ * we'll use that; otherwise, we'll scan for Cloudpack-enabled app and present the user
10
+ * with a menu. If no apps are found, Cloudpack will just try to run in the CWD anyway.
11
+ *
12
+ * @returns App path(s) (just one unless `discover: 'multi'`), or an exit options object if
13
+ * there was an error.
14
+ */
15
+ export async function discoverAppPaths(params) {
16
+ const { cwd, desiredApp, discover } = params;
17
+ const multiApp = discover === 'multi';
18
+ if (!desiredApp && fs.existsSync(path.join(cwd, appConfigFileName))) {
19
+ // If no specific app was requested, and the cwd is a cloudpack app, just use that.
20
+ return [cwd];
21
+ }
22
+ // Get all cloudpack app paths based on the presence of cloudpack.config.json
23
+ const cloudpackAppPaths = (glob.sync([`**/${appConfigFileName}`], { cwd, ignore: ['**/node_modules/**'] }) ?? []).map((file) => path.join(cwd, path.dirname(file)));
24
+ if (!cloudpackAppPaths.length) {
25
+ // Include the cwd if there are no configs found, since it's possible to run start or init
26
+ // without a config.
27
+ cloudpackAppPaths.push(cwd);
28
+ }
29
+ if (!desiredApp && (multiApp || cloudpackAppPaths.length === 1)) {
30
+ // Return all apps found if we're in multi-app mode or only one app was found
31
+ // (and no specific app was requested).
32
+ return cloudpackAppPaths;
33
+ }
34
+ // Get each app's name and description, filtered by `desiredApp` if specified.
35
+ // (These use Choice format in case they're later used in a prompt.)
36
+ const packages = new PackageDefinitions();
37
+ const appChoices = (await Promise.all(cloudpackAppPaths.map(async (dir) => {
38
+ const pkg = await packages.get(dir);
39
+ return {
40
+ title: pkg.name,
41
+ description: pkg?.description ?? 'An awesome app that would be even more awesome with a proper description',
42
+ value: dir,
43
+ };
44
+ })))
45
+ .filter((choice) => !desiredApp || choice.title.includes(desiredApp))
46
+ .sort((c1, c2) => c1.title.localeCompare(c2.title));
47
+ // Figure out if there are any matches for `desiredApp`
48
+ if (desiredApp) {
49
+ if (!appChoices.length) {
50
+ return {
51
+ message: `No Cloudpack apps found matching the name "${desiredApp}".`,
52
+ hasErrors: true,
53
+ };
54
+ }
55
+ // Prefer an exact match
56
+ const exactMatch = appChoices.find((choice) => choice.title === desiredApp);
57
+ if (exactMatch) {
58
+ return [exactMatch.value];
59
+ }
60
+ // If there's no exact match, it means at least one substring match was found
61
+ if (multiApp || appChoices.length === 1) {
62
+ // Return them all if we're in multi-app mode or only one match was found
63
+ return appChoices.map((choice) => choice.value);
64
+ }
65
+ }
66
+ // There are multiple candidates, so prompt the user to choose one
67
+ // (implicitly, we're in single-app mode if we reach here)
68
+ const response = await prompts({
69
+ type: 'select',
70
+ name: 'app',
71
+ message: 'Select the app you want to start',
72
+ choices: appChoices,
73
+ });
74
+ // This will be undefined if the user cancels the prompt
75
+ if (!response.app) {
76
+ return { isInterrupted: true, message: '' };
77
+ }
78
+ return [response.app];
79
+ }
80
+ //# sourceMappingURL=discoverAppPaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discoverAppPaths.js","sourceRoot":"","sources":["../../src/utilities/discoverAppPaths.ts"],"names":[],"mappings":"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","sourcesContent":["import { PackageDefinitions } from '@ms-cloudpack/package-utilities';\nimport glob from 'fast-glob';\nimport fs from 'fs';\nimport path from 'path';\nimport prompts, { type Choice } from 'prompts';\nimport type { CommandExitParams } from '../types/CommandAction.js';\nimport { appConfigFileName } from '@ms-cloudpack/config';\nimport type { AppPathDiscoveryMode } from '../types/AppPathDiscoveryMode.js';\n\nexport type _AppPromptQuestionName = 'app';\n\n/**\n * Gets the appPath from which Cloudpack will run. If the CWD is a Cloudpack-enabled app,\n * we'll use that; otherwise, we'll scan for Cloudpack-enabled app and present the user\n * with a menu. If no apps are found, Cloudpack will just try to run in the CWD anyway.\n *\n * @returns App path(s) (just one unless `discover: 'multi'`), or an exit options object if\n * there was an error.\n */\nexport async function discoverAppPaths(params: {\n /** Working directory to start from. */\n cwd: string;\n\n /**\n * How to determine the app path(s). (`--app` in the docs refers to `desiredApp` here.)\n * @default 'single'\n */\n discover?: AppPathDiscoveryMode;\n\n /**\n * Desired app name or substring, from the `--app` option.\n * - If there's an exact match, only that app will be returned.\n * - If multiple apps match a substring, see `discover` for behavior.\n * - If no match, it's an error.\n */\n desiredApp?: string;\n}): Promise<string[] | CommandExitParams> {\n const { cwd, desiredApp, discover } = params;\n const multiApp = discover === 'multi';\n\n if (!desiredApp && fs.existsSync(path.join(cwd, appConfigFileName))) {\n // If no specific app was requested, and the cwd is a cloudpack app, just use that.\n return [cwd];\n }\n\n // Get all cloudpack app paths based on the presence of cloudpack.config.json\n const cloudpackAppPaths = (glob.sync([`**/${appConfigFileName}`], { cwd, ignore: ['**/node_modules/**'] }) ?? []).map(\n (file) => path.join(cwd, path.dirname(file)),\n );\n\n if (!cloudpackAppPaths.length) {\n // Include the cwd if there are no configs found, since it's possible to run start or init\n // without a config.\n cloudpackAppPaths.push(cwd);\n }\n\n if (!desiredApp && (multiApp || cloudpackAppPaths.length === 1)) {\n // Return all apps found if we're in multi-app mode or only one app was found\n // (and no specific app was requested).\n return cloudpackAppPaths;\n }\n\n // Get each app's name and description, filtered by `desiredApp` if specified.\n // (These use Choice format in case they're later used in a prompt.)\n const packages = new PackageDefinitions();\n const appChoices = (\n await Promise.all<Omit<Choice, 'value'> & { value: string }>(\n cloudpackAppPaths.map(async (dir) => {\n const pkg = await packages.get(dir);\n return {\n title: pkg.name,\n description: pkg?.description ?? 'An awesome app that would be even more awesome with a proper description',\n value: dir,\n };\n }),\n )\n )\n .filter((choice) => !desiredApp || choice.title.includes(desiredApp))\n .sort((c1, c2) => c1.title.localeCompare(c2.title));\n\n // Figure out if there are any matches for `desiredApp`\n if (desiredApp) {\n if (!appChoices.length) {\n return {\n message: `No Cloudpack apps found matching the name \"${desiredApp}\".`,\n hasErrors: true,\n };\n }\n\n // Prefer an exact match\n const exactMatch = appChoices.find((choice) => choice.title === desiredApp);\n if (exactMatch) {\n return [exactMatch.value];\n }\n\n // If there's no exact match, it means at least one substring match was found\n if (multiApp || appChoices.length === 1) {\n // Return them all if we're in multi-app mode or only one match was found\n return appChoices.map((choice) => choice.value);\n }\n }\n\n // There are multiple candidates, so prompt the user to choose one\n // (implicitly, we're in single-app mode if we reach here)\n const response = await prompts<_AppPromptQuestionName>({\n type: 'select',\n name: 'app',\n message: 'Select the app you want to start',\n choices: appChoices,\n });\n\n // This will be undefined if the user cancels the prompt\n if (!response.app) {\n return { isInterrupted: true, message: '' };\n }\n\n return [response.app as string];\n}\n"]}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Parse a `--feature` argument.
3
+ * (This follows the signature of commander's `Option.argParser()`.)
4
+ */
5
+ export declare function parseFeature(partialFeatureName: string, accFeatures?: Record<string, boolean>, featureSet?: Record<string, unknown>): Record<string, boolean>;
6
+ //# sourceMappingURL=parseFeature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseFeature.d.ts","sourceRoot":"","sources":["../../src/utilities/parseFeature.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,kBAAkB,EAAE,MAAM,EAC1B,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACzC,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAe,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoCzB"}
@@ -0,0 +1,42 @@
1
+ import { allFeatures } from '@ms-cloudpack/common-types';
2
+ import { InvalidArgumentError } from 'commander';
3
+ import didyoumean from 'didyoumean';
4
+ /**
5
+ * Parse a `--feature` argument.
6
+ * (This follows the signature of commander's `Option.argParser()`.)
7
+ */
8
+ export function parseFeature(partialFeatureName, accFeatures = {}, featureSet = allFeatures) {
9
+ const featureList = Object.keys(featureSet);
10
+ // Mapping from lowercase feature name to original name
11
+ const lowerFeatures = Object.fromEntries(featureList.map((f) => [f.toLowerCase(), f]));
12
+ const lowerFeatureName = partialFeatureName.toLowerCase();
13
+ if (featureSet[partialFeatureName]) {
14
+ // Simple case: valid verbatim name
15
+ accFeatures[partialFeatureName] = true;
16
+ }
17
+ else if (lowerFeatures[lowerFeatureName]) {
18
+ // Case-insensitive match
19
+ accFeatures[lowerFeatures[lowerFeatureName]] = true;
20
+ }
21
+ else {
22
+ // Fall back to a partial match
23
+ const matchedNames = Object.entries(lowerFeatures)
24
+ .filter(([lowerFeat]) => lowerFeat.includes(lowerFeatureName))
25
+ .map(([, origFeat]) => origFeat);
26
+ if (matchedNames.length === 1) {
27
+ // Exactly one substring match
28
+ accFeatures[matchedNames[0]] = true;
29
+ console.log(`Expanded --feature "${partialFeatureName}" to "${matchedNames[0]}".`);
30
+ }
31
+ else if (matchedNames.length > 1) {
32
+ throw new InvalidArgumentError(`Ambiguous feature "${partialFeatureName}". Did you mean one of these? ${matchedNames.join(', ')}`);
33
+ }
34
+ else {
35
+ // If there is no exact match, suggest the closest match.
36
+ const suggestion = didyoumean(partialFeatureName, featureList);
37
+ throw new InvalidArgumentError(`Unknown feature "${partialFeatureName}".${suggestion ? ` Did you mean "${suggestion}"?` : ''}`);
38
+ }
39
+ }
40
+ return accFeatures;
41
+ }
42
+ //# sourceMappingURL=parseFeature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseFeature.js","sourceRoot":"","sources":["../../src/utilities/parseFeature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,kBAA0B,EAC1B,cAAuC,EAAE,EACzC,aAAsC,WAAW;IAEjD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5C,uDAAuD;IACvD,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvF,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,WAAW,EAAE,CAAC;IAE1D,IAAI,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACnC,mCAAmC;QACnC,WAAW,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IACzC,CAAC;SAAM,IAAI,aAAa,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC3C,yBAAyB;QACzB,WAAW,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,+BAA+B;QAC/B,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;aAC/C,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;aAC7D,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;QAEnC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,8BAA8B;YAC9B,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,uBAAuB,kBAAkB,SAAS,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACrF,CAAC;aAAM,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,oBAAoB,CAC5B,sBAAsB,kBAAkB,iCAAiC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnG,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,yDAAyD;YACzD,MAAM,UAAU,GAAG,UAAU,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;YAC/D,MAAM,IAAI,oBAAoB,CAC5B,oBAAoB,kBAAkB,KAAK,UAAU,CAAC,CAAC,CAAC,kBAAkB,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAChG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import { allFeatures } from '@ms-cloudpack/common-types';\nimport { InvalidArgumentError } from 'commander';\nimport didyoumean from 'didyoumean';\n\n/**\n * Parse a `--feature` argument.\n * (This follows the signature of commander's `Option.argParser()`.)\n */\nexport function parseFeature(\n partialFeatureName: string,\n accFeatures: Record<string, boolean> = {},\n featureSet: Record<string, unknown> = allFeatures,\n): Record<string, boolean> {\n const featureList = Object.keys(featureSet);\n // Mapping from lowercase feature name to original name\n const lowerFeatures = Object.fromEntries(featureList.map((f) => [f.toLowerCase(), f]));\n const lowerFeatureName = partialFeatureName.toLowerCase();\n\n if (featureSet[partialFeatureName]) {\n // Simple case: valid verbatim name\n accFeatures[partialFeatureName] = true;\n } else if (lowerFeatures[lowerFeatureName]) {\n // Case-insensitive match\n accFeatures[lowerFeatures[lowerFeatureName]] = true;\n } else {\n // Fall back to a partial match\n const matchedNames = Object.entries(lowerFeatures)\n .filter(([lowerFeat]) => lowerFeat.includes(lowerFeatureName))\n .map(([, origFeat]) => origFeat);\n\n if (matchedNames.length === 1) {\n // Exactly one substring match\n accFeatures[matchedNames[0]] = true;\n console.log(`Expanded --feature \"${partialFeatureName}\" to \"${matchedNames[0]}\".`);\n } else if (matchedNames.length > 1) {\n throw new InvalidArgumentError(\n `Ambiguous feature \"${partialFeatureName}\". Did you mean one of these? ${matchedNames.join(', ')}`,\n );\n } else {\n // If there is no exact match, suggest the closest match.\n const suggestion = didyoumean(partialFeatureName, featureList);\n throw new InvalidArgumentError(\n `Unknown feature \"${partialFeatureName}\".${suggestion ? ` Did you mean \"${suggestion}\"?` : ''}`,\n );\n }\n }\n\n return accFeatures;\n}\n"]}
@@ -3,6 +3,14 @@ import { Option } from 'commander';
3
3
  * These options are used by multiple commands, but should be manually added.
4
4
  */
5
5
  export declare const reusedOptions: {
6
+ /**
7
+ * Specific app(s) to target. NOTE: This will only be respected if the `program.addSubCommand` call
8
+ * also sets `discoverAppPaths`.
9
+ */
10
+ readonly app: (options?: {
11
+ multi?: boolean;
12
+ }) => Option;
13
+ readonly bundler: () => Option;
6
14
  readonly logBundleInfo: (options?: {
7
15
  requiresNoCache?: boolean;
8
16
  }) => Option;
@@ -1 +1 @@
1
- {"version":3,"file":"reusedOptions.d.ts","sourceRoot":"","sources":["../../src/utilities/reusedOptions.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,MAAM,EAAE,MAAM,WAAW,CAAC;AAKzD;;GAEG;AACH,eAAO,MAAM,aAAa;uCACE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE;;IAOvD;;;OAGG;uCACuB,MAAM;6BAKhB;QAAE,MAAM,EAAE,QAAQ,GAAG,KAAK,CAAA;KAAE;IAO5C,0BAA0B;;;CAQgD,CAAC"}
1
+ {"version":3,"file":"reusedOptions.d.ts","sourceRoot":"","sources":["../../src/utilities/reusedOptions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,MAAM,EAAE,MAAM,WAAW,CAAC;AAKzD;;GAEG;AACH,eAAO,MAAM,aAAa;IACxB;;;OAGG;6BACa;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;;uCAOT;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE;;IAOvD;;;OAGG;uCACuB,MAAM;6BAKhB;QAAE,MAAM,EAAE,QAAQ,GAAG,KAAK,CAAA;KAAE;IAO5C,0BAA0B;;;CAQgD,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { bundlerNames } from '@ms-cloudpack/bundler';
1
2
  import { InvalidArgumentError, Option } from 'commander';
2
3
  import { parseMatch } from './parseMatch.js';
3
4
  import { environmentInfo } from '@ms-cloudpack/environment';
@@ -5,6 +6,13 @@ import { environmentInfo } from '@ms-cloudpack/environment';
5
6
  * These options are used by multiple commands, but should be manually added.
6
7
  */
7
8
  export const reusedOptions = {
9
+ /**
10
+ * Specific app(s) to target. NOTE: This will only be respected if the `program.addSubCommand` call
11
+ * also sets `discoverAppPaths`.
12
+ */
13
+ app: (options) => new Option('--app <appPackageName>', `Run Cloudpack targeting ${options?.multi ? 'specific app(s)' : 'a specific app'} ` +
14
+ '(prefers an exact match, or falls back to substrings).'),
15
+ bundler: () => new Option('--bundler <name>', 'Force using a specific bundler.').choices(bundlerNames),
8
16
  logBundleInfo: (options) => new Option('--log-bundle-info', 'For each package, write log files in its output folder with bundle input, output, and analyzed info.' +
9
17
  (options?.requiresNoCache ? ' (Note: requires --no-cache option if bundle output already exists.)' : '')),
10
18
  logResolveMap: () => new Option('--log-resolve-map', 'Log the resolve map to "resolve-map.json" for diagnostics.'),
@@ -1 +1 @@
1
- {"version":3,"file":"reusedOptions.js","sourceRoot":"","sources":["../../src/utilities/reusedOptions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,aAAa,EAAE,CAAC,OAAuC,EAAE,EAAE,CACzD,IAAI,MAAM,CACR,mBAAmB,EACnB,sGAAsG;QACpG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,sEAAsE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC3G;IACH,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,4DAA4D,CAAC;IAClH;;;OAGG;IACH,KAAK,EAAE,CAAC,gBAAwB,EAAE,EAAE,CAClC,IAAI,MAAM,CACR,oBAAoB,EACpB,GAAG,gBAAgB,gEAAgE,CACpF,CAAC,SAAS,CAAC,UAAU,CAAC;IACzB,IAAI,EAAE,CAAC,OAAqC,EAAE,EAAE,CAC9C,IAAI,MAAM,CACR,eAAe,EACf,eAAe,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,aAAa,6BAA6B,CAC/G;SACE,SAAS,CAAC,eAAe,CAAC;SAC1B,OAAO,CAAC,SAAS,CAAC;IACvB,0BAA0B;IAC1B,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,wDAAwD,CAAC;IAC/F,KAAK,EAAE,GAAG,EAAE,CACV,IAAI,MAAM,CAAC,kBAAkB,EAAE,+CAA+C,CAAC;SAC5E,OAAO,CAAC,CAAC,aAAa,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;SACpD,OAAO,CAAC,eAAe,EAAE,EAAE,gFAAgF,CAAC;IACjH,+EAA+E;IAC/E,8DAA8D;CACY,CAAC;AAE7E,kFAAkF;AAClF,SAAS,eAAe,CAAC,IAAY;IACnC,QAAQ,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3B,KAAK,KAAK,CAAC;QACX,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC;QACnB,KAAK,KAAK,CAAC;QACX,KAAK,aAAa;YAChB,OAAO,aAAa,CAAC;QACvB,KAAK,MAAM,CAAC;QACZ,KAAK,YAAY;YACf,OAAO,YAAY,CAAC;QACtB;YACE,MAAM,IAAI,oBAAoB,CAAC,4CAA4C,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC;AAC3G,CAAC","sourcesContent":["import type { BundleMode } from '@ms-cloudpack/common-types';\nimport { InvalidArgumentError, Option } from 'commander';\nimport { parseMatch } from './parseMatch.js';\nimport { environmentInfo } from '@ms-cloudpack/environment';\nimport type { ReusedOptions } from '../types/ReusedOptions.js';\n\n/**\n * These options are used by multiple commands, but should be manually added.\n */\nexport const reusedOptions = {\n logBundleInfo: (options?: { requiresNoCache?: boolean }) =>\n new Option(\n '--log-bundle-info',\n 'For each package, write log files in its output folder with bundle input, output, and analyzed info.' +\n (options?.requiresNoCache ? ' (Note: requires --no-cache option if bundle output already exists.)' : ''),\n ),\n logResolveMap: () => new Option('--log-resolve-map', 'Log the resolve map to \"resolve-map.json\" for diagnostics.'),\n /**\n * @param descriptionStart Start of description for this command, e.g. \"Bundle specific package(s)\"\n * (it will automatically include an optional version note and examples)\n */\n match: (descriptionStart: string) =>\n new Option(\n '--match <match...>',\n `${descriptionStart}, optionally with a version: e.g. \"foo\", \"@foo/*\", \"foo@1.2.3\"`,\n ).argParser(parseMatch),\n mode: (options: { action: 'bundle' | 'run' }) =>\n new Option(\n '--mode <mode>',\n `The mode to ${options.action === 'bundle' ? 'bundle the package' : 'run the app'} in. (library | production)`,\n )\n .argParser(parseBundleMode)\n .default('library'),\n /** `--no-cache` option */\n cache: () => new Option('--no-cache', 'Rebuild all packages, rather than using cached assets.'),\n login: () =>\n new Option('--login <method>', 'How to authenticate against the remote cache.')\n .choices(['interactive', 'azure-cli', 'device-code'])\n .default(getDefaultLogin(), '\"azure-cli\" in CI, \"device-code\" in Github Codespaces, \"interactive\" otherwise'),\n // Verify the type with `satisfies` to preserve individual function signatures.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n} as const satisfies Record<keyof ReusedOptions, (...args: any[]) => Option>;\n\n/** Parse the session mode based on user input (e.g. --mode argument in start.) */\nfunction parseBundleMode(mode: string): BundleMode {\n switch (mode.toLowerCase()) {\n case 'lib':\n case 'library':\n return 'library';\n case 'dev':\n case 'development':\n return 'development';\n case 'prod':\n case 'production':\n return 'production';\n default:\n throw new InvalidArgumentError(`Valid options are 'lib', 'dev', or 'prod'.`);\n }\n}\n\nfunction getDefaultLogin(): string {\n return environmentInfo.isCI ? 'azure-cli' : environmentInfo.isCodespaces ? 'device-code' : 'interactive';\n}\n"]}
1
+ {"version":3,"file":"reusedOptions.js","sourceRoot":"","sources":["../../src/utilities/reusedOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B;;;OAGG;IACH,GAAG,EAAE,CAAC,OAA6B,EAAE,EAAE,CACrC,IAAI,MAAM,CACR,wBAAwB,EACxB,2BAA2B,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,gBAAgB,GAAG;QACjF,wDAAwD,CAC3D;IACH,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,kBAAkB,EAAE,iCAAiC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;IACtG,aAAa,EAAE,CAAC,OAAuC,EAAE,EAAE,CACzD,IAAI,MAAM,CACR,mBAAmB,EACnB,sGAAsG;QACpG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,sEAAsE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC3G;IACH,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,4DAA4D,CAAC;IAClH;;;OAGG;IACH,KAAK,EAAE,CAAC,gBAAwB,EAAE,EAAE,CAClC,IAAI,MAAM,CACR,oBAAoB,EACpB,GAAG,gBAAgB,gEAAgE,CACpF,CAAC,SAAS,CAAC,UAAU,CAAC;IACzB,IAAI,EAAE,CAAC,OAAqC,EAAE,EAAE,CAC9C,IAAI,MAAM,CACR,eAAe,EACf,eAAe,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,aAAa,6BAA6B,CAC/G;SACE,SAAS,CAAC,eAAe,CAAC;SAC1B,OAAO,CAAC,SAAS,CAAC;IACvB,0BAA0B;IAC1B,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,wDAAwD,CAAC;IAC/F,KAAK,EAAE,GAAG,EAAE,CACV,IAAI,MAAM,CAAC,kBAAkB,EAAE,+CAA+C,CAAC;SAC5E,OAAO,CAAC,CAAC,aAAa,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;SACpD,OAAO,CAAC,eAAe,EAAE,EAAE,gFAAgF,CAAC;IACjH,+EAA+E;IAC/E,8DAA8D;CACY,CAAC;AAE7E,kFAAkF;AAClF,SAAS,eAAe,CAAC,IAAY;IACnC,QAAQ,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3B,KAAK,KAAK,CAAC;QACX,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC;QACnB,KAAK,KAAK,CAAC;QACX,KAAK,aAAa;YAChB,OAAO,aAAa,CAAC;QACvB,KAAK,MAAM,CAAC;QACZ,KAAK,YAAY;YACf,OAAO,YAAY,CAAC;QACtB;YACE,MAAM,IAAI,oBAAoB,CAAC,4CAA4C,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC;AAC3G,CAAC","sourcesContent":["import { bundlerNames } from '@ms-cloudpack/bundler';\nimport type { BundleMode } from '@ms-cloudpack/common-types';\nimport { InvalidArgumentError, Option } from 'commander';\nimport { parseMatch } from './parseMatch.js';\nimport { environmentInfo } from '@ms-cloudpack/environment';\nimport type { ReusedOptions } from '../types/ReusedOptions.js';\n\n/**\n * These options are used by multiple commands, but should be manually added.\n */\nexport const reusedOptions = {\n /**\n * Specific app(s) to target. NOTE: This will only be respected if the `program.addSubCommand` call\n * also sets `discoverAppPaths`.\n */\n app: (options?: { multi?: boolean }) =>\n new Option(\n '--app <appPackageName>',\n `Run Cloudpack targeting ${options?.multi ? 'specific app(s)' : 'a specific app'} ` +\n '(prefers an exact match, or falls back to substrings).',\n ),\n bundler: () => new Option('--bundler <name>', 'Force using a specific bundler.').choices(bundlerNames),\n logBundleInfo: (options?: { requiresNoCache?: boolean }) =>\n new Option(\n '--log-bundle-info',\n 'For each package, write log files in its output folder with bundle input, output, and analyzed info.' +\n (options?.requiresNoCache ? ' (Note: requires --no-cache option if bundle output already exists.)' : ''),\n ),\n logResolveMap: () => new Option('--log-resolve-map', 'Log the resolve map to \"resolve-map.json\" for diagnostics.'),\n /**\n * @param descriptionStart Start of description for this command, e.g. \"Bundle specific package(s)\"\n * (it will automatically include an optional version note and examples)\n */\n match: (descriptionStart: string) =>\n new Option(\n '--match <match...>',\n `${descriptionStart}, optionally with a version: e.g. \"foo\", \"@foo/*\", \"foo@1.2.3\"`,\n ).argParser(parseMatch),\n mode: (options: { action: 'bundle' | 'run' }) =>\n new Option(\n '--mode <mode>',\n `The mode to ${options.action === 'bundle' ? 'bundle the package' : 'run the app'} in. (library | production)`,\n )\n .argParser(parseBundleMode)\n .default('library'),\n /** `--no-cache` option */\n cache: () => new Option('--no-cache', 'Rebuild all packages, rather than using cached assets.'),\n login: () =>\n new Option('--login <method>', 'How to authenticate against the remote cache.')\n .choices(['interactive', 'azure-cli', 'device-code'])\n .default(getDefaultLogin(), '\"azure-cli\" in CI, \"device-code\" in Github Codespaces, \"interactive\" otherwise'),\n // Verify the type with `satisfies` to preserve individual function signatures.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n} as const satisfies Record<keyof ReusedOptions, (...args: any[]) => Option>;\n\n/** Parse the session mode based on user input (e.g. --mode argument in start.) */\nfunction parseBundleMode(mode: string): BundleMode {\n switch (mode.toLowerCase()) {\n case 'lib':\n case 'library':\n return 'library';\n case 'dev':\n case 'development':\n return 'development';\n case 'prod':\n case 'production':\n return 'production';\n default:\n throw new InvalidArgumentError(`Valid options are 'lib', 'dev', or 'prod'.`);\n }\n}\n\nfunction getDefaultLogin(): string {\n return environmentInfo.isCI ? 'azure-cli' : environmentInfo.isCodespaces ? 'device-code' : 'interactive';\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ms-cloudpack/cli",
3
- "version": "0.72.49",
3
+ "version": "0.72.50",
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",
@@ -10,14 +10,14 @@
10
10
  "cloudpack": "./bin/cloudpack.js"
11
11
  },
12
12
  "dependencies": {
13
- "@ms-cloudpack/api-server": "^0.58.14",
14
- "@ms-cloudpack/app-server": "^0.17.44",
15
- "@ms-cloudpack/bundler": "^0.23.37",
13
+ "@ms-cloudpack/api-server": "^0.58.15",
14
+ "@ms-cloudpack/app-server": "^0.17.45",
15
+ "@ms-cloudpack/bundler": "^0.23.38",
16
16
  "@ms-cloudpack/common-types": "^0.24.6",
17
- "@ms-cloudpack/config": "^0.33.13",
17
+ "@ms-cloudpack/config": "^0.33.14",
18
18
  "@ms-cloudpack/environment": "^0.1.1",
19
19
  "@ms-cloudpack/json-utilities": "^0.1.10",
20
- "@ms-cloudpack/overlay": "^0.17.125",
20
+ "@ms-cloudpack/overlay": "^0.17.126",
21
21
  "@ms-cloudpack/package-utilities": "^11.3.3",
22
22
  "@ms-cloudpack/path-string-parsing": "^1.2.6",
23
23
  "@ms-cloudpack/path-utilities": "^3.0.3",
@@ -1,12 +0,0 @@
1
- import type { CommandExitParams } from '../../types/CommandAction.js';
2
- export declare const appPromptQuestionName = "app";
3
- /**
4
- * Gets the appPath from which Cloudpack will start. If the CWD is a Cloudpack-enabled app,
5
- * we'll start there; otherwise, we'll scan for Cloudpack-enabled app and present the user
6
- * with a menu. If no app are found, Cloudpack will just try to start the CWD anyway.
7
- * @param cwd - The current working directory to start in when finding the starting app path
8
- * @param desiredApp - The app that should be started as specified via --app arg
9
- * @returns The app path of the app that Cloudpack should start, or an exit options object if the user cancels
10
- */
11
- export declare function getStartingAppPath(cwd: string, desiredApp?: string): Promise<string | CommandExitParams>;
12
- //# sourceMappingURL=getStartingAppPath.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getStartingAppPath.d.ts","sourceRoot":"","sources":["../../../src/commands/start/getStartingAppPath.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGtE,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAG3C;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,iBAAiB,CAAC,CAoD9G"}
@@ -1,60 +0,0 @@
1
- import { PackageDefinitions } from '@ms-cloudpack/package-utilities';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import prompts from 'prompts';
5
- import { findCloudpackAppPaths } from '../../utilities/findCloudpackAppPaths.js';
6
- import { appConfigFileName } from '@ms-cloudpack/config';
7
- export const appPromptQuestionName = 'app';
8
- /**
9
- * Gets the appPath from which Cloudpack will start. If the CWD is a Cloudpack-enabled app,
10
- * we'll start there; otherwise, we'll scan for Cloudpack-enabled app and present the user
11
- * with a menu. If no app are found, Cloudpack will just try to start the CWD anyway.
12
- * @param cwd - The current working directory to start in when finding the starting app path
13
- * @param desiredApp - The app that should be started as specified via --app arg
14
- * @returns The app path of the app that Cloudpack should start, or an exit options object if the user cancels
15
- */
16
- export async function getStartingAppPath(cwd, desiredApp) {
17
- const cwdIsCloudpackApp = fs.existsSync(path.join(cwd, appConfigFileName));
18
- if (cwdIsCloudpackApp) {
19
- return cwd;
20
- }
21
- const cloudpackAppPaths = findCloudpackAppPaths(cwd);
22
- if (cloudpackAppPaths.length === 0) {
23
- return cwd;
24
- }
25
- if (cloudpackAppPaths.length === 1) {
26
- return cloudpackAppPaths[0];
27
- }
28
- const packages = new PackageDefinitions();
29
- const choices = await Promise.all(cloudpackAppPaths.map(async (dir) => {
30
- const pkg = await packages.get(dir);
31
- return {
32
- title: pkg.name,
33
- description: pkg?.description ?? 'An awesome app that would be even more awesome with a proper description',
34
- value: dir,
35
- };
36
- }));
37
- choices.sort((c1, c2) => c1.title.localeCompare(c2.title));
38
- if (desiredApp) {
39
- const matchingApps = choices.filter((choice) => choice.title.includes(desiredApp));
40
- if (matchingApps.length === 1) {
41
- return matchingApps[0].value;
42
- }
43
- const exactMatch = matchingApps.find((choice) => choice.title === desiredApp);
44
- if (exactMatch) {
45
- return exactMatch.value;
46
- }
47
- }
48
- const response = await prompts({
49
- type: 'select',
50
- name: appPromptQuestionName,
51
- message: 'Select the app you want to start',
52
- choices,
53
- });
54
- // This will be undefined if the user cancels the prompt
55
- if (!response.app) {
56
- return { isInterrupted: true, message: '' };
57
- }
58
- return response.app;
59
- }
60
- //# sourceMappingURL=getStartingAppPath.js.map