@flowscripter/dynamic-cli-framework 5.1.6 → 5.1.7

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.
@@ -1,11 +1,17 @@
1
1
  import type { PluginService } from "@flowscripter/dynamic-cli-framework-api";
2
2
  import type { KeyValueService } from "@flowscripter/dynamic-cli-framework-api";
3
- import type { MarketplacePluginManager, SearchQuery, VersionedPluginDescriptor, NpmjsPluginRepositoryConfig, NpmPluginRepositoryConfig } from "@flowscripter/dynamic-plugin-framework";
3
+ import type { MarketplacePluginManager, SearchQuery, VersionedPluginDescriptor, NpmjsPluginRepositoryConfig, NpmPluginRepositoryConfig, FetchInterface } from "@flowscripter/dynamic-plugin-framework";
4
4
  export default class DefaultPluginService implements PluginService {
5
5
  #private;
6
6
  constructor(remoteConfig: NpmjsPluginRepositoryConfig, localConfig: NpmPluginRepositoryConfig);
7
7
  get pluginManager(): MarketplacePluginManager;
8
8
  applyKeyValueOverrides(keyValueService: KeyValueService): Promise<void>;
9
+ /**
10
+ * Supply the {@link FetchInterface} for the underlying `pluginManager` to delegate fetch calls
11
+ * to, so it respects the host CLI's shutdown handling and default timeout.
12
+ */
13
+ setFetch(fetchInterface: FetchInterface): void;
14
+ checkAvailable(pluginId: string, version?: string): Promise<boolean>;
9
15
  search(query: Readonly<SearchQuery>): AsyncIterable<Readonly<VersionedPluginDescriptor>>;
10
16
  install(descriptor: Readonly<VersionedPluginDescriptor>): Promise<void>;
11
17
  uninstall(pluginId: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultPluginService.d.ts","sourceRoot":"","sources":["../../../../src/service/plugin/DefaultPluginService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EACV,wBAAwB,EACxB,WAAW,EACX,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,EAC1B,MAAM,wCAAwC,CAAC;AAOhD,MAAM,CAAC,OAAO,OAAO,oBAAqB,YAAW,aAAa;;gBAKpD,YAAY,EAAE,2BAA2B,EAAE,WAAW,EAAE,yBAAyB;IAS7F,IAAI,aAAa,IAAI,wBAAwB,CAE5C;IAEK,sBAAsB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB7E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IAIlF,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,yBAAyB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,aAAa,IAAI,aAAa,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IAInE,eAAe,IAAI,aAAa,CAAC;QAC/B,UAAU,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAChD,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CAGH"}
1
+ {"version":3,"file":"DefaultPluginService.d.ts","sourceRoot":"","sources":["../../../../src/service/plugin/DefaultPluginService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EACV,wBAAwB,EACxB,WAAW,EACX,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,EAEzB,cAAc,EACf,MAAM,wCAAwC,CAAC;AAWhD,MAAM,CAAC,OAAO,OAAO,oBAAqB,YAAW,aAAa;;gBAKpD,YAAY,EAAE,2BAA2B,EAAE,WAAW,EAAE,yBAAyB;IAS7F,IAAI,aAAa,IAAI,wBAAwB,CAE5C;IAEK,sBAAsB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB7E;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI;IAMxC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IAIlF,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,yBAAyB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,aAAa,IAAI,aAAa,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IAInE,eAAe,IAAI,aAAa,CAAC;QAC/B,UAAU,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAChD,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CAGH"}
@@ -1,4 +1,7 @@
1
1
  import { NpmPluginManager, NpmjsPluginRepository, NpmPluginRepository, } from "@flowscripter/dynamic-plugin-framework";
2
+ function isFetchCapable(value) {
3
+ return typeof value === "object" && value !== null && "setFetch" in value;
4
+ }
2
5
  export default class DefaultPluginService {
3
6
  #defaultRemoteConfig;
4
7
  #defaultLocalConfig;
@@ -22,6 +25,18 @@ export default class DefaultPluginService {
22
25
  }
23
26
  this.#pluginManager = new NpmPluginManager(remotesConfig.map((config) => new NpmjsPluginRepository(config)), new NpmPluginRepository(localConfig));
24
27
  }
28
+ /**
29
+ * Supply the {@link FetchInterface} for the underlying `pluginManager` to delegate fetch calls
30
+ * to, so it respects the host CLI's shutdown handling and default timeout.
31
+ */
32
+ setFetch(fetchInterface) {
33
+ if (isFetchCapable(this.#pluginManager)) {
34
+ this.#pluginManager.setFetch(fetchInterface);
35
+ }
36
+ }
37
+ async checkAvailable(pluginId, version) {
38
+ return this.#pluginManager.checkAvailable(pluginId, version);
39
+ }
25
40
  search(query) {
26
41
  return this.#pluginManager.search(query);
27
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PluginServiceProvider.d.ts","sourceRoot":"","sources":["../../../../src/service/plugin/PluginServiceProvider.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;AAWzE,OAAO,KAAK,EAEV,2BAA2B,EAC3B,yBAAyB,EAE1B,MAAM,wCAAwC,CAAC;AAIhD,OAA8B,EAC5B,KAAK,4BAA4B,EAClC,MAAM,4BAA4B,CAAC;AACpC,OAA8B,EAC5B,KAAK,4BAA4B,EAClC,MAAM,4BAA4B,CAAC;AACpC,OAAO,sBAAsB,MAAM,kDAAkD,CAAC;AACtF,OAAO,8BAA8B,MAAM,0DAA0D,CAAC;AAMtG,MAAM,CAAC,OAAO,OAAO,qBAAsB,YAAW,eAAe;;IACnE,QAAQ,CAAC,SAAS,oBAAqB;IACvC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAW/B,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,2BAA2B,EACzC,WAAW,EAAE,yBAAyB,EACtC,eAAe,EAAE,sBAAsB,EACvC,uBAAuB,EAAE,8BAA8B,EACvD,4BAA4B,GAAE,4BAAiC,EAC/D,4BAA4B,GAAE,4BAAiC;IAW3D,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAS1D,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAmEnD"}
1
+ {"version":3,"file":"PluginServiceProvider.d.ts","sourceRoot":"","sources":["../../../../src/service/plugin/PluginServiceProvider.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;AAWzE,OAAO,KAAK,EACV,2BAA2B,EAC3B,yBAAyB,EAE1B,MAAM,wCAAwC,CAAC;AAIhD,OAA8B,EAC5B,KAAK,4BAA4B,EAClC,MAAM,4BAA4B,CAAC;AACpC,OAA8B,EAC5B,KAAK,4BAA4B,EAClC,MAAM,4BAA4B,CAAC;AACpC,OAAO,sBAAsB,MAAM,kDAAkD,CAAC;AACtF,OAAO,8BAA8B,MAAM,0DAA0D,CAAC;AAMtG,MAAM,CAAC,OAAO,OAAO,qBAAsB,YAAW,eAAe;;IACnE,QAAQ,CAAC,SAAS,oBAAqB;IACvC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAW/B,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,2BAA2B,EACzC,WAAW,EAAE,yBAAyB,EACtC,eAAe,EAAE,sBAAsB,EACvC,uBAAuB,EAAE,8BAA8B,EACvD,4BAA4B,GAAE,4BAAiC,EAC/D,4BAA4B,GAAE,4BAAiC;IAW3D,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAS1D,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAiEnD"}
@@ -60,15 +60,12 @@ export default class PluginServiceProvider {
60
60
  pluginManager.setSpawn(adapter);
61
61
  }
62
62
  if (!context.doesServiceExist(FETCH_SERVICE_ID)) {
63
- logger.debug("FetchService not available, plugin manager will fetch directly");
64
- }
65
- else if (!("setFetch" in pluginManager)) {
66
- logger.debug("Plugin manager does not support FetchCapable, skipping fetch injection");
63
+ logger.debug("FetchService not available, plugin service will fetch directly");
67
64
  }
68
65
  else {
69
66
  const fetchService = context.getServiceById(FETCH_SERVICE_ID);
70
67
  const adapter = new FetchInterfaceAdapter(fetchService, this.#fetchInterfaceAdapterOptions);
71
- pluginManager.setFetch(adapter);
68
+ pluginService.setFetch(adapter);
72
69
  }
73
70
  await pluginManager.registerExtensions(DYNAMIC_CLI_FRAMEWORK_COMMAND_FACTORY_EXTENSION_POINT);
74
71
  await pluginManager.registerExtensions(DYNAMIC_CLI_FRAMEWORK_SERVICE_PROVIDER_FACTORY_EXTENSION_POINT);
@@ -1 +1 @@
1
- {"version":3,"file":"PluginAddSubCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/plugin/command/PluginAddSubCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AASxE,qBAAa,mBAAoB,YAAW,UAAU;IACpD,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,WAAW,6BAA6B;IACjD,QAAQ,CAAC,mBAAmB,SAAS;IACrC,QAAQ,CAAC,OAAO,UAAM;IACtB,QAAQ,CAAC,WAAW;;;;QAMlB;IAEI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAkDvE"}
1
+ {"version":3,"file":"PluginAddSubCommand.d.ts","sourceRoot":"","sources":["../../../../../src/service/plugin/command/PluginAddSubCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AASxE,qBAAa,mBAAoB,YAAW,UAAU;IACpD,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,WAAW,6BAA6B;IACjD,QAAQ,CAAC,mBAAmB,SAAS;IACrC,QAAQ,CAAC,OAAO,UAAM;IACtB,QAAQ,CAAC,WAAW;;;;QAMlB;IAEI,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAgEvE"}
@@ -52,6 +52,16 @@ export class PluginAddSubCommand {
52
52
  const installLabel = descriptor.version && descriptor.version !== "latest"
53
53
  ? `${descriptor.pluginId}@${descriptor.version}`
54
54
  : descriptor.pluginId;
55
+ // Confirm the package (and specific version/tag, if requested) actually exists on the
56
+ // remote marketplace before invoking the package manager - so a non-existent plugin or
57
+ // version is reported clearly instead of failing later (and less clearly) inside
58
+ // `bun add`/`npm install`.
59
+ const versionToCheck = descriptor.version === "latest" ? undefined : descriptor.version;
60
+ if (!(await pluginService.checkAvailable(descriptor.pluginId, versionToCheck))) {
61
+ throw new Error(versionToCheck
62
+ ? `Version ${versionToCheck} of plugin ${descriptor.pluginId} was not found in the configured plugin registry`
63
+ : `Plugin ${descriptor.pluginId} was not found in the configured plugin registry`);
64
+ }
55
65
  await printerService.info(`Installing ${installLabel}...\n`, Icon.INFORMATION);
56
66
  await pluginService.install(descriptor);
57
67
  await printerService.print(`Plugin ${descriptor.pluginId} installed.\n`, Icon.SUCCESS);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowscripter/dynamic-cli-framework",
3
- "version": "5.1.6",
3
+ "version": "5.1.7",
4
4
  "description": "A framework for developing CLI applications which supports dynamic discovery and installation of new commands",
5
5
  "keywords": [
6
6
  "bun",
@@ -48,8 +48,8 @@
48
48
  "build": "tsc -p tsconfig.build.json"
49
49
  },
50
50
  "dependencies": {
51
- "@flowscripter/dynamic-cli-framework-api": "^2.2.1",
52
- "@flowscripter/dynamic-plugin-framework": "2.1.1",
51
+ "@flowscripter/dynamic-cli-framework-api": "^2.3.0",
52
+ "@flowscripter/dynamic-plugin-framework": "^2.2.1",
53
53
  "emphasize": "^7.0.0",
54
54
  "fastest-levenshtein": "^1.0.16",
55
55
  "figlet": "^1.11.0",
@@ -6,6 +6,8 @@ import type {
6
6
  VersionedPluginDescriptor,
7
7
  NpmjsPluginRepositoryConfig,
8
8
  NpmPluginRepositoryConfig,
9
+ FetchCapable,
10
+ FetchInterface,
9
11
  } from "@flowscripter/dynamic-plugin-framework";
10
12
  import {
11
13
  NpmPluginManager,
@@ -13,6 +15,10 @@ import {
13
15
  NpmPluginRepository,
14
16
  } from "@flowscripter/dynamic-plugin-framework";
15
17
 
18
+ function isFetchCapable(value: unknown): value is FetchCapable {
19
+ return typeof value === "object" && value !== null && "setFetch" in value;
20
+ }
21
+
16
22
  export default class DefaultPluginService implements PluginService {
17
23
  readonly #defaultRemoteConfig: NpmjsPluginRepositoryConfig;
18
24
  readonly #defaultLocalConfig: NpmPluginRepositoryConfig;
@@ -50,6 +56,20 @@ export default class DefaultPluginService implements PluginService {
50
56
  );
51
57
  }
52
58
 
59
+ /**
60
+ * Supply the {@link FetchInterface} for the underlying `pluginManager` to delegate fetch calls
61
+ * to, so it respects the host CLI's shutdown handling and default timeout.
62
+ */
63
+ setFetch(fetchInterface: FetchInterface): void {
64
+ if (isFetchCapable(this.#pluginManager)) {
65
+ this.#pluginManager.setFetch(fetchInterface);
66
+ }
67
+ }
68
+
69
+ async checkAvailable(pluginId: string, version?: string): Promise<boolean> {
70
+ return this.#pluginManager.checkAvailable(pluginId, version);
71
+ }
72
+
53
73
  search(query: Readonly<SearchQuery>): AsyncIterable<Readonly<VersionedPluginDescriptor>> {
54
74
  return this.#pluginManager.search(query);
55
75
  }
@@ -12,7 +12,6 @@ import { DYNAMIC_CLI_FRAMEWORK_SERVICE_PROVIDER_FACTORY_EXTENSION_POINT } from "
12
12
  import type { CommandFactory } from "@flowscripter/dynamic-cli-framework-api";
13
13
  import type { ServiceProviderFactory } from "@flowscripter/dynamic-cli-framework-api";
14
14
  import type {
15
- FetchCapable,
16
15
  NpmjsPluginRepositoryConfig,
17
16
  NpmPluginRepositoryConfig,
18
17
  SpawnCapable,
@@ -98,13 +97,11 @@ export default class PluginServiceProvider implements ServiceProvider {
98
97
  }
99
98
 
100
99
  if (!context.doesServiceExist(FETCH_SERVICE_ID)) {
101
- logger.debug("FetchService not available, plugin manager will fetch directly");
102
- } else if (!("setFetch" in pluginManager)) {
103
- logger.debug("Plugin manager does not support FetchCapable, skipping fetch injection");
100
+ logger.debug("FetchService not available, plugin service will fetch directly");
104
101
  } else {
105
102
  const fetchService = context.getServiceById(FETCH_SERVICE_ID) as FetchService;
106
103
  const adapter = new FetchInterfaceAdapter(fetchService, this.#fetchInterfaceAdapterOptions);
107
- (pluginManager as unknown as FetchCapable).setFetch(adapter);
104
+ pluginService.setFetch(adapter);
108
105
  }
109
106
 
110
107
  await pluginManager.registerExtensions(DYNAMIC_CLI_FRAMEWORK_COMMAND_FACTORY_EXTENSION_POINT);
@@ -69,6 +69,20 @@ export class PluginAddSubCommand implements SubCommand {
69
69
  descriptor.version && descriptor.version !== "latest"
70
70
  ? `${descriptor.pluginId}@${descriptor.version}`
71
71
  : descriptor.pluginId;
72
+
73
+ // Confirm the package (and specific version/tag, if requested) actually exists on the
74
+ // remote marketplace before invoking the package manager - so a non-existent plugin or
75
+ // version is reported clearly instead of failing later (and less clearly) inside
76
+ // `bun add`/`npm install`.
77
+ const versionToCheck = descriptor.version === "latest" ? undefined : descriptor.version;
78
+ if (!(await pluginService.checkAvailable(descriptor.pluginId, versionToCheck))) {
79
+ throw new Error(
80
+ versionToCheck
81
+ ? `Version ${versionToCheck} of plugin ${descriptor.pluginId} was not found in the configured plugin registry`
82
+ : `Plugin ${descriptor.pluginId} was not found in the configured plugin registry`,
83
+ );
84
+ }
85
+
72
86
  await printerService.info(`Installing ${installLabel}...\n`, Icon.INFORMATION);
73
87
  await pluginService.install(descriptor);
74
88
  await printerService.print(`Plugin ${descriptor.pluginId} installed.\n`, Icon.SUCCESS);