@rness/cli 0.4.0 → 0.5.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.
- package/README.md +204 -7
- package/dist/bin/rness.js +40 -2
- package/dist/bin/rness.js.map +1 -1
- package/dist/chunk-C6HBGV5V.js +4040 -0
- package/dist/chunk-C6HBGV5V.js.map +1 -0
- package/dist/index.js +23 -1
- package/package.json +4 -4
- package/scaffold/.github/dependabot.yml +12 -0
- package/scaffold/.github/workflows/validate.yml +5 -1
- package/scaffold/README.md +1 -1
- package/scaffold/WORKSPACE.md +7 -5
- package/dist/chunk-IW5IHSPC.js +0 -1740
- package/dist/chunk-IW5IHSPC.js.map +0 -1
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@ Not an agent — no LLM loop.
|
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
|
-
npm create rness
|
|
9
|
+
npm create rness # prompts for the organization, then the repositories for your workspace
|
|
10
|
+
npm create rness acme # the organization github.com/acme, no first prompt
|
|
10
11
|
npm i -g @rness/cli # the command is `rness`
|
|
11
12
|
npx @rness/cli --help
|
|
12
13
|
|
|
@@ -15,9 +16,12 @@ Inside a workspace, every `rness` delegates to the copy pinned in
|
|
|
15
16
|
|
|
16
17
|
## Commands
|
|
17
18
|
|
|
18
|
-
rness create <org>
|
|
19
|
-
rness add <repo> [--scopes apps/web,packages/ui] [--ssh] -y
|
|
20
|
-
rness sync [--scope <name>] [--check] [--pull] -y
|
|
19
|
+
rness create [<org>] [--repos a,b] [--pm npm|pnpm|yarn|bun] [--ssh|--https] [--skip-install] -y
|
|
20
|
+
rness add <repo> [--scopes apps/web,packages/ui] [--ssh|--https] -y
|
|
21
|
+
rness sync [--all] [--scope <name>] [--check] [--pull] -y
|
|
22
|
+
rness upgrade [<version>] -y
|
|
23
|
+
rness login [--setup-git|--no-setup-git]
|
|
24
|
+
rness logout
|
|
21
25
|
rness context [--scope <name>] [--json]
|
|
22
26
|
rness validate
|
|
23
27
|
|
|
@@ -25,9 +29,185 @@ Inside a workspace, every `rness` delegates to the copy pinned in
|
|
|
25
29
|
confirmation in a terminal; pass `-y`/`--yes` in scripts. `sync --check`
|
|
26
30
|
writes nothing and exits 1 when a block is out of date — use it in CI.
|
|
27
31
|
|
|
32
|
+
### Log in
|
|
33
|
+
|
|
34
|
+
rness login # shows a code and https://github.com/login/device
|
|
35
|
+
rness logout
|
|
36
|
+
|
|
37
|
+
`rness login` connects rness to your GitHub account (OAuth device flow: you
|
|
38
|
+
approve a code in a browser, on any machine). Logged in, `create` lists the
|
|
39
|
+
private repositories you can access, offers your organizations to choose
|
|
40
|
+
from, and says as whom it looks at one (`member acme (as you)`). The
|
|
41
|
+
`create` wizard offers the login itself when it would otherwise list
|
|
42
|
+
anonymously.
|
|
43
|
+
|
|
44
|
+
- The login is one file, `~/.config/rness/auth.json` (`$XDG_CONFIG_HOME`,
|
|
45
|
+
`%APPDATA%` on Windows), readable by you only. The access token lives 8
|
|
46
|
+
hours and is renewed on its own. `GITHUB_TOKEN`, then `GH_TOKEN`, win over
|
|
47
|
+
it — CI needs no login.
|
|
48
|
+
- rness asks for `repo` and `read:org`: GitHub has no read-only scope for
|
|
49
|
+
private repositories. It only lists and clones.
|
|
50
|
+
- A new workspace has to reach GitHub before teammates can join it. Logged
|
|
51
|
+
in, the `create` wizard offers to do it: it creates the private repository
|
|
52
|
+
`<org>/.rness` and pushes the context with `git`. Declined, refused by
|
|
53
|
+
GitHub, anonymous or with `--yes`, it prints the two manual steps instead
|
|
54
|
+
— create the empty repository on github.com, then `git remote add origin …
|
|
55
|
+
&& git push`. No other tool is ever needed.
|
|
56
|
+
- An organization that restricts OAuth apps hides its private repositories
|
|
57
|
+
until an owner approves "Rness"; `create` says so, with the link.
|
|
58
|
+
- Over HTTPS, rness's own clones and pulls carry the login — through the
|
|
59
|
+
environment of that one git command, never in a URL or `.git/config`. For
|
|
60
|
+
your own `git pull` and `git push`, `login` offers to make rness git's
|
|
61
|
+
credential helper for github.com (`--setup-git`, `--no-setup-git`);
|
|
62
|
+
`logout` undoes it. It needs a global install (`npm i -g @rness/cli`): a
|
|
63
|
+
copy run through `npx` lives in a cache. Over SSH none of this is needed.
|
|
64
|
+
The helper names `node` by its absolute path: after a Node upgrade through
|
|
65
|
+
a version manager (mise, nvm), run `rness login --setup-git` again.
|
|
66
|
+
- `rness logout` forgets the login; revoke the authorization itself in
|
|
67
|
+
GitHub's settings (the command prints the link).
|
|
68
|
+
|
|
69
|
+
### SSH or HTTPS
|
|
70
|
+
|
|
71
|
+
`create` and `add` test your SSH access to github.com once
|
|
72
|
+
(`ssh -T git@github.com`) and write `git@github.com:` URLs when GitHub accepts
|
|
73
|
+
your key, `https://github.com/` ones otherwise; `--ssh` and `--https` decide
|
|
74
|
+
without the test. In a terminal `ssh` may ask for your key's passphrase;
|
|
75
|
+
without one (`--yes`, CI) it never prompts, so a key that needs a passphrase
|
|
76
|
+
counts as no access unless an agent holds it.
|
|
77
|
+
|
|
78
|
+
`rness.json` is authoritative: a URL written there is cloned as written, never
|
|
79
|
+
converted. In a workspace whose catalogue clones over SSH, `create` (joining)
|
|
80
|
+
and `sync` stop before the first clone when the SSH test fails and say how to
|
|
81
|
+
set up a key; `add` offers "Clone <name> over HTTPS instead?" (or `--https`),
|
|
82
|
+
which writes an HTTPS URL for that repository only.
|
|
83
|
+
|
|
84
|
+
Without an agent, a protected key is asked for again by every `git clone`.
|
|
85
|
+
Load it once per session: `ssh-add --apple-use-keychain ~/.ssh/id_ed25519` on
|
|
86
|
+
macOS, `ssh-add ~/.ssh/id_ed25519` elsewhere.
|
|
87
|
+
|
|
88
|
+
### Colour
|
|
89
|
+
|
|
90
|
+
In a terminal `create`, `login`, `add`, `sync` and `upgrade` run as one
|
|
91
|
+
session: an intro, a line per finished step, spinners, a "Next" box, an
|
|
92
|
+
outro — in the same gutter as the questions. A spinner never animates while
|
|
93
|
+
git might ask for a passphrase: rness first tests SSH unattended, and clones
|
|
94
|
+
animate only when that passed. The help and the banner are coloured. Through a pipe, in CI, or with `NO_COLOR=1`, the output is plain text —
|
|
95
|
+
the same bytes as before 0.5.0; `FORCE_COLOR=1` paints it anyway. No
|
|
96
|
+
dependency does this: `util.styleText`, and a banner kept as a constant.
|
|
97
|
+
|
|
98
|
+
### Upgrade
|
|
99
|
+
|
|
100
|
+
rness upgrade # the latest release; `rness upgrade 0.5.0` for another
|
|
101
|
+
npx @rness/cli@latest upgrade # from a workspace pinned below 0.5.0
|
|
102
|
+
|
|
103
|
+
The version is written in one place, `.rness/package.json`. `upgrade` pins it
|
|
104
|
+
there (exact, the rest of the file untouched), installs with the workspace's
|
|
105
|
+
package manager, then syncs through the new copy; a failed install restores
|
|
106
|
+
the file. Commit `.rness`. Teammates pull, and the next `rness` command in that
|
|
107
|
+
workspace installs the new pin itself — frozen, so the working tree stays
|
|
108
|
+
clean — and carries on: nothing to remember, nothing to run.
|
|
109
|
+
`RNESS_NO_INSTALL=1` turns that off and restores the warning, for CI, a
|
|
110
|
+
container image, or a machine that cannot install. A workspace still on 0.5.0
|
|
111
|
+
has no such catch-up: moving it to 0.5.1 is the last manual install.
|
|
112
|
+
|
|
113
|
+
Usually nobody runs `upgrade` at all. A workspace ships
|
|
114
|
+
`.github/dependabot.yml`, so each release opens a pull request on the
|
|
115
|
+
organization's `.rness`: the pin and the lockfile in the diff, `validate`
|
|
116
|
+
running on the new version, review, merge. `upgrade` writes that file into
|
|
117
|
+
workspaces created before 0.5.1.
|
|
118
|
+
|
|
119
|
+
`upgrade` is never delegated to the pinned copy, which is what it replaces
|
|
120
|
+
— so a workspace pinned below 0.5.0, whose copy has no such command, starts
|
|
121
|
+
with the `npx` form.
|
|
122
|
+
|
|
123
|
+
An upgrade touches `.rness` only: a generated block is current when its hash
|
|
124
|
+
is, whatever wrote it, so no `AGENTS.md` of the organization changes unless
|
|
125
|
+
its content does.
|
|
126
|
+
|
|
28
127
|
Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
|
|
29
128
|
`RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
|
|
30
129
|
|
|
130
|
+
## 0.5.1 — the version of a workspace moves by pull request
|
|
131
|
+
|
|
132
|
+
- Joining an organization pinned to an older `@rness/cli` no longer mentions
|
|
133
|
+
versions, and no longer invites a newcomer to move the whole team: the
|
|
134
|
+
workspace is served by the version the organization agreed on.
|
|
135
|
+
- A workspace whose pin moved is reinstalled on the next command, with the
|
|
136
|
+
package manager's frozen install so the working tree stays clean. Set
|
|
137
|
+
`RNESS_NO_INSTALL=1` to keep the old warning instead — for CI, a container
|
|
138
|
+
image, or a machine that cannot install.
|
|
139
|
+
- New workspaces ship `.github/dependabot.yml`, and `rness upgrade` writes it
|
|
140
|
+
into workspaces created earlier: a pull request per release, reviewed, with
|
|
141
|
+
`validate` running on the new version before the merge.
|
|
142
|
+
- A delegated child can no longer wait on an invisible SSH passphrase prompt:
|
|
143
|
+
it fails with a readable line instead of hanging.
|
|
144
|
+
- A join that wrote its blocks succeeds even when a repository nobody picked
|
|
145
|
+
failed to clone; those failures are hints.
|
|
146
|
+
|
|
147
|
+
## 0.5.0 — the organization is the workspace; rness.json is its catalogue
|
|
148
|
+
|
|
149
|
+
- `create <org>` names the organization, not a directory any more (`--org
|
|
150
|
+
<org>` and the prompt "What is your GitHub organization named?" do the
|
|
151
|
+
same). The workspace directory is `./<org>`, with the organization's exact
|
|
152
|
+
name; `--dir` is removed. With `npm create`, flags go after `--`:
|
|
153
|
+
`npm create rness acme -- --yes`.
|
|
154
|
+
- SSH first: `create` and `add` write `git@github.com:` URLs when
|
|
155
|
+
`ssh -T git@github.com` accepts your key, HTTPS ones otherwise (0.4.0
|
|
156
|
+
wrote HTTPS unless `--ssh`). `--https` is new. A private `.rness` you reach
|
|
157
|
+
over SSH is now found when joining. See "SSH or HTTPS" above.
|
|
158
|
+
- `create` does not offer repositories whose name starts with a dot
|
|
159
|
+
(`.github`, …).
|
|
160
|
+
- Colour, a banner and progress lines in a terminal (see "Colour" above);
|
|
161
|
+
nothing changes for scripts.
|
|
162
|
+
- `rness login` / `rness logout` are new: private repositories are listed,
|
|
163
|
+
and cloned over HTTPS with the login (see "Log in" above). Without a login
|
|
164
|
+
the note reads `rness login lists the private ones you can access`.
|
|
165
|
+
- `rness upgrade` is new (see "Upgrade" above). From 0.4.0:
|
|
166
|
+
`npx @rness/cli@latest upgrade`.
|
|
167
|
+
- The header of a generated block no longer names the CLI version
|
|
168
|
+
(`<!-- rness · scope: … -->`), and `sync` decides by the hash like
|
|
169
|
+
`validate`: upgrading rewrites no `AGENTS.md`. Blocks written by 0.2–0.4
|
|
170
|
+
stay as they are until their content changes. A 0.4.0 CLI calls the new
|
|
171
|
+
header stale — upgrade every copy together.
|
|
172
|
+
- The scaffold's CI workflow reads the version from `package.json` instead of
|
|
173
|
+
naming it; `upgrade` migrates the old line.
|
|
174
|
+
- `.rness/rness.json` is the organization's catalogue — every repository
|
|
175
|
+
rness knows about, shared by the team. Your workspace is the part of it
|
|
176
|
+
you cloned into `org/`; two teammates can clone different repositories,
|
|
177
|
+
and nothing but `org/` records the choice. A choice never removes a
|
|
178
|
+
repository from the catalogue.
|
|
179
|
+
- `create` lists the organization's repositories to search and pick from,
|
|
180
|
+
with every catalogue repository pre-selected when joining (a catalogue
|
|
181
|
+
repository the listing does not return is still offered, marked
|
|
182
|
+
`in .rness`). A picked catalogue repository is cloned; a picked new one is
|
|
183
|
+
added to the catalogue, as `rness add` does. Without a picker, `--repos`
|
|
184
|
+
is the selection; a join without `--repos` clones the whole catalogue. A
|
|
185
|
+
cancelled or declined prompt writes nothing and exits 0.
|
|
186
|
+
- The listing needs no credentials. Without a `GITHUB_TOKEN` (or `GH_TOKEN`)
|
|
187
|
+
only public repositories are listed — and a personal account always lists
|
|
188
|
+
only its public ones; add the others later with `rness add <repo>`.
|
|
189
|
+
- `rness sync` works on your clones: it writes the blocks of the repositories
|
|
190
|
+
in `org/`, never of `rness.json` as a whole. In a terminal it asks "Do you
|
|
191
|
+
want to sync as well?" with the catalogue repositories you have not cloned
|
|
192
|
+
("Select all", or pick some); what you pick is cloned first. With `--yes`,
|
|
193
|
+
or `--check`, nothing is cloned and one `not cloned:` line names them
|
|
194
|
+
(`--check` does not fail on it). `rness sync --all` clones them all without
|
|
195
|
+
asking. A clone `rness.json` does not know gets no block and a
|
|
196
|
+
`not in rness.json:` line pointing at `rness add`.
|
|
197
|
+
- A workspace pinned to 0.4.x clones every catalogue repository on sync —
|
|
198
|
+
`create` runs the pinned copy's sync after joining.
|
|
199
|
+
- Joining a workspace whose `.rness` pins an older `@rness/cli` than the one
|
|
200
|
+
you run says so, and that `rness upgrade` moves it.
|
|
201
|
+
- Repository and scope names take what GitHub allows, in lowercase: letters,
|
|
202
|
+
digits, `.`, `_` and `-` (`my_lib`, `angular.js`). A name that differs only
|
|
203
|
+
by case is declared in lowercase. A 0.4.0 CLI rejects a `rness.json` that
|
|
204
|
+
holds a `.` or a `_` in a name — upgrade every copy together.
|
|
205
|
+
- Organization names follow GitHub's rule — letters, digits and single
|
|
206
|
+
hyphens, not at either end, at most 39 characters — in `--org` and in
|
|
207
|
+
`rness.json`'s `"org"`; the case is kept as typed.
|
|
208
|
+
- `"org"` in `rness.json` now accepts uppercase letters: a 0.4.0 CLI rejects
|
|
209
|
+
a workspace whose `"org"` has any, so upgrade every copy together.
|
|
210
|
+
|
|
31
211
|
## 0.4.0 — create, add, the shims
|
|
32
212
|
|
|
33
213
|
- `npm create rness <org>` starts a new workspace for `github.com/<org>` or
|
|
@@ -57,9 +237,26 @@ Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
|
|
|
57
237
|
pnpm --filter @rness/cli test # node:test on the TypeScript sources
|
|
58
238
|
pnpm --filter @rness/cli typecheck
|
|
59
239
|
pnpm --filter @rness/cli build # tsup → dist/
|
|
60
|
-
|
|
240
|
+
pnpm dev --help # the CLI, straight from these sources
|
|
241
|
+
|
|
242
|
+
`pnpm dev` runs `packages/cli/src/bin/rness.ts`: Node ≥ 24 strips the types,
|
|
243
|
+
so nothing is built between an edit and the next run. It turns delegation off,
|
|
244
|
+
because inside a workspace the launcher would otherwise hand the command to the
|
|
245
|
+
published `@rness/cli` pinned in `.rness/` rather than to the sources under
|
|
246
|
+
test; `RNESS_NO_DELEGATE=0 pnpm dev …` puts it back, to exercise delegation
|
|
247
|
+
itself.
|
|
248
|
+
|
|
249
|
+
To reach it from a workspace elsewhere on the machine, link it once:
|
|
250
|
+
|
|
251
|
+
ln -s "$PWD/scripts/dev.mjs" ~/.local/bin/rness-dev # from the repository root
|
|
252
|
+
cd ~/somewhere/acme && rness-dev validate
|
|
253
|
+
|
|
254
|
+
`create` is never delegated, so it always runs these sources — and it refuses
|
|
255
|
+
to run inside a workspace, so call it from an empty directory.
|
|
61
256
|
|
|
62
|
-
|
|
63
|
-
|
|
257
|
+
`pnpm verdaccio` is the other loop: a local registry that serves this build as
|
|
258
|
+
a real package, for what only shows up through an install (`npm create rness`,
|
|
259
|
+
the pinned copy, a version bump). It is slower, and its caches have to be
|
|
260
|
+
forgotten on every redeploy, which `deploy` now does.
|
|
64
261
|
|
|
65
262
|
Node ≥ 24. MIT.
|
package/dist/bin/rness.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
VERSION,
|
|
4
|
+
driftWarning,
|
|
5
|
+
ensureInstalled,
|
|
4
6
|
findDelegate,
|
|
7
|
+
findWorkspace,
|
|
8
|
+
pinDrift,
|
|
9
|
+
pinnedBinPath,
|
|
5
10
|
reportError,
|
|
6
11
|
run
|
|
7
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-C6HBGV5V.js";
|
|
8
13
|
|
|
9
14
|
// src/bin/rness.ts
|
|
15
|
+
import { spawnSync } from "child_process";
|
|
10
16
|
import { pathToFileURL } from "url";
|
|
11
17
|
|
|
12
18
|
// src/core/node-version.ts
|
|
@@ -33,7 +39,39 @@ async function main() {
|
|
|
33
39
|
return 1;
|
|
34
40
|
}
|
|
35
41
|
const argv = process.argv.slice(2);
|
|
36
|
-
const
|
|
42
|
+
const own = [
|
|
43
|
+
"create",
|
|
44
|
+
"upgrade",
|
|
45
|
+
"update",
|
|
46
|
+
"login",
|
|
47
|
+
"logout",
|
|
48
|
+
"git-credential"
|
|
49
|
+
].includes(argv[0] ?? "");
|
|
50
|
+
const noDelegate = process.env["RNESS_NO_DELEGATE"] === "1";
|
|
51
|
+
const skipDelegation = own || noDelegate;
|
|
52
|
+
const command = argv[0];
|
|
53
|
+
if (command !== void 0 && !command.startsWith("-") && !skipDelegation) {
|
|
54
|
+
const ws = await findWorkspace(process.cwd()).catch(() => null);
|
|
55
|
+
const outcome = ws === null ? null : await ensureInstalled(ws.rnessDir, {
|
|
56
|
+
announce: (pin) => process.stderr.write(`installing @rness/cli ${pin} in .rness\u2026
|
|
57
|
+
`)
|
|
58
|
+
});
|
|
59
|
+
if (outcome !== null && !outcome.installed) {
|
|
60
|
+
const warning = await driftWarning(process.cwd());
|
|
61
|
+
if (warning !== null) process.stderr.write(`${warning}
|
|
62
|
+
`);
|
|
63
|
+
}
|
|
64
|
+
if (ws !== null && outcome?.installed === true && await pinDrift(ws.rnessDir) === null) {
|
|
65
|
+
const pinnedBin = await pinnedBinPath(ws.rnessDir);
|
|
66
|
+
if (pinnedBin !== null) {
|
|
67
|
+
const { status } = spawnSync(process.execPath, [pinnedBin, ...argv], {
|
|
68
|
+
cwd: process.cwd(),
|
|
69
|
+
stdio: "inherit"
|
|
70
|
+
});
|
|
71
|
+
return status ?? 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
37
75
|
const delegate = skipDelegation ? null : await findDelegate(process.cwd(), VERSION);
|
|
38
76
|
if (delegate !== null) {
|
|
39
77
|
const broken = (reason) => new Error(
|
package/dist/bin/rness.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { pathToFileURL } from 'node:url'\n\nimport { run } from '../cli.ts'\nimport { findDelegate } from '../core/delegate.ts'\nimport { MIN_NODE_MAJOR, isSupportedNode } from '../core/node-version.ts'\nimport { reportError } from '../report.ts'\nimport { VERSION } from '../version.ts'\n\n// `rness context | head`: once the reader has its lines it closes the pipe and\n// every further write emits EPIPE on stdout. Nothing is left to deliver, so end\n// quietly with success. This is the one process.exit() in the code base — it\n// runs only when there is no output left to drain (see main() below).\nprocess.stdout.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'EPIPE') process.exit(0)\n throw e\n})\n\n// Set process.exitCode rather than calling process.exit(): process.exit()\n// terminates before Node drains an async stdout pipe, truncating piped output\n// at the ~64 KiB pipe buffer (breaks `rness context --json | jq`, `$(...)`).\nasync function main(): Promise<number> {\n if (!isSupportedNode(process.versions.node)) {\n process.stderr.write(\n `rness needs Node ${MIN_NODE_MAJOR} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n const
|
|
1
|
+
{"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { spawnSync } from 'node:child_process'\nimport { pathToFileURL } from 'node:url'\n\nimport { run } from '../cli.ts'\nimport { findDelegate, pinnedBinPath } from '../core/delegate.ts'\nimport { MIN_NODE_MAJOR, isSupportedNode } from '../core/node-version.ts'\nimport { driftWarning, ensureInstalled, pinDrift } from '../core/pinned.ts'\nimport { findWorkspace } from '../core/workspace.ts'\nimport { reportError } from '../report.ts'\nimport { VERSION } from '../version.ts'\n\n// `rness context | head`: once the reader has its lines it closes the pipe and\n// every further write emits EPIPE on stdout. Nothing is left to deliver, so end\n// quietly with success. This is the one process.exit() in the code base — it\n// runs only when there is no output left to drain (see main() below).\nprocess.stdout.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'EPIPE') process.exit(0)\n throw e\n})\n\n// Set process.exitCode rather than calling process.exit(): process.exit()\n// terminates before Node drains an async stdout pipe, truncating piped output\n// at the ~64 KiB pipe buffer (breaks `rness context --json | jq`, `$(...)`).\nasync function main(): Promise<number> {\n if (!isSupportedNode(process.versions.node)) {\n process.stderr.write(\n `rness needs Node ${MIN_NODE_MAJOR} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n // `create` makes a workspace and `upgrade` replaces the pinned copy: both\n // are served by the copy the user invoked (spec 0006 §3). The login concerns\n // the machine, not a workspace — and git runs `git-credential` from inside\n // a clone, on every fetch: no delegation, and no warning there either.\n const own = [\n 'create',\n 'upgrade',\n 'update',\n 'login',\n 'logout',\n 'git-credential',\n ].includes(argv[0] ?? '')\n const noDelegate = process.env['RNESS_NO_DELEGATE'] === '1'\n const skipDelegation = own || noDelegate\n const command = argv[0]\n if (command !== undefined && !command.startsWith('-') && !skipDelegation) {\n const ws = await findWorkspace(process.cwd()).catch(() => null)\n // The version was decided by the pull request that moved the pin, so\n // catching up asks nothing (spec 0008 §4).\n const outcome =\n ws === null\n ? null\n : await ensureInstalled(ws.rnessDir, {\n announce: (pin) =>\n process.stderr.write(`installing @rness/cli ${pin} in .rness…\\n`),\n })\n if (outcome !== null && !outcome.installed) {\n const warning = await driftWarning(process.cwd())\n if (warning !== null) process.stderr.write(`${warning}\\n`)\n }\n // The pinned tree was just rebuilt: importing out of it in this process is\n // fragile, so the freshly installed copy runs as its own process.\n // Only hand off when the install actually closed the drift: a child that\n // would install again on every run must never be spawned.\n if (\n ws !== null &&\n outcome?.installed === true &&\n (await pinDrift(ws.rnessDir)) === null\n ) {\n const pinnedBin = await pinnedBinPath(ws.rnessDir)\n if (pinnedBin !== null) {\n const { status } = spawnSync(process.execPath, [pinnedBin, ...argv], {\n cwd: process.cwd(),\n stdio: 'inherit',\n })\n return status ?? 1\n }\n }\n }\n const delegate = skipDelegation\n ? null\n : await findDelegate(process.cwd(), VERSION)\n if (delegate !== null) {\n const broken = (reason: string): Error =>\n new Error(\n `@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`\n )\n if (process.env['RNESS_DEBUG'] === '1') {\n process.stderr.write(\n `rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})\\n`\n )\n }\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(delegate.entry).href)) as Record<\n string,\n unknown\n >\n } catch (e) {\n throw broken(e instanceof Error ? e.message : String(e))\n }\n if (typeof mod['run'] !== 'function')\n throw broken('dist/index.js does not export run')\n const delegateRun = mod['run'] as (argv: string[]) => Promise<unknown>\n const code = await delegateRun(argv)\n return typeof code === 'number' ? code : 1\n }\n return run(argv)\n}\n\nmain()\n .then((code) => {\n process.exitCode = code\n })\n .catch((e: unknown) => {\n process.exitCode = reportError(e)\n })\n","export const MIN_NODE_MAJOR = 24\n\nexport function nodeMajor(version: string): number {\n const major = Number.parseInt(version.split('.')[0] ?? '', 10)\n return Number.isNaN(major) ? 0 : major\n}\n\nexport function isSupportedNode(version: string): boolean {\n return nodeMajor(version) >= MIN_NODE_MAJOR\n}\n"],"mappings":"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","names":[]}
|