@flowscripter/dynamic-cli-framework 2.4.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/src/cli/BaseCLI.d.ts +1 -0
- package/dist/src/cli/BaseCLI.d.ts.map +1 -1
- package/dist/src/cli/BaseCLI.js +6 -0
- package/dist/src/cli/BaseCLIFeatureOptions.d.ts +1 -0
- package/dist/src/cli/BaseCLIFeatureOptions.d.ts.map +1 -1
- package/dist/src/command/MultiCommandCliHelpCommand.d.ts +4 -4
- package/dist/src/command/MultiCommandCliHelpCommand.d.ts.map +1 -1
- package/dist/src/command/MultiCommandCliHelpCommand.js +3 -3
- package/dist/src/runtime/command/CommandValidator.d.ts.map +1 -1
- package/dist/src/runtime/command/CommandValidator.js +14 -16
- package/dist/src/runtime/parser.d.ts +5 -5
- package/dist/src/runtime/parser.d.ts.map +1 -1
- package/dist/src/runtime/parser.js +2 -2
- package/dist/src/runtime/runner.d.ts.map +1 -1
- package/dist/src/runtime/values/ValuePopulationResult.d.ts +3 -3
- package/dist/src/runtime/values/ValuePopulationResult.d.ts.map +1 -1
- package/dist/src/runtime/values/argumentValueMerge.d.ts +2 -2
- package/dist/src/runtime/values/argumentValueMerge.d.ts.map +1 -1
- package/dist/src/runtime/values/argumentValueValidation.d.ts +4 -4
- package/dist/src/runtime/values/argumentValueValidation.d.ts.map +1 -1
- package/dist/src/runtime/values/argumentValueValidation.js +6 -6
- package/dist/src/runtime/values/globalCommandValuePopulation.d.ts +4 -4
- package/dist/src/runtime/values/globalCommandValuePopulation.d.ts.map +1 -1
- package/dist/src/runtime/values/globalCommandValuePopulation.js +5 -5
- package/dist/src/runtime/values/subCommandValuePopulation.d.ts +5 -5
- package/dist/src/runtime/values/subCommandValuePopulation.d.ts.map +1 -1
- package/dist/src/runtime/values/subCommandValuePopulation.js +8 -7
- package/dist/src/service/argumentPrompter/DefaultArgumentPrompterService.d.ts.map +1 -1
- package/dist/src/service/argumentPrompter/DefaultArgumentPrompterService.js +6 -6
- package/dist/src/service/banner/command/NoBannerCommand.d.ts +2 -2
- package/dist/src/service/banner/command/NoBannerCommand.d.ts.map +1 -1
- package/dist/src/service/banner/command/NoBannerCommand.js +2 -2
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts +2 -2
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.d.ts.map +1 -1
- package/dist/src/service/completion/command/CompletionCompleteSubCommand.js +3 -3
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts +2 -2
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.d.ts.map +1 -1
- package/dist/src/service/completion/command/CompletionIntegrationSubCommand.js +3 -3
- package/dist/src/service/configuration/ConfigurationServiceProvider.d.ts +6 -6
- package/dist/src/service/configuration/ConfigurationServiceProvider.d.ts.map +1 -1
- package/dist/src/service/configuration/ConfigurationServiceProvider.js +4 -4
- package/dist/src/service/configuration/command/ConfigCommand.d.ts +2 -2
- package/dist/src/service/configuration/command/ConfigCommand.d.ts.map +1 -1
- package/dist/src/service/configuration/command/ConfigCommand.js +2 -2
- package/dist/src/service/fetch/DefaultFetchService.d.ts +7 -0
- package/dist/src/service/fetch/DefaultFetchService.d.ts.map +1 -0
- package/dist/src/service/fetch/DefaultFetchService.js +44 -0
- package/dist/src/service/fetch/FetchServiceProvider.d.ts +10 -0
- package/dist/src/service/fetch/FetchServiceProvider.d.ts.map +1 -0
- package/dist/src/service/fetch/FetchServiceProvider.js +22 -0
- package/dist/src/service/plugin/DefaultPluginServiceProvider.d.ts +2 -1
- package/dist/src/service/plugin/DefaultPluginServiceProvider.d.ts.map +1 -1
- package/dist/src/service/plugin/DefaultPluginServiceProvider.js +23 -8
- package/dist/src/service/plugin/FetchInterfaceAdapter.d.ts +17 -0
- package/dist/src/service/plugin/FetchInterfaceAdapter.d.ts.map +1 -0
- package/dist/src/service/plugin/FetchInterfaceAdapter.js +16 -0
- package/dist/src/service/plugin/SpawnInterfaceAdapter.js +1 -1
- package/dist/src/service/plugin/command/PluginAddSubCommand.d.ts +4 -4
- package/dist/src/service/plugin/command/PluginAddSubCommand.d.ts.map +1 -1
- package/dist/src/service/plugin/command/PluginAddSubCommand.js +2 -2
- package/dist/src/service/plugin/command/PluginListSubCommand.d.ts +2 -2
- package/dist/src/service/plugin/command/PluginListSubCommand.d.ts.map +1 -1
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.d.ts +4 -4
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.d.ts.map +1 -1
- package/dist/src/service/plugin/command/PluginRemoveSubCommand.js +2 -2
- package/dist/src/service/plugin/command/PluginSearchSubCommand.d.ts +4 -4
- package/dist/src/service/plugin/command/PluginSearchSubCommand.d.ts.map +1 -1
- package/dist/src/service/plugin/command/PluginSearchSubCommand.js +2 -2
- package/dist/src/service/plugin/command/PluginUpgradeSubCommand.d.ts +2 -2
- package/dist/src/service/plugin/command/PluginUpgradeSubCommand.d.ts.map +1 -1
- package/dist/src/service/printer/command/DarkModeCommand.d.ts +2 -2
- package/dist/src/service/printer/command/DarkModeCommand.d.ts.map +1 -1
- package/dist/src/service/printer/command/DarkModeCommand.js +2 -2
- package/dist/src/service/printer/command/LogLevelCommand.d.ts +2 -2
- package/dist/src/service/printer/command/LogLevelCommand.d.ts.map +1 -1
- package/dist/src/service/printer/command/LogLevelCommand.js +2 -2
- package/dist/src/service/printer/command/NoColorCommand.d.ts +2 -2
- package/dist/src/service/printer/command/NoColorCommand.d.ts.map +1 -1
- package/dist/src/service/printer/command/NoColorCommand.js +2 -2
- package/dist/src/service/printer/command/NoHyperlinksCommand.d.ts +2 -2
- package/dist/src/service/printer/command/NoHyperlinksCommand.d.ts.map +1 -1
- package/dist/src/service/printer/command/NoHyperlinksCommand.js +2 -2
- package/dist/src/service/prompter/command/NoPromptCommand.d.ts +2 -2
- package/dist/src/service/prompter/command/NoPromptCommand.d.ts.map +1 -1
- package/dist/src/service/prompter/command/NoPromptCommand.js +2 -2
- package/dist/src/service/spawn/DefaultSpawnService.js +6 -6
- package/dist/src/service/upgrade/DefaultUpgradeService.d.ts +2 -2
- package/dist/src/service/upgrade/DefaultUpgradeService.d.ts.map +1 -1
- package/dist/src/service/upgrade/DefaultUpgradeService.js +33 -51
- package/dist/src/service/upgrade/UpgradeServiceProvider.d.ts.map +1 -1
- package/dist/src/service/upgrade/UpgradeServiceProvider.js +12 -9
- package/dist/src/service/upgrade/command/UpgradeSubCommand.d.ts +2 -2
- package/dist/src/service/upgrade/command/UpgradeSubCommand.d.ts.map +1 -1
- package/dist/src/service/upgrade/command/UpgradeSubCommand.js +3 -3
- package/dist/src/util/envVarHelper.d.ts +3 -3
- package/dist/src/util/envVarHelper.d.ts.map +1 -1
- package/dist/src/util/envVarHelper.js +9 -12
- package/dist/src/util/helpHelper.d.ts.map +1 -1
- package/dist/src/util/helpHelper.js +27 -28
- package/index.ts +12 -10
- package/package.json +3 -3
- package/src/cli/BaseCLI.ts +7 -0
- package/src/cli/BaseCLIFeatureOptions.ts +1 -0
- package/src/command/MultiCommandCliHelpCommand.ts +7 -7
- package/src/runtime/command/CommandValidator.ts +17 -26
- package/src/runtime/parser.ts +8 -8
- package/src/runtime/runner.ts +16 -19
- package/src/runtime/values/ValuePopulationResult.ts +4 -4
- package/src/runtime/values/argumentValueMerge.ts +33 -50
- package/src/runtime/values/argumentValueValidation.ts +38 -52
- package/src/runtime/values/globalCommandValuePopulation.ts +7 -7
- package/src/runtime/values/subCommandValuePopulation.ts +42 -47
- package/src/service/argumentPrompter/DefaultArgumentPrompterService.ts +23 -26
- package/src/service/banner/command/NoBannerCommand.ts +3 -6
- package/src/service/completion/command/CompletionCompleteSubCommand.ts +4 -7
- package/src/service/completion/command/CompletionIntegrationSubCommand.ts +4 -7
- package/src/service/configuration/ConfigurationServiceProvider.ts +21 -21
- package/src/service/configuration/command/ConfigCommand.ts +3 -6
- package/src/service/fetch/DefaultFetchService.ts +55 -0
- package/src/service/fetch/FetchServiceProvider.ts +33 -0
- package/src/service/plugin/DefaultPluginServiceProvider.ts +29 -12
- package/src/service/plugin/FetchInterfaceAdapter.ts +28 -0
- package/src/service/plugin/SpawnInterfaceAdapter.ts +1 -1
- package/src/service/plugin/command/PluginAddSubCommand.ts +4 -4
- package/src/service/plugin/command/PluginListSubCommand.ts +2 -2
- package/src/service/plugin/command/PluginRemoveSubCommand.ts +4 -4
- package/src/service/plugin/command/PluginSearchSubCommand.ts +4 -4
- package/src/service/plugin/command/PluginUpgradeSubCommand.ts +2 -2
- package/src/service/printer/command/DarkModeCommand.ts +3 -6
- package/src/service/printer/command/LogLevelCommand.ts +3 -6
- package/src/service/printer/command/NoColorCommand.ts +3 -6
- package/src/service/printer/command/NoHyperlinksCommand.ts +3 -6
- package/src/service/prompter/command/NoPromptCommand.ts +3 -6
- package/src/service/prompter/prompt/promptText.ts +2 -2
- package/src/service/spawn/DefaultSpawnService.ts +6 -6
- package/src/service/upgrade/DefaultUpgradeService.ts +66 -65
- package/src/service/upgrade/UpgradeServiceProvider.ts +13 -9
- package/src/service/upgrade/command/UpgradeSubCommand.ts +4 -7
- package/src/util/envVarHelper.ts +23 -26
- package/src/util/helpHelper.ts +28 -36
|
@@ -4,7 +4,7 @@ import { tmpdir } from "node:os";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import type {
|
|
6
6
|
CLIConfig,
|
|
7
|
-
|
|
7
|
+
FetchService,
|
|
8
8
|
SpawnResult,
|
|
9
9
|
SpawnService,
|
|
10
10
|
UpgradeCheckResult,
|
|
@@ -40,7 +40,7 @@ const OS_LABELS: Record<SupportedOs, string> = {
|
|
|
40
40
|
|
|
41
41
|
export default class DefaultUpgradeService implements UpgradeService {
|
|
42
42
|
#spawnService: SpawnService | undefined;
|
|
43
|
-
#
|
|
43
|
+
#fetchService: FetchService | undefined;
|
|
44
44
|
#upgradeCheckPromise: Promise<UpgradeCheckResult | undefined> | undefined;
|
|
45
45
|
readonly #config: UpgradeLocationsConfig;
|
|
46
46
|
readonly #cliConfig: CLIConfig;
|
|
@@ -50,9 +50,12 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
50
50
|
this.#cliConfig = cliConfig;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
public setDependencies(
|
|
53
|
+
public setDependencies(
|
|
54
|
+
spawnService: SpawnService | undefined,
|
|
55
|
+
fetchService: FetchService | undefined,
|
|
56
|
+
): void {
|
|
54
57
|
this.#spawnService = spawnService;
|
|
55
|
-
this.#
|
|
58
|
+
this.#fetchService = fetchService;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
public getUpgradeCheckResult(waitForResult = false): Promise<UpgradeCheckResult | undefined> {
|
|
@@ -170,6 +173,9 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
170
173
|
if (!this.#spawnService) {
|
|
171
174
|
return { ok: false, oldVersion, error: new Error("SpawnService is not available") };
|
|
172
175
|
}
|
|
176
|
+
if (checkResult.installMethod === InstallMethod.GITHUB_RELEASE && !this.#fetchService) {
|
|
177
|
+
return { ok: false, oldVersion, error: new Error("FetchService is not available") };
|
|
178
|
+
}
|
|
173
179
|
|
|
174
180
|
try {
|
|
175
181
|
switch (checkResult.installMethod) {
|
|
@@ -204,7 +210,7 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
204
210
|
}
|
|
205
211
|
const result = await this.#spawnService.spawn(
|
|
206
212
|
["brew", "list", "--versions", this.#config.homebrew.formula],
|
|
207
|
-
{
|
|
213
|
+
{ mode: "ignore", longRunning: false, timeoutMs: VERSION_CHECK_TIMEOUT_MS },
|
|
208
214
|
);
|
|
209
215
|
return result.ok;
|
|
210
216
|
}
|
|
@@ -215,7 +221,7 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
215
221
|
}
|
|
216
222
|
const result = await this.#spawnService.spawn(
|
|
217
223
|
["winget", "list", "--id", this.#config.winget.packageId],
|
|
218
|
-
{
|
|
224
|
+
{ mode: "ignore", longRunning: false, timeoutMs: VERSION_CHECK_TIMEOUT_MS },
|
|
219
225
|
);
|
|
220
226
|
return result.ok;
|
|
221
227
|
}
|
|
@@ -239,14 +245,14 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
239
245
|
}
|
|
240
246
|
|
|
241
247
|
async #getLatestGithubReleaseVersion(): Promise<string | undefined> {
|
|
242
|
-
if (!this.#config.githubRelease) {
|
|
248
|
+
if (!this.#config.githubRelease || !this.#fetchService) {
|
|
243
249
|
return undefined;
|
|
244
250
|
}
|
|
245
251
|
const { owner, repo } = this.#config.githubRelease;
|
|
246
252
|
try {
|
|
247
|
-
const response = await fetch(
|
|
253
|
+
const response = await this.#fetchService.fetch(
|
|
248
254
|
`https://api.github.com/repos/${owner}/${repo}/releases/latest`,
|
|
249
|
-
{
|
|
255
|
+
{ timeoutMs: VERSION_CHECK_TIMEOUT_MS },
|
|
250
256
|
);
|
|
251
257
|
if (!response.ok) {
|
|
252
258
|
return undefined;
|
|
@@ -260,7 +266,7 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
260
266
|
}
|
|
261
267
|
|
|
262
268
|
async #getLatestHomebrewVersion(): Promise<string | undefined> {
|
|
263
|
-
if (!this.#config.homebrew) {
|
|
269
|
+
if (!this.#config.homebrew || !this.#fetchService) {
|
|
264
270
|
return undefined;
|
|
265
271
|
}
|
|
266
272
|
const { tap, formula } = this.#config.homebrew;
|
|
@@ -269,9 +275,9 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
269
275
|
return undefined;
|
|
270
276
|
}
|
|
271
277
|
try {
|
|
272
|
-
const response = await fetch(
|
|
278
|
+
const response = await this.#fetchService.fetch(
|
|
273
279
|
`https://raw.githubusercontent.com/${tapOwner}/homebrew-${tapName}/main/${formula}.rb`,
|
|
274
|
-
{
|
|
280
|
+
{ timeoutMs: VERSION_CHECK_TIMEOUT_MS },
|
|
275
281
|
);
|
|
276
282
|
if (!response.ok) {
|
|
277
283
|
return undefined;
|
|
@@ -292,7 +298,7 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
292
298
|
const result = await this.#spawnService.spawn(
|
|
293
299
|
["winget", "show", "--id", this.#config.winget.packageId],
|
|
294
300
|
{
|
|
295
|
-
|
|
301
|
+
mode: "wrapped",
|
|
296
302
|
longRunning: false,
|
|
297
303
|
timeoutMs: VERSION_CHECK_TIMEOUT_MS,
|
|
298
304
|
onOutput: (line) => lines.push(line),
|
|
@@ -312,7 +318,9 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
312
318
|
|
|
313
319
|
async #upgradeViaLinuxScript(): Promise<void> {
|
|
314
320
|
const { scriptUrl } = this.#config.linuxScript!;
|
|
315
|
-
const result = await this.#spawnService!.spawn(["sh", "-c", `curl -fsSL ${scriptUrl} | sh`]
|
|
321
|
+
const result = await this.#spawnService!.spawn(["sh", "-c", `curl -fsSL ${scriptUrl} | sh`], {
|
|
322
|
+
mode: "ignore",
|
|
323
|
+
});
|
|
316
324
|
if (!result.ok) {
|
|
317
325
|
throw new Error(`Install script failed: ${describeSpawnFailure(result)}`);
|
|
318
326
|
}
|
|
@@ -320,7 +328,9 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
320
328
|
|
|
321
329
|
async #upgradeViaHomebrew(): Promise<void> {
|
|
322
330
|
const { tap, formula } = this.#config.homebrew!;
|
|
323
|
-
const result = await this.#spawnService!.spawn(["brew", "upgrade", `${tap}/${formula}`]
|
|
331
|
+
const result = await this.#spawnService!.spawn(["brew", "upgrade", `${tap}/${formula}`], {
|
|
332
|
+
mode: "ignore",
|
|
333
|
+
});
|
|
324
334
|
if (!result.ok) {
|
|
325
335
|
throw new Error(`brew upgrade failed: ${describeSpawnFailure(result)}`);
|
|
326
336
|
}
|
|
@@ -328,15 +338,18 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
328
338
|
|
|
329
339
|
async #upgradeViaWinget(): Promise<void> {
|
|
330
340
|
const { packageId } = this.#config.winget!;
|
|
331
|
-
const result = await this.#spawnService!.spawn(
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
341
|
+
const result = await this.#spawnService!.spawn(
|
|
342
|
+
[
|
|
343
|
+
"winget",
|
|
344
|
+
"upgrade",
|
|
345
|
+
"--id",
|
|
346
|
+
packageId,
|
|
347
|
+
"--silent",
|
|
348
|
+
"--accept-package-agreements",
|
|
349
|
+
"--accept-source-agreements",
|
|
350
|
+
],
|
|
351
|
+
{ mode: "ignore" },
|
|
352
|
+
);
|
|
340
353
|
if (!result.ok) {
|
|
341
354
|
throw new Error(`winget upgrade failed: ${describeSpawnFailure(result)}`);
|
|
342
355
|
}
|
|
@@ -349,19 +362,13 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
349
362
|
const assetName = assetPattern.replace("{os}", OS_LABELS[os]).replace("{arch}", archLabel);
|
|
350
363
|
const url = `https://github.com/${owner}/${repo}/releases/latest/download/${assetName}`;
|
|
351
364
|
|
|
352
|
-
//
|
|
353
|
-
//
|
|
354
|
-
this.#
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
const response = await fetch(url);
|
|
358
|
-
if (!response.ok) {
|
|
359
|
-
throw new Error(`Failed to download release asset '${assetName}': HTTP ${response.status}`);
|
|
360
|
-
}
|
|
361
|
-
archiveData = await response.arrayBuffer();
|
|
362
|
-
} finally {
|
|
363
|
-
this.#shutdownService?.leaveLongRunningMode();
|
|
365
|
+
// longRunning: true gets cooperative Ctrl-C handling during what can be the slowest step of
|
|
366
|
+
// the upgrade.
|
|
367
|
+
const response = await this.#fetchService!.fetch(url, { longRunning: true });
|
|
368
|
+
if (!response.ok) {
|
|
369
|
+
throw new Error(`Failed to download release asset '${assetName}': HTTP ${response.status}`);
|
|
364
370
|
}
|
|
371
|
+
const archiveData = await response.arrayBuffer();
|
|
365
372
|
|
|
366
373
|
const tmpDir = await mkdtemp(join(tmpdir(), "upgrade-"));
|
|
367
374
|
const archivePath = join(tmpDir, assetName);
|
|
@@ -370,52 +377,46 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
370
377
|
const currentExecutable = process.execPath;
|
|
371
378
|
|
|
372
379
|
if (os === SupportedOs.WINDOWS) {
|
|
373
|
-
const extractResult = await this.#spawnService!.spawn(
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
380
|
+
const extractResult = await this.#spawnService!.spawn(
|
|
381
|
+
[
|
|
382
|
+
"powershell",
|
|
383
|
+
"-Command",
|
|
384
|
+
`Expand-Archive -Path '${archivePath}' -DestinationPath '${tmpDir}' -Force`,
|
|
385
|
+
],
|
|
386
|
+
{ mode: "ignore" },
|
|
387
|
+
);
|
|
378
388
|
if (!extractResult.ok) {
|
|
379
389
|
throw new Error("Failed to extract release archive");
|
|
380
390
|
}
|
|
381
391
|
const extractedBinary = join(tmpDir, `${this.#cliConfig.name}.exe`);
|
|
382
392
|
const oldPath = `${currentExecutable}.old.exe`;
|
|
383
|
-
const moveResult = await this.#spawnService!.spawn(
|
|
384
|
-
"cmd",
|
|
385
|
-
"
|
|
386
|
-
|
|
387
|
-
"/y",
|
|
388
|
-
currentExecutable,
|
|
389
|
-
oldPath,
|
|
390
|
-
]);
|
|
393
|
+
const moveResult = await this.#spawnService!.spawn(
|
|
394
|
+
["cmd", "/c", "move", "/y", currentExecutable, oldPath],
|
|
395
|
+
{ mode: "ignore" },
|
|
396
|
+
);
|
|
391
397
|
if (!moveResult.ok) {
|
|
392
398
|
throw new Error("Failed to move current executable aside");
|
|
393
399
|
}
|
|
394
|
-
const copyResult = await this.#spawnService!.spawn(
|
|
395
|
-
"cmd",
|
|
396
|
-
"
|
|
397
|
-
|
|
398
|
-
"/y",
|
|
399
|
-
extractedBinary,
|
|
400
|
-
currentExecutable,
|
|
401
|
-
]);
|
|
400
|
+
const copyResult = await this.#spawnService!.spawn(
|
|
401
|
+
["cmd", "/c", "copy", "/y", extractedBinary, currentExecutable],
|
|
402
|
+
{ mode: "ignore" },
|
|
403
|
+
);
|
|
402
404
|
if (!copyResult.ok) {
|
|
403
405
|
throw new Error("Failed to copy new executable into place");
|
|
404
406
|
}
|
|
405
407
|
} else {
|
|
406
|
-
const extractResult = await this.#spawnService!.spawn(
|
|
407
|
-
"unzip",
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
]);
|
|
408
|
+
const extractResult = await this.#spawnService!.spawn(
|
|
409
|
+
["unzip", "-o", archivePath, "-d", tmpDir],
|
|
410
|
+
{
|
|
411
|
+
mode: "ignore",
|
|
412
|
+
},
|
|
413
|
+
);
|
|
413
414
|
if (!extractResult.ok) {
|
|
414
415
|
throw new Error("Failed to extract release archive");
|
|
415
416
|
}
|
|
416
417
|
const extractedBinary = join(tmpDir, this.#cliConfig.name);
|
|
417
418
|
await Bun.write(currentExecutable, Bun.file(extractedBinary));
|
|
418
|
-
await this.#spawnService!.spawn(["chmod", "+x", currentExecutable]);
|
|
419
|
+
await this.#spawnService!.spawn(["chmod", "+x", currentExecutable], { mode: "ignore" });
|
|
419
420
|
}
|
|
420
421
|
}
|
|
421
422
|
}
|
|
@@ -8,8 +8,8 @@ import { KEY_VALUE_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
|
8
8
|
import type { KeyValueService } from "@flowscripter/dynamic-cli-framework-api";
|
|
9
9
|
import { SPAWN_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
10
10
|
import type { SpawnService } from "@flowscripter/dynamic-cli-framework-api";
|
|
11
|
-
import {
|
|
12
|
-
import type {
|
|
11
|
+
import { FETCH_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
12
|
+
import type { FetchService } from "@flowscripter/dynamic-cli-framework-api";
|
|
13
13
|
import { Icon, PRINTER_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
14
14
|
import type { PrinterService } from "@flowscripter/dynamic-cli-framework-api";
|
|
15
15
|
import DefaultUpgradeService from "./DefaultUpgradeService.ts";
|
|
@@ -44,15 +44,19 @@ export default class UpgradeServiceProvider implements ServiceProvider {
|
|
|
44
44
|
const upgradeService = this.#upgradeService!;
|
|
45
45
|
const cliConfig = this.#cliConfig!;
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
const spawnService = context.doesServiceExist(SPAWN_SERVICE_ID)
|
|
48
|
+
? (context.getServiceById(SPAWN_SERVICE_ID) as SpawnService)
|
|
49
|
+
: undefined;
|
|
50
|
+
const fetchService = context.doesServiceExist(FETCH_SERVICE_ID)
|
|
51
|
+
? (context.getServiceById(FETCH_SERVICE_ID) as FetchService)
|
|
52
|
+
: undefined;
|
|
53
|
+
if (spawnService === undefined) {
|
|
54
54
|
logger.debug(() => "SpawnService not available, upgrade install methods will be unavailable");
|
|
55
55
|
}
|
|
56
|
+
if (fetchService === undefined) {
|
|
57
|
+
logger.debug(() => "FetchService not available, upgrade version checks will be unavailable");
|
|
58
|
+
}
|
|
59
|
+
upgradeService.setDependencies(spawnService, fetchService);
|
|
56
60
|
|
|
57
61
|
void upgradeService.getUpgradeCheckResult();
|
|
58
62
|
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { SubCommand } from "@flowscripter/dynamic-cli-framework-api";
|
|
2
2
|
import type { Option } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
3
|
import type { Context } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
|
-
import {
|
|
5
|
-
type ArgumentValues,
|
|
6
|
-
ArgumentValueTypeName,
|
|
7
|
-
} from "@flowscripter/dynamic-cli-framework-api";
|
|
4
|
+
import { type Values, ValueTypeName } from "@flowscripter/dynamic-cli-framework-api";
|
|
8
5
|
import {
|
|
9
6
|
Icon,
|
|
10
7
|
InstallMethod,
|
|
@@ -24,14 +21,14 @@ export class UpgradeSubCommand implements SubCommand {
|
|
|
24
21
|
readonly options: ReadonlyArray<Option> = [
|
|
25
22
|
{
|
|
26
23
|
name: "os",
|
|
27
|
-
type:
|
|
24
|
+
type: ValueTypeName.STRING,
|
|
28
25
|
isOptional: true,
|
|
29
26
|
allowableValues: Object.values(SupportedOs),
|
|
30
27
|
description: "Override the detected operating system",
|
|
31
28
|
},
|
|
32
29
|
{
|
|
33
30
|
name: "install-method",
|
|
34
|
-
type:
|
|
31
|
+
type: ValueTypeName.STRING,
|
|
35
32
|
isOptional: true,
|
|
36
33
|
allowableValues: Object.values(InstallMethod),
|
|
37
34
|
description: "Override the detected install method",
|
|
@@ -44,7 +41,7 @@ export class UpgradeSubCommand implements SubCommand {
|
|
|
44
41
|
this.#upgradeService = upgradeService;
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
public async execute(context: Context, argumentValues:
|
|
44
|
+
public async execute(context: Context, argumentValues: Values): Promise<void> {
|
|
48
45
|
const printerService = context.getServiceById(PRINTER_SERVICE_ID) as PrinterService;
|
|
49
46
|
const cliName = context.cliConfig.name;
|
|
50
47
|
|
package/src/util/envVarHelper.ts
CHANGED
|
@@ -2,10 +2,10 @@ import process from "node:process";
|
|
|
2
2
|
import type { Command } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
3
|
import type { CLIConfig } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
ValueTypeName,
|
|
6
6
|
ComplexValueTypeName,
|
|
7
|
-
type
|
|
8
|
-
type
|
|
7
|
+
type PopulatedSingleValueType,
|
|
8
|
+
type PopulatedValues,
|
|
9
9
|
} from "@flowscripter/dynamic-cli-framework-api";
|
|
10
10
|
type ProcessEnv = NodeJS.ProcessEnv;
|
|
11
11
|
|
|
@@ -59,7 +59,7 @@ function getGlobalArgumentKeyPrefix(
|
|
|
59
59
|
export function getGlobalCommandValueFromEnvVars(
|
|
60
60
|
cliConfig: CLIConfig,
|
|
61
61
|
command: GlobalCommand,
|
|
62
|
-
):
|
|
62
|
+
): PopulatedSingleValueType {
|
|
63
63
|
const { argument } = command;
|
|
64
64
|
if (argument === undefined) {
|
|
65
65
|
return undefined;
|
|
@@ -67,7 +67,7 @@ export function getGlobalCommandValueFromEnvVars(
|
|
|
67
67
|
|
|
68
68
|
// simple check for a specific env var name
|
|
69
69
|
let envVarValue = process.env[getGlobalArgumentKeyPrefix(cliConfig, command, argument)];
|
|
70
|
-
if (envVarValue != undefined && argument.type ===
|
|
70
|
+
if (envVarValue != undefined && argument.type === ValueTypeName.BOOLEAN) {
|
|
71
71
|
envVarValue = envVarValue.length > 0 ? "true" : "false";
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -75,7 +75,7 @@ export function getGlobalCommandValueFromEnvVars(
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function getOptionValuesFromEnvVars(
|
|
78
|
-
envVarValues:
|
|
78
|
+
envVarValues: PopulatedValues,
|
|
79
79
|
potentialEnvVarNames: Array<string>,
|
|
80
80
|
env: ProcessEnv,
|
|
81
81
|
option: Option | ComplexOption,
|
|
@@ -126,17 +126,16 @@ function getOptionValuesFromEnvVars(
|
|
|
126
126
|
if (suffix.length > 0) {
|
|
127
127
|
if (option.type === ComplexValueTypeName.COMPLEX) {
|
|
128
128
|
if (
|
|
129
|
-
(envVarValues[option.name] as Array<
|
|
130
|
-
undefined
|
|
129
|
+
(envVarValues[option.name] as Array<PopulatedSingleValueType>)[index] === undefined
|
|
131
130
|
) {
|
|
132
|
-
(envVarValues[option.name] as Array<
|
|
131
|
+
(envVarValues[option.name] as Array<PopulatedValues>)[index] = Object.create(
|
|
133
132
|
null,
|
|
134
|
-
) as
|
|
133
|
+
) as PopulatedValues;
|
|
135
134
|
}
|
|
136
135
|
(option as ComplexOption).properties.forEach((property) => {
|
|
137
136
|
const propertySegment = property.configurationKey || getKeySegment(property.name);
|
|
138
137
|
getOptionValuesFromEnvVars(
|
|
139
|
-
(envVarValues[option.name] as Array<
|
|
138
|
+
(envVarValues[option.name] as Array<PopulatedValues>)[index]!,
|
|
140
139
|
matches,
|
|
141
140
|
env,
|
|
142
141
|
property,
|
|
@@ -145,13 +144,13 @@ function getOptionValuesFromEnvVars(
|
|
|
145
144
|
});
|
|
146
145
|
if (
|
|
147
146
|
Object.keys(
|
|
148
|
-
(envVarValues[option.name] as Array<
|
|
147
|
+
(envVarValues[option.name] as Array<PopulatedValues>)[index] as Record<
|
|
149
148
|
string,
|
|
150
149
|
string
|
|
151
150
|
>,
|
|
152
151
|
).length === 0
|
|
153
152
|
) {
|
|
154
|
-
delete (envVarValues[option.name] as Array<
|
|
153
|
+
delete (envVarValues[option.name] as Array<PopulatedValues>)[index];
|
|
155
154
|
}
|
|
156
155
|
} else {
|
|
157
156
|
throw new Error(`Unidentified suffix ${suffix} in env var: ${match}`);
|
|
@@ -161,14 +160,13 @@ function getOptionValuesFromEnvVars(
|
|
|
161
160
|
} else {
|
|
162
161
|
// set primitive value
|
|
163
162
|
let envVarValue = env[match];
|
|
164
|
-
if (envVarValue != undefined && option.type ===
|
|
163
|
+
if (envVarValue != undefined && option.type === ValueTypeName.BOOLEAN) {
|
|
165
164
|
envVarValue = envVarValue.length > 1 ? "true" : "false";
|
|
166
165
|
}
|
|
167
|
-
(envVarValues[option.name] as Array<
|
|
168
|
-
envVarValue;
|
|
166
|
+
(envVarValues[option.name] as Array<PopulatedSingleValueType>)[index] = envVarValue;
|
|
169
167
|
}
|
|
170
168
|
|
|
171
|
-
const elements = envVarValues[option.name] as Array<
|
|
169
|
+
const elements = envVarValues[option.name] as Array<PopulatedSingleValueType>;
|
|
172
170
|
for (let i = elements.length - 1; i > -1; i--) {
|
|
173
171
|
if (elements[i] === undefined) {
|
|
174
172
|
elements.length = i;
|
|
@@ -182,11 +180,11 @@ function getOptionValuesFromEnvVars(
|
|
|
182
180
|
} else if (option.type === ComplexValueTypeName.COMPLEX) {
|
|
183
181
|
(option as ComplexOption).properties.forEach((property) => {
|
|
184
182
|
if (envVarValues[option.name] === undefined) {
|
|
185
|
-
envVarValues[option.name] = Object.create(null) as
|
|
183
|
+
envVarValues[option.name] = Object.create(null) as PopulatedValues;
|
|
186
184
|
}
|
|
187
185
|
const propertySegment = property.configurationKey || getKeySegment(property.name);
|
|
188
186
|
getOptionValuesFromEnvVars(
|
|
189
|
-
envVarValues[option.name] as
|
|
187
|
+
envVarValues[option.name] as PopulatedValues,
|
|
190
188
|
potentialEnvVarNames,
|
|
191
189
|
env,
|
|
192
190
|
property,
|
|
@@ -202,7 +200,7 @@ function getOptionValuesFromEnvVars(
|
|
|
202
200
|
if (value === undefined) {
|
|
203
201
|
return undefined;
|
|
204
202
|
}
|
|
205
|
-
if (option.type ===
|
|
203
|
+
if (option.type === ValueTypeName.BOOLEAN) {
|
|
206
204
|
value = value.length > 1 ? "true" : "false";
|
|
207
205
|
}
|
|
208
206
|
// set primitive value
|
|
@@ -220,8 +218,8 @@ function getOptionValuesFromEnvVars(
|
|
|
220
218
|
export function getSubCommandValuesFromEnvVars(
|
|
221
219
|
cliConfig: CLIConfig,
|
|
222
220
|
command: SubCommand,
|
|
223
|
-
):
|
|
224
|
-
const envVarValues = Object.create(null) as
|
|
221
|
+
): PopulatedValues | undefined {
|
|
222
|
+
const envVarValues = Object.create(null) as PopulatedValues;
|
|
225
223
|
if (command.options) {
|
|
226
224
|
for (const option of command.options) {
|
|
227
225
|
const potentialEnvVarNames = Object.keys(process.env);
|
|
@@ -270,11 +268,10 @@ export function getSubCommandValuesFromEnvVars(
|
|
|
270
268
|
}
|
|
271
269
|
// set primitive value
|
|
272
270
|
let envVarValue = process.env[match];
|
|
273
|
-
if (envVarValue != undefined && positional.type ===
|
|
271
|
+
if (envVarValue != undefined && positional.type === ValueTypeName.BOOLEAN) {
|
|
274
272
|
envVarValue = envVarValue.length > 1 ? "true" : "false";
|
|
275
273
|
}
|
|
276
|
-
(envVarValues[positional.name] as Array<
|
|
277
|
-
envVarValue;
|
|
274
|
+
(envVarValues[positional.name] as Array<PopulatedSingleValueType>)[index] = envVarValue;
|
|
278
275
|
}
|
|
279
276
|
});
|
|
280
277
|
} else {
|
|
@@ -283,7 +280,7 @@ export function getSubCommandValuesFromEnvVars(
|
|
|
283
280
|
if (value === undefined) {
|
|
284
281
|
return undefined;
|
|
285
282
|
}
|
|
286
|
-
if (positional.type ===
|
|
283
|
+
if (positional.type === ValueTypeName.BOOLEAN) {
|
|
287
284
|
value = value.length > 1 ? "true" : "false";
|
|
288
285
|
}
|
|
289
286
|
// set primitive value
|
package/src/util/helpHelper.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { distance } from "fastest-levenshtein";
|
|
2
2
|
import type { GlobalCommand } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
3
|
import type { GlobalCommandArgument } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
|
-
import {
|
|
5
|
-
ArgumentValueTypeName,
|
|
6
|
-
ComplexValueTypeName,
|
|
7
|
-
} from "@flowscripter/dynamic-cli-framework-api";
|
|
4
|
+
import { ValueTypeName, ComplexValueTypeName } from "@flowscripter/dynamic-cli-framework-api";
|
|
8
5
|
import type { SubCommand } from "@flowscripter/dynamic-cli-framework-api";
|
|
9
6
|
import type { Context } from "@flowscripter/dynamic-cli-framework-api";
|
|
10
7
|
import type { UsageExample } from "@flowscripter/dynamic-cli-framework-api";
|
|
@@ -144,24 +141,21 @@ function getGlobalCommandArgumentForm(globalCommandArgument: GlobalCommandArgume
|
|
|
144
141
|
let argumentSyntax = "";
|
|
145
142
|
|
|
146
143
|
switch (globalCommandArgument.type) {
|
|
147
|
-
case
|
|
144
|
+
case ValueTypeName.BOOLEAN:
|
|
148
145
|
argumentSyntax = "true|false";
|
|
149
146
|
break;
|
|
150
|
-
case
|
|
147
|
+
case ValueTypeName.INTEGER:
|
|
151
148
|
argumentSyntax = "<integer_value>";
|
|
152
149
|
break;
|
|
153
|
-
case
|
|
150
|
+
case ValueTypeName.NUMBER:
|
|
154
151
|
argumentSyntax = "<number_value>";
|
|
155
152
|
break;
|
|
156
|
-
case
|
|
153
|
+
case ValueTypeName.STRING:
|
|
157
154
|
argumentSyntax = "<string_value>";
|
|
158
155
|
break;
|
|
159
156
|
}
|
|
160
157
|
|
|
161
|
-
if (
|
|
162
|
-
globalCommandArgument.isOptional ||
|
|
163
|
-
globalCommandArgument.type === ArgumentValueTypeName.BOOLEAN
|
|
164
|
-
) {
|
|
158
|
+
if (globalCommandArgument.isOptional || globalCommandArgument.type === ValueTypeName.BOOLEAN) {
|
|
165
159
|
argumentSyntax = `[${argumentSyntax}]`;
|
|
166
160
|
}
|
|
167
161
|
|
|
@@ -187,13 +181,13 @@ export function getGlobalArgumentHelpEntry(
|
|
|
187
181
|
notesItems.push(`valid values: ${argument.allowableValues.join("|")}`);
|
|
188
182
|
} else {
|
|
189
183
|
switch (argument.type) {
|
|
190
|
-
case
|
|
184
|
+
case ValueTypeName.STRING:
|
|
191
185
|
notesItems.push("string value");
|
|
192
186
|
break;
|
|
193
|
-
case
|
|
187
|
+
case ValueTypeName.INTEGER:
|
|
194
188
|
notesItems.push("integer value");
|
|
195
189
|
break;
|
|
196
|
-
case
|
|
190
|
+
case ValueTypeName.NUMBER:
|
|
197
191
|
notesItems.push("number value");
|
|
198
192
|
break;
|
|
199
193
|
}
|
|
@@ -240,17 +234,17 @@ export function getSubCommandArgumentsSyntax(subCommand: SubCommand): string {
|
|
|
240
234
|
|
|
241
235
|
subCommand.options.forEach((option) => {
|
|
242
236
|
let optionSyntax = `--${option.name}`;
|
|
243
|
-
switch (option.type as
|
|
244
|
-
case
|
|
237
|
+
switch (option.type as ValueTypeName | ComplexValueTypeName) {
|
|
238
|
+
case ValueTypeName.BOOLEAN:
|
|
245
239
|
optionSyntax = `${optionSyntax} [true|false]`;
|
|
246
240
|
break;
|
|
247
|
-
case
|
|
241
|
+
case ValueTypeName.INTEGER:
|
|
248
242
|
optionSyntax = `${optionSyntax} <integer_value>`;
|
|
249
243
|
break;
|
|
250
|
-
case
|
|
244
|
+
case ValueTypeName.NUMBER:
|
|
251
245
|
optionSyntax = `${optionSyntax} <number_value>`;
|
|
252
246
|
break;
|
|
253
|
-
case
|
|
247
|
+
case ValueTypeName.STRING:
|
|
254
248
|
optionSyntax = `${optionSyntax} <string_value>`;
|
|
255
249
|
break;
|
|
256
250
|
case ComplexValueTypeName.COMPLEX:
|
|
@@ -318,16 +312,16 @@ function getOptionHelpEntry(
|
|
|
318
312
|
notesItems.push(`valid values: ${option.allowableValues.join("|")}`);
|
|
319
313
|
} else {
|
|
320
314
|
switch (option.type) {
|
|
321
|
-
case
|
|
315
|
+
case ValueTypeName.STRING:
|
|
322
316
|
notesItems.push(`string value`);
|
|
323
317
|
break;
|
|
324
|
-
case
|
|
318
|
+
case ValueTypeName.INTEGER:
|
|
325
319
|
notesItems.push(`integer value`);
|
|
326
320
|
break;
|
|
327
|
-
case
|
|
321
|
+
case ValueTypeName.NUMBER:
|
|
328
322
|
notesItems.push(`number value`);
|
|
329
323
|
break;
|
|
330
|
-
case
|
|
324
|
+
case ValueTypeName.BOOLEAN:
|
|
331
325
|
notesItems.push(`boolean value`);
|
|
332
326
|
break;
|
|
333
327
|
}
|
|
@@ -403,16 +397,16 @@ function getPositionalHelpEntry(
|
|
|
403
397
|
notesItems.push(`valid values: ${positional.allowableValues.join("|")}`);
|
|
404
398
|
} else {
|
|
405
399
|
switch (positional.type) {
|
|
406
|
-
case
|
|
400
|
+
case ValueTypeName.STRING:
|
|
407
401
|
notesItems.push(`string value`);
|
|
408
402
|
break;
|
|
409
|
-
case
|
|
403
|
+
case ValueTypeName.INTEGER:
|
|
410
404
|
notesItems.push(`integer value`);
|
|
411
405
|
break;
|
|
412
|
-
case
|
|
406
|
+
case ValueTypeName.NUMBER:
|
|
413
407
|
notesItems.push(`number value`);
|
|
414
408
|
break;
|
|
415
|
-
case
|
|
409
|
+
case ValueTypeName.BOOLEAN:
|
|
416
410
|
notesItems.push(`boolean value`);
|
|
417
411
|
break;
|
|
418
412
|
}
|
|
@@ -544,7 +538,7 @@ export function getMultiCommandAppSyntax(
|
|
|
544
538
|
modifier.argument !== undefined &&
|
|
545
539
|
!modifier.argument.isOptional &&
|
|
546
540
|
modifier.argument.defaultValue === undefined &&
|
|
547
|
-
modifier.argument.type !==
|
|
541
|
+
modifier.argument.type !== ValueTypeName.BOOLEAN,
|
|
548
542
|
);
|
|
549
543
|
syntax += optionArgMandatory ? " <value>" : " [<value>]";
|
|
550
544
|
}
|
|
@@ -571,7 +565,7 @@ export function getMultiCommandAppSyntax(
|
|
|
571
565
|
argValueOptional = globalCommands.some(
|
|
572
566
|
(globalCommand) =>
|
|
573
567
|
globalCommand.argument !== undefined &&
|
|
574
|
-
globalCommand.argument.type ===
|
|
568
|
+
globalCommand.argument.type === ValueTypeName.BOOLEAN,
|
|
575
569
|
);
|
|
576
570
|
}
|
|
577
571
|
}
|
|
@@ -623,19 +617,17 @@ export function getMultiCommandAppSyntax(
|
|
|
623
617
|
groupCommand.memberSubCommands.some((memberCommand) =>
|
|
624
618
|
memberCommand.options.some(
|
|
625
619
|
(option) =>
|
|
626
|
-
option.type ===
|
|
620
|
+
option.type === ValueTypeName.BOOLEAN ||
|
|
627
621
|
memberCommand.positionals.some(
|
|
628
|
-
(positional) => positional.type ===
|
|
622
|
+
(positional) => positional.type === ValueTypeName.BOOLEAN,
|
|
629
623
|
),
|
|
630
624
|
),
|
|
631
625
|
),
|
|
632
626
|
) ||
|
|
633
627
|
subCommands.some(
|
|
634
628
|
(subCommand) =>
|
|
635
|
-
subCommand.options.some((option) => option.type ===
|
|
636
|
-
subCommand.positionals.some(
|
|
637
|
-
(positional) => positional.type === ArgumentValueTypeName.BOOLEAN,
|
|
638
|
-
),
|
|
629
|
+
subCommand.options.some((option) => option.type === ValueTypeName.BOOLEAN) ||
|
|
630
|
+
subCommand.positionals.some((positional) => positional.type === ValueTypeName.BOOLEAN),
|
|
639
631
|
);
|
|
640
632
|
multipleArg =
|
|
641
633
|
multipleArg ||
|