@flowscripter/dynamic-cli-framework 3.0.0 → 3.0.2

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 +1 @@
1
- {"version":3,"file":"DefaultUpgradeService.d.ts","sourceRoot":"","sources":["../../../../src/service/upgrade/DefaultUpgradeService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EAEZ,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;AAO1E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAc5C,MAAM,CAAC,OAAO,OAAO,qBAAsB,YAAW,cAAc;;gBAO/C,MAAM,EAAE,sBAAsB,EAAE,SAAS,EAAE,SAAS;IAKhE,eAAe,CACpB,YAAY,EAAE,YAAY,GAAG,SAAS,EACtC,YAAY,EAAE,YAAY,GAAG,SAAS,GACrC,IAAI;IAKA,qBAAqB,CAAC,aAAa,UAAQ,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IAerF,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;CAuQ1B"}
1
+ {"version":3,"file":"DefaultUpgradeService.d.ts","sourceRoot":"","sources":["../../../../src/service/upgrade/DefaultUpgradeService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EAEZ,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;AAS1E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAc5C,MAAM,CAAC,OAAO,OAAO,qBAAsB,YAAW,cAAc;;gBAO/C,MAAM,EAAE,sBAAsB,EAAE,SAAS,EAAE,SAAS;IAKhE,eAAe,CACpB,YAAY,EAAE,YAAY,GAAG,SAAS,EACtC,YAAY,EAAE,YAAY,GAAG,SAAS,GACrC,IAAI;IAKA,qBAAqB,CAAC,aAAa,UAAQ,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC;IA0BrF,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;CAoQ1B"}
@@ -7,7 +7,9 @@ import semver from "semver";
7
7
  import getLogger from "../../util/logger.js";
8
8
  const logger = getLogger("DefaultUpgradeService");
9
9
  // checkForUpgrade() runs opportunistically on every CLI invocation (via BannerServiceProvider),
10
- // so its version-check network/spawn calls must never be allowed to stall CLI startup.
10
+ // so that opportunistic call is raced against this timeout so it never stalls CLI startup.
11
+ // A deliberate caller (waitForResult=true, e.g. the `upgrade` command) awaits checkForUpgrade()
12
+ // directly with no timeout, so its underlying network/spawn calls are never artificially cut off.
11
13
  export const VERSION_CHECK_TIMEOUT_MS = 250;
12
14
  function describeSpawnFailure(result) {
13
15
  return "timedOut" in result
@@ -35,7 +37,18 @@ export default class DefaultUpgradeService {
35
37
  }
36
38
  getUpgradeCheckResult(waitForResult = false) {
37
39
  if (!this.#upgradeCheckPromise) {
38
- this.#upgradeCheckPromise = this.checkForUpgrade();
40
+ // Only cache a successful result. An `undefined` result can come from a transient
41
+ // failure (e.g. the opportunistic startup check racing past VERSION_CHECK_TIMEOUT_MS
42
+ // before checkForUpgrade() itself resolves) - caching that would permanently deny a
43
+ // later, deliberate caller (e.g. the `upgrade` command explicitly waiting via
44
+ // waitForResult=true) any chance of a fresh attempt for the rest of this process's
45
+ // lifetime.
46
+ this.#upgradeCheckPromise = this.checkForUpgrade().then((result) => {
47
+ if (result === undefined) {
48
+ this.#upgradeCheckPromise = undefined;
49
+ }
50
+ return result;
51
+ });
39
52
  }
40
53
  if (waitForResult) {
41
54
  return this.#upgradeCheckPromise;
@@ -159,14 +172,14 @@ export default class DefaultUpgradeService {
159
172
  if (!this.#spawnService || !this.#config.homebrew) {
160
173
  return false;
161
174
  }
162
- const result = await this.#spawnService.spawn(["brew", "list", "--versions", this.#config.homebrew.formula], { mode: "ignore", longRunning: false, timeoutMs: VERSION_CHECK_TIMEOUT_MS });
175
+ const result = await this.#spawnService.spawn(["brew", "list", "--versions", this.#config.homebrew.formula], { mode: "ignore", longRunning: false });
163
176
  return result.ok;
164
177
  }
165
178
  async #isWingetInstalled() {
166
179
  if (!this.#spawnService || !this.#config.winget) {
167
180
  return false;
168
181
  }
169
- const result = await this.#spawnService.spawn(["winget", "list", "--id", this.#config.winget.packageId], { mode: "ignore", longRunning: false, timeoutMs: VERSION_CHECK_TIMEOUT_MS });
182
+ const result = await this.#spawnService.spawn(["winget", "list", "--id", this.#config.winget.packageId], { mode: "ignore", longRunning: false });
170
183
  return result.ok;
171
184
  }
172
185
  #isLinuxScriptInstall() {
@@ -191,7 +204,7 @@ export default class DefaultUpgradeService {
191
204
  }
192
205
  const { owner, repo } = this.#config.githubRelease;
193
206
  try {
194
- const response = await this.#fetchService.fetch(`https://api.github.com/repos/${owner}/${repo}/releases/latest`, { timeoutMs: VERSION_CHECK_TIMEOUT_MS });
207
+ const response = await this.#fetchService.fetch(`https://api.github.com/repos/${owner}/${repo}/releases/latest`);
195
208
  if (!response.ok) {
196
209
  return undefined;
197
210
  }
@@ -213,7 +226,7 @@ export default class DefaultUpgradeService {
213
226
  return undefined;
214
227
  }
215
228
  try {
216
- const response = await this.#fetchService.fetch(`https://raw.githubusercontent.com/${tapOwner}/homebrew-${tapName}/main/${formula}.rb`, { timeoutMs: VERSION_CHECK_TIMEOUT_MS });
229
+ const response = await this.#fetchService.fetch(`https://raw.githubusercontent.com/${tapOwner}/homebrew-${tapName}/main/${formula}.rb`);
217
230
  if (!response.ok) {
218
231
  return undefined;
219
232
  }
@@ -233,7 +246,6 @@ export default class DefaultUpgradeService {
233
246
  const result = await this.#spawnService.spawn(["winget", "show", "--id", this.#config.winget.packageId], {
234
247
  mode: "wrapped",
235
248
  longRunning: false,
236
- timeoutMs: VERSION_CHECK_TIMEOUT_MS,
237
249
  onOutput: (line) => lines.push(line),
238
250
  });
239
251
  if (!result.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowscripter/dynamic-cli-framework",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "A framework for developing CLI applications which supports dynamic discovery and installation of new commands",
5
5
  "keywords": [
6
6
  "bun",
@@ -23,7 +23,9 @@ import getLogger from "../../util/logger.ts";
23
23
  const logger = getLogger("DefaultUpgradeService");
24
24
 
25
25
  // checkForUpgrade() runs opportunistically on every CLI invocation (via BannerServiceProvider),
26
- // so its version-check network/spawn calls must never be allowed to stall CLI startup.
26
+ // so that opportunistic call is raced against this timeout so it never stalls CLI startup.
27
+ // A deliberate caller (waitForResult=true, e.g. the `upgrade` command) awaits checkForUpgrade()
28
+ // directly with no timeout, so its underlying network/spawn calls are never artificially cut off.
27
29
  export const VERSION_CHECK_TIMEOUT_MS = 250;
28
30
 
29
31
  function describeSpawnFailure(result: Extract<SpawnResult, { ok: false }>): string {
@@ -60,7 +62,18 @@ export default class DefaultUpgradeService implements UpgradeService {
60
62
 
61
63
  public getUpgradeCheckResult(waitForResult = false): Promise<UpgradeCheckResult | undefined> {
62
64
  if (!this.#upgradeCheckPromise) {
63
- this.#upgradeCheckPromise = this.checkForUpgrade();
65
+ // Only cache a successful result. An `undefined` result can come from a transient
66
+ // failure (e.g. the opportunistic startup check racing past VERSION_CHECK_TIMEOUT_MS
67
+ // before checkForUpgrade() itself resolves) - caching that would permanently deny a
68
+ // later, deliberate caller (e.g. the `upgrade` command explicitly waiting via
69
+ // waitForResult=true) any chance of a fresh attempt for the rest of this process's
70
+ // lifetime.
71
+ this.#upgradeCheckPromise = this.checkForUpgrade().then((result) => {
72
+ if (result === undefined) {
73
+ this.#upgradeCheckPromise = undefined;
74
+ }
75
+ return result;
76
+ });
64
77
  }
65
78
  if (waitForResult) {
66
79
  return this.#upgradeCheckPromise;
@@ -210,7 +223,7 @@ export default class DefaultUpgradeService implements UpgradeService {
210
223
  }
211
224
  const result = await this.#spawnService.spawn(
212
225
  ["brew", "list", "--versions", this.#config.homebrew.formula],
213
- { mode: "ignore", longRunning: false, timeoutMs: VERSION_CHECK_TIMEOUT_MS },
226
+ { mode: "ignore", longRunning: false },
214
227
  );
215
228
  return result.ok;
216
229
  }
@@ -221,7 +234,7 @@ export default class DefaultUpgradeService implements UpgradeService {
221
234
  }
222
235
  const result = await this.#spawnService.spawn(
223
236
  ["winget", "list", "--id", this.#config.winget.packageId],
224
- { mode: "ignore", longRunning: false, timeoutMs: VERSION_CHECK_TIMEOUT_MS },
237
+ { mode: "ignore", longRunning: false },
225
238
  );
226
239
  return result.ok;
227
240
  }
@@ -252,7 +265,6 @@ export default class DefaultUpgradeService implements UpgradeService {
252
265
  try {
253
266
  const response = await this.#fetchService.fetch(
254
267
  `https://api.github.com/repos/${owner}/${repo}/releases/latest`,
255
- { timeoutMs: VERSION_CHECK_TIMEOUT_MS },
256
268
  );
257
269
  if (!response.ok) {
258
270
  return undefined;
@@ -277,7 +289,6 @@ export default class DefaultUpgradeService implements UpgradeService {
277
289
  try {
278
290
  const response = await this.#fetchService.fetch(
279
291
  `https://raw.githubusercontent.com/${tapOwner}/homebrew-${tapName}/main/${formula}.rb`,
280
- { timeoutMs: VERSION_CHECK_TIMEOUT_MS },
281
292
  );
282
293
  if (!response.ok) {
283
294
  return undefined;
@@ -300,7 +311,6 @@ export default class DefaultUpgradeService implements UpgradeService {
300
311
  {
301
312
  mode: "wrapped",
302
313
  longRunning: false,
303
- timeoutMs: VERSION_CHECK_TIMEOUT_MS,
304
314
  onOutput: (line) => lines.push(line),
305
315
  },
306
316
  );