@flowscripter/dynamic-cli-framework 2.3.1 → 2.3.3
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/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 +43 -11
- package/dist/src/service/upgrade/UpgradeServiceProvider.d.ts.map +1 -1
- package/dist/src/service/upgrade/UpgradeServiceProvider.js +5 -1
- package/package.json +1 -1
- package/src/service/upgrade/DefaultUpgradeService.ts +54 -16
- package/src/service/upgrade/UpgradeServiceProvider.ts +6 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { CLIConfig, SpawnService, UpgradeCheckResult, UpgradeResult } from "@flowscripter/dynamic-cli-framework-api";
|
|
1
|
+
import type { CLIConfig, ShutdownService, SpawnService, UpgradeCheckResult, UpgradeResult } from "@flowscripter/dynamic-cli-framework-api";
|
|
2
2
|
import { InstallMethod, SupportedArch, SupportedOs, type UpgradeService } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
3
|
import type { UpgradeLocationsConfig } from "./UpgradeLocationsConfig.ts";
|
|
4
4
|
export default class DefaultUpgradeService implements UpgradeService {
|
|
5
5
|
#private;
|
|
6
6
|
constructor(config: UpgradeLocationsConfig, cliConfig: CLIConfig);
|
|
7
|
-
setDependencies(spawnService: SpawnService): void;
|
|
7
|
+
setDependencies(spawnService: SpawnService, shutdownService?: ShutdownService): void;
|
|
8
8
|
detectOs(): SupportedOs | undefined;
|
|
9
9
|
detectArch(): SupportedArch | undefined;
|
|
10
10
|
detectInstallMethod(os: SupportedOs): Promise<InstallMethod | undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultUpgradeService.d.ts","sourceRoot":"","sources":["../../../../src/service/upgrade/DefaultUpgradeService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACd,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,KAAK,cAAc,EACpB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"DefaultUpgradeService.d.ts","sourceRoot":"","sources":["../../../../src/service/upgrade/DefaultUpgradeService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACd,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,KAAK,cAAc,EACpB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AA0B1E,MAAM,CAAC,OAAO,OAAO,qBAAsB,YAAW,cAAc;;gBAM/C,MAAM,EAAE,sBAAsB,EAAE,SAAS,EAAE,SAAS;IAKhE,eAAe,CAAC,YAAY,EAAE,YAAY,EAAE,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI;IAKpF,QAAQ,IAAI,WAAW,GAAG,SAAS;IAanC,UAAU,IAAI,aAAa,GAAG,SAAS;IAWjC,mBAAmB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAgBxE,eAAe,CAC1B,UAAU,CAAC,EAAE,WAAW,EACxB,YAAY,CAAC,EAAE,aAAa,EAC5B,qBAAqB,CAAC,EAAE,aAAa,GACpC,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAmC7B,OAAO,CAClB,UAAU,CAAC,EAAE,WAAW,EACxB,YAAY,CAAC,EAAE,aAAa,EAC5B,qBAAqB,CAAC,EAAE,aAAa,GACpC,OAAO,CAAC,aAAa,CAAC;CAiR1B"}
|
|
@@ -6,6 +6,19 @@ import { InstallMethod, SupportedArch, SupportedOs, } from "@flowscripter/dynami
|
|
|
6
6
|
import semver from "semver";
|
|
7
7
|
import getLogger from "../../util/logger.js";
|
|
8
8
|
const logger = getLogger("DefaultUpgradeService");
|
|
9
|
+
// checkForUpgrade() runs opportunistically on every CLI invocation (via BannerServiceProvider),
|
|
10
|
+
// so its version-check network calls must never be allowed to stall CLI startup.
|
|
11
|
+
const VERSION_CHECK_TIMEOUT_MS = 250;
|
|
12
|
+
// SpawnService has no built-in cancellation, so a stalled `brew`/`winget` invocation (e.g. winget's
|
|
13
|
+
// first-ever run on a machine prompting to accept Microsoft Store terms) can otherwise hang
|
|
14
|
+
// checkForUpgrade() indefinitely. Racing against this bounds how long we wait for a result; the
|
|
15
|
+
// underlying process is not killed, but the CLI stops blocking on it.
|
|
16
|
+
async function withSpawnTimeout(spawnPromise, fallback) {
|
|
17
|
+
return Promise.race([
|
|
18
|
+
spawnPromise,
|
|
19
|
+
new Promise((resolve) => setTimeout(() => resolve(fallback), VERSION_CHECK_TIMEOUT_MS)),
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
9
22
|
const OS_LABELS = {
|
|
10
23
|
[SupportedOs.LINUX]: "Linux",
|
|
11
24
|
[SupportedOs.MACOS]: "MacOS",
|
|
@@ -13,14 +26,16 @@ const OS_LABELS = {
|
|
|
13
26
|
};
|
|
14
27
|
export default class DefaultUpgradeService {
|
|
15
28
|
#spawnService;
|
|
29
|
+
#shutdownService;
|
|
16
30
|
#config;
|
|
17
31
|
#cliConfig;
|
|
18
32
|
constructor(config, cliConfig) {
|
|
19
33
|
this.#config = config;
|
|
20
34
|
this.#cliConfig = cliConfig;
|
|
21
35
|
}
|
|
22
|
-
setDependencies(spawnService) {
|
|
36
|
+
setDependencies(spawnService, shutdownService) {
|
|
23
37
|
this.#spawnService = spawnService;
|
|
38
|
+
this.#shutdownService = shutdownService;
|
|
24
39
|
}
|
|
25
40
|
detectOs() {
|
|
26
41
|
switch (process.platform) {
|
|
@@ -130,14 +145,20 @@ export default class DefaultUpgradeService {
|
|
|
130
145
|
if (!this.#spawnService || !this.#config.homebrew) {
|
|
131
146
|
return false;
|
|
132
147
|
}
|
|
133
|
-
const result = await this.#spawnService.spawn(["brew", "list", "--versions", this.#config.homebrew.formula], {
|
|
148
|
+
const result = await withSpawnTimeout(this.#spawnService.spawn(["brew", "list", "--versions", this.#config.homebrew.formula], {
|
|
149
|
+
stdio: "wrapped",
|
|
150
|
+
longRunning: false,
|
|
151
|
+
}), { ok: false });
|
|
134
152
|
return result.ok;
|
|
135
153
|
}
|
|
136
154
|
async #isWingetInstalled() {
|
|
137
155
|
if (!this.#spawnService || !this.#config.winget) {
|
|
138
156
|
return false;
|
|
139
157
|
}
|
|
140
|
-
const result = await this.#spawnService.spawn(["winget", "list", "--id", this.#config.winget.packageId], {
|
|
158
|
+
const result = await withSpawnTimeout(this.#spawnService.spawn(["winget", "list", "--id", this.#config.winget.packageId], {
|
|
159
|
+
stdio: "wrapped",
|
|
160
|
+
longRunning: false,
|
|
161
|
+
}), { ok: false });
|
|
141
162
|
return result.ok;
|
|
142
163
|
}
|
|
143
164
|
#isLinuxScriptInstall() {
|
|
@@ -162,7 +183,7 @@ export default class DefaultUpgradeService {
|
|
|
162
183
|
}
|
|
163
184
|
const { owner, repo } = this.#config.githubRelease;
|
|
164
185
|
try {
|
|
165
|
-
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/releases/latest
|
|
186
|
+
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/releases/latest`, { signal: AbortSignal.timeout(VERSION_CHECK_TIMEOUT_MS) });
|
|
166
187
|
if (!response.ok) {
|
|
167
188
|
return undefined;
|
|
168
189
|
}
|
|
@@ -184,7 +205,7 @@ export default class DefaultUpgradeService {
|
|
|
184
205
|
return undefined;
|
|
185
206
|
}
|
|
186
207
|
try {
|
|
187
|
-
const response = await fetch(`https://raw.githubusercontent.com/${tapOwner}/homebrew-${tapName}/main/${formula}.rb
|
|
208
|
+
const response = await fetch(`https://raw.githubusercontent.com/${tapOwner}/homebrew-${tapName}/main/${formula}.rb`, { signal: AbortSignal.timeout(VERSION_CHECK_TIMEOUT_MS) });
|
|
188
209
|
if (!response.ok) {
|
|
189
210
|
return undefined;
|
|
190
211
|
}
|
|
@@ -201,11 +222,11 @@ export default class DefaultUpgradeService {
|
|
|
201
222
|
return undefined;
|
|
202
223
|
}
|
|
203
224
|
const lines = [];
|
|
204
|
-
const result = await this.#spawnService.spawn(["winget", "show", "--id", this.#config.winget.packageId], {
|
|
225
|
+
const result = await withSpawnTimeout(this.#spawnService.spawn(["winget", "show", "--id", this.#config.winget.packageId], {
|
|
205
226
|
stdio: "wrapped",
|
|
206
227
|
longRunning: false,
|
|
207
228
|
onOutput: (line) => lines.push(line),
|
|
208
|
-
});
|
|
229
|
+
}), { ok: false });
|
|
209
230
|
if (!result.ok) {
|
|
210
231
|
return undefined;
|
|
211
232
|
}
|
|
@@ -251,13 +272,24 @@ export default class DefaultUpgradeService {
|
|
|
251
272
|
const archLabel = os === SupportedOs.MACOS ? "aarch64" : arch === SupportedArch.X64 ? "x64" : "arm64";
|
|
252
273
|
const assetName = assetPattern.replace("{os}", OS_LABELS[os]).replace("{arch}", archLabel);
|
|
253
274
|
const url = `https://github.com/${owner}/${repo}/releases/latest/download/${assetName}`;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
275
|
+
// Downloading the release asset happens outside SpawnService (which enters long-running mode
|
|
276
|
+
// for its own subprocesses by default), so bracket it here to get the same cooperative
|
|
277
|
+
// Ctrl-C handling during what can be the slowest step of the upgrade.
|
|
278
|
+
this.#shutdownService?.enterLongRunningMode();
|
|
279
|
+
let archiveData;
|
|
280
|
+
try {
|
|
281
|
+
const response = await fetch(url);
|
|
282
|
+
if (!response.ok) {
|
|
283
|
+
throw new Error(`Failed to download release asset '${assetName}': HTTP ${response.status}`);
|
|
284
|
+
}
|
|
285
|
+
archiveData = await response.arrayBuffer();
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
this.#shutdownService?.leaveLongRunningMode();
|
|
257
289
|
}
|
|
258
290
|
const tmpDir = await mkdtemp(join(tmpdir(), "upgrade-"));
|
|
259
291
|
const archivePath = join(tmpDir, assetName);
|
|
260
|
-
await Bun.write(archivePath,
|
|
292
|
+
await Bun.write(archivePath, archiveData);
|
|
261
293
|
const currentExecutable = process.execPath;
|
|
262
294
|
if (os === SupportedOs.WINDOWS) {
|
|
263
295
|
const extractResult = await this.#spawnService.spawn([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpgradeServiceProvider.d.ts","sourceRoot":"","sources":["../../../../src/service/upgrade/UpgradeServiceProvider.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;
|
|
1
|
+
{"version":3,"file":"UpgradeServiceProvider.d.ts","sourceRoot":"","sources":["../../../../src/service/upgrade/UpgradeServiceProvider.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,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAK1E,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,eAAe;;IACpE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAsB;IAChD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAKd,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,sBAAsB;IAKnE,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IASpD,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAgH1D"}
|
|
@@ -2,6 +2,7 @@ import { UPGRADE_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
|
2
2
|
import { PROMPTER_SERVICE_ID, PromptType } from "@flowscripter/dynamic-cli-framework-api";
|
|
3
3
|
import { KEY_VALUE_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
4
4
|
import { SPAWN_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
5
|
+
import { SHUTDOWN_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
5
6
|
import { Icon, PRINTER_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
6
7
|
import DefaultUpgradeService from "./DefaultUpgradeService.js";
|
|
7
8
|
import { UpgradeSubCommand } from "./command/UpgradeSubCommand.js";
|
|
@@ -30,7 +31,10 @@ export default class UpgradeServiceProvider {
|
|
|
30
31
|
const cliConfig = this.#cliConfig;
|
|
31
32
|
if (context.doesServiceExist(SPAWN_SERVICE_ID)) {
|
|
32
33
|
const spawnService = context.getServiceById(SPAWN_SERVICE_ID);
|
|
33
|
-
|
|
34
|
+
const shutdownService = context.doesServiceExist(SHUTDOWN_SERVICE_ID)
|
|
35
|
+
? context.getServiceById(SHUTDOWN_SERVICE_ID)
|
|
36
|
+
: undefined;
|
|
37
|
+
upgradeService.setDependencies(spawnService, shutdownService);
|
|
34
38
|
}
|
|
35
39
|
else {
|
|
36
40
|
logger.debug(() => "SpawnService not available, upgrade install methods will be unavailable");
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import { tmpdir } from "node:os";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import type {
|
|
6
6
|
CLIConfig,
|
|
7
|
+
ShutdownService,
|
|
7
8
|
SpawnService,
|
|
8
9
|
UpgradeCheckResult,
|
|
9
10
|
UpgradeResult,
|
|
@@ -20,6 +21,21 @@ import getLogger from "../../util/logger.ts";
|
|
|
20
21
|
|
|
21
22
|
const logger = getLogger("DefaultUpgradeService");
|
|
22
23
|
|
|
24
|
+
// checkForUpgrade() runs opportunistically on every CLI invocation (via BannerServiceProvider),
|
|
25
|
+
// so its version-check network calls must never be allowed to stall CLI startup.
|
|
26
|
+
const VERSION_CHECK_TIMEOUT_MS = 250;
|
|
27
|
+
|
|
28
|
+
// SpawnService has no built-in cancellation, so a stalled `brew`/`winget` invocation (e.g. winget's
|
|
29
|
+
// first-ever run on a machine prompting to accept Microsoft Store terms) can otherwise hang
|
|
30
|
+
// checkForUpgrade() indefinitely. Racing against this bounds how long we wait for a result; the
|
|
31
|
+
// underlying process is not killed, but the CLI stops blocking on it.
|
|
32
|
+
async function withSpawnTimeout<T>(spawnPromise: Promise<T>, fallback: T): Promise<T> {
|
|
33
|
+
return Promise.race([
|
|
34
|
+
spawnPromise,
|
|
35
|
+
new Promise<T>((resolve) => setTimeout(() => resolve(fallback), VERSION_CHECK_TIMEOUT_MS)),
|
|
36
|
+
]);
|
|
37
|
+
}
|
|
38
|
+
|
|
23
39
|
const OS_LABELS: Record<SupportedOs, string> = {
|
|
24
40
|
[SupportedOs.LINUX]: "Linux",
|
|
25
41
|
[SupportedOs.MACOS]: "MacOS",
|
|
@@ -28,6 +44,7 @@ const OS_LABELS: Record<SupportedOs, string> = {
|
|
|
28
44
|
|
|
29
45
|
export default class DefaultUpgradeService implements UpgradeService {
|
|
30
46
|
#spawnService: SpawnService | undefined;
|
|
47
|
+
#shutdownService: ShutdownService | undefined;
|
|
31
48
|
readonly #config: UpgradeLocationsConfig;
|
|
32
49
|
readonly #cliConfig: CLIConfig;
|
|
33
50
|
|
|
@@ -36,8 +53,9 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
36
53
|
this.#cliConfig = cliConfig;
|
|
37
54
|
}
|
|
38
55
|
|
|
39
|
-
public setDependencies(spawnService: SpawnService): void {
|
|
56
|
+
public setDependencies(spawnService: SpawnService, shutdownService?: ShutdownService): void {
|
|
40
57
|
this.#spawnService = spawnService;
|
|
58
|
+
this.#shutdownService = shutdownService;
|
|
41
59
|
}
|
|
42
60
|
|
|
43
61
|
public detectOs(): SupportedOs | undefined {
|
|
@@ -168,9 +186,12 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
168
186
|
if (!this.#spawnService || !this.#config.homebrew) {
|
|
169
187
|
return false;
|
|
170
188
|
}
|
|
171
|
-
const result = await
|
|
172
|
-
["brew", "list", "--versions", this.#config.homebrew.formula],
|
|
173
|
-
|
|
189
|
+
const result = await withSpawnTimeout(
|
|
190
|
+
this.#spawnService.spawn(["brew", "list", "--versions", this.#config.homebrew.formula], {
|
|
191
|
+
stdio: "wrapped",
|
|
192
|
+
longRunning: false,
|
|
193
|
+
}),
|
|
194
|
+
{ ok: false } as const,
|
|
174
195
|
);
|
|
175
196
|
return result.ok;
|
|
176
197
|
}
|
|
@@ -179,9 +200,12 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
179
200
|
if (!this.#spawnService || !this.#config.winget) {
|
|
180
201
|
return false;
|
|
181
202
|
}
|
|
182
|
-
const result = await
|
|
183
|
-
["winget", "list", "--id", this.#config.winget.packageId],
|
|
184
|
-
|
|
203
|
+
const result = await withSpawnTimeout(
|
|
204
|
+
this.#spawnService.spawn(["winget", "list", "--id", this.#config.winget.packageId], {
|
|
205
|
+
stdio: "wrapped",
|
|
206
|
+
longRunning: false,
|
|
207
|
+
}),
|
|
208
|
+
{ ok: false } as const,
|
|
185
209
|
);
|
|
186
210
|
return result.ok;
|
|
187
211
|
}
|
|
@@ -210,7 +234,10 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
210
234
|
}
|
|
211
235
|
const { owner, repo } = this.#config.githubRelease;
|
|
212
236
|
try {
|
|
213
|
-
const response = await fetch(
|
|
237
|
+
const response = await fetch(
|
|
238
|
+
`https://api.github.com/repos/${owner}/${repo}/releases/latest`,
|
|
239
|
+
{ signal: AbortSignal.timeout(VERSION_CHECK_TIMEOUT_MS) },
|
|
240
|
+
);
|
|
214
241
|
if (!response.ok) {
|
|
215
242
|
return undefined;
|
|
216
243
|
}
|
|
@@ -234,6 +261,7 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
234
261
|
try {
|
|
235
262
|
const response = await fetch(
|
|
236
263
|
`https://raw.githubusercontent.com/${tapOwner}/homebrew-${tapName}/main/${formula}.rb`,
|
|
264
|
+
{ signal: AbortSignal.timeout(VERSION_CHECK_TIMEOUT_MS) },
|
|
237
265
|
);
|
|
238
266
|
if (!response.ok) {
|
|
239
267
|
return undefined;
|
|
@@ -251,13 +279,13 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
251
279
|
return undefined;
|
|
252
280
|
}
|
|
253
281
|
const lines: string[] = [];
|
|
254
|
-
const result = await
|
|
255
|
-
["winget", "show", "--id", this.#config.winget.packageId],
|
|
256
|
-
{
|
|
282
|
+
const result = await withSpawnTimeout(
|
|
283
|
+
this.#spawnService.spawn(["winget", "show", "--id", this.#config.winget.packageId], {
|
|
257
284
|
stdio: "wrapped",
|
|
258
285
|
longRunning: false,
|
|
259
286
|
onOutput: (line) => lines.push(line),
|
|
260
|
-
},
|
|
287
|
+
}),
|
|
288
|
+
{ ok: false } as const,
|
|
261
289
|
);
|
|
262
290
|
if (!result.ok) {
|
|
263
291
|
return undefined;
|
|
@@ -316,14 +344,24 @@ export default class DefaultUpgradeService implements UpgradeService {
|
|
|
316
344
|
const assetName = assetPattern.replace("{os}", OS_LABELS[os]).replace("{arch}", archLabel);
|
|
317
345
|
const url = `https://github.com/${owner}/${repo}/releases/latest/download/${assetName}`;
|
|
318
346
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
347
|
+
// Downloading the release asset happens outside SpawnService (which enters long-running mode
|
|
348
|
+
// for its own subprocesses by default), so bracket it here to get the same cooperative
|
|
349
|
+
// Ctrl-C handling during what can be the slowest step of the upgrade.
|
|
350
|
+
this.#shutdownService?.enterLongRunningMode();
|
|
351
|
+
let archiveData: ArrayBuffer;
|
|
352
|
+
try {
|
|
353
|
+
const response = await fetch(url);
|
|
354
|
+
if (!response.ok) {
|
|
355
|
+
throw new Error(`Failed to download release asset '${assetName}': HTTP ${response.status}`);
|
|
356
|
+
}
|
|
357
|
+
archiveData = await response.arrayBuffer();
|
|
358
|
+
} finally {
|
|
359
|
+
this.#shutdownService?.leaveLongRunningMode();
|
|
322
360
|
}
|
|
323
361
|
|
|
324
362
|
const tmpDir = await mkdtemp(join(tmpdir(), "upgrade-"));
|
|
325
363
|
const archivePath = join(tmpDir, assetName);
|
|
326
|
-
await Bun.write(archivePath,
|
|
364
|
+
await Bun.write(archivePath, archiveData);
|
|
327
365
|
|
|
328
366
|
const currentExecutable = process.execPath;
|
|
329
367
|
|
|
@@ -8,6 +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 { SHUTDOWN_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
12
|
+
import type { ShutdownService } from "@flowscripter/dynamic-cli-framework-api";
|
|
11
13
|
import { Icon, PRINTER_SERVICE_ID } from "@flowscripter/dynamic-cli-framework-api";
|
|
12
14
|
import type { PrinterService } from "@flowscripter/dynamic-cli-framework-api";
|
|
13
15
|
import DefaultUpgradeService from "./DefaultUpgradeService.ts";
|
|
@@ -44,7 +46,10 @@ export default class UpgradeServiceProvider implements ServiceProvider {
|
|
|
44
46
|
|
|
45
47
|
if (context.doesServiceExist(SPAWN_SERVICE_ID)) {
|
|
46
48
|
const spawnService = context.getServiceById(SPAWN_SERVICE_ID) as SpawnService;
|
|
47
|
-
|
|
49
|
+
const shutdownService = context.doesServiceExist(SHUTDOWN_SERVICE_ID)
|
|
50
|
+
? (context.getServiceById(SHUTDOWN_SERVICE_ID) as ShutdownService)
|
|
51
|
+
: undefined;
|
|
52
|
+
upgradeService.setDependencies(spawnService, shutdownService);
|
|
48
53
|
} else {
|
|
49
54
|
logger.debug(() => "SpawnService not available, upgrade install methods will be unavailable");
|
|
50
55
|
}
|