@flowscripter/dynamic-cli-framework 7.0.11 → 7.1.1

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 (70) hide show
  1. package/dist/src/cli/BaseCLI.d.ts.map +1 -1
  2. package/dist/src/cli/BaseCLI.js +7 -1
  3. package/dist/src/cli/BaseCLIFeatureOptions.d.ts +5 -0
  4. package/dist/src/cli/BaseCLIFeatureOptions.d.ts.map +1 -1
  5. package/dist/src/cli/DefaultRuntimeCLI.js +1 -1
  6. package/dist/src/runtime/runner.d.ts +10 -1
  7. package/dist/src/runtime/runner.d.ts.map +1 -1
  8. package/dist/src/runtime/runner.js +7 -1
  9. package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts.map +1 -1
  10. package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts.map +1 -1
  11. package/dist/src/service/configuration/DefaultKeyValueService.d.ts +9 -1
  12. package/dist/src/service/configuration/DefaultKeyValueService.d.ts.map +1 -1
  13. package/dist/src/service/configuration/DefaultKeyValueService.js +16 -1
  14. package/dist/src/service/configuration/KeyValueServiceProvider.d.ts.map +1 -1
  15. package/dist/src/service/configuration/KeyValueServiceProvider.js +13 -6
  16. package/dist/src/service/prompter/DefaultPrompterService.d.ts +2 -1
  17. package/dist/src/service/prompter/DefaultPrompterService.d.ts.map +1 -1
  18. package/dist/src/service/prompter/DefaultPrompterService.js +3 -0
  19. package/dist/src/service/prompter/PrompterServiceProvider.d.ts +2 -3
  20. package/dist/src/service/prompter/PrompterServiceProvider.d.ts.map +1 -1
  21. package/dist/src/service/prompter/PrompterServiceProvider.js +5 -1
  22. package/dist/src/service/prompter/prompt/PromptContext.d.ts +4 -1
  23. package/dist/src/service/prompter/prompt/PromptContext.d.ts.map +1 -1
  24. package/dist/src/service/prompter/prompt/PromptContext.js +10 -0
  25. package/dist/src/service/prompter/prompt/promptMultiSelect.d.ts.map +1 -1
  26. package/dist/src/service/prompter/prompt/promptMultiSelect.js +2 -3
  27. package/dist/src/service/prompter/prompt/promptOpenUrl.d.ts +2 -1
  28. package/dist/src/service/prompter/prompt/promptOpenUrl.d.ts.map +1 -1
  29. package/dist/src/service/prompter/prompt/promptOpenUrl.js +14 -10
  30. package/dist/src/service/prompter/prompt/promptSingleSelect.d.ts.map +1 -1
  31. package/dist/src/service/prompter/prompt/promptSingleSelect.js +2 -3
  32. package/dist/src/service/prompter/prompt/promptText.d.ts.map +1 -1
  33. package/dist/src/service/prompter/prompt/promptText.js +2 -3
  34. package/dist/src/service/shutdown/DefaultShutdownService.d.ts +3 -0
  35. package/dist/src/service/shutdown/DefaultShutdownService.d.ts.map +1 -1
  36. package/dist/src/service/shutdown/DefaultShutdownService.js +7 -0
  37. package/dist/src/service/shutdown/ShutdownServiceProvider.js +4 -4
  38. package/dist/src/service/spawn/DefaultSpawnService.d.ts.map +1 -1
  39. package/dist/src/service/spawn/DefaultSpawnService.js +1 -0
  40. package/dist/src/service/upgrade/DefaultUpgradeService.d.ts +30 -2
  41. package/dist/src/service/upgrade/DefaultUpgradeService.d.ts.map +1 -1
  42. package/dist/src/service/upgrade/DefaultUpgradeService.js +99 -6
  43. package/dist/src/service/upgrade/UpgradeServiceProvider.d.ts +19 -4
  44. package/dist/src/service/upgrade/UpgradeServiceProvider.d.ts.map +1 -1
  45. package/dist/src/service/upgrade/UpgradeServiceProvider.js +51 -12
  46. package/dist/src/startup/banner/bannerStartupTask.d.ts.map +1 -1
  47. package/dist/src/startup/banner/bannerStartupTask.js +9 -5
  48. package/package.json +2 -2
  49. package/src/cli/BaseCLI.ts +7 -0
  50. package/src/cli/BaseCLIFeatureOptions.ts +5 -0
  51. package/src/cli/DefaultRuntimeCLI.ts +1 -1
  52. package/src/runtime/runner.ts +17 -2
  53. package/src/service/completion/command/CompletionCompleteSubCommand.ts +2 -4
  54. package/src/service/completion/command/CompletionIntegrationSubCommand.ts +2 -4
  55. package/src/service/configuration/DefaultKeyValueService.ts +22 -1
  56. package/src/service/configuration/KeyValueServiceProvider.ts +18 -6
  57. package/src/service/prompter/DefaultPrompterService.ts +6 -2
  58. package/src/service/prompter/PrompterServiceProvider.ts +6 -3
  59. package/src/service/prompter/prompt/PromptContext.ts +19 -1
  60. package/src/service/prompter/prompt/promptMultiSelect.ts +2 -3
  61. package/src/service/prompter/prompt/promptOpenUrl.ts +18 -11
  62. package/src/service/prompter/prompt/promptSingleSelect.ts +2 -3
  63. package/src/service/prompter/prompt/promptText.ts +2 -3
  64. package/src/service/shutdown/DefaultShutdownService.ts +10 -0
  65. package/src/service/shutdown/ShutdownServiceProvider.ts +4 -4
  66. package/src/service/spawn/DefaultSpawnService.ts +1 -0
  67. package/src/service/upgrade/DefaultUpgradeService.ts +112 -5
  68. package/src/service/upgrade/UpgradeServiceProvider.ts +77 -19
  69. package/src/service/upgrade/command/UpgradeSubCommand.ts +2 -2
  70. package/src/startup/banner/bannerStartupTask.ts +11 -5
@@ -1 +1 @@
1
- {"version":3,"file":"BaseCLI.d.ts","sourceRoot":"","sources":["../../../src/cli/BaseCLI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,yCAAyC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAGvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAS3E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAChD,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AAqCpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,CAAC,OAAO,OAAO,OAAQ,YAAW,GAAG;;IAazC,YACE,SAAS,EAAE,SAAS,EACpB,oBAAoB,EAAE,cAAc,EACpC,oBAAoB,EAAE,cAAc,EACpC,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,OAAO,EACtB,cAAc,EAAE,QAAQ,EACxB,cAAc,EAAE,QAAQ,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,OAAO,CAAC,EAAE,qBAAqB,EAkEhC;IAED;;;;;;;OAOG;IACI,kBAAkB,CAAC,eAAe,EAAE,eAAe,QAEzD;IAED;;;;;;;;OAQG;IACH;;;;;OAKG;IACI,cAAc,CAAC,IAAI,EAAE,WAAW,QAEtC;IAEM,UAAU,CAAC,OAAO,EAAE,OAAO,QAQjC;IAEK,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CA8PzD;CACF"}
1
+ {"version":3,"file":"BaseCLI.d.ts","sourceRoot":"","sources":["../../../src/cli/BaseCLI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,yCAAyC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAGvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAS3E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAChD,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AAqCpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,CAAC,OAAO,OAAO,OAAQ,YAAW,GAAG;;IAazC,YACE,SAAS,EAAE,SAAS,EACpB,oBAAoB,EAAE,cAAc,EACpC,oBAAoB,EAAE,cAAc,EACpC,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,OAAO,EACtB,cAAc,EAAE,QAAQ,EACxB,cAAc,EAAE,QAAQ,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,OAAO,CAAC,EAAE,qBAAqB,EAmEhC;IAED;;;;;;;OAOG;IACI,kBAAkB,CAAC,eAAe,EAAE,eAAe,QAEzD;IAED;;;;;;;;OAQG;IACH;;;;;OAKG;IACI,cAAc,CAAC,IAAI,EAAE,WAAW,QAEtC;IAEM,UAAU,CAAC,OAAO,EAAE,OAAO,QAQjC;IAEK,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAoQzD;CACF"}
@@ -109,6 +109,7 @@ export default class BaseCLI {
109
109
  fetchServiceEnabled: false,
110
110
  upgradeServiceEnabled: false,
111
111
  upgradeLocationsConfig: { supportedPlatforms: [] },
112
+ restartAfterAutoUpgrade: false,
112
113
  pluginServiceEnabled: false,
113
114
  pluginServiceRemoteConfig: { name: "", registryUrl: "", packageJsonNamespace: "" },
114
115
  pluginServiceLocalConfig: { nodeModulesPath: "", packageJsonNamespace: "" },
@@ -229,7 +230,8 @@ export default class BaseCLI {
229
230
  }
230
231
  let upgradeServiceProvider;
231
232
  if (this.#options.upgradeServiceEnabled) {
232
- upgradeServiceProvider = new UpgradeServiceProvider(UPGRADE_SERVICE_PRIORITY, this.#options.upgradeLocationsConfig);
233
+ upgradeServiceProvider = new UpgradeServiceProvider(UPGRADE_SERVICE_PRIORITY, this.#options.upgradeLocationsConfig, this.#options.restartAfterAutoUpgrade);
234
+ upgradeServiceProvider.setRestartArgs(args);
233
235
  this.addServiceProvider(upgradeServiceProvider);
234
236
  }
235
237
  if (this.#options.pluginServiceEnabled) {
@@ -285,6 +287,10 @@ export default class BaseCLI {
285
287
  this.#commandRegistry.addCommand(new VersionCommand());
286
288
  // run...
287
289
  const runResult = await run(args, this.#commandRegistry, this.#serviceProviderRegistry, configurationServiceProvider, keyValueServiceProvider, this.#context, defaultCommand, this.#startupServiceProvider.startupService);
290
+ // a startup task ended the run, having already handled its outcome itself
291
+ if (runResult.exitRequested) {
292
+ return { runState: runResult.runState };
293
+ }
288
294
  // then handle the result...
289
295
  if (runResult.runState === RunState.NO_COMMAND) {
290
296
  // print usage
@@ -12,6 +12,11 @@ export default interface BaseCLIFeatureOptions {
12
12
  readonly fetchServiceEnabled?: boolean;
13
13
  readonly upgradeServiceEnabled?: boolean;
14
14
  readonly upgradeLocationsConfig?: UpgradeLocationsConfig;
15
+ /**
16
+ * When an automatic upgrade on startup succeeds, run the upgraded executable with the same
17
+ * arguments and end this run with its result, rather than continuing on the old version.
18
+ */
19
+ readonly restartAfterAutoUpgrade?: boolean;
15
20
  readonly pluginServiceEnabled?: boolean;
16
21
  readonly pluginServiceRemoteConfig?: NpmjsPluginRepositoryConfig;
17
22
  readonly pluginServiceLocalConfig?: NpmPluginRepositoryConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"BaseCLIFeatureOptions.d.ts","sourceRoot":"","sources":["../../../src/cli/BaseCLIFeatureOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AAC3F,OAAO,KAAK,EACV,2BAA2B,EAC3B,yBAAyB,EAC1B,MAAM,wCAAwC,CAAC;AAEhD,MAAM,CAAC,OAAO,WAAW,qBAAqB;IAC5C,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IAClD,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAC9C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IACzD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,2BAA2B,CAAC;IACjE,QAAQ,CAAC,wBAAwB,CAAC,EAAE,yBAAyB,CAAC;IAC9D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC"}
1
+ {"version":3,"file":"BaseCLIFeatureOptions.d.ts","sourceRoot":"","sources":["../../../src/cli/BaseCLIFeatureOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AAC3F,OAAO,KAAK,EACV,2BAA2B,EAC3B,yBAAyB,EAC1B,MAAM,wCAAwC,CAAC;AAEhD,MAAM,CAAC,OAAO,WAAW,qBAAqB;IAC5C,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IAClD,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAC9C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IACzD;;;OAGG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAC3C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,2BAA2B,CAAC;IACjE,QAAQ,CAAC,wBAAwB,CAAC,EAAE,yBAAyB,CAAC;IAC9D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC"}
@@ -39,7 +39,7 @@ export default class DefaultRuntimeCLI extends BaseCLI {
39
39
  logger.debug(() => `keyReader constructed: ${keyReader !== undefined}`);
40
40
  const promptingEnabled = stdinIsTty && stderrIsTty;
41
41
  logger.debug(() => `promptingEnabled default: ${promptingEnabled}`);
42
- super(cliConfig, Writable.toWeb(process.stdout), Writable.toWeb(process.stderr), supportsColor.stdout !== false, supportsColor.stderr !== false, stdoutTerminal, stderrTerminal, new TtyStyler(colorLevel, supportsHyperlinks(process.stderr)), keyReader, { promptingEnabled, ...options });
42
+ super(cliConfig, Writable.toWeb(process.stdout), Writable.toWeb(process.stderr), supportsColor.stdout !== false, supportsColor.stderr !== false, stdoutTerminal, stderrTerminal, new TtyStyler(colorLevel, supportsHyperlinks(process.stderr)), keyReader, { promptingEnabled, restartAfterAutoUpgrade: true, ...options });
43
43
  }
44
44
  async run() {
45
45
  const runResult = await super.run(process.argv.slice(2));
@@ -6,6 +6,13 @@ import type ConfigurationServiceProvider from "../service/configuration/Configur
6
6
  import type KeyValueServiceProvider from "../service/configuration/KeyValueServiceProvider.ts";
7
7
  import type { Command } from "@flowscripter/dynamic-cli-framework-api";
8
8
  import DefaultStartupService from "../service/startup/DefaultStartupService.ts";
9
+ /**
10
+ * The {@link RunResult} returned by {@link run}, with `exitRequested` set when a startup task ended
11
+ * the run early by returning an `exitRequest`.
12
+ */
13
+ export type RunnerResult = RunResult & {
14
+ readonly exitRequested?: true;
15
+ };
9
16
  /**
10
17
  * Scan arguments and execute the parsed {@link Command} clauses with provided argument values
11
18
  * using the provided {@link Context}.
@@ -34,6 +41,8 @@ import DefaultStartupService from "../service/startup/DefaultStartupService.ts";
34
41
  * - Run the task: awaited before continuing if its mode is "blocking" (the default, and how
35
42
  * every ServiceProvider's initService() behaves); fired without awaiting if "background"
36
43
  * (errors logged, not propagated).
44
+ * - Return immediately if a "blocking" task returned an exitRequest, using its runState and
45
+ * skipping the remaining tasks and the command.
37
46
  * 2. Scan arguments for any GlobalModifierCommand clauses not provided by a StartupTask
38
47
  * - For each discovered clause:
39
48
  * - Set any argument defaults from ConfigurationServiceProvider
@@ -80,5 +89,5 @@ import DefaultStartupService from "../service/startup/DefaultStartupService.ts";
80
89
  * @param defaultCommand optional {@link SubCommand} or {@link GlobalCommand} implementation to attempt to parse arguments for and execute if
81
90
  * no non-modifier {@link Command} name is identified in the provided arguments.
82
91
  */
83
- export declare function run(args: ReadonlyArray<string>, commandRegistry: CommandRegistry, serviceProviderRegistry: ServiceProviderRegistry, configurationServiceProvider: ConfigurationServiceProvider | undefined, keyValueServiceProvider: KeyValueServiceProvider | undefined, context: Context, defaultCommand?: Command, startupService?: DefaultStartupService): Promise<RunResult>;
92
+ export declare function run(args: ReadonlyArray<string>, commandRegistry: CommandRegistry, serviceProviderRegistry: ServiceProviderRegistry, configurationServiceProvider: ConfigurationServiceProvider | undefined, keyValueServiceProvider: KeyValueServiceProvider | undefined, context: Context, defaultCommand?: Command, startupService?: DefaultStartupService): Promise<RunnerResult>;
84
93
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/runtime/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAiB/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAEvF,OAAO,KAAK,4BAA4B,MAAM,0DAA0D,CAAC;AACzG,OAAO,KAAK,uBAAuB,MAAM,qDAAqD,CAAC;AAK/F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAKvE,OAAO,qBAAqB,MAAM,6CAA6C,CAAC;AAqfhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,wBAAsB,GAAG,CACvB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,eAAe,EAAE,eAAe,EAChC,uBAAuB,EAAE,uBAAuB,EAChD,4BAA4B,EAAE,4BAA4B,GAAG,SAAS,EACtE,uBAAuB,EAAE,uBAAuB,GAAG,SAAS,EAC5D,OAAO,EAAE,OAAO,EAChB,cAAc,CAAC,EAAE,OAAO,EACxB,cAAc,CAAC,EAAE,qBAAqB,GACrC,OAAO,CAAC,SAAS,CAAC,CA6JpB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/runtime/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAiB/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAEvF,OAAO,KAAK,4BAA4B,MAAM,0DAA0D,CAAC;AACzG,OAAO,KAAK,uBAAuB,MAAM,qDAAqD,CAAC;AAK/F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAKvE,OAAO,qBAAqB,MAAM,6CAA6C,CAAC;AAKhF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAkfzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,wBAAsB,GAAG,CACvB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,eAAe,EAAE,eAAe,EAChC,uBAAuB,EAAE,uBAAuB,EAChD,4BAA4B,EAAE,4BAA4B,GAAG,SAAS,EACtE,uBAAuB,EAAE,uBAAuB,GAAG,SAAS,EAC5D,OAAO,EAAE,OAAO,EAChB,cAAc,CAAC,EAAE,OAAO,EACxB,cAAc,CAAC,EAAE,qBAAqB,GACrC,OAAO,CAAC,YAAY,CAAC,CAoKvB"}
@@ -389,6 +389,8 @@ async function findAndExecuteDefaultNonModifierCommand(availableArgs, unusedArgs
389
389
  * - Run the task: awaited before continuing if its mode is "blocking" (the default, and how
390
390
  * every ServiceProvider's initService() behaves); fired without awaiting if "background"
391
391
  * (errors logged, not propagated).
392
+ * - Return immediately if a "blocking" task returned an exitRequest, using its runState and
393
+ * skipping the remaining tasks and the command.
392
394
  * 2. Scan arguments for any GlobalModifierCommand clauses not provided by a StartupTask
393
395
  * - For each discovered clause:
394
396
  * - Set any argument defaults from ConfigurationServiceProvider
@@ -477,7 +479,11 @@ export async function run(args, commandRegistry, serviceProviderRegistry, config
477
479
  ? keyValueServiceProvider.getContextForScope(context, "service", task.id)
478
480
  : context;
479
481
  if ((task.mode ?? "blocking") === "blocking") {
480
- await task.run(taskContext);
482
+ const outcome = await task.run(taskContext);
483
+ if (outcome?.exitRequest) {
484
+ logger.debug(() => `Startup task '${task.id}' requested exit with run state ${outcome.exitRequest.runState}`);
485
+ return { runState: outcome.exitRequest.runState, exitRequested: true };
486
+ }
481
487
  }
482
488
  else {
483
489
  void task.run(taskContext).catch((error) => {
@@ -1 +1 @@
1
- {"version":3,"file":"CompletionCompleteSubCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/completion/command/CompletionCompleteSubCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,yCAAyC,CAAC;AAMrF,qBAAa,4BAA6B,YAAW,UAAU;IAC7D,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,WAAW,gDAAgD;IACpE,QAAQ,CAAC,mBAAmB,SAAS;IACrC,QAAQ,CAAC,yBAAyB,QAAQ;IAE1C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAM;IAE7C,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAc7C;IAEI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBrE;CACF"}
1
+ {"version":3,"file":"CompletionCompleteSubCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/completion/command/CompletionCompleteSubCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,yCAAyC,CAAC;AAMrF,qBAAa,4BAA6B,YAAW,UAAU;IAC7D,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,WAAW,gDAAgD;IACpE,QAAQ,CAAC,mBAAmB,SAAS;IACrC,QAAQ,CAAC,yBAAyB,QAAQ;IAE1C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAM;IAE7C,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAc7C;IAEI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBrE;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"CompletionIntegrationSubCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/completion/command/CompletionIntegrationSubCommand.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,yCAAyC,CAAC;AAMrF,qBAAa,+BAAgC,YAAW,UAAU;IAChE,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,0CAA0C;IAC9D,QAAQ,CAAC,mBAAmB,SAAS;IAErC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAOrC;IAEF,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAO7C;IAEI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DrE;CACF"}
1
+ {"version":3,"file":"CompletionIntegrationSubCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/completion/command/CompletionIntegrationSubCommand.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,yCAAyC,CAAC;AAMrF,qBAAa,+BAAgC,YAAW,UAAU;IAChE,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,0CAA0C;IAC9D,QAAQ,CAAC,mBAAmB,SAAS;IAErC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAOrC;IAEF,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAO7C;IAEI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDrE;CACF"}
@@ -7,8 +7,16 @@ import type DefaultSecretService from "./DefaultSecretService.ts";
7
7
  */
8
8
  export default class DefaultKeyValueService implements KeyValueService {
9
9
  #private;
10
- constructor(keyValueData: Map<string, ValueNode>, secretService?: DefaultSecretService);
10
+ /**
11
+ * @param keyValueData the scope's data.
12
+ * @param secretService optional secret service for {@link Secret} values.
13
+ * @param flushToStorage optional callback which writes every scope's pending changes to storage
14
+ * and marks them clean, invoked by {@link flush}.
15
+ */
16
+ constructor(keyValueData: Map<string, ValueNode>, secretService?: DefaultSecretService, flushToStorage?: () => Promise<void>);
11
17
  isDirty(): boolean;
18
+ markClean(): void;
19
+ flush(): Promise<void>;
12
20
  get<T extends ValueNode = ValueNode>(key: string): Promise<T>;
13
21
  has(key: string): Promise<boolean>;
14
22
  set(key: string, value: SettableValueNode): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultKeyValueService.d.ts","sourceRoot":"","sources":["../../../../src/service/configuration/DefaultKeyValueService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,iBAAiB,EAClB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,KAAK,oBAAoB,MAAM,2BAA2B,CAAC;AAGlE;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,eAAe;;IAKpE,YAAY,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,aAAa,CAAC,EAAE,oBAAoB,EAGrF;IAEM,OAAO,IAAI,OAAO,CAExB;IAEY,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAsBzE;IAEM,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAExC;IAEY,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;IAsCY,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9C;CAsBF"}
1
+ {"version":3,"file":"DefaultKeyValueService.d.ts","sourceRoot":"","sources":["../../../../src/service/configuration/DefaultKeyValueService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,iBAAiB,EAClB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,KAAK,oBAAoB,MAAM,2BAA2B,CAAC;AAGlE;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,eAAe;;IAMpE;;;;;OAKG;IACH,YACE,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,EACpC,aAAa,CAAC,EAAE,oBAAoB,EACpC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAKrC;IAEM,OAAO,IAAI,OAAO,CAExB;IAEM,SAAS,IAAI,IAAI,CAEvB;IAEY,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAGlC;IAEY,GAAG,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAsBzE;IAEM,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAExC;IAEY,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;IAsCY,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9C;CAsBF"}
@@ -9,13 +9,28 @@ export default class DefaultKeyValueService {
9
9
  #keyValueData;
10
10
  #dirty = false;
11
11
  #secretService;
12
- constructor(keyValueData, secretService) {
12
+ #flushToStorage;
13
+ /**
14
+ * @param keyValueData the scope's data.
15
+ * @param secretService optional secret service for {@link Secret} values.
16
+ * @param flushToStorage optional callback which writes every scope's pending changes to storage
17
+ * and marks them clean, invoked by {@link flush}.
18
+ */
19
+ constructor(keyValueData, secretService, flushToStorage) {
13
20
  this.#keyValueData = keyValueData;
14
21
  this.#secretService = secretService;
22
+ this.#flushToStorage = flushToStorage;
15
23
  }
16
24
  isDirty() {
17
25
  return this.#dirty;
18
26
  }
27
+ markClean() {
28
+ this.#dirty = false;
29
+ }
30
+ async flush() {
31
+ await this.#flushToStorage?.();
32
+ this.#dirty = false;
33
+ }
19
34
  async get(key) {
20
35
  const value = this.#keyValueData.get(key);
21
36
  if (value === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"KeyValueServiceProvider.d.ts","sourceRoot":"","sources":["../../../../src/service/configuration/KeyValueServiceProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,yCAAyC,CAAC;AAIjD,OAAO,KAAK,4BAA4B,MAAM,mCAAmC,CAAC;AAClF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAgClF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,eAAe;;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAwB;IAClD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAIjC,SAAgB,sBAAsB,EAAE,OAAO,CAAC;IAChD,SAAgB,oBAAoB,EAAE,OAAO,CAAC;IAW9C;;;;;;;;OAQG;IACH,YACE,eAAe,EAAE,MAAM,EACvB,4BAA4B,EAAE,4BAA4B,EAC1D,sBAAsB,UAAQ,EAC9B,oBAAoB,UAAQ,EAY7B;IAEM,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAUhE;IAED;;;;;;;;;;OAUG;IACI,wBAAwB,CAC7B,SAAS,EAAE,wBAAwB,EACnC,QAAQ,EAAE,MAAM,GACf,eAAe,CAsBjB;IAED;;;;;;;;;;;;;;OAcG;IACI,kBAAkB,CACvB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,wBAAwB,EACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAaT;IAeY,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CASxD;CACF"}
1
+ {"version":3,"file":"KeyValueServiceProvider.d.ts","sourceRoot":"","sources":["../../../../src/service/configuration/KeyValueServiceProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,yCAAyC,CAAC;AAIjD,OAAO,KAAK,4BAA4B,MAAM,mCAAmC,CAAC;AAClF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAoClF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,eAAe;;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAwB;IAClD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAIjC,SAAgB,sBAAsB,EAAE,OAAO,CAAC;IAChD,SAAgB,oBAAoB,EAAE,OAAO,CAAC;IAW9C;;;;;;;;OAQG;IACH,YACE,eAAe,EAAE,MAAM,EACvB,4BAA4B,EAAE,4BAA4B,EAC1D,sBAAsB,UAAQ,EAC9B,oBAAoB,UAAQ,EAY7B;IAEM,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAUhE;IAED;;;;;;;;;;OAUG;IACI,wBAAwB,CAC7B,SAAS,EAAE,wBAAwB,EACnC,QAAQ,EAAE,MAAM,GACf,eAAe,CAwBjB;IAED;;;;;;;;;;;;;;OAcG;IACI,kBAAkB,CACvB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,wBAAwB,EACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAaT;IAqBY,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CASxD;CACF"}
@@ -22,6 +22,9 @@ class UnreachableKeyValueService {
22
22
  delete() {
23
23
  return Promise.reject(new Error(UnreachableKeyValueService.#message));
24
24
  }
25
+ flush() {
26
+ return Promise.reject(new Error(UnreachableKeyValueService.#message));
27
+ }
25
28
  static #message = "KeyValueService accessed without a resolved scope - this should be unreachable";
26
29
  }
27
30
  /**
@@ -151,7 +154,7 @@ export default class KeyValueServiceProvider {
151
154
  const secretService = this.secretServiceEnabled
152
155
  ? new DefaultSecretService(this.#cliConfigName, `${scopeType}_${scopeKey}`)
153
156
  : undefined;
154
- const scopedService = new DefaultKeyValueService(keyValueData, secretService);
157
+ const scopedService = new DefaultKeyValueService(keyValueData, secretService, () => this.#flushDirtyScopes());
155
158
  scopedServices.set(scopeKey, scopedService);
156
159
  return scopedService;
157
160
  }
@@ -184,15 +187,19 @@ export default class KeyValueServiceProvider {
184
187
  }
185
188
  /**
186
189
  * Flush every scoped KeyValueService's data to the configuration file, if any of them report
187
- * themselves dirty. Registered as a low-priority ShutdownTask (see {@link initService}) so it
188
- * runs once, after other shutdown cleanup, regardless of how long any scope was written to.
190
+ * themselves dirty, then mark them all clean. Registered as a low-priority ShutdownTask (see
191
+ * {@link initService}) so it runs once, after other shutdown cleanup, regardless of how long any
192
+ * scope was written to. Also backs {@link KeyValueService.flush} for every scope.
189
193
  */
190
194
  async #flushDirtyScopes() {
191
- const anyDirty = [
195
+ const scopedServices = [
192
196
  ...this.#commandScopedKeyValueServices.values(),
193
197
  ...this.#serviceScopedKeyValueServices.values(),
194
- ].some((service) => service.isDirty());
195
- await this.#configurationServiceProvider.flushIfDirty(anyDirty);
198
+ ];
199
+ await this.#configurationServiceProvider.flushIfDirty(scopedServices.some((service) => service.isDirty()));
200
+ for (const service of scopedServices) {
201
+ service.markClean();
202
+ }
196
203
  }
197
204
  async initService(context) {
198
205
  if (this.keyValueServiceEnabled || this.secretServiceEnabled) {
@@ -1,4 +1,4 @@
1
- import type { PrompterService } from "@flowscripter/dynamic-cli-framework-api";
1
+ import type { Context, PrompterService } from "@flowscripter/dynamic-cli-framework-api";
2
2
  import { type Prompt, type PromptResult } from "@flowscripter/dynamic-cli-framework-api";
3
3
  import type Terminal from "../../terminal/Terminal.ts";
4
4
  import type KeyReader from "../../terminal/KeyReader.ts";
@@ -15,6 +15,7 @@ export default class DefaultPrompterService implements PrompterService {
15
15
  #private;
16
16
  promptEnabled: boolean;
17
17
  constructor(config: PrompterServiceConfig, terminal: Terminal, keyReader: KeyReader, printerService: PrinterService);
18
+ setContext(context: Context): void;
18
19
  prompt(promptDef: Prompt): Promise<PromptResult>;
19
20
  promptAll(prompts: ReadonlyArray<Prompt>): Promise<ReadonlyArray<PromptResult>>;
20
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultPrompterService.d.ts","sourceRoot":"","sources":["../../../../src/service/prompter/DefaultPrompterService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EACL,KAAK,MAAM,EACX,KAAK,YAAY,EAElB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,QAAQ,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,SAAS,MAAM,6BAA6B,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAS9E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,eAAO,MAAM,uBAAuB,EAAE,qBAKrC,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,eAAe;;IACpE,aAAa,UAAQ;IAIrB,YACE,MAAM,EAAE,qBAAqB,EAC7B,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,cAAc,EAG/B;IAED,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2B/C;IAEK,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAMpF;CACF"}
1
+ {"version":3,"file":"DefaultPrompterService.d.ts","sourceRoot":"","sources":["../../../../src/service/prompter/DefaultPrompterService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AACxF,OAAO,EACL,KAAK,MAAM,EACX,KAAK,YAAY,EAElB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,QAAQ,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,SAAS,MAAM,6BAA6B,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAS9E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,eAAO,MAAM,uBAAuB,EAAE,qBAKrC,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,eAAe;;IACpE,aAAa,UAAQ;IAIrB,YACE,MAAM,EAAE,qBAAqB,EAC7B,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,cAAc,EAG/B;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEjC;IAED,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2B/C;IAEK,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAMpF;CACF"}
@@ -17,6 +17,9 @@ export default class DefaultPrompterService {
17
17
  constructor(config, terminal, keyReader, printerService) {
18
18
  this.#ctx = { config, terminal, keyReader, printerService };
19
19
  }
20
+ setContext(context) {
21
+ this.#ctx = { ...this.#ctx, context };
22
+ }
20
23
  prompt(promptDef) {
21
24
  if (!this.promptEnabled) {
22
25
  if (promptDef.defaultOption) {
@@ -1,13 +1,12 @@
1
1
  import type { Context } from "@flowscripter/dynamic-cli-framework-api";
2
2
  import type { ServiceInfo, ServiceProvider } from "@flowscripter/dynamic-cli-framework-api";
3
- import type { PrompterService } from "@flowscripter/dynamic-cli-framework-api";
4
- import type { CLIConfig } from "@flowscripter/dynamic-cli-framework-api";
3
+ import type { CLIConfig, PrompterService } from "@flowscripter/dynamic-cli-framework-api";
5
4
  export default class PrompterServiceProvider implements ServiceProvider {
6
5
  readonly serviceId: string;
7
6
  readonly servicePriority: number;
8
7
  readonly prompterService: PrompterService;
9
8
  constructor(servicePriority: number, prompterService: PrompterService);
10
9
  getServiceInfo(_cliConfig: CLIConfig): Promise<ServiceInfo>;
11
- initService(_context: Context): Promise<void>;
10
+ initService(context: Context): Promise<void>;
12
11
  }
13
12
  //# sourceMappingURL=PrompterServiceProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PrompterServiceProvider.d.ts","sourceRoot":"","sources":["../../../../src/service/prompter/PrompterServiceProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC5F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAG/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,eAAe;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAuB;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAE1C,YAAmB,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,EAG3E;IAEM,cAAc,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAKjE;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5C;CACF"}
1
+ {"version":3,"file":"PrompterServiceProvider.d.ts","sourceRoot":"","sources":["../../../../src/service/prompter/PrompterServiceProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAG5F,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAG1F,MAAM,CAAC,OAAO,OAAO,uBAAwB,YAAW,eAAe;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAuB;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAE1C,YAAmB,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,EAG3E;IAEM,cAAc,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAKjE;IAED,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3C;CACF"}
@@ -1,5 +1,6 @@
1
1
  import { PROMPTER_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
2
2
  import NoPromptCommand from "./command/NoPromptCommand.js";
3
+ import DefaultPrompterService from "./DefaultPrompterService.js";
3
4
  export default class PrompterServiceProvider {
4
5
  serviceId = PROMPTER_SERVICE_ID;
5
6
  servicePriority;
@@ -14,7 +15,10 @@ export default class PrompterServiceProvider {
14
15
  commands: [new NoPromptCommand(this.servicePriority)],
15
16
  });
16
17
  }
17
- initService(_context) {
18
+ initService(context) {
19
+ if (this.prompterService instanceof DefaultPrompterService) {
20
+ this.prompterService.setContext(context);
21
+ }
18
22
  return Promise.resolve();
19
23
  }
20
24
  }
@@ -1,4 +1,4 @@
1
- import type { Prompt } from "@flowscripter/dynamic-cli-framework-api";
1
+ import type { Context, Prompt, SpawnService } from "@flowscripter/dynamic-cli-framework-api";
2
2
  import type Terminal from "../../../terminal/Terminal.ts";
3
3
  import type KeyReader from "../../../terminal/KeyReader.ts";
4
4
  import type { PrinterService } from "@flowscripter/dynamic-cli-framework-api";
@@ -8,7 +8,10 @@ export interface PromptContext {
8
8
  readonly terminal: Terminal;
9
9
  readonly keyReader: KeyReader;
10
10
  readonly printerService: PrinterService;
11
+ readonly context?: Context;
11
12
  }
13
+ export declare function interrupt(ctx: PromptContext): void;
14
+ export declare function getSpawnService(ctx: PromptContext): SpawnService | undefined;
12
15
  export declare function physicalLineCount(terminal: Terminal, text: string): number;
13
16
  export declare function headerLineCount(terminal: Terminal, promptDef: Prompt): number;
14
17
  export declare function renderPromptHeader(ctx: PromptContext, promptDef: Prompt): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"PromptContext.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/PromptContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,KAAK,QAAQ,MAAM,+BAA+B,CAAC;AAC1D,OAAO,KAAK,SAAS,MAAM,gCAAgC,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAO1E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAM7E;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7F"}
1
+ {"version":3,"file":"PromptContext.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/PromptContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,MAAM,EAEN,YAAY,EACb,MAAM,yCAAyC,CAAC;AAEjD,OAAO,KAAK,QAAQ,MAAM,+BAA+B,CAAC;AAC1D,OAAO,KAAK,SAAS,MAAM,gCAAgC,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAElD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,GAAG,SAAS,CAK5E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAO1E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAM7E;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7F"}
@@ -1,3 +1,13 @@
1
+ import { SHUTDOWN_SERVICE_ID, SPAWN_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
2
+ export function interrupt(ctx) {
3
+ ctx.context?.getServiceById(SHUTDOWN_SERVICE_ID)?.interrupt();
4
+ }
5
+ export function getSpawnService(ctx) {
6
+ if (!ctx.context?.doesServiceExist(SPAWN_SERVICE_ID)) {
7
+ return undefined;
8
+ }
9
+ return ctx.context.getServiceById(SPAWN_SERVICE_ID);
10
+ }
1
11
  export function physicalLineCount(terminal, text) {
2
12
  const cols = terminal.columns();
3
13
  if (cols <= 0)
@@ -1 +1 @@
1
- {"version":3,"file":"promptMultiSelect.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/promptMultiSelect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAIpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAA8B,iBAAiB,CAC7C,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,CAAC,CA0EvB"}
1
+ {"version":3,"file":"promptMultiSelect.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/promptMultiSelect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAGpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAA8B,iBAAiB,CAC7C,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,CAAC,CA0EvB"}
@@ -1,6 +1,5 @@
1
1
  import { SpecialKey } from "../../../terminal/KeyReader.js";
2
- import ShutdownServiceProvider from "../../shutdown/ShutdownServiceProvider.js";
3
- import { headerLineCount, renderPromptHeader } from "./PromptContext.js";
2
+ import { headerLineCount, renderPromptHeader, interrupt } from "./PromptContext.js";
4
3
  export default async function promptMultiSelect(ctx, promptDef) {
5
4
  const options = promptDef.options;
6
5
  if (options.length === 0) {
@@ -63,7 +62,7 @@ export default async function promptMultiSelect(ctx, promptDef) {
63
62
  }
64
63
  else if (keyEvent.specialKey === SpecialKey.INTERRUPT) {
65
64
  await ctx.terminal.showCursor();
66
- ShutdownServiceProvider.onInterrupt();
65
+ interrupt(ctx);
67
66
  throw new Error("Interrupted");
68
67
  }
69
68
  }
@@ -1,4 +1,5 @@
1
- import type { Prompt, PromptResult } from "@flowscripter/dynamic-cli-framework-api";
1
+ import type { Prompt, PromptResult, SpawnService } from "@flowscripter/dynamic-cli-framework-api";
2
2
  import type { PromptContext } from "./PromptContext.ts";
3
+ export declare function defaultOpenUrl(spawnService: SpawnService, url: string): Promise<void>;
3
4
  export default function promptOpenUrl(ctx: PromptContext, promptDef: Prompt): Promise<PromptResult>;
4
5
  //# sourceMappingURL=promptOpenUrl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"promptOpenUrl.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/promptOpenUrl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAIpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA2BxD,wBAA8B,aAAa,CACzC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,CAAC,CA+CvB"}
1
+ {"version":3,"file":"promptOpenUrl.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/promptOpenUrl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAGlG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMxD,wBAAsB,cAAc,CAAC,YAAY,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB3F;AAED,wBAA8B,aAAa,CACzC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,CAAC,CAkDvB"}
@@ -1,10 +1,9 @@
1
1
  import { SpecialKey } from "../../../terminal/KeyReader.js";
2
- import ShutdownServiceProvider from "../../shutdown/ShutdownServiceProvider.js";
3
- import { renderPromptHeader } from "./PromptContext.js";
2
+ import { getSpawnService, interrupt, renderPromptHeader } from "./PromptContext.js";
4
3
  function isRemoteSession() {
5
4
  return !!(process.env.SSH_CONNECTION || process.env.SSH_CLIENT || process.env.SSH_TTY);
6
5
  }
7
- async function defaultOpenUrl(url) {
6
+ export async function defaultOpenUrl(spawnService, url) {
8
7
  const parsed = new URL(url);
9
8
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
10
9
  throw new Error(`Unsupported URL protocol: ${parsed.protocol}`);
@@ -20,11 +19,14 @@ async function defaultOpenUrl(url) {
20
19
  else {
21
20
  cmd = ["xdg-open", url];
22
21
  }
23
- const proc = Bun.spawn(cmd, { stdout: "ignore", stderr: "ignore" });
24
- const exitCode = await proc.exited;
25
- if (exitCode !== 0) {
26
- throw new Error(`Failed to open URL (exit code ${exitCode})`);
22
+ const result = await spawnService.spawn(cmd, { mode: "ignore", longRunning: false });
23
+ if (result.ok) {
24
+ return;
27
25
  }
26
+ if ("error" in result && result.error) {
27
+ throw result.error;
28
+ }
29
+ throw new Error(`Failed to open URL (exit code ${"exitCode" in result ? result.exitCode : "unknown"})`);
28
30
  }
29
31
  export default async function promptOpenUrl(ctx, promptDef) {
30
32
  if (promptDef.options.length === 0) {
@@ -32,8 +34,10 @@ export default async function promptOpenUrl(ctx, promptDef) {
32
34
  }
33
35
  const url = String(promptDef.options[0].returnedValue);
34
36
  const displayLabel = promptDef.options[0].displayValue;
35
- const openUrlFn = ctx.config.openUrl ?? defaultOpenUrl;
36
- const canOpenBrowser = !isRemoteSession();
37
+ const spawnService = getSpawnService(ctx);
38
+ const openUrlFn = ctx.config.openUrl ??
39
+ (spawnService ? (target) => defaultOpenUrl(spawnService, target) : undefined);
40
+ const canOpenBrowser = openUrlFn !== undefined && !isRemoteSession();
37
41
  ctx.keyReader.enableRawMode();
38
42
  try {
39
43
  await renderPromptHeader(ctx, promptDef);
@@ -59,7 +63,7 @@ export default async function promptOpenUrl(ctx, promptDef) {
59
63
  throw new Error("Prompt cancelled");
60
64
  }
61
65
  else if (keyEvent.specialKey === SpecialKey.INTERRUPT) {
62
- ShutdownServiceProvider.onInterrupt();
66
+ interrupt(ctx);
63
67
  throw new Error("Interrupted");
64
68
  }
65
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"promptSingleSelect.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/promptSingleSelect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAIpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAA8B,kBAAkB,CAC9C,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,CAAC,CA2EvB"}
1
+ {"version":3,"file":"promptSingleSelect.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/promptSingleSelect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAGpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAA8B,kBAAkB,CAC9C,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,CAAC,CA2EvB"}
@@ -1,6 +1,5 @@
1
1
  import { SpecialKey } from "../../../terminal/KeyReader.js";
2
- import ShutdownServiceProvider from "../../shutdown/ShutdownServiceProvider.js";
3
- import { headerLineCount, renderPromptHeader } from "./PromptContext.js";
2
+ import { headerLineCount, renderPromptHeader, interrupt } from "./PromptContext.js";
4
3
  export default async function promptSingleSelect(ctx, promptDef) {
5
4
  const options = promptDef.options;
6
5
  if (options.length === 0) {
@@ -62,7 +61,7 @@ export default async function promptSingleSelect(ctx, promptDef) {
62
61
  }
63
62
  else if (keyEvent.specialKey === SpecialKey.INTERRUPT) {
64
63
  await ctx.terminal.showCursor();
65
- ShutdownServiceProvider.onInterrupt();
64
+ interrupt(ctx);
66
65
  throw new Error("Interrupted");
67
66
  }
68
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"promptText.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/promptText.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAKpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAA8B,UAAU,CACtC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,CAAC,CA+EvB"}
1
+ {"version":3,"file":"promptText.d.ts","sourceRoot":"","sources":["../../../../../src/service/prompter/prompt/promptText.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAIpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAA8B,UAAU,CACtC,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,YAAY,CAAC,CA+EvB"}
@@ -1,6 +1,5 @@
1
1
  import { SpecialKey } from "../../../terminal/KeyReader.js";
2
- import ShutdownServiceProvider from "../../shutdown/ShutdownServiceProvider.js";
3
- import { renderPromptHeader } from "./PromptContext.js";
2
+ import { renderPromptHeader, interrupt } from "./PromptContext.js";
4
3
  export default async function promptText(ctx, promptDef) {
5
4
  ctx.keyReader.enableRawMode();
6
5
  try {
@@ -24,7 +23,7 @@ export default async function promptText(ctx, promptDef) {
24
23
  }
25
24
  else if (keyEvent.specialKey === SpecialKey.INTERRUPT) {
26
25
  await ctx.terminal.write("\n");
27
- ShutdownServiceProvider.onInterrupt();
26
+ interrupt(ctx);
28
27
  throw new Error("Interrupted");
29
28
  }
30
29
  else if (keyEvent.specialKey === SpecialKey.BACKSPACE) {
@@ -1,10 +1,13 @@
1
1
  import type { ShutdownService, ShutdownTask } from "@flowscripter/dynamic-cli-framework-api";
2
2
  import PriorityTaskList from "../../runtime/lifecycle/PriorityTaskList.ts";
3
3
  export default class DefaultShutdownService implements ShutdownService {
4
+ #private;
4
5
  static readonly taskList: PriorityTaskList<ShutdownTask>;
6
+ constructor(onInterrupt?: () => void);
5
7
  registerTask(task: ShutdownTask): void;
6
8
  enterLongRunningMode(): void;
7
9
  leaveLongRunningMode(): void;
10
+ interrupt(): void;
8
11
  get isShutdownRequested(): boolean;
9
12
  }
10
13
  //# sourceMappingURL=DefaultShutdownService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultShutdownService.d.ts","sourceRoot":"","sources":["../../../../src/service/shutdown/DefaultShutdownService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAC7F,OAAO,gBAAgB,MAAM,6CAA6C,CAAC;AAG3E,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,eAAe;IACpE,MAAM,CAAC,QAAQ,CAAC,QAAQ,iCAAwC;IAEhE,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAErC;IAED,oBAAoB,IAAI,IAAI,CAE3B;IAED,oBAAoB,IAAI,IAAI,CAE3B;IAED,IAAI,mBAAmB,IAAI,OAAO,CAEjC;CACF"}
1
+ {"version":3,"file":"DefaultShutdownService.d.ts","sourceRoot":"","sources":["../../../../src/service/shutdown/DefaultShutdownService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAC7F,OAAO,gBAAgB,MAAM,6CAA6C,CAAC;AAG3E,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,eAAe;;IACpE,MAAM,CAAC,QAAQ,CAAC,QAAQ,iCAAwC;IAIhE,YAAmB,WAAW,GAAE,MAAM,IAAe,EAEpD;IAED,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAErC;IAED,oBAAoB,IAAI,IAAI,CAE3B;IAED,oBAAoB,IAAI,IAAI,CAE3B;IAED,SAAS,IAAI,IAAI,CAEhB;IAED,IAAI,mBAAmB,IAAI,OAAO,CAEjC;CACF"}
@@ -2,6 +2,10 @@ import PriorityTaskList from "../../runtime/lifecycle/PriorityTaskList.js";
2
2
  import { shutdownState } from "./ShutdownState.js";
3
3
  export default class DefaultShutdownService {
4
4
  static taskList = new PriorityTaskList();
5
+ #onInterrupt;
6
+ constructor(onInterrupt = () => { }) {
7
+ this.#onInterrupt = onInterrupt;
8
+ }
5
9
  registerTask(task) {
6
10
  DefaultShutdownService.taskList.add(task);
7
11
  }
@@ -11,6 +15,9 @@ export default class DefaultShutdownService {
11
15
  leaveLongRunningMode() {
12
16
  shutdownState.longRunningMode = false;
13
17
  }
18
+ interrupt() {
19
+ this.#onInterrupt();
20
+ }
14
21
  get isShutdownRequested() {
15
22
  return shutdownState.shutdownRequested;
16
23
  }
@@ -1,6 +1,6 @@
1
1
  import process from "node:process";
2
2
  import DefaultShutdownService from "./DefaultShutdownService.js";
3
- import { SHUTDOWN_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
3
+ import { RunState, SHUTDOWN_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
4
4
  import getLogger from "../../util/logger.js";
5
5
  import { shutdownState } from "./ShutdownState.js";
6
6
  const logger = getLogger("ShutdownServiceProvider");
@@ -11,7 +11,7 @@ export default class ShutdownServiceProvider {
11
11
  static #shutdownInProgress = false;
12
12
  constructor(servicePriority) {
13
13
  this.servicePriority = servicePriority;
14
- this.#shutdownService = new DefaultShutdownService();
14
+ this.#shutdownService = new DefaultShutdownService(ShutdownServiceProvider.onInterrupt);
15
15
  process.on("beforeExit", ShutdownServiceProvider.shutdown);
16
16
  process.on("SIGINT", ShutdownServiceProvider.onInterrupt);
17
17
  process.on("SIGTERM", ShutdownServiceProvider.onTerminate);
@@ -29,7 +29,7 @@ export default class ShutdownServiceProvider {
29
29
  shutdownState.interruptCount++;
30
30
  if (!shutdownState.longRunningMode || shutdownState.interruptCount >= 3) {
31
31
  ShutdownServiceProvider.shutdown().then(() => {
32
- process.exit(130);
32
+ process.exit(RunState.INTERRUPTED);
33
33
  });
34
34
  }
35
35
  else {
@@ -38,7 +38,7 @@ export default class ShutdownServiceProvider {
38
38
  }
39
39
  static onTerminate() {
40
40
  ShutdownServiceProvider.shutdown().then(() => {
41
- process.exit(143);
41
+ process.exit(RunState.TERMINATED);
42
42
  });
43
43
  }
44
44
  static async shutdown() {
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultSpawnService.d.ts","sourceRoot":"","sources":["../../../../src/service/spawn/DefaultSpawnService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EAGP,YAAY,EACZ,WAAW,EACX,YAAY,EACb,MAAM,yCAAyC,CAAC;AASjD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAa3E;AAED,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,YAAY;;IAGvD,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExC;IA+CY,KAAK,CAChB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CA0FtB;CACF"}
1
+ {"version":3,"file":"DefaultSpawnService.d.ts","sourceRoot":"","sources":["../../../../src/service/spawn/DefaultSpawnService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EAGP,YAAY,EACZ,WAAW,EACX,YAAY,EACb,MAAM,yCAAyC,CAAC;AASjD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAa3E;AAED,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,YAAY;;IAGvD,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExC;IA+CY,KAAK,CAChB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,EAC9B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CA2FtB;CACF"}
@@ -80,6 +80,7 @@ export default class DefaultSpawnService {
80
80
  try {
81
81
  proc = Bun.spawn(resolveForPlatform(command), {
82
82
  cwd: options.cwd,
83
+ env: options.env === undefined ? undefined : { ...process.env, ...options.env },
83
84
  stdin: mode === "inherit" ? "inherit" : "ignore",
84
85
  stdout: mode === "wrapped" ? "pipe" : mode === "ignore" ? "ignore" : "inherit",
85
86
  stderr: mode === "wrapped" ? "pipe" : mode === "ignore" ? "ignore" : "inherit",