@timurproko/a1-install 0.2.1-dev.602 → 0.2.1-dev.604

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/README.md CHANGED
@@ -2,18 +2,26 @@
2
2
 
3
3
  Dependency-free installer for [`@timurproko/a1`](https://www.npmjs.com/package/@timurproko/a1).
4
4
 
5
+ Release:
6
+
5
7
  ```sh
6
8
  npx -y @timurproko/a1-install
7
9
  ```
8
10
 
9
- Development channel:
11
+ Develop:
10
12
 
11
13
  ```sh
12
14
  npx -y @timurproko/a1-install --develop
13
15
  ```
14
16
 
15
- Exact development version:
17
+ Preview number:
18
+
19
+ ```sh
20
+ npx -y @timurproko/a1-install --develop 107
21
+ ```
22
+
23
+ Exact preview:
16
24
 
17
25
  ```sh
18
- npx -y @timurproko/a1-install --version 0.1.8-dev.107
26
+ npx -y @timurproko/a1-install --develop 0.1.8-dev.107
19
27
  ```
package/bin/a1-install.js CHANGED
@@ -21,6 +21,7 @@ const PHASES = new Set([
21
21
  ]);
22
22
  const STABLE_VERSION_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/u;
23
23
  const DEVELOPMENT_VERSION_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)-dev\.[1-9]\d*$/u;
24
+ const PREVIEW_NUMBER_PATTERN = /^[1-9]\d*$/u;
24
25
  const VERSION_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-dev\.[1-9]\d*)?$/u;
25
26
 
26
27
  class InstallationFailure extends Error {
@@ -59,23 +60,15 @@ export function parseArguments(argv) {
59
60
  continue;
60
61
  }
61
62
  if (value === "--develop") {
62
- if (target.kind === "version") throw new InstallationFailure("--develop cannot be combined with --version", "", 2);
63
63
  if (target.kind !== "stable") throw new InstallationFailure("--develop was supplied more than once", "", 2);
64
- target = { kind: "develop" };
65
- continue;
66
- }
67
- if (value === "--version") {
68
- const version = argv[index + 1];
69
- if (version === undefined || version.startsWith("-")) {
70
- throw new InstallationFailure("--version requires an exact development version", "", 2);
71
- }
72
- if (!DEVELOPMENT_VERSION_PATTERN.test(version)) {
73
- throw new InstallationFailure("--version requires an exact development version", "", 2);
74
- }
75
- if (target.kind === "develop") throw new InstallationFailure("--develop cannot be combined with --version", "", 2);
76
- if (target.kind !== "stable") throw new InstallationFailure("--version was supplied more than once", "", 2);
77
- target = { kind: "version", version };
78
- index += 1;
64
+ const requested = argv[index + 1];
65
+ if (requested !== undefined && !requested.startsWith("-")) {
66
+ if (!PREVIEW_NUMBER_PATTERN.test(requested) && !DEVELOPMENT_VERSION_PATTERN.test(requested)) {
67
+ throw new InstallationFailure("unexpected argument", requested, 2);
68
+ }
69
+ target = { kind: "preview", requested };
70
+ index += 1;
71
+ } else target = { kind: "develop" };
79
72
  continue;
80
73
  }
81
74
  if (value?.startsWith("-")) throw new InstallationFailure("unsupported option", "", 2);
@@ -91,7 +84,7 @@ export function installerHelp() {
91
84
  return [
92
85
  "a1-install",
93
86
  "a1-install --develop",
94
- "a1-install --version <x.y.z-dev.n>",
87
+ "a1-install --develop <preview-or-version>",
95
88
  "a1-install --verbose",
96
89
  "",
97
90
  ].join("\n");
@@ -152,17 +145,15 @@ class ProgressDisplay {
152
145
  this.interval = options.interval ?? 200;
153
146
  this.current = 0;
154
147
  this.shown = -1;
155
- this.label = "Preparing";
156
148
  this.timer = null;
157
149
  this.visible = false;
158
- this.maxWidth = PROGRESS_WIDTH + 6 + 1 + 64;
150
+ this.maxWidth = PROGRESS_WIDTH + 6;
159
151
  }
160
152
 
161
- set(percent, label, creepTo = percent) {
153
+ set(percent, _label, creepTo = percent) {
162
154
  if (!this.enabled) return;
163
155
  this.stop();
164
156
  this.current = Math.max(this.current, percent);
165
- if (PHASES.has(label)) this.label = label;
166
157
  this.shown = -1;
167
158
  this.draw();
168
159
  if (creepTo <= this.current) return;
@@ -179,7 +170,7 @@ class ProgressDisplay {
179
170
  this.shown = rounded;
180
171
  if (!this.visible) this.output.write("\u001b[?25l");
181
172
  this.visible = true;
182
- this.output.write(`\r${renderProgressBar(rounded)} ${this.label}`);
173
+ this.output.write(`\r${renderProgressBar(rounded)}\u001b[K`);
183
174
  }
184
175
 
185
176
  finish() {
@@ -278,13 +269,19 @@ async function runChild(command, args, options) {
278
269
 
279
270
  function targetSpec(target) {
280
271
  if (target.kind === "develop") return `${APPLICATION_PACKAGE}@next`;
281
- if (target.kind === "version") return `${APPLICATION_PACKAGE}@${target.version}`;
282
272
  return `${APPLICATION_PACKAGE}@latest`;
283
273
  }
284
274
 
285
- function updateArguments(target) {
275
+ function resolutionArguments(target) {
276
+ if (target.kind === "preview") {
277
+ return ["view", APPLICATION_PACKAGE, "versions", "--json", "--loglevel=verbose", "--no-fund", "--no-audit"];
278
+ }
279
+ return ["view", targetSpec(target), "version", "--json", "--loglevel=verbose", "--no-fund", "--no-audit"];
280
+ }
281
+
282
+ function updateArguments(target, targetVersion) {
286
283
  if (target.kind === "develop") return ["update", "--develop"];
287
- if (target.kind === "version") return ["update", "--develop", target.version];
284
+ if (target.kind === "preview") return ["update", "--develop", targetVersion];
288
285
  return ["update"];
289
286
  }
290
287
 
@@ -302,10 +299,28 @@ function parseResolvedVersion(stdout, target) {
302
299
  if (!VERSION_PATTERN.test(value)) throw new InstallationFailure("could not resolve the selected release", text);
303
300
  if (target.kind === "stable" && !STABLE_VERSION_PATTERN.test(value)) throw new InstallationFailure("could not resolve the selected release", text);
304
301
  if (target.kind === "develop" && !DEVELOPMENT_VERSION_PATTERN.test(value)) throw new InstallationFailure("could not resolve the selected release", text);
305
- if (target.kind === "version" && value !== target.version) throw new InstallationFailure("the selected release was not found", text);
302
+ if (target.kind === "preview" && value !== target.requested) throw new InstallationFailure("the selected release was not found", text);
306
303
  return value;
307
304
  }
308
305
 
306
+ export function resolvePublishedPreview(stdout, requested) {
307
+ let published;
308
+ try { published = JSON.parse(String(stdout).trim() || "[]"); }
309
+ catch { throw new InstallationFailure("could not resolve the selected release", String(stdout)); }
310
+ const versions = (Array.isArray(published) ? published : [published])
311
+ .filter(value => typeof value === "string" && DEVELOPMENT_VERSION_PATTERN.test(value));
312
+ if (DEVELOPMENT_VERSION_PATTERN.test(requested)) {
313
+ if (versions.includes(requested)) return requested;
314
+ throw new InstallationFailure("the selected release was not found", `published no preview ${requested}`);
315
+ }
316
+ const matches = versions.filter(version => version.endsWith(`-dev.${requested}`));
317
+ if (matches.length === 1) return matches[0];
318
+ const detail = matches.length === 0
319
+ ? `published no preview for ${requested}`
320
+ : `found more than one preview for ${requested}: ${matches.join(", ")}`;
321
+ throw new InstallationFailure("the selected release was not found", detail);
322
+ }
323
+
309
324
  function packageRootFor(globalRoot) {
310
325
  return resolve(globalRoot, ...APPLICATION_PACKAGE.split("/"));
311
326
  }
@@ -360,11 +375,13 @@ async function verifyLaunchers(globalRoot, platform) {
360
375
  const paths = launcherPaths(globalRoot, platform);
361
376
  const entry = resolve(packageRootFor(globalRoot), "bin", "cli.js");
362
377
  const expectedSuffix = `${APPLICATION_PACKAGE}/bin/cli.js`;
378
+ let canonicalEntry = null;
363
379
  for (const path of paths) {
364
380
  try {
365
381
  const metadata = await lstat(path);
366
382
  if (metadata.isSymbolicLink()) {
367
- if (normalizePath(await realpath(path), platform) !== normalizePath(entry, platform)) throw new Error("launcher target differs");
383
+ if (canonicalEntry === null) canonicalEntry = normalizePath(await realpath(entry), platform);
384
+ if (normalizePath(await realpath(path), platform) !== canonicalEntry) throw new Error("launcher target differs");
368
385
  } else if (metadata.isFile()) {
369
386
  const content = await readFile(path, "utf8");
370
387
  if (content.length > 32_768 || !content.replaceAll("\\", "/").includes(expectedSuffix)) throw new Error("launcher content differs");
@@ -505,16 +522,16 @@ export async function runInstaller(argv, options = {}) {
505
522
  try {
506
523
  progress.set(3, "Preparing", 10);
507
524
  let phase = "Resolving version";
508
- const resolveResult = await runner.npm([
509
- "view", targetSpec(parsed.target), "version", "--json", "--loglevel=verbose", "--no-fund", "--no-audit",
510
- ], {
525
+ const resolveResult = await runner.npm(resolutionArguments(parsed.target), {
511
526
  onChild: setActiveChild,
512
527
  onStderrLine: line => { phase = classifyProgressLine(line, phase); progress.set(10, phase, 18); },
513
528
  });
514
529
  setActiveChild(null);
515
530
  if (cancelled) throw new InstallationCancelled();
516
531
  if (resolveResult.code !== 0) throw new InstallationFailure(conciseFailure("resolve", resolveResult.stderr), resolveResult.stderr);
517
- const targetVersion = parseResolvedVersion(resolveResult.stdout, parsed.target);
532
+ const targetVersion = parsed.target.kind === "preview"
533
+ ? resolvePublishedPreview(resolveResult.stdout, parsed.target.requested)
534
+ : parseResolvedVersion(resolveResult.stdout, parsed.target);
518
535
  progress.set(18, "Resolving packages", 24);
519
536
 
520
537
  const rootResult = await runner.npm(["root", "--global", "--loglevel=error", "--no-fund", "--no-audit"], { onChild: setActiveChild });
@@ -541,7 +558,7 @@ export async function runInstaller(argv, options = {}) {
541
558
  throw new InstallationFailure("existing installation ownership could not be verified", error instanceof Error ? error.message : String(error));
542
559
  }
543
560
  progress.set(24, "Installing", 90);
544
- const updateResult = await runner.node(cli, updateArguments(parsed.target), { onChild: setActiveChild });
561
+ const updateResult = await runner.node(cli, updateArguments(parsed.target, targetVersion), { onChild: setActiveChild });
545
562
  setActiveChild(null);
546
563
  if (cancelled) throw new InstallationCancelled();
547
564
  if (updateResult.code !== 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timurproko/a1-install",
3
- "version": "0.2.1-dev.602",
3
+ "version": "0.2.1-dev.604",
4
4
  "description": "Dependency-free installer for a1",
5
5
  "type": "module",
6
6
  "bin": {