@vincentt-xr/cli 0.15.1 → 0.15.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.
- package/dist/cli/index.js +5 -4
- package/dist/dx/clusters.js +10 -1
- package/dist/lib/exitCodes.d.ts +24 -0
- package/dist/lib/exitCodes.js +28 -0
- package/dist/lib/initFrom.js +12 -2
- package/dist/lib/lifecycle.d.ts +5 -1
- package/dist/lib/projects.js +9 -2
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { ensureLoggedIn } from "../login/ensure.js";
|
|
|
21
21
|
import { clearMachineToken, loadMachineConfig, locateProjectBinding, resolveConfig, writeDxEnablement, MACHINE_CONFIG_PATH, } from "../shared/config.js";
|
|
22
22
|
import { fileLocationStore } from "../shared/locationStore.js";
|
|
23
23
|
import { getMe, listProjects, ProjectUnreachableError } from "../lib/backend.js";
|
|
24
|
+
import { EXIT } from "../lib/exitCodes.js";
|
|
24
25
|
import { listProjectsCommand } from "../lib/listProjects.js";
|
|
25
26
|
import { initCommand } from "../lib/initCommand.js";
|
|
26
27
|
import { linkCommand, printUnreachable, unlinkCommand } from "../lib/projects.js";
|
|
@@ -813,7 +814,7 @@ async function feedbackWait(cwd, timeoutMs, verbose) {
|
|
|
813
814
|
break;
|
|
814
815
|
for (const l of feedbackCopy.windowElapsed(timeoutMs))
|
|
815
816
|
console.error(l);
|
|
816
|
-
return
|
|
817
|
+
return EXIT.WINDOW_ELAPSED;
|
|
817
818
|
}
|
|
818
819
|
if (result.kind === "closed") {
|
|
819
820
|
if (handed > 0)
|
|
@@ -825,7 +826,7 @@ async function feedbackWait(cwd, timeoutMs, verbose) {
|
|
|
825
826
|
console.error(l);
|
|
826
827
|
}
|
|
827
828
|
}
|
|
828
|
-
return
|
|
829
|
+
return EXIT.CHANNEL_ENDED;
|
|
829
830
|
}
|
|
830
831
|
await handOver(cwd, result.annotation);
|
|
831
832
|
after = result.annotation.seq;
|
|
@@ -882,7 +883,7 @@ async function feedbackWatch(cwd, timeoutMs, verbose) {
|
|
|
882
883
|
console.error(l);
|
|
883
884
|
}
|
|
884
885
|
}
|
|
885
|
-
return
|
|
886
|
+
return EXIT.CHANNEL_ENDED;
|
|
886
887
|
}
|
|
887
888
|
const a = result.annotation;
|
|
888
889
|
await handOver(cwd, a);
|
|
@@ -1110,7 +1111,7 @@ async function assets() {
|
|
|
1110
1111
|
for (const l of unreachableLines("auth", 'vincentt assets search "<what you want>"')) {
|
|
1111
1112
|
console.error(l);
|
|
1112
1113
|
}
|
|
1113
|
-
process.exitCode =
|
|
1114
|
+
process.exitCode = EXIT.NOT_AUTHENTICATED;
|
|
1114
1115
|
return;
|
|
1115
1116
|
}
|
|
1116
1117
|
const deps = {
|
package/dist/dx/clusters.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* Detection is deliberately loose. A false positive costs a line in a report a
|
|
16
16
|
* human is already reading; a miss costs a DX gap nobody ever hears about.
|
|
17
17
|
*/
|
|
18
|
+
import { EXIT } from "../lib/exitCodes.js";
|
|
18
19
|
import { verbOf } from "./skeleton.js";
|
|
19
20
|
/**
|
|
20
21
|
* Non-zero exits a verb DEFINES as ordinary outcomes, not failures.
|
|
@@ -26,11 +27,19 @@ import { verbOf } from "./skeleton.js";
|
|
|
26
27
|
* fight-with-the-tool that never happened, and the nudge narrates the intended
|
|
27
28
|
* loop as friction — on stderr, which in this loop is a caller's own input.
|
|
28
29
|
*
|
|
30
|
+
* `create` and `init` exit 3 when the scaffold landed but no account was on the
|
|
31
|
+
* machine to reserve an address. The creator holds a working project, so
|
|
32
|
+
* counting it as a fault would make the nudge narrate a delivered project as a
|
|
33
|
+
* fight with the tool. `LOOPING_VERBS` deliberately does NOT gain these two:
|
|
34
|
+
* re-running create without signing in first IS real repetition.
|
|
35
|
+
*
|
|
29
36
|
* A verb's neutral exits are ITS OWN. Nothing here generalizes 64/65 across the
|
|
30
37
|
* CLI; another verb adding a non-zero-but-fine exit adds a row.
|
|
31
38
|
*/
|
|
32
39
|
const NEUTRAL_EXITS = {
|
|
33
|
-
feedback: new Set([
|
|
40
|
+
feedback: new Set([EXIT.WINDOW_ELAPSED, EXIT.CHANNEL_ENDED]),
|
|
41
|
+
create: new Set([EXIT.DELIVERED_NOT_REGISTERED]),
|
|
42
|
+
init: new Set([EXIT.DELIVERED_NOT_REGISTERED]),
|
|
34
43
|
};
|
|
35
44
|
/**
|
|
36
45
|
* Verbs whose contract is "run it again". Repeating them is not a caller failing
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every exit code the CLI returns. B-F12-1: APPEND-ONLY — a code may be added,
|
|
3
|
+
* an existing code's meaning never changes. Removing or repurposing one breaks
|
|
4
|
+
* grounding that already shipped into a creator's repository and is never read
|
|
5
|
+
* back, so the platform cannot warn about it or repair it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const EXIT: {
|
|
8
|
+
/** The command did what it was asked. */
|
|
9
|
+
readonly OK: 0;
|
|
10
|
+
/** The command failed and nothing lasting was produced. */
|
|
11
|
+
readonly FAILED: 1;
|
|
12
|
+
/**
|
|
13
|
+
* The project source was written by this invocation, but no address was
|
|
14
|
+
* reserved: no account on this machine, and no browser to get one. The
|
|
15
|
+
* creator holds a working local project; only registration is deferred.
|
|
16
|
+
*/
|
|
17
|
+
readonly DELIVERED_NOT_REGISTERED: 3;
|
|
18
|
+
/** A platform call needed an account and the command did not answer for it. */
|
|
19
|
+
readonly NOT_AUTHENTICATED: 4;
|
|
20
|
+
/** A bounded wait elapsed with nothing handed over. */
|
|
21
|
+
readonly WINDOW_ELAPSED: 64;
|
|
22
|
+
/** The channel ended before anything was handed over. */
|
|
23
|
+
readonly CHANNEL_ENDED: 65;
|
|
24
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every exit code the CLI returns. B-F12-1: APPEND-ONLY — a code may be added,
|
|
3
|
+
* an existing code's meaning never changes. Removing or repurposing one breaks
|
|
4
|
+
* grounding that already shipped into a creator's repository and is never read
|
|
5
|
+
* back, so the platform cannot warn about it or repair it.
|
|
6
|
+
*/
|
|
7
|
+
export const EXIT = {
|
|
8
|
+
/** The command did what it was asked. */
|
|
9
|
+
OK: 0,
|
|
10
|
+
/** The command failed and nothing lasting was produced. */
|
|
11
|
+
FAILED: 1,
|
|
12
|
+
/**
|
|
13
|
+
* The project source was written by this invocation, but no address was
|
|
14
|
+
* reserved: no account on this machine, and no browser to get one. The
|
|
15
|
+
* creator holds a working local project; only registration is deferred.
|
|
16
|
+
*/
|
|
17
|
+
DELIVERED_NOT_REGISTERED: 3,
|
|
18
|
+
/** A platform call needed an account and the command did not answer for it. */
|
|
19
|
+
NOT_AUTHENTICATED: 4,
|
|
20
|
+
/** A bounded wait elapsed with nothing handed over. */
|
|
21
|
+
WINDOW_ELAPSED: 64,
|
|
22
|
+
/** The channel ended before anything was handed over. */
|
|
23
|
+
CHANNEL_ENDED: 65,
|
|
24
|
+
};
|
|
25
|
+
// 2 is deliberately unallocated. Shells conventionally use 2 for misuse of a
|
|
26
|
+
// builtin, and a CLI that returns it invites a caller to misread a shell error
|
|
27
|
+
// as ours. The gap is recorded here so a later change does not fill it by
|
|
28
|
+
// looking for the lowest free number.
|
package/dist/lib/initFrom.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// be wrong.
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import { SlugTakenError } from "./backend.js";
|
|
13
|
+
import { EXIT } from "./exitCodes.js";
|
|
13
14
|
import { slugify } from "./slug.js";
|
|
14
15
|
import { formatSourceRef } from "./sourceRef.js";
|
|
15
16
|
/** How many times the address prompt re-asks before falling back to the printed block. */
|
|
@@ -70,7 +71,9 @@ export async function registerAfterScaffold(deps, opts = {}) {
|
|
|
70
71
|
if (!token) {
|
|
71
72
|
if (!deps.ask) {
|
|
72
73
|
deps.print("");
|
|
73
|
-
deps.print(
|
|
74
|
+
deps.print(scaffolded
|
|
75
|
+
? "→ Not signed in, so no address is reserved yet."
|
|
76
|
+
: "✗ Not signed in, and signing in needs a browser.");
|
|
74
77
|
deps.print("");
|
|
75
78
|
if (scaffolded)
|
|
76
79
|
reassure(deps.print, deps.dirLabel);
|
|
@@ -81,9 +84,16 @@ export async function registerAfterScaffold(deps, opts = {}) {
|
|
|
81
84
|
deps.print("");
|
|
82
85
|
deps.print(" Then finish:");
|
|
83
86
|
resume(deps.print, deps.dirLabel, resumeCommand, needsCd);
|
|
87
|
+
if (scaffolded) {
|
|
88
|
+
deps.print("");
|
|
89
|
+
// B-F2-9(a): the open route must be named in something the creator's
|
|
90
|
+
// agent reads. On a non-TTY this output IS that artifact — the TTY
|
|
91
|
+
// branch's login prompt, which carries the same line, is unreachable here.
|
|
92
|
+
deps.print(" Or don't — the local dev loop needs no account.");
|
|
93
|
+
}
|
|
84
94
|
deps.print("");
|
|
85
95
|
deps.print(closing);
|
|
86
|
-
return
|
|
96
|
+
return scaffolded ? EXIT.DELIVERED_NOT_REGISTERED : EXIT.FAILED;
|
|
87
97
|
}
|
|
88
98
|
deps.print("");
|
|
89
99
|
deps.print("→ Now registering the project so it gets an address.");
|
package/dist/lib/lifecycle.d.ts
CHANGED
|
@@ -36,7 +36,11 @@ export interface CreateOptions {
|
|
|
36
36
|
export interface CreateResult {
|
|
37
37
|
/** The full transcript, exactly as the CLI prints it. */
|
|
38
38
|
message: string;
|
|
39
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Non-zero when the address was not reserved. Code 1 means nothing was created
|
|
41
|
+
* (already linked, address taken, no org); code 3 means the project source was
|
|
42
|
+
* written but registration was deferred for want of an account.
|
|
43
|
+
*/
|
|
40
44
|
exitCode: number;
|
|
41
45
|
}
|
|
42
46
|
/**
|
package/dist/lib/projects.js
CHANGED
|
@@ -8,6 +8,7 @@ import { promises as fs } from "node:fs";
|
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { BackendError, SlugTakenError, createProject, getProject, } from "./backend.js";
|
|
10
10
|
import { classifyTarget } from "./classifyTarget.js";
|
|
11
|
+
import { EXIT } from "./exitCodes.js";
|
|
11
12
|
import { registerAfterScaffold } from "./initFrom.js";
|
|
12
13
|
import { slugify } from "./slug.js";
|
|
13
14
|
import { detectPackageManager, installDependencies, scaffoldFromTemplate, } from "../scaffold/index.js";
|
|
@@ -169,7 +170,10 @@ export async function createCommand(deps, opts = {}) {
|
|
|
169
170
|
name: opts.name ?? path.basename(target),
|
|
170
171
|
slug: opts.slug ?? slugify(opts.name ?? path.basename(target)),
|
|
171
172
|
});
|
|
172
|
-
|
|
173
|
+
// The gate is DELIVERY, not zero. A run that wrote the source and deferred
|
|
174
|
+
// only the address still delivered a project, so it still prints how to run
|
|
175
|
+
// it. The endings that stay exit 1 delivered nothing and correctly skip this.
|
|
176
|
+
if (code !== 0 && code !== EXIT.DELIVERED_NOT_REGISTERED)
|
|
173
177
|
return code;
|
|
174
178
|
if (scaffolded) {
|
|
175
179
|
// This reader has never run the dev server, so the block that fits is the one
|
|
@@ -187,7 +191,10 @@ export async function createCommand(deps, opts = {}) {
|
|
|
187
191
|
for (const line of alignedSteps(steps))
|
|
188
192
|
deps.print(line);
|
|
189
193
|
}
|
|
190
|
-
|
|
194
|
+
// Printing the steps must not launder the ending: a delivered-not-registered
|
|
195
|
+
// run still reports 3, so a caller never reads success for an unregistered
|
|
196
|
+
// project.
|
|
197
|
+
return code;
|
|
191
198
|
}
|
|
192
199
|
/** Two columns, aligned on the widest command, so the block reads as a table. */
|
|
193
200
|
function alignedSteps(steps) {
|
package/package.json
CHANGED