@edspencer/paddock 0.82.0 → 0.82.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 (107) hide show
  1. package/package.json +1 -1
  2. package/packages/server/dist/cli/args.js +2 -2
  3. package/packages/server/dist/cli/busy-command.js +1 -1
  4. package/packages/server/dist/cli/busy.js +10 -12
  5. package/packages/server/dist/cli/exit-codes.d.ts +21 -45
  6. package/packages/server/dist/cli/exit-codes.js +42 -45
  7. package/packages/server/dist/cli/output.js +5 -6
  8. package/packages/server/dist/cli/paddock.js +9 -9
  9. package/packages/server/dist/cli/service/index.d.ts +2 -2
  10. package/packages/server/dist/cli/service/index.js +30 -24
  11. package/packages/server/dist/cli/service/launchd.d.ts +31 -84
  12. package/packages/server/dist/cli/service/launchd.js +104 -304
  13. package/packages/server/dist/cli/service/logs.d.ts +9 -28
  14. package/packages/server/dist/cli/service/logs.js +33 -75
  15. package/packages/server/dist/cli/service/manager.d.ts +93 -0
  16. package/packages/server/dist/cli/service/manager.js +21 -0
  17. package/packages/server/dist/cli/service/path-env.d.ts +7 -18
  18. package/packages/server/dist/cli/service/path-env.js +30 -81
  19. package/packages/server/dist/cli/service/spec.d.ts +4 -31
  20. package/packages/server/dist/cli/service/spec.js +9 -0
  21. package/packages/server/dist/cli/service/systemd.d.ts +27 -101
  22. package/packages/server/dist/cli/service/systemd.js +106 -262
  23. package/packages/server/dist/cli/update/health.d.ts +48 -0
  24. package/packages/server/dist/cli/update/health.js +64 -0
  25. package/packages/server/dist/cli/update/install-method.d.ts +29 -76
  26. package/packages/server/dist/cli/update/install-method.js +103 -178
  27. package/packages/server/dist/cli/update/lock.d.ts +7 -12
  28. package/packages/server/dist/cli/update/lock.js +28 -62
  29. package/packages/server/dist/cli/update/package-manager.d.ts +39 -74
  30. package/packages/server/dist/cli/update/package-manager.js +95 -160
  31. package/packages/server/dist/cli/update/registry.d.ts +17 -54
  32. package/packages/server/dist/cli/update/registry.js +46 -89
  33. package/packages/server/dist/cli/update/semver.d.ts +18 -41
  34. package/packages/server/dist/cli/update/semver.js +74 -124
  35. package/packages/server/dist/cli/update/update-check.d.ts +15 -26
  36. package/packages/server/dist/cli/update/update-check.js +30 -60
  37. package/packages/server/dist/cli/update/update.d.ts +57 -91
  38. package/packages/server/dist/cli/update/update.js +230 -431
  39. package/packages/server/dist/cli/update-command.js +3 -5
  40. package/packages/server/package.json +1 -1
  41. package/packages/web/dist/assets/{DeleteProjectDialog-CphdGB3R.js → DeleteProjectDialog-CgHpQctt.js} +1 -1
  42. package/packages/web/dist/assets/DiscoverPage-CG6cf-0i.js +2 -0
  43. package/packages/web/dist/assets/{DiscoverView-B_kcF4sm.js → DiscoverView-BKqI0I1E.js} +1 -1
  44. package/packages/web/dist/assets/{InstanceConfigPage-CvUK5DKW.js → InstanceConfigPage-DL3raCK1.js} +1 -1
  45. package/packages/web/dist/assets/{MarkdownRenderer-DvZ-j_Ao.js → MarkdownRenderer-DcjEuf3s.js} +1 -1
  46. package/packages/web/dist/assets/{ProjectRedirect-DayHvUH2.js → ProjectRedirect-DerkA-nE.js} +1 -1
  47. package/packages/web/dist/assets/{ProjectView-CCw83gUi.js → ProjectView-NwfC3_w7.js} +3 -3
  48. package/packages/web/dist/assets/{ProjectsGrid-B3Klg2H4.js → ProjectsGrid-BeORa0UH.js} +1 -1
  49. package/packages/web/dist/assets/{RootHome-BxcDvpgI.js → RootHome-BYJs8qJ6.js} +1 -1
  50. package/packages/web/dist/assets/{Surfaces-7UlhFBSG.js → Surfaces-w-kEaAYU.js} +1 -1
  51. package/packages/web/dist/assets/{arc-DNkh5o5Q.js → arc-Bv56hasM.js} +1 -1
  52. package/packages/web/dist/assets/{architectureDiagram-3BPJPVTR-BrgN3oLF.js → architectureDiagram-3BPJPVTR-BHEknx9i.js} +1 -1
  53. package/packages/web/dist/assets/{blockDiagram-GPEHLZMM-D05XOJSk.js → blockDiagram-GPEHLZMM-DtxTMrPX.js} +1 -1
  54. package/packages/web/dist/assets/{c4Diagram-AAUBKEIU-CKaMBhMP.js → c4Diagram-AAUBKEIU-DRpEYOlM.js} +1 -1
  55. package/packages/web/dist/assets/channel-CdIiAqY2.js +2 -0
  56. package/packages/web/dist/assets/{chunk-2J33WTMH-8hgadCQc.js → chunk-2J33WTMH-S4s7GCg7.js} +1 -1
  57. package/packages/web/dist/assets/{chunk-4BX2VUAB-CBfEC-pu.js → chunk-4BX2VUAB-BkWVPLf1.js} +1 -1
  58. package/packages/web/dist/assets/{chunk-55IACEB6-DV1eMgHk.js → chunk-55IACEB6-4-FQp01F.js} +1 -1
  59. package/packages/web/dist/assets/{chunk-727SXJPM-Cfgl5fxY.js → chunk-727SXJPM-BeyDWdIb.js} +1 -1
  60. package/packages/web/dist/assets/{chunk-AQP2D5EJ-BXhqD295.js → chunk-AQP2D5EJ-ZSxKy745.js} +1 -1
  61. package/packages/web/dist/assets/{chunk-FMBD7UC4-TFGOPtek.js → chunk-FMBD7UC4-Bq8uV9j-.js} +1 -1
  62. package/packages/web/dist/assets/{chunk-ND2GUHAM-CHFM665R.js → chunk-ND2GUHAM-BOFsRyHk.js} +1 -1
  63. package/packages/web/dist/assets/{chunk-QZHKN3VN-CqEf6MMT.js → chunk-QZHKN3VN-uZ6oNc4m.js} +1 -1
  64. package/packages/web/dist/assets/classDiagram-4FO5ZUOK-DCCUHba0.js +2 -0
  65. package/packages/web/dist/assets/classDiagram-v2-Q7XG4LA2-DCCUHba0.js +2 -0
  66. package/packages/web/dist/assets/{core-DmEaKxBb.js → core-CYuJAM2U.js} +1 -1
  67. package/packages/web/dist/assets/{cose-bilkent-S5V4N54A-BnGI6jkr.js → cose-bilkent-S5V4N54A-DIzkVSFb.js} +1 -1
  68. package/packages/web/dist/assets/{dagre-BM42HDAG-CKoPx61E.js → dagre-BM42HDAG-CHR6jJBv.js} +1 -1
  69. package/packages/web/dist/assets/{diagram-2AECGRRQ-mMmtlBl1.js → diagram-2AECGRRQ-BAFXCH8Q.js} +1 -1
  70. package/packages/web/dist/assets/{diagram-5GNKFQAL-Cdz9Mtnt.js → diagram-5GNKFQAL-BJ5t5gbz.js} +1 -1
  71. package/packages/web/dist/assets/{diagram-KO2AKTUF-DQxM3wYj.js → diagram-KO2AKTUF-D9Xt0IVg.js} +1 -1
  72. package/packages/web/dist/assets/{diagram-LMA3HP47-BWrinPsq.js → diagram-LMA3HP47-Bq38u6sy.js} +1 -1
  73. package/packages/web/dist/assets/{diagram-OG6HWLK6-U6MYUve2.js → diagram-OG6HWLK6-CMQVqkpi.js} +1 -1
  74. package/packages/web/dist/assets/{documentTitle-DGjRXuTP.js → documentTitle-M1lrfXRU.js} +1 -1
  75. package/packages/web/dist/assets/{erDiagram-TEJ5UH35-xqMCsXxY.js → erDiagram-TEJ5UH35-C63M1g9b.js} +1 -1
  76. package/packages/web/dist/assets/{flowDiagram-I6XJVG4X-PMfy_czF.js → flowDiagram-I6XJVG4X-D3j8ACN7.js} +1 -1
  77. package/packages/web/dist/assets/{ganttDiagram-6RSMTGT7-whhYYE4N.js → ganttDiagram-6RSMTGT7-B1Fd1A2Y.js} +1 -1
  78. package/packages/web/dist/assets/{gitGraphDiagram-PVQCEYII-C51JW4tf.js → gitGraphDiagram-PVQCEYII-CEhZhDdR.js} +1 -1
  79. package/packages/web/dist/assets/{index-CHOtvlnO.js → index-1E9yHciS.js} +2 -2
  80. package/packages/web/dist/assets/{infoDiagram-5YYISTIA-SH8cr905.js → infoDiagram-5YYISTIA-Ctquaew6.js} +1 -1
  81. package/packages/web/dist/assets/{ishikawaDiagram-YF4QCWOH-BjqaoU3U.js → ishikawaDiagram-YF4QCWOH-DV4GvA1R.js} +1 -1
  82. package/packages/web/dist/assets/{journeyDiagram-JHISSGLW-CBmdEVrd.js → journeyDiagram-JHISSGLW-C_Cy9waA.js} +1 -1
  83. package/packages/web/dist/assets/{kanban-definition-UN3LZRKU-U8njjMLZ.js → kanban-definition-UN3LZRKU-CGr9ctEf.js} +1 -1
  84. package/packages/web/dist/assets/{linear-DF66GPs1.js → linear-D3U8NOkt.js} +1 -1
  85. package/packages/web/dist/assets/{mermaid.core-CouJz7Ph.js → mermaid.core-BiArdWKV.js} +4 -4
  86. package/packages/web/dist/assets/{mindmap-definition-RKZ34NQL-BYIf0oFt.js → mindmap-definition-RKZ34NQL-CZIpzj8Z.js} +1 -1
  87. package/packages/web/dist/assets/{pieDiagram-4H26LBE5-Cm8rgg09.js → pieDiagram-4H26LBE5-1MaeS3rt.js} +1 -1
  88. package/packages/web/dist/assets/{quadrantDiagram-W4KKPZXB-C3Il5kOH.js → quadrantDiagram-W4KKPZXB-B5pgQ54e.js} +1 -1
  89. package/packages/web/dist/assets/{requirementDiagram-4Y6WPE33-D3PE2nTe.js → requirementDiagram-4Y6WPE33-BNnxrpGr.js} +1 -1
  90. package/packages/web/dist/assets/{sankeyDiagram-5OEKKPKP-DdmvBM18.js → sankeyDiagram-5OEKKPKP-DsxVH-hM.js} +1 -1
  91. package/packages/web/dist/assets/{sequenceDiagram-3UESZ5HK-B8M_GAIq.js → sequenceDiagram-3UESZ5HK-Ke9LcFZI.js} +1 -1
  92. package/packages/web/dist/assets/{stateDiagram-AJRCARHV-DZkXnK1_.js → stateDiagram-AJRCARHV-UJzmflND.js} +1 -1
  93. package/packages/web/dist/assets/stateDiagram-v2-BHNVJYJU-DgUc3HkP.js +2 -0
  94. package/packages/web/dist/assets/{timeline-definition-PNZ67QCA-IHXq7rqi.js → timeline-definition-PNZ67QCA-BRjNALVI.js} +1 -1
  95. package/packages/web/dist/assets/{vennDiagram-CIIHVFJN-Dga7tLtT.js → vennDiagram-CIIHVFJN-ClMAspxz.js} +1 -1
  96. package/packages/web/dist/assets/{wardley-L42UT6IY-CmcwnEJ-.js → wardley-L42UT6IY-UPv4JEmz.js} +1 -1
  97. package/packages/web/dist/assets/{wardleyDiagram-YWT4CUSO-zHuSLrD4.js → wardleyDiagram-YWT4CUSO-BgYJbdEx.js} +1 -1
  98. package/packages/web/dist/assets/{xychartDiagram-2RQKCTM6-D93MU_ic.js → xychartDiagram-2RQKCTM6-Bfk5HjGx.js} +1 -1
  99. package/packages/web/dist/index.html +1 -1
  100. package/packages/web/dist/sw.js +1 -1
  101. package/packages/server/dist/cli/service/backend.d.ts +0 -115
  102. package/packages/server/dist/cli/service/backend.js +0 -19
  103. package/packages/web/dist/assets/DiscoverPage-C4OPLNO8.js +0 -2
  104. package/packages/web/dist/assets/channel-JrEedxB8.js +0 -2
  105. package/packages/web/dist/assets/classDiagram-4FO5ZUOK-CHJiQp-W.js +0 -2
  106. package/packages/web/dist/assets/classDiagram-v2-Q7XG4LA2-CHJiQp-W.js +0 -2
  107. package/packages/web/dist/assets/stateDiagram-v2-BHNVJYJU-CjCdT9Ls.js +0 -2
@@ -1,55 +1,24 @@
1
- /**
2
- * The npm registry, as `update` asks it (CLI contract SPEC §5 step 3).
3
- *
4
- * Two requests, both with `fetch` and a 10-second abort, and nothing else:
5
- *
6
- * GET <registry>/-/package/<name>/dist-tags which version is `latest`
7
- * GET <registry>/<name>/<version> that version's `engines`
8
- *
9
- * Deliberately NOT `npm view`: spawning npm to read two small JSON documents
10
- * costs a second of process start-up, needs npm to be on PATH at all, and puts
11
- * the registry's answer through a program whose output format is not a
12
- * contract. `fetch` is in Node 22 and the registry's REST surface has been
13
- * stable for a decade.
14
- *
15
- * **Nothing here is called except by a person.** SPEC §3: only `update`,
16
- * `update --check` and `doctor` contact the registry, and only when someone
17
- * runs them. There is no background check and no check at startup, which is why
18
- * this module is reachable from the CLI and from nowhere in the server.
19
- *
20
- * Generic: wave C4 lifts it into `reference/registry.ts`.
21
- */
22
- /** SPEC §5: 10 seconds, and it is the budget for each request rather than the pair. */
1
+ /** SPEC §5: 10 seconds for each request. */
23
2
  export declare const REGISTRY_TIMEOUT_MS = 10000;
24
3
  export declare const DEFAULT_REGISTRY = "https://registry.npmjs.org";
25
4
  export interface RegistryOptions {
26
5
  packageName: string;
27
- /** Base URL, no trailing slash required — {@link registryUrl} normalises it. */
6
+ /** The base URL; a trailing slash is fine. */
28
7
  registry: string;
29
8
  fetch?: typeof globalThis.fetch;
30
9
  timeoutMs?: number;
31
10
  }
32
11
  /**
33
- * Which registry to ask: `npm_config_registry`, else `npm config get registry`,
34
- * else the public one (SPEC §5 step 3).
35
- *
36
- * The first is what makes the fake-registry tests possible without touching a
37
- * global npm config — an `npm_config_registry` in the environment is how npm
38
- * itself takes the same setting, so a test and a real `.npmrc` arrive by the
39
- * same door.
12
+ * Which registry to ask: `npm_config_registry`, else `npm config get registry`, else the public one (SPEC §5 step 3).
13
+ * The variable comes first because it's how npm itself takes the setting, so a test and a real `.npmrc` arrive the
14
+ * same way.
40
15
  */
41
16
  export declare function resolveRegistry(env: NodeJS.ProcessEnv, npmConfigGet?: (key: string) => string | undefined): string;
42
- /**
43
- * Join a path onto the registry base.
44
- *
45
- * A scoped name's `/` is written `%2f` (SPEC §5 step 3). That is required by
46
- * the dist-tags route and accepted by the manifest route, so both are built the
47
- * same way — one rule instead of two, and no chance of only one of them being
48
- * right for `@scope/name`.
49
- */
17
+ /** Joins path parts onto the registry, writing a scoped name's `/` as `%2f` (SPEC §5 step 3). Both routes take it. */
50
18
  export declare function registryUrl(registry: string, ...parts: string[]): string;
51
- /** Everything that went wrong talking to the registry, as one reportable error. */
19
+ /** Anything that went wrong talking to the registry, with the URL, as one reportable error. */
52
20
  export declare class RegistryError extends Error {
21
+ name: string;
53
22
  readonly url: string;
54
23
  constructor(url: string, message: string);
55
24
  }
@@ -62,28 +31,22 @@ export interface PackageManifest {
62
31
  node?: string;
63
32
  };
64
33
  }
65
- /** One version's manifest — read for `engines` (SPEC §5 step 3). */
34
+ /** One version's manifest, read for `engines`. */
66
35
  export declare function fetchManifest(o: RegistryOptions & {
67
36
  version: string;
68
37
  }): Promise<PackageManifest>;
69
- export interface ResolveTargetInput extends RegistryOptions {
70
- /** `--to <version|tag>`, or undefined for `latest`. */
71
- to?: string;
72
- }
73
38
  export interface ResolvedTarget {
74
39
  version: string;
75
- /** The dist-tag asked for, or null when `--to` named a version (schema field). */
40
+ /** The dist-tag asked for, or null when `--to` named a version. */
76
41
  tag: string | null;
42
+ /** The target's `engines.node`. */
77
43
  engines: string | null;
78
44
  }
79
45
  /**
80
- * Turn `--to` (or its absence) into one concrete version, plus its `engines`.
81
- *
82
- * `--to` is a version or a dist-tag and the two are told apart by shape, not by
83
- * asking: anything that parses as a version is a version, everything else is a
84
- * tag. That ordering matters because a registry will happily serve a manifest
85
- * for a tag name as well, and resolving `--to next` as a literal version would
86
- * silently install whatever `next` pointed at while REPORTING the target as
87
- * "next".
46
+ * `--to` (or `latest` without it) as one version, with its `engines`. A version and a tag are told apart by shape:
47
+ * anything that looks like a version is one. Asking first would be wrong, since a registry may serve a manifest for a
48
+ * tag's name too, and `--to next` would then install `next` while reporting it as a version called "next".
88
49
  */
89
- export declare function resolveTarget(o: ResolveTargetInput): Promise<ResolvedTarget>;
50
+ export declare function resolveTarget(o: RegistryOptions & {
51
+ to?: string;
52
+ }): Promise<ResolvedTarget>;
@@ -1,60 +1,36 @@
1
- /**
2
- * The npm registry, as `update` asks it (CLI contract SPEC §5 step 3).
3
- *
4
- * Two requests, both with `fetch` and a 10-second abort, and nothing else:
5
- *
6
- * GET <registry>/-/package/<name>/dist-tags which version is `latest`
7
- * GET <registry>/<name>/<version> that version's `engines`
8
- *
9
- * Deliberately NOT `npm view`: spawning npm to read two small JSON documents
10
- * costs a second of process start-up, needs npm to be on PATH at all, and puts
11
- * the registry's answer through a program whose output format is not a
12
- * contract. `fetch` is in Node 22 and the registry's REST surface has been
13
- * stable for a decade.
14
- *
15
- * **Nothing here is called except by a person.** SPEC §3: only `update`,
16
- * `update --check` and `doctor` contact the registry, and only when someone
17
- * runs them. There is no background check and no check at startup, which is why
18
- * this module is reachable from the CLI and from nowhere in the server.
19
- *
20
- * Generic: wave C4 lifts it into `reference/registry.ts`.
21
- */
22
- /** SPEC §5: 10 seconds, and it is the budget for each request rather than the pair. */
1
+ // From edspencer/cli-contract reference/registry.ts @ 0.2; local changes: `.ts` import specifiers → `.js`.
2
+ // The npm registry, as `update` asks it (SPEC §5 step 3): two requests with `fetch` and a 10-second abort.
3
+ //
4
+ // GET <registry>/-/package/<name>/dist-tags which version `latest` (or `--to <tag>`) is
5
+ // GET <registry>/<name>/<version> that version's `engines`
6
+ //
7
+ // Not `npm view`: that's a second of start-up to read two small documents, through a program whose output isn't a
8
+ // contract. Only `update`, `update --check` and `doctor` call this, and only when a person runs them (SPEC §3).
9
+ // Node built-ins only.
10
+ /** SPEC §5: 10 seconds for each request. */
23
11
  export const REGISTRY_TIMEOUT_MS = 10_000;
24
- export const DEFAULT_REGISTRY = "https://registry.npmjs.org";
12
+ export const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
25
13
  /**
26
- * Which registry to ask: `npm_config_registry`, else `npm config get registry`,
27
- * else the public one (SPEC §5 step 3).
28
- *
29
- * The first is what makes the fake-registry tests possible without touching a
30
- * global npm config — an `npm_config_registry` in the environment is how npm
31
- * itself takes the same setting, so a test and a real `.npmrc` arrive by the
32
- * same door.
14
+ * Which registry to ask: `npm_config_registry`, else `npm config get registry`, else the public one (SPEC §5 step 3).
15
+ * The variable comes first because it's how npm itself takes the setting, so a test and a real `.npmrc` arrive the
16
+ * same way.
33
17
  */
34
18
  export function resolveRegistry(env, npmConfigGet) {
35
19
  const fromEnv = env.npm_config_registry ?? env.NPM_CONFIG_REGISTRY;
36
- if (fromEnv !== undefined && fromEnv.trim() !== "")
20
+ if (fromEnv !== undefined && fromEnv.trim() !== '')
37
21
  return fromEnv.trim();
38
- const fromNpm = npmConfigGet?.("registry");
39
- if (fromNpm !== undefined && fromNpm.trim() !== "" && fromNpm.trim() !== "undefined") {
40
- return fromNpm.trim();
41
- }
22
+ const fromNpm = npmConfigGet?.('registry')?.trim();
23
+ if (fromNpm !== undefined && fromNpm !== '' && fromNpm !== 'undefined')
24
+ return fromNpm;
42
25
  return DEFAULT_REGISTRY;
43
26
  }
44
- /**
45
- * Join a path onto the registry base.
46
- *
47
- * A scoped name's `/` is written `%2f` (SPEC §5 step 3). That is required by
48
- * the dist-tags route and accepted by the manifest route, so both are built the
49
- * same way — one rule instead of two, and no chance of only one of them being
50
- * right for `@scope/name`.
51
- */
27
+ /** Joins path parts onto the registry, writing a scoped name's `/` as `%2f` (SPEC §5 step 3). Both routes take it. */
52
28
  export function registryUrl(registry, ...parts) {
53
- const base = registry.replace(/\/+$/, "");
54
- return `${base}/${parts.map((p) => p.replace(/\//g, "%2f")).join("/")}`;
29
+ return `${registry.replace(/\/+$/, '')}/${parts.map((p) => p.replace(/\//g, '%2f')).join('/')}`;
55
30
  }
56
- /** Everything that went wrong talking to the registry, as one reportable error. */
31
+ /** Anything that went wrong talking to the registry, with the URL, as one reportable error. */
57
32
  export class RegistryError extends Error {
33
+ name = 'RegistryError';
58
34
  url;
59
35
  constructor(url, message) {
60
36
  super(message);
@@ -62,83 +38,64 @@ export class RegistryError extends Error {
62
38
  }
63
39
  }
64
40
  async function getJson(url, o) {
65
- const doFetch = o.fetch ?? globalThis.fetch;
41
+ const timeoutMs = o.timeoutMs ?? REGISTRY_TIMEOUT_MS;
66
42
  let res;
67
43
  try {
68
- res = await doFetch(url, {
69
- signal: AbortSignal.timeout(o.timeoutMs ?? REGISTRY_TIMEOUT_MS),
70
- headers: { accept: "application/json" },
71
- });
44
+ res = await (o.fetch ?? globalThis.fetch)(url, { signal: AbortSignal.timeout(timeoutMs), headers: { accept: 'application/json' } });
72
45
  }
73
46
  catch (err) {
74
- const why = err.name === "TimeoutError" || err.name === "AbortError"
75
- ? `no answer within ${(o.timeoutMs ?? REGISTRY_TIMEOUT_MS) / 1000} seconds`
76
- : (err.message ?? String(err));
77
- throw new RegistryError(url, `could not reach the registry: ${why}`);
47
+ const name = err.name;
48
+ const why = name === 'TimeoutError' || name === 'AbortError' ? `no answer within ${timeoutMs / 1000} seconds` : (err.message ?? String(err));
49
+ throw new RegistryError(url, `couldn't reach the registry: ${why}`);
78
50
  }
79
51
  if (res.status === 404)
80
- throw new RegistryError(url, "the registry has no such package or version");
52
+ throw new RegistryError(url, 'the registry has no such package or version');
81
53
  if (!res.ok)
82
54
  throw new RegistryError(url, `the registry answered HTTP ${res.status}`);
83
55
  try {
84
56
  return (await res.json());
85
57
  }
86
58
  catch {
87
- throw new RegistryError(url, "the registry's answer was not JSON");
59
+ throw new RegistryError(url, "the registry's answer isn't JSON");
88
60
  }
89
61
  }
90
62
  /** `{ latest: "0.81.0", next: "0.82.0-rc.1" }`. */
91
63
  export async function fetchDistTags(o) {
92
- const url = registryUrl(o.registry, "-", "package", o.packageName, "dist-tags");
93
- const body = await getJson(url, o);
64
+ const url = registryUrl(o.registry, '-', 'package', o.packageName, 'dist-tags');
94
65
  const tags = {};
95
- for (const [k, v] of Object.entries(body))
96
- if (typeof v === "string")
66
+ for (const [k, v] of Object.entries(await getJson(url, o)))
67
+ if (typeof v === 'string')
97
68
  tags[k] = v;
98
69
  if (Object.keys(tags).length === 0)
99
- throw new RegistryError(url, "the registry listed no dist-tags");
70
+ throw new RegistryError(url, 'the registry lists no dist-tags');
100
71
  return tags;
101
72
  }
102
- /** One version's manifest — read for `engines` (SPEC §5 step 3). */
103
- export async function fetchManifest(o) {
104
- const url = registryUrl(o.registry, o.packageName, o.version);
105
- return getJson(url, o);
73
+ /** One version's manifest, read for `engines`. */
74
+ export function fetchManifest(o) {
75
+ return getJson(registryUrl(o.registry, o.packageName, o.version), o);
106
76
  }
107
77
  /**
108
- * Turn `--to` (or its absence) into one concrete version, plus its `engines`.
109
- *
110
- * `--to` is a version or a dist-tag and the two are told apart by shape, not by
111
- * asking: anything that parses as a version is a version, everything else is a
112
- * tag. That ordering matters because a registry will happily serve a manifest
113
- * for a tag name as well, and resolving `--to next` as a literal version would
114
- * silently install whatever `next` pointed at while REPORTING the target as
115
- * "next".
78
+ * `--to` (or `latest` without it) as one version, with its `engines`. A version and a tag are told apart by shape:
79
+ * anything that looks like a version is one. Asking first would be wrong, since a registry may serve a manifest for a
80
+ * tag's name too, and `--to next` would then install `next` while reporting it as a version called "next".
116
81
  */
117
82
  export async function resolveTarget(o) {
118
- const { to } = o;
83
+ const to = o.to?.trim();
119
84
  let version;
120
85
  let tag;
121
- if (to === undefined) {
122
- const tags = await fetchDistTags(o);
123
- const latest = tags.latest;
124
- if (latest === undefined) {
125
- throw new RegistryError(registryUrl(o.registry, "-", "package", o.packageName, "dist-tags"), "the registry has no `latest` dist-tag for this package");
126
- }
127
- version = latest;
128
- tag = "latest";
129
- }
130
- else if (/^v?\d+\.\d+\.\d+/.test(to.trim())) {
131
- version = to.trim().replace(/^v/, "");
86
+ if (to !== undefined && /^v?\d+\.\d+\.\d+/.test(to)) {
87
+ version = to.replace(/^v/, '');
132
88
  tag = null;
133
89
  }
134
90
  else {
91
+ tag = to ?? 'latest';
135
92
  const tags = await fetchDistTags(o);
136
- const resolved = tags[to];
93
+ const resolved = tags[tag];
137
94
  if (resolved === undefined) {
138
- throw new RegistryError(registryUrl(o.registry, "-", "package", o.packageName, "dist-tags"), `no dist-tag \`${to}\` (the registry has: ${Object.keys(tags).sort().join(", ")})`);
95
+ const url = registryUrl(o.registry, '-', 'package', o.packageName, 'dist-tags');
96
+ throw new RegistryError(url, `no dist-tag \`${tag}\` (the registry has: ${Object.keys(tags).sort().join(', ')})`);
139
97
  }
140
98
  version = resolved;
141
- tag = to;
142
99
  }
143
100
  const manifest = await fetchManifest({ ...o, version });
144
101
  return { version, tag, engines: manifest.engines?.node ?? null };
@@ -1,67 +1,44 @@
1
- /**
2
- * The small semver `update` needs, and no more (CLI contract SPEC §5 step 4).
3
- *
4
- * Three questions are asked of versions in this contract: is the target newer
5
- * than what we have, is it a prerelease, and does the target's `engines.node`
6
- * accept the Node running the update. That is it — so this is ~120 lines of
7
- * Node built-ins rather than a dependency, which is what SPEC §5 asks for and
8
- * what keeps `update` runnable from a CLI that must not load the server.
9
- *
10
- * **What it deliberately does not do.** No `semver` package behaviours beyond
11
- * the above: no ranges with hyphens (`1.2 - 2.3`), no `x`-ranges (`1.x`), no
12
- * build metadata ordering. An `engines.node` we cannot parse is reported as
13
- * "cannot tell" rather than as "fails", because refusing an update on the
14
- * strength of a range this file does not understand would be the worse error of
15
- * the two — see {@link satisfiesEngines}.
16
- *
17
- * Generic: wave C4 lifts this into `reference/` with the rest of `update`.
18
- */
19
1
  export interface Version {
20
2
  major: number;
21
3
  minor: number;
22
4
  patch: number;
23
- /** The dot-separated identifiers after `-`, empty for a release. */
5
+ /** The dot-separated identifiers after `-`; empty for a release. */
24
6
  prerelease: (string | number)[];
25
7
  }
26
- /** `1.2.3-rc.1` → a {@link Version}, or undefined if it is not a version. */
8
+ /** `1.2.3-rc.1` as a `Version`, or undefined if it isn't one. */
27
9
  export declare function parseVersion(raw: string): Version | undefined;
28
- /** Is this a prerelease? SPEC §5: prereleases count only when `--to` names them. */
10
+ /** SPEC §5: prereleases count only when `--to` names them. */
29
11
  export declare function isPrerelease(raw: string): boolean;
30
12
  /**
31
- * -1, 0 or 1, by the semver rules — including the prerelease ones, which are
32
- * the only interesting part: `1.0.0-rc.1` is LOWER than `1.0.0`, numeric
33
- * identifiers compare numerically and sort below alphanumeric ones, and a
34
- * longer run of identifiers wins when every shared one is equal.
35
- *
36
- * Build metadata is ignored, as semver says it must be.
13
+ * -1, 0 or 1, by semver's rules: `1.0.0-rc.1` is lower than `1.0.0`, numeric identifiers compare as numbers and sort
14
+ * below alphanumeric ones, and a longer run of identifiers wins when the shared ones are equal. Build metadata is
15
+ * ignored. Something that isn't a version compares as equal rather than throwing.
37
16
  */
38
17
  export declare function compareVersions(a: string, b: string): number;
39
- /** Is `a` strictly newer than `b`? */
18
+ /** Whether `a` is strictly newer than `b`. */
40
19
  export declare const isNewer: (a: string, b: string) => boolean;
41
- /** The highest of a list, ignoring anything unparseable. Undefined if none parse. */
20
+ /** The highest of a list, ignoring anything that isn't a version. */
42
21
  export declare function maxVersion(versions: readonly string[]): string | undefined;
22
+ /** `0.82.0` → `0.83.0` (`minor`), or `0.82.1` (`patch`). A prerelease's suffix is dropped. */
23
+ export declare function bumpVersion(raw: string, part: 'major' | 'minor' | 'patch'): string;
43
24
  /**
44
- * Does `version` satisfy `range`? Undefined means "this file cannot tell".
25
+ * Whether `version` satisfies `range`; undefined when this file can't tell.
45
26
  *
46
- * Supports the forms an `engines.node` actually uses: `>=22`, `>=22.0.0`,
47
- * `^22.1.0`, `~22.1`, `22`, `22.x`, `>=20 <23`, and `||` between any of those.
48
- * `*` and an empty range accept everything.
27
+ * Reads what `engines.node` uses in practice: `>=22`, `>=22.0.0`, `^22.1.0`, `~22.1`, `22`, `22.x`, `>=20 <23`, and
28
+ * `||` between them. `*` and an empty range accept everything. Alternatives it can't read are ignored; if it can read
29
+ * none of them, the answer is undefined.
49
30
  */
50
31
  export declare function satisfies(version: string, range: string): boolean | undefined;
51
32
  export interface EnginesVerdict {
52
- /** True pass, false genuine fail, undefined when the range could not be read. */
33
+ /** true passes, false fails, undefined when the range couldn't be read. */
53
34
  ok: boolean | undefined;
54
35
  /** The range as published, for the message. */
55
36
  range: string | undefined;
56
37
  }
57
38
  /**
58
- * Will the target version run on this Node? (SPEC §5 step 4.)
59
- *
60
- * The three-way answer is the point. A target with no `engines.node` at all, or
61
- * one whose range this file cannot parse, must NOT block an update: the cost of
62
- * a false refusal is a tool that cannot update itself and says something the
63
- * user cannot act on, while the cost of letting an incompatible Node through is
64
- * the failure `engines` would have produced anyway, with a rollback behind it.
39
+ * Will the target run on this Node? (SPEC §5 step 4.) No `engines.node`, or one this file can't read, doesn't block
40
+ * an update: callers treat `ok: undefined` as a pass. A false refusal leaves a tool that can't update itself, saying
41
+ * something nobody can act on; letting an unsuitable Node through fails the install, and the rollback runs.
65
42
  */
66
43
  export declare function satisfiesEngines(nodeVersion: string, engines: {
67
44
  node?: string;