@tokenoftrust/cli 2.1.0 → 2.1.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/package.json +1 -1
- package/src/capability-registry.mjs +3 -3
- package/src/commands/report.mjs +21 -3
- package/src/commands/start.mjs +34 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
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",
|
|
@@ -64,7 +64,7 @@ export const CAPABILITIES = [
|
|
|
64
64
|
'Declared old->new paths materialize into the PUBLISHED artifact and are served by the edge '
|
|
65
65
|
+ 'function on the public path. They correctly 404 on the preview/test channel — that is by '
|
|
66
66
|
+ 'design and is not a missing declaration.',
|
|
67
|
-
implementedBy: ['
|
|
67
|
+
implementedBy: ['agency-kit/tools/validate-site.mjs'],
|
|
68
68
|
populatedBy: 'content/redirects.json in the tenant repo',
|
|
69
69
|
verifiedBy: 'Step 9 post-cutover crawl (not provable pre-cutover)',
|
|
70
70
|
appliesTo: ['commerce', 'marketing'],
|
|
@@ -105,7 +105,7 @@ export const CAPABILITIES = [
|
|
|
105
105
|
'The merchant\'s own pre-migration scores, captured before cutover, so parity can be judged '
|
|
106
106
|
+ 'and improvement proven. NOT re-derivable once the hostname moves.',
|
|
107
107
|
implementedBy: [
|
|
108
|
-
'
|
|
108
|
+
'agency-kit/tools/capture-source-baseline.mjs',
|
|
109
109
|
'docs/devkit-staging/tools/lib/lighthouse-parity.mjs',
|
|
110
110
|
],
|
|
111
111
|
populatedBy: 'Step 8 — capture-source-baseline.mjs, before cutover',
|
|
@@ -202,7 +202,7 @@ export const CAPABILITIES = [
|
|
|
202
202
|
+ 'category, so the score is visible and the dimension is offerable as an add-on — but a '
|
|
203
203
|
+ 'good score needs the surface built.',
|
|
204
204
|
implementedBy: [
|
|
205
|
-
'
|
|
205
|
+
'agency-kit/tools/capture-source-baseline.mjs',
|
|
206
206
|
'docs/devkit-staging/tools/validate-page-browser.mjs',
|
|
207
207
|
'apps/storefront/src/lib/diag/evidence.ts',
|
|
208
208
|
],
|
package/src/commands/report.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `tot report go-live` — the merchant-facing go-live readiness report for one store.
|
|
3
3
|
*
|
|
4
|
-
* tot report go-live --pages <dir> [--style <json>] [--workspace <dir>] [--out <md>]
|
|
4
|
+
* tot report go-live --pages <dir> [--style <json>] [--workspace <dir>] [--out <md>] [--json]
|
|
5
5
|
*
|
|
6
6
|
* It is generated FROM measurements, never authored:
|
|
7
7
|
*
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
* `.tot/lighthouse-source-baseline.json` (the source site's pre-migration scores).
|
|
16
16
|
*
|
|
17
17
|
* Writes <out> (default <pages>/go-live-report.md) and its implementor companion
|
|
18
|
-
* <out>.internal.md.
|
|
18
|
+
* <out>.internal.md. --json also prints the readiness checks it reported on to stdout.
|
|
19
|
+
* No network, no credentials: reproducible from the same inputs.
|
|
19
20
|
* Exit 0 written; 2 usage; 3 refused (no measurements to report on).
|
|
20
21
|
*/
|
|
21
22
|
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
@@ -34,6 +35,7 @@ export const USAGE = `tot report go-live — the go-live readiness report for yo
|
|
|
34
35
|
[--style <json>] the style-concept audit's JSON (default <pages>/style.json)
|
|
35
36
|
[--workspace <dir>] the store checkout (default: this checkout)
|
|
36
37
|
[--out <md>] where to write it (default <pages>/go-live-report.md)
|
|
38
|
+
[--json] also print the readiness checks as JSON
|
|
37
39
|
|
|
38
40
|
Save each page's JSON from the devkit page checks into <dir> first, e.g.
|
|
39
41
|
validate-page.sh <base> / > <dir>/home.json
|
|
@@ -58,6 +60,7 @@ export function parseArgs(argv) {
|
|
|
58
60
|
for (let i = 0; i < argv.length; i += 1) {
|
|
59
61
|
const t = argv[i];
|
|
60
62
|
if (t === "--help" || t === "-h") { a.help = true; continue; }
|
|
63
|
+
if (t === "--json") { a.json = true; continue; }
|
|
61
64
|
if (!t.startsWith("--")) {
|
|
62
65
|
if (a.sub === null) { a.sub = t; continue; }
|
|
63
66
|
return { ...a, error: `unexpected argument: ${t}` };
|
|
@@ -164,10 +167,22 @@ export function evidenceFromDir({ pagesDir, stylePath = null, lint = null }) {
|
|
|
164
167
|
};
|
|
165
168
|
|
|
166
169
|
if (summary) {
|
|
170
|
+
// A site-wide run that recorded its checks is reported as recorded; one that did not has them
|
|
171
|
+
// derived here from its own aggregate, by the same derivation as single-page results.
|
|
172
|
+
const checks = Array.isArray(summary.readiness?.checks)
|
|
173
|
+
? summary.readiness.checks
|
|
174
|
+
: [
|
|
175
|
+
storeConfigCheck(lint),
|
|
176
|
+
...buildReadinessChecks({
|
|
177
|
+
aggregate: { ...summary, totals: { ...summary.totals, issues: summary.totals?.issues ?? { lowRiskOpen: 0 } } },
|
|
178
|
+
styleJson: styleJson ?? (summary.style?.gates ? { gates: summary.style.gates } : null),
|
|
179
|
+
args: { manifest: summary.manifest ?? "(none supplied to the style-concept audit)" },
|
|
180
|
+
}),
|
|
181
|
+
];
|
|
167
182
|
return {
|
|
168
183
|
measured: true,
|
|
169
184
|
generatedAt: summary.generatedAt ?? null,
|
|
170
|
-
checks
|
|
185
|
+
checks,
|
|
171
186
|
totals: summary.totals ?? {},
|
|
172
187
|
pages,
|
|
173
188
|
...styleFacts,
|
|
@@ -303,6 +318,9 @@ export function run(argv, ctx, io = {}) {
|
|
|
303
318
|
pages: evidence.pages,
|
|
304
319
|
commerceSync,
|
|
305
320
|
}));
|
|
321
|
+
if (args.json) {
|
|
322
|
+
out(`${JSON.stringify({ tenant, report: outPath, internal: internalPath, totals: evidence.totals, checks: evidence.checks }, null, 2)}\n`);
|
|
323
|
+
}
|
|
306
324
|
err(`wrote ${outPath}\nwrote ${internalPath}\n${TEASER}\n`);
|
|
307
325
|
return 0;
|
|
308
326
|
}
|
package/src/commands/start.mjs
CHANGED
|
@@ -267,10 +267,18 @@ export async function run(argv, ctx) {
|
|
|
267
267
|
noLogin: false, noOpen: args.noOpen, docker: args.docker,
|
|
268
268
|
});
|
|
269
269
|
const runtime = /** @type {{ useDocker: boolean, runnerDir: any }} */ ({ useDocker: args.docker, runnerDir: null });
|
|
270
|
-
await
|
|
270
|
+
await settleCheckoutAndRuntime(
|
|
271
271
|
ensureCheckout(client, tenant, dir, env),
|
|
272
272
|
prefetchRuntime(client, devArgs, env, runtime, ctx),
|
|
273
|
-
|
|
273
|
+
{
|
|
274
|
+
onRuntimeFailedAfterCheckout: () => {
|
|
275
|
+
printCheckoutLocation(dir);
|
|
276
|
+
console.log(
|
|
277
|
+
` Once the problem below is fixed, run \`tot start\` again from ${resolve(dir, "..")} — it reuses ./${tenant}.`,
|
|
278
|
+
);
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
);
|
|
274
282
|
|
|
275
283
|
// Say EXACTLY where the code landed + THE one next step, so a freshly
|
|
276
284
|
// checked-out dev is never left wondering what to open. Absolute path (works
|
|
@@ -690,10 +698,32 @@ export function formatElapsed(ms) {
|
|
|
690
698
|
* Developer Cockpit URL, the one next step is framed as "edit a line → see it in
|
|
691
699
|
* your cockpit"; otherwise it's the same edit-to-see-it-reload action.
|
|
692
700
|
*/
|
|
693
|
-
/** @param {string} dir
|
|
694
|
-
function
|
|
701
|
+
/** @param {string} dir */
|
|
702
|
+
function printCheckoutLocation(dir) {
|
|
695
703
|
console.log("");
|
|
696
704
|
console.log(` 📁 Your store code is at: ${dir}`);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Run the checkout and the runner prefetch together, but never let a failed prefetch hide
|
|
709
|
+
* a checkout that succeeded: the code is already on disk, so say where before re-throwing
|
|
710
|
+
* the prefetch error. A failed checkout wins (nothing landed, nothing to point at).
|
|
711
|
+
* @param {Promise<unknown>} checkout
|
|
712
|
+
* @param {Promise<unknown>} runtime
|
|
713
|
+
* @param {{ onRuntimeFailedAfterCheckout: () => void }} hooks
|
|
714
|
+
*/
|
|
715
|
+
export async function settleCheckoutAndRuntime(checkout, runtime, { onRuntimeFailedAfterCheckout }) {
|
|
716
|
+
const [checkedOut, prepared] = await Promise.allSettled([checkout, runtime]);
|
|
717
|
+
if (checkedOut.status === "rejected") throw checkedOut.reason;
|
|
718
|
+
if (prepared.status === "rejected") {
|
|
719
|
+
onRuntimeFailedAfterCheckout();
|
|
720
|
+
throw prepared.reason;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/** @param {string} dir @param {string|null} [cockpitUrl] */
|
|
725
|
+
function printCheckoutLanding(dir, cockpitUrl = null) {
|
|
726
|
+
printCheckoutLocation(dir);
|
|
697
727
|
const where = cockpitUrl ? `your ${DEVELOPER_COCKPIT}` : "your browser";
|
|
698
728
|
console.log(` Next: open it in your editor and change one line in`);
|
|
699
729
|
console.log(` content/home.html — you'll see it reflected in ${where}.`);
|