@tokenoftrust/cli 1.4.0 → 1.5.0
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 +5 -0
- package/bin/tot.mjs +148 -57
- package/package.json +6 -1
- package/src/activity.mjs +379 -0
- package/src/app-scaffold.mjs +4 -4
- package/src/auth.mjs +13 -5
- package/src/candidate-state.mjs +3 -3
- package/src/commands/accept.mjs +498 -59
- package/src/commands/app/dev.mjs +8 -4
- package/src/commands/app/index.mjs +3 -3
- package/src/commands/app/scaffold.mjs +1 -1
- package/src/commands/branches.mjs +297 -0
- package/src/commands/cleanup.mjs +264 -0
- package/src/commands/clone.mjs +307 -25
- package/src/commands/dev.mjs +440 -156
- package/src/commands/doctor.mjs +4 -4
- package/src/commands/git-credential.mjs +180 -0
- package/src/commands/go-live.mjs +9 -5
- package/src/commands/grants.mjs +7 -5
- package/src/commands/hotfix.mjs +428 -0
- package/src/commands/ideas.mjs +2 -2
- package/src/commands/link.mjs +2 -2
- package/src/commands/login.mjs +5 -6
- package/src/commands/pr.mjs +62 -25
- package/src/commands/preview-build.mjs +6 -6
- package/src/commands/preview-doctor.mjs +225 -0
- package/src/commands/preview-retry-evidence.mjs +156 -0
- package/src/commands/preview.mjs +19 -3
- package/src/commands/revert.mjs +322 -0
- package/src/commands/rollback.mjs +18 -16
- package/src/commands/ship.mjs +51 -14
- package/src/commands/start.mjs +101 -59
- package/src/commands/submit.mjs +1183 -169
- package/src/commands/sync.mjs +203 -0
- package/src/commands/validate.mjs +10 -4
- package/src/commands/whoami.mjs +1 -1
- package/src/dev-heartbeat.mjs +3 -2
- package/src/dev-logs.mjs +2 -2
- package/src/errors.mjs +11 -4
- package/src/git-credential.mjs +257 -0
- package/src/last-tenant.mjs +1 -1
- package/src/mcp.mjs +6 -1
- package/src/merge-doctor-report.mjs +208 -0
- package/src/no-gitea-links.test.mjs +55 -0
- package/src/oauth.mjs +18 -14
- package/src/obstacle-beacon.cjs +2 -2
- package/src/obstacle.mjs +1 -1
- package/src/plan.mjs +83 -15
- package/src/sample.mjs +4 -4
- package/src/validate.mjs +187 -15
- package/src/vendor/private-apps-devkit.mjs +3 -3
- package/src/viewer-session.mjs +118 -0
- package/template/private-app/README.md +12 -6
- package/src/commands/retire.mjs +0 -203
package/README.md
CHANGED
|
@@ -19,6 +19,11 @@ install, no hand-provisioned AWS credentials. (Docker remains available as a
|
|
|
19
19
|
fallback — `tot dev --docker` — or automatically if the native artifact can't
|
|
20
20
|
be fetched.)
|
|
21
21
|
|
|
22
|
+
For Storefront Private App contracts, examples, and LLM-ready developer material, start at
|
|
23
|
+
[Storefront Devkit — Apps / Private](https://github.com/tokenoftrust/storefront-devkit/tree/main/apps/private).
|
|
24
|
+
The `tot app` commands use the CLI's self-contained helper; they do not require a separately
|
|
25
|
+
published npm SDK.
|
|
26
|
+
|
|
22
27
|
## Commands
|
|
23
28
|
|
|
24
29
|
| Command | Status | What it does |
|
package/bin/tot.mjs
CHANGED
|
@@ -2,27 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* `tot` — the Token of Trust developer CLI.
|
|
4
4
|
*
|
|
5
|
-
* One command a developer learns to go from an invite to a running store
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* tot login sign in to Token of Trust (OAuth) ← built (MCP OAuth PKCE loopback; caches ~/.tot/credentials.json)
|
|
9
|
-
* tot logout sign out (clear the cached session) ← built (deletes ~/.tot/credentials.json; local-only, no server revoke)
|
|
10
|
-
* tot whoami who you're signed in as ← built
|
|
11
|
-
* tot link link your identity to the ToT broker (resolve store scope) ← built
|
|
12
|
-
* tot grants capability/tier/expiry per store you can act on ← built (introspection diagnostics)
|
|
13
|
-
* tot clone [<tenant>] clone a store you can build on ← built
|
|
14
|
-
* tot validate lint your store before you submit ← built
|
|
15
|
-
* tot dev run your store locally with save→reload ← built (monorepo: host astro; standalone: runs the published runner image)
|
|
16
|
-
* tot preview push your store to a reviewable preview ← built (validate + push preview ref; MCP preview_status read-back). `submit`/`deploy` are teaching aliases.
|
|
17
|
-
* tot ship publish the current green aggregate live ← built (GET/POST /api/changes/ship → b09 orchestrator; exact plan + y/N confirm; waits for VERIFIED live truth)
|
|
18
|
-
* tot accept / tot merge queue a PR into the preview aggregate ← built (b08: plan + y/N confirm → POST /api/changes/integrate = b07 queue enqueue; NO merge-to-main, NO go-live; refuses non-TTY without --yes)
|
|
19
|
-
* tot rollback [<version>] instant re-point to a prior live version ← built (u3 promotion_status/promotion_rollback seam; diff + y/N confirm; refuses non-TTY / ineligible)
|
|
20
|
-
* tot pr list / view / close your candidate PRs ← built (candidate_status/candidate_close; gh-pr-shaped)
|
|
21
|
-
* tot doctor check this machine is ready
|
|
22
|
-
* tot ideas copy-paste AI prompts that reliably wow
|
|
23
|
-
* tot feedback send a note to ToT + your recent CLI activity ← built (activity-log.mjs → feedback_submit MCP tool)
|
|
24
|
-
* tot app scaffold/dev build + locally exercise a Private App ← built (offline; see src/commands/app/)
|
|
25
|
-
* tot help this help
|
|
5
|
+
* One command a developer learns to go from an invite to a running store. The
|
|
6
|
+
* user-facing command list is the single source of truth in `COMMANDS` below;
|
|
7
|
+
* `usage()` renders it, so add new commands there — never in a second list.
|
|
26
8
|
*
|
|
27
9
|
* Context-aware (see src/context.mjs): the same `tot` does the right thing from
|
|
28
10
|
* inside the storefront monorepo, from inside a standalone tenant checkout, or
|
|
@@ -37,6 +19,7 @@ import { readFileSync } from "node:fs";
|
|
|
37
19
|
import { detectContext } from "../src/context.mjs";
|
|
38
20
|
import { printError } from "../src/errors.mjs";
|
|
39
21
|
import { recordActivity, redactArgs } from "../src/activity-log.mjs";
|
|
22
|
+
import { emitActivity, capRendered } from "../src/activity.mjs";
|
|
40
23
|
import { maybeNotifyUpdate } from "../src/update-check.mjs";
|
|
41
24
|
|
|
42
25
|
const BUILD_ORDER = ["clone", "validate", "dev", "preview"];
|
|
@@ -50,33 +33,47 @@ const VERSION = (() => {
|
|
|
50
33
|
}
|
|
51
34
|
})();
|
|
52
35
|
|
|
36
|
+
// Single source of truth for the user-facing command list. `usage()` renders
|
|
37
|
+
// it and the file header points here; keep new commands in this one array so the
|
|
38
|
+
// help output can't drift from a second hand-maintained copy. `invocation` is the
|
|
39
|
+
// text after `tot ` (including any argument hint); `blurb` is the one-line help.
|
|
40
|
+
const COMMANDS = [
|
|
41
|
+
{ invocation: "start", blurb: "invite → running store in one command (start here)" },
|
|
42
|
+
{ invocation: "login", blurb: "sign in to Token of Trust" },
|
|
43
|
+
{ invocation: "logout", blurb: "sign out (clear the cached session)" },
|
|
44
|
+
{ invocation: "whoami", blurb: "show who you're signed in as" },
|
|
45
|
+
{ invocation: "link", blurb: "link your identity so your stores resolve" },
|
|
46
|
+
{ invocation: "grants", blurb: "capability/tier/expiry per store you can act on" },
|
|
47
|
+
{ invocation: "clone [<tenant>]", blurb: "clone a store you can build on" },
|
|
48
|
+
{ invocation: "validate", blurb: "lint your store before you submit" },
|
|
49
|
+
{ invocation: "dev", blurb: "run your store locally with save→reload" },
|
|
50
|
+
{ invocation: "preview", blurb: "push your store to a reviewable preview" },
|
|
51
|
+
{ invocation: "ship", blurb: "publish the tenant's current green aggregate live (plan → confirm → ship)" },
|
|
52
|
+
{ invocation: "accept / tot merge", blurb: "queue a PR into the preview aggregate — operator verb, no go-live (plan → confirm → integrate)" },
|
|
53
|
+
{ invocation: "sync", blurb: "fetch `preview` and merge it into your local branch (accept-conflict recovery)" },
|
|
54
|
+
{ invocation: "rollback [<version>]", blurb: "instant re-point to a prior live version (list → confirm → rollback)" },
|
|
55
|
+
{ invocation: "revert --preview <PR|sha>", blurb: "remove already-integrated content from the preview aggregate via a new revert commit — no force-reset (plan → confirm → revert)" },
|
|
56
|
+
{ invocation: "hotfix --pr <N>", blurb: "OWNER-ONLY exception: release an urgent fix from main to live, bypassing unshipped preview work (plan → confirm → release → auto forward-integrate)", },
|
|
57
|
+
{ invocation: "go-live", blurb: "cut the apex domain over to the storefront (readiness → confirm → cutover)" },
|
|
58
|
+
{ invocation: "pr", blurb: "list / view / close your candidate PRs" },
|
|
59
|
+
{ invocation: "branches", blurb: "full branch-cleanup report — every branch, any PR state, cleanup eligibility" },
|
|
60
|
+
{ invocation: "cleanup", blurb: "owner-confirmed branch GC (--dry-run to classify only; deletes terminal branches only)" },
|
|
61
|
+
{ invocation: "doctor", blurb: "check this machine is ready" },
|
|
62
|
+
{ invocation: "ideas", blurb: "copy-paste AI prompts that reliably wow" },
|
|
63
|
+
{ invocation: 'feedback "<msg>"', blurb: "send feedback to Token of Trust (attaches recent activity)" },
|
|
64
|
+
{ invocation: "app scaffold <name>", blurb: "scaffold a Storefront Private App" },
|
|
65
|
+
{ invocation: "app dev ...", blurb: "local, offline Private App webhook/manifest/JWT harness" },
|
|
66
|
+
{ invocation: "help", blurb: "show this help" },
|
|
67
|
+
{ invocation: "--version", blurb: "print the CLI version" },
|
|
68
|
+
];
|
|
69
|
+
|
|
53
70
|
function usage() {
|
|
71
|
+
const col = Math.max(...COMMANDS.map((c) => `tot ${c.invocation}`.length)) + 2;
|
|
72
|
+
const lines = COMMANDS.map((c) => ` ${`tot ${c.invocation}`.padEnd(col)}${c.blurb}`).join("\n");
|
|
54
73
|
console.log(`
|
|
55
74
|
tot — Token of Trust developer CLI
|
|
56
75
|
|
|
57
|
-
|
|
58
|
-
tot login sign in to Token of Trust
|
|
59
|
-
tot logout sign out (clear the cached session)
|
|
60
|
-
tot whoami show who you're signed in as
|
|
61
|
-
tot link link your identity so your stores resolve
|
|
62
|
-
tot grants capability/tier/expiry per store you can act on
|
|
63
|
-
tot clone [<tenant>] clone a store you can build on
|
|
64
|
-
tot validate lint your store before you submit
|
|
65
|
-
tot dev run your store locally with save→reload
|
|
66
|
-
tot preview push your store to a reviewable preview
|
|
67
|
-
tot ship publish the tenant's current green aggregate live (plan → confirm → ship)
|
|
68
|
-
tot accept / tot merge queue a PR into the preview aggregate — operator verb, no go-live (plan → confirm → integrate)
|
|
69
|
-
tot rollback [<version>] instant re-point to a prior live version (list → confirm → rollback)
|
|
70
|
-
tot retire evict a candidate PR's preview to reclaim space — operator verb, rebuildable (plan → confirm → evict)
|
|
71
|
-
tot go-live cut the apex domain over to the storefront (readiness → confirm → cutover)
|
|
72
|
-
tot pr list / view / close your candidate PRs
|
|
73
|
-
tot doctor check this machine is ready
|
|
74
|
-
tot ideas copy-paste AI prompts that reliably wow
|
|
75
|
-
tot feedback "<msg>" send feedback to Token of Trust (attaches recent activity)
|
|
76
|
-
tot app scaffold <name> scaffold a Storefront Private App
|
|
77
|
-
tot app dev ... local, offline Private App webhook/manifest/JWT harness
|
|
78
|
-
tot help show this help
|
|
79
|
-
tot --version print the CLI version
|
|
76
|
+
${lines}
|
|
80
77
|
|
|
81
78
|
Run \`tot <command> --help\` for command-specific options.
|
|
82
79
|
`);
|
|
@@ -108,12 +105,12 @@ async function dispatch(cmd, rest, ctx) {
|
|
|
108
105
|
|
|
109
106
|
if (cmd === "logout") {
|
|
110
107
|
const { run } = await import("../src/commands/logout.mjs");
|
|
111
|
-
return run(rest, ctx);
|
|
108
|
+
return /** @type {any} */ (run)(rest, ctx);
|
|
112
109
|
}
|
|
113
110
|
|
|
114
111
|
if (cmd === "feedback") {
|
|
115
112
|
const { run } = await import("../src/commands/feedback.mjs");
|
|
116
|
-
return run(rest, ctx);
|
|
113
|
+
return /** @type {any} */ (run)(rest, ctx);
|
|
117
114
|
}
|
|
118
115
|
|
|
119
116
|
if (cmd === "whoami") {
|
|
@@ -146,6 +143,15 @@ async function dispatch(cmd, rest, ctx) {
|
|
|
146
143
|
return run(rest, ctx);
|
|
147
144
|
}
|
|
148
145
|
|
|
146
|
+
// Plumbing, not a developer-facing verb (like git's own credential helpers,
|
|
147
|
+
// never listed in `git help`) — `tot clone` configures it as this checkout's
|
|
148
|
+
// `credential.helper`, and git alone invokes it (get/store/erase) on every
|
|
149
|
+
// fetch/push. See src/commands/git-credential.mjs's header.
|
|
150
|
+
if (cmd === "git-credential") {
|
|
151
|
+
const { run } = await import("../src/commands/git-credential.mjs");
|
|
152
|
+
return run(rest, ctx);
|
|
153
|
+
}
|
|
154
|
+
|
|
149
155
|
if (cmd === "validate") {
|
|
150
156
|
const { run } = await import("../src/commands/validate.mjs");
|
|
151
157
|
return run(rest, ctx);
|
|
@@ -174,26 +180,49 @@ async function dispatch(cmd, rest, ctx) {
|
|
|
174
180
|
return run(rest, ctx);
|
|
175
181
|
}
|
|
176
182
|
|
|
177
|
-
// `accept` queue-integrates a PR into the protected `preview` aggregate
|
|
183
|
+
// `accept` queue-integrates a PR into the protected `preview` aggregate —
|
|
178
184
|
// NO merge-to-main, NO go-live; going live is `tot ship`, which publishes the
|
|
179
|
-
// whole current GREEN AGGREGATE
|
|
180
|
-
// (
|
|
185
|
+
// whole current GREEN AGGREGATE. Backed by POST /api/changes/integrate
|
|
186
|
+
// (TenantIntegrationQueue.enqueue); see accept.mjs's header. `merge` is a
|
|
181
187
|
// first-class alias, not a teaching nudge: both dispatch straight to the same command.
|
|
182
188
|
if (cmd === "accept" || cmd === "merge") {
|
|
183
189
|
const { run } = await import("../src/commands/accept.mjs");
|
|
184
190
|
return run(rest, ctx);
|
|
185
191
|
}
|
|
186
192
|
|
|
193
|
+
// `sync` is the common accept-conflict recovery path: fetches the
|
|
194
|
+
// protected `preview` branch and merges it into the developer's local branch so
|
|
195
|
+
// they can resolve locally, then re-`tot preview`. Purely local — no push, no
|
|
196
|
+
// MCP call, never touches the shared `preview`/`main` refs themselves. See
|
|
197
|
+
// sync.mjs's header for the full contract.
|
|
198
|
+
if (cmd === "sync") {
|
|
199
|
+
const { run } = await import("../src/commands/sync.mjs");
|
|
200
|
+
return run(rest, ctx);
|
|
201
|
+
}
|
|
202
|
+
|
|
187
203
|
if (cmd === "rollback") {
|
|
188
204
|
const { run } = await import("../src/commands/rollback.mjs");
|
|
189
205
|
return run(rest, ctx);
|
|
190
206
|
}
|
|
191
207
|
|
|
192
|
-
// `
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
|
|
208
|
+
// `revert --preview <PR|integration-sha>` removes already-integrated content from
|
|
209
|
+
// the protected `preview` aggregate via a NEW auditable revert commit — NO
|
|
210
|
+
// force-reset, NO touch to main/live. Backed by POST /api/changes/revert
|
|
211
|
+
// (TenantIntegrationQueue.enqueueRevert). To undo something already LIVE, that's
|
|
212
|
+
// `tot rollback`, not this. See revert.mjs's header.
|
|
213
|
+
if (cmd === "revert") {
|
|
214
|
+
const { run } = await import("../src/commands/revert.mjs");
|
|
215
|
+
return run(rest, ctx);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// `hotfix --pr <N>` is the OWNER-ONLY EXCEPTION lane: release an urgent fix
|
|
219
|
+
// from `main` to live while `preview` still holds other unshipped work, EXCLUDING
|
|
220
|
+
// that unshipped preview head, then automatically forward-integrate main → preview
|
|
221
|
+
// and re-validate. It is DELIBERATELY a distinct verb — never a `--base main` flag
|
|
222
|
+
// on `tot ship` (which publishes the whole green preview aggregate). Backed by
|
|
223
|
+
// GET/POST /api/changes/hotfix → HotfixOrchestrator. See hotfix.mjs's header.
|
|
224
|
+
if (cmd === "hotfix") {
|
|
225
|
+
const { run } = await import("../src/commands/hotfix.mjs");
|
|
197
226
|
return run(rest, ctx);
|
|
198
227
|
}
|
|
199
228
|
|
|
@@ -207,6 +236,23 @@ async function dispatch(cmd, rest, ctx) {
|
|
|
207
236
|
return run(rest, ctx);
|
|
208
237
|
}
|
|
209
238
|
|
|
239
|
+
// `branches` is the FULL branch-cleanup report (every branch, any PR state) —
|
|
240
|
+
// distinct from `tot pr list`, which only shows OPEN PRs. Read-only;
|
|
241
|
+
// always safe to run, and the report `tot cleanup` reuses before deleting anything.
|
|
242
|
+
if (cmd === "branches") {
|
|
243
|
+
const { run } = await import("../src/commands/branches.mjs");
|
|
244
|
+
return run(rest, ctx);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// `cleanup` is owner-confirmed BRANCH GC — an irreversible git-ref
|
|
248
|
+
// delete for terminal candidates. `--dry-run` classifies and prints; it never deletes. Age alone
|
|
249
|
+
// never makes a branch eligible; main/preview are always kept; orphans are
|
|
250
|
+
// quarantined, never auto-deleted. See cleanup.mjs's header.
|
|
251
|
+
if (cmd === "cleanup") {
|
|
252
|
+
const { run } = await import("../src/commands/cleanup.mjs");
|
|
253
|
+
return run(rest, ctx);
|
|
254
|
+
}
|
|
255
|
+
|
|
210
256
|
if (cmd === "app") {
|
|
211
257
|
const { run } = await import("../src/commands/app/index.mjs");
|
|
212
258
|
return run(rest, ctx);
|
|
@@ -238,12 +284,39 @@ async function dispatch(cmd, rest, ctx) {
|
|
|
238
284
|
return 2;
|
|
239
285
|
}
|
|
240
286
|
|
|
287
|
+
/**
|
|
288
|
+
* The safe `subcommand` value for a command's activity event. Only the fixed
|
|
289
|
+
* sub-dispatcher verbs (e.g. `app scaffold` / `app dev`) are surfaced — an
|
|
290
|
+
* arbitrary positional (a tenant name, a path, a code) is NEVER used, so the
|
|
291
|
+
* activity `subcommand` field can't carry PII even before redaction. Returns
|
|
292
|
+
* undefined for every command without a fixed subcommand vocabulary.
|
|
293
|
+
*/
|
|
294
|
+
function safeSubcommand(cmd, rest) {
|
|
295
|
+
if (cmd === "app") {
|
|
296
|
+
const sub = rest.find((t) => t && !t.startsWith("-"));
|
|
297
|
+
if (sub === "scaffold" || sub === "dev") return sub;
|
|
298
|
+
}
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
|
|
241
302
|
async function main() {
|
|
242
303
|
const [cmd, ...rest] = process.argv.slice(2);
|
|
243
304
|
const ctx = detectContext();
|
|
244
305
|
const startedAt = Date.now();
|
|
306
|
+
const command = cmd || "(none)";
|
|
307
|
+
const subcommand = safeSubcommand(cmd, rest);
|
|
245
308
|
let code = 0;
|
|
246
309
|
let errMsg = null;
|
|
310
|
+
|
|
311
|
+
// Emit `cli.command.invoked` on start — best-effort, a SILENT no-op without a
|
|
312
|
+
// hosted-bridge credential (never a network call / never blocks). Fired without
|
|
313
|
+
// await so it adds no latency to the command; settled alongside the result below.
|
|
314
|
+
const invokedEmit = emitActivity({
|
|
315
|
+
action: "cli.command.invoked",
|
|
316
|
+
outcome: { status: "invoked" },
|
|
317
|
+
payload: { args: { command, ...(subcommand ? { subcommand } : {}), cliVersion: VERSION, node: process.version } },
|
|
318
|
+
});
|
|
319
|
+
|
|
247
320
|
try {
|
|
248
321
|
code = await dispatch(cmd, rest, ctx);
|
|
249
322
|
return code;
|
|
@@ -251,17 +324,35 @@ async function main() {
|
|
|
251
324
|
errMsg = e?.message || String(e);
|
|
252
325
|
throw e;
|
|
253
326
|
} finally {
|
|
327
|
+
const exitCode = errMsg ? 1 : (code ?? 0);
|
|
328
|
+
const durationMs = Date.now() - startedAt;
|
|
254
329
|
// Best-effort activity breadcrumb (never throws, never blocks). `feedback`'s own
|
|
255
330
|
// free-text message is omitted — it's user-typed and belongs only in the report.
|
|
256
331
|
recordActivity({
|
|
257
332
|
ts: new Date().toISOString(),
|
|
258
333
|
v: VERSION,
|
|
259
|
-
cmd:
|
|
334
|
+
cmd: command,
|
|
260
335
|
args: cmd === "feedback" ? ["«omitted»"] : redactArgs(rest),
|
|
261
|
-
code:
|
|
262
|
-
ms:
|
|
336
|
+
code: exitCode,
|
|
337
|
+
ms: durationMs,
|
|
263
338
|
...(errMsg ? { err: String(errMsg).slice(0, 200) } : {}),
|
|
264
339
|
});
|
|
340
|
+
// Emit `cli.command.result` (exit code + duration + a bounded/redacted
|
|
341
|
+
// rendered field). The house-style error text is capped + run through the JS
|
|
342
|
+
// redaction mirror; per the activity catalog the `cli.*` rendered lane is empty-
|
|
343
|
+
// allowlisted, so it's DROPPED by design (the safe default for a high-volume
|
|
344
|
+
// action) — the emit path still exercises the mirror. Bounded-await here (with
|
|
345
|
+
// the invoked emit) so a live bridge flushes before the process exits; a no-op
|
|
346
|
+
// when there's no credential.
|
|
347
|
+
const resultEmit = emitActivity({
|
|
348
|
+
action: "cli.command.result",
|
|
349
|
+
outcome: { status: errMsg ? "failed" : "succeeded", durationMs },
|
|
350
|
+
payload: {
|
|
351
|
+
args: { command, ...(subcommand ? { subcommand } : {}), cliVersion: VERSION, exitCode, durationMs },
|
|
352
|
+
...(errMsg ? { rendered: { output: capRendered(errMsg) } } : {}),
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
await Promise.allSettled([invokedEmit, resultEmit]);
|
|
265
356
|
// Nudge if a newer/unsupported version exists (drawn from cache — instant),
|
|
266
357
|
// and kick a detached registry refresh if stale. Never throws, never blocks.
|
|
267
358
|
maybeNotifyUpdate(VERSION);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Token of Trust developer CLI — clone a tenant store, run it locally with save→reload, and submit it for preview. Installs the `tot` command.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Token of Trust",
|
|
@@ -36,7 +36,12 @@
|
|
|
36
36
|
"access": "public",
|
|
37
37
|
"registry": "https://registry.npmjs.org"
|
|
38
38
|
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^20.16.0",
|
|
41
|
+
"typescript": "^5.6.3"
|
|
42
|
+
},
|
|
39
43
|
"scripts": {
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
40
45
|
"test": "node --test",
|
|
41
46
|
"prepublishOnly": "node ../../scripts/build/check-cli-clean.mjs ."
|
|
42
47
|
}
|