@taprootio/site-authoring 0.8.4 → 0.8.6
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 +85 -3
- package/examples/riverbend-wellness/settings/taproot-styles.json +2 -188
- package/package.json +1 -1
- package/src/api.js +71 -2
- package/src/cli.js +126 -5
- package/src/constants.js +8 -1
- package/src/delivery-browser.js +276 -0
- package/src/delivery-check.js +821 -0
- package/src/errors.js +12 -1
- package/src/presentation-reference.js +98 -10
- package/src/reference-help.js +118 -1
- package/src/settings-catalog.js +14 -1
- package/src/staging-check.js +9 -0
- package/src/theme-projection.js +213 -0
- package/src/theme-validation.js +64 -4
- package/src/transport.js +20 -2
- package/src/verbs/delivery-check.js +185 -0
- package/src/verbs/deploy.js +88 -3
- package/src/verbs/index.js +6 -0
- package/src/verbs/preview-revoke.js +2 -2
- package/src/verbs/staging-review.js +29 -0
- package/src/verbs/theme-push.js +3 -3
package/README.md
CHANGED
|
@@ -29,6 +29,17 @@ npm install --global @taprootio/site-authoring
|
|
|
29
29
|
taproot-site --help
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
Or run the current release without installing it:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx --yes @taprootio/site-authoring@latest --version
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Always name `@latest` with `npx`: an unversioned `npx @taprootio/site-authoring`
|
|
39
|
+
reuses whatever copy npx cached, which is how a design pass ran an old release.
|
|
40
|
+
`--version` prints what is running; `status` reports the latest known release
|
|
41
|
+
as `cliRelease`, and every online verb refuses an outdated CLI (below).
|
|
42
|
+
|
|
32
43
|
Node 22 or later. The package has one runtime dependency,
|
|
33
44
|
`@taprootio/espalier`, pinned to an exact version: the CLI validates themes
|
|
34
45
|
against one Espalier theme contract, and a floating range would let an install
|
|
@@ -257,6 +268,39 @@ distribution, and every other host is refused before a bearer can be built.
|
|
|
257
268
|
Sign-ins are stored per origin, so switching away and back finds the one that
|
|
258
269
|
was already there.
|
|
259
270
|
|
|
271
|
+
## Design walkthrough
|
|
272
|
+
|
|
273
|
+
`taproot-site help walkthrough` is the self-contained version of this pass;
|
|
274
|
+
each step names the reference it relies on.
|
|
275
|
+
|
|
276
|
+
1. **Select a supported site.** `login`, then `sites` and
|
|
277
|
+
`use <site-name-or-id>`. A standard site takes every verb; a managed Docs
|
|
278
|
+
site takes presentation only (`pull`, `theme push`, `footer push`,
|
|
279
|
+
`media upload`, `deploy`, `status`) because its pages, navigation and
|
|
280
|
+
redirects come from the Docs artifact; a prebuilt Docs site takes no verb.
|
|
281
|
+
2. **Pull and keep the baseline.** `pull` writes both schemes' complete
|
|
282
|
+
effective themes, the appearance files and the footer. Edit that pull;
|
|
283
|
+
never build a theme from memory or an example.
|
|
284
|
+
3. **Edit both schemes and the appearance.** `help theme` lists every field,
|
|
285
|
+
the role slots, how anchor references resolve and what wins when a pin and
|
|
286
|
+
a role disagree; `help appearance` covers the default scheme, header, logos
|
|
287
|
+
and favicon.
|
|
288
|
+
4. **Prepare media locally.** Raster files only (PNG, JPEG, GIF, WebP),
|
|
289
|
+
relative to the workspace root; make the transparent logo, its `@2x` copy,
|
|
290
|
+
a dark-scheme logo when needed and a square favicon with your own tools,
|
|
291
|
+
upload them with `media upload`, then assign `lightLogoId`, `darkLogoId`
|
|
292
|
+
and `brand.faviconId` from the returned ids. There is no recolor, crop or
|
|
293
|
+
SVG upload command.
|
|
294
|
+
5. **Validate, then push.** `validate` runs offline; `theme push` writes the
|
|
295
|
+
footer colours, the appearance scalars and then both themes in that order,
|
|
296
|
+
not atomically, and a failure names `completedWrites` — pull, reconcile,
|
|
297
|
+
push again.
|
|
298
|
+
6. **Review on staging in both schemes.** `deploy --staging` returns a
|
|
299
|
+
single-use handoff in `stagingPreview.url`, on a managed Docs site too;
|
|
300
|
+
open it once and use the site's theme toggle. No page draft is needed;
|
|
301
|
+
`preview page` renders one draft and is a different tool.
|
|
302
|
+
7. **Promote only after review.** `deploy --production`.
|
|
303
|
+
|
|
260
304
|
## The authoring loop
|
|
261
305
|
|
|
262
306
|
```bash
|
|
@@ -292,7 +336,12 @@ moved since this workspace last reconciled with it, naming both revisions;
|
|
|
292
336
|
`media upload [path...]` uploads raster files and records component-ready
|
|
293
337
|
delivery fields. `nav push`, `theme push`, and `footer push` replace the whole
|
|
294
338
|
navigation tree, the complete light/dark theme pair with its appearance
|
|
295
|
-
settings, and the closed footer document. `
|
|
339
|
+
settings, and the closed footer document. `pull` writes each scheme's
|
|
340
|
+
complete effective theme — the stored theme resolved over the same defaults
|
|
341
|
+
every consumer renders — so a fresh workspace validates as pulled, and it
|
|
342
|
+
keeps only authored `semanticMappings` pins (listed in
|
|
343
|
+
`explicitMappingTokens`) because a pinned token shadows its role.
|
|
344
|
+
`redirects pull` writes the site's
|
|
296
345
|
redirect map to `redirects.json` with a baseline, and `redirects push`
|
|
297
346
|
validates the file offline and replaces the whole map; `help redirects`
|
|
298
347
|
states the entry shape (`path`, `kind` redirect or gone, `target`, `status`
|
|
@@ -304,7 +353,10 @@ result. **Each handoff is single-use.** Opening the URL consumes it; a reused,
|
|
|
304
353
|
shared, or bookmarked preview URL answers `Not found`, which is the handoff
|
|
305
354
|
being spent rather than the preview being broken. Run `preview page` again
|
|
306
355
|
for another. The handoff also expires two minutes after it is minted;
|
|
307
|
-
`preview revoke <page-id> <snapshot-id>` releases a preview early.
|
|
356
|
+
`preview revoke <page-id> <snapshot-id>` releases a preview early. It
|
|
357
|
+
addresses the snapshot, so it still works after `approve` has consumed the
|
|
358
|
+
draft; revoking an already revoked snapshot succeeds again, and an unknown or
|
|
359
|
+
cleaned-up snapshot answers `preview.not_found`.
|
|
308
360
|
|
|
309
361
|
`approve [page-path...]` publishes drafts into the approved candidate pool.
|
|
310
362
|
It stages; nothing reaches an audience until `deploy --staging` publishes the
|
|
@@ -406,7 +458,12 @@ with the exact fact field path. A label is optional and stays outside the value'
|
|
|
406
458
|
### Staging verification and deployment evidence
|
|
407
459
|
|
|
408
460
|
`deploy --staging` selects the same changed pages, settings groups and navigation
|
|
409
|
-
as the Deployments page
|
|
461
|
+
as the Deployments page, and returns a single-use staging review handoff in
|
|
462
|
+
`stagingPreview.url` — on a managed Docs site too, where it stages settings
|
|
463
|
+
only: open the URL once, then use the site's theme toggle to review both
|
|
464
|
+
schemes before promoting. When no handoff can be minted, `stagingPreview.reason`
|
|
465
|
+
and `stagingPreview.recovery` say why and what to do next; `staging review`
|
|
466
|
+
mints another on any surface. `status` checks that exact current candidate, so a
|
|
410
467
|
completed CLI stage counts as successful until that candidate changes.
|
|
411
468
|
|
|
412
469
|
A retained failed preview of selected page content refuses deployment as
|
|
@@ -441,6 +498,31 @@ are calculated only between recorded transitions. `truncated` marks missing
|
|
|
441
498
|
older history; `known: false` marks legacy rows. CLI polling never invents phase
|
|
442
499
|
timestamps. Progress reports the same recorded timestamps and durations.
|
|
443
500
|
|
|
501
|
+
### Verify what visitors receive
|
|
502
|
+
|
|
503
|
+
A completed deployment job is not a verified delivery. `delivery check
|
|
504
|
+
(--staging | --production --url https://<published-domain>/)` reads the target
|
|
505
|
+
the way a visitor does and reports each dimension separately: the latest
|
|
506
|
+
completed deployment for the target, HTTP delivery of the authored routes and
|
|
507
|
+
the favicon, images, module preloads and site bundle they declare (status and
|
|
508
|
+
content type, no redirects followed), internal link targets, accidental
|
|
509
|
+
local-only references, and the declared runtime — the major pointer's stream,
|
|
510
|
+
entry and capability modules, and whether the pointer lags the fallback copy
|
|
511
|
+
the site shipped with. The browser dimension (a fresh and a returning load
|
|
512
|
+
compared against the pointer's entry, every document request in the browser,
|
|
513
|
+
popups included, held to the site origin before it is sent, and cache reuse
|
|
514
|
+
on the returning load observed rather than assumed)
|
|
515
|
+
runs only when Playwright resolves from the CLI's own install (install
|
|
516
|
+
`@taprootio/site-authoring` and `playwright` together globally and run the
|
|
517
|
+
installed `taproot-site` command; a copy run through `npx` cannot see a
|
|
518
|
+
global Playwright) and is reported as `unchecked` with that recovery
|
|
519
|
+
otherwise. `--wait <seconds>` re-checks
|
|
520
|
+
failures once for edge propagation; `--no-browser` skips the browser; `--url`
|
|
521
|
+
is a production option, since staging always checks the acknowledged host
|
|
522
|
+
with an authorized preview session. Only same-origin assets and the declared
|
|
523
|
+
runtime are fetched, and the check is read-only and bounded; `help delivery`
|
|
524
|
+
states the limits and verdicts.
|
|
525
|
+
|
|
444
526
|
### Export a pulled workspace as an offline fixture
|
|
445
527
|
|
|
446
528
|
From a pulled workspace (or its configured project), run:
|
|
@@ -256,100 +256,7 @@
|
|
|
256
256
|
"success": 150,
|
|
257
257
|
"warning": 90
|
|
258
258
|
},
|
|
259
|
-
"semanticMappings": {
|
|
260
|
-
"actionBackground": {
|
|
261
|
-
"lightness": "raised3",
|
|
262
|
-
"source": "primary"
|
|
263
|
-
},
|
|
264
|
-
"actionText": {
|
|
265
|
-
"lightness": "ink",
|
|
266
|
-
"source": "primary"
|
|
267
|
-
},
|
|
268
|
-
"background": {
|
|
269
|
-
"lightness": "surface",
|
|
270
|
-
"source": "primary"
|
|
271
|
-
},
|
|
272
|
-
"border": {
|
|
273
|
-
"lightness": "border",
|
|
274
|
-
"source": "primary"
|
|
275
|
-
},
|
|
276
|
-
"dangerText": {
|
|
277
|
-
"lightness": "text",
|
|
278
|
-
"source": "danger"
|
|
279
|
-
},
|
|
280
|
-
"headings": {
|
|
281
|
-
"lightness": "muted",
|
|
282
|
-
"source": "primary"
|
|
283
|
-
},
|
|
284
|
-
"headingsHover": {
|
|
285
|
-
"lightness": "text",
|
|
286
|
-
"source": "primary"
|
|
287
|
-
},
|
|
288
|
-
"inputCaret": {
|
|
289
|
-
"lightness": "ink",
|
|
290
|
-
"source": "triadic-right"
|
|
291
|
-
},
|
|
292
|
-
"inputSelection": {
|
|
293
|
-
"lightness": "text",
|
|
294
|
-
"source": "complementary"
|
|
295
|
-
},
|
|
296
|
-
"inputSelectionBg": {
|
|
297
|
-
"lightness": "raised2",
|
|
298
|
-
"source": "triadic-left"
|
|
299
|
-
},
|
|
300
|
-
"layer1": {
|
|
301
|
-
"lightness": "raised1",
|
|
302
|
-
"source": "primary"
|
|
303
|
-
},
|
|
304
|
-
"layer2": {
|
|
305
|
-
"lightness": "raised2",
|
|
306
|
-
"source": "primary"
|
|
307
|
-
},
|
|
308
|
-
"layer3": {
|
|
309
|
-
"lightness": "raised3",
|
|
310
|
-
"source": "primary"
|
|
311
|
-
},
|
|
312
|
-
"layer4": {
|
|
313
|
-
"lightness": "raised4",
|
|
314
|
-
"source": "primary"
|
|
315
|
-
},
|
|
316
|
-
"link": {
|
|
317
|
-
"lightness": "accent",
|
|
318
|
-
"source": "complementary"
|
|
319
|
-
},
|
|
320
|
-
"linkHover": {
|
|
321
|
-
"lightness": "text",
|
|
322
|
-
"source": "complementary"
|
|
323
|
-
},
|
|
324
|
-
"linkHoverBg": {
|
|
325
|
-
"lightness": "raised2",
|
|
326
|
-
"source": "triadic-left"
|
|
327
|
-
},
|
|
328
|
-
"shadow": {
|
|
329
|
-
"lightness": "shadow",
|
|
330
|
-
"source": "primary"
|
|
331
|
-
},
|
|
332
|
-
"text": {
|
|
333
|
-
"lightness": "text",
|
|
334
|
-
"source": "primary"
|
|
335
|
-
},
|
|
336
|
-
"typeCaption": {
|
|
337
|
-
"lightness": "text",
|
|
338
|
-
"source": "primary"
|
|
339
|
-
},
|
|
340
|
-
"typeLabel": {
|
|
341
|
-
"lightness": "text",
|
|
342
|
-
"source": "primary"
|
|
343
|
-
},
|
|
344
|
-
"typeLead": {
|
|
345
|
-
"lightness": "text",
|
|
346
|
-
"source": "primary"
|
|
347
|
-
},
|
|
348
|
-
"typeOverline": {
|
|
349
|
-
"lightness": "text",
|
|
350
|
-
"source": "primary"
|
|
351
|
-
}
|
|
352
|
-
},
|
|
259
|
+
"semanticMappings": {},
|
|
353
260
|
"spaceRatio": 1.618,
|
|
354
261
|
"stylesheets": [],
|
|
355
262
|
"tones": {},
|
|
@@ -613,100 +520,7 @@
|
|
|
613
520
|
"success": 150,
|
|
614
521
|
"warning": 90
|
|
615
522
|
},
|
|
616
|
-
"semanticMappings": {
|
|
617
|
-
"actionBackground": {
|
|
618
|
-
"lightness": "raised3",
|
|
619
|
-
"source": "primary"
|
|
620
|
-
},
|
|
621
|
-
"actionText": {
|
|
622
|
-
"lightness": "ink",
|
|
623
|
-
"source": "primary"
|
|
624
|
-
},
|
|
625
|
-
"background": {
|
|
626
|
-
"lightness": "surface",
|
|
627
|
-
"source": "primary"
|
|
628
|
-
},
|
|
629
|
-
"border": {
|
|
630
|
-
"lightness": "border",
|
|
631
|
-
"source": "primary"
|
|
632
|
-
},
|
|
633
|
-
"dangerText": {
|
|
634
|
-
"lightness": "text",
|
|
635
|
-
"source": "danger"
|
|
636
|
-
},
|
|
637
|
-
"headings": {
|
|
638
|
-
"lightness": "muted",
|
|
639
|
-
"source": "primary"
|
|
640
|
-
},
|
|
641
|
-
"headingsHover": {
|
|
642
|
-
"lightness": "text",
|
|
643
|
-
"source": "primary"
|
|
644
|
-
},
|
|
645
|
-
"inputCaret": {
|
|
646
|
-
"lightness": "ink",
|
|
647
|
-
"source": "triadic-right"
|
|
648
|
-
},
|
|
649
|
-
"inputSelection": {
|
|
650
|
-
"lightness": "text",
|
|
651
|
-
"source": "complementary"
|
|
652
|
-
},
|
|
653
|
-
"inputSelectionBg": {
|
|
654
|
-
"lightness": "raised2",
|
|
655
|
-
"source": "triadic-left"
|
|
656
|
-
},
|
|
657
|
-
"layer1": {
|
|
658
|
-
"lightness": "raised1",
|
|
659
|
-
"source": "primary"
|
|
660
|
-
},
|
|
661
|
-
"layer2": {
|
|
662
|
-
"lightness": "raised2",
|
|
663
|
-
"source": "primary"
|
|
664
|
-
},
|
|
665
|
-
"layer3": {
|
|
666
|
-
"lightness": "raised3",
|
|
667
|
-
"source": "primary"
|
|
668
|
-
},
|
|
669
|
-
"layer4": {
|
|
670
|
-
"lightness": "raised4",
|
|
671
|
-
"source": "primary"
|
|
672
|
-
},
|
|
673
|
-
"link": {
|
|
674
|
-
"lightness": "accent",
|
|
675
|
-
"source": "complementary"
|
|
676
|
-
},
|
|
677
|
-
"linkHover": {
|
|
678
|
-
"lightness": "text",
|
|
679
|
-
"source": "complementary"
|
|
680
|
-
},
|
|
681
|
-
"linkHoverBg": {
|
|
682
|
-
"lightness": "raised2",
|
|
683
|
-
"source": "triadic-left"
|
|
684
|
-
},
|
|
685
|
-
"shadow": {
|
|
686
|
-
"lightness": "shadow",
|
|
687
|
-
"source": "primary"
|
|
688
|
-
},
|
|
689
|
-
"text": {
|
|
690
|
-
"lightness": "text",
|
|
691
|
-
"source": "primary"
|
|
692
|
-
},
|
|
693
|
-
"typeCaption": {
|
|
694
|
-
"lightness": "text",
|
|
695
|
-
"source": "primary"
|
|
696
|
-
},
|
|
697
|
-
"typeLabel": {
|
|
698
|
-
"lightness": "text",
|
|
699
|
-
"source": "primary"
|
|
700
|
-
},
|
|
701
|
-
"typeLead": {
|
|
702
|
-
"lightness": "text",
|
|
703
|
-
"source": "primary"
|
|
704
|
-
},
|
|
705
|
-
"typeOverline": {
|
|
706
|
-
"lightness": "text",
|
|
707
|
-
"source": "primary"
|
|
708
|
-
}
|
|
709
|
-
},
|
|
523
|
+
"semanticMappings": {},
|
|
710
524
|
"spaceRatio": 1.618,
|
|
711
525
|
"stylesheets": [],
|
|
712
526
|
"tones": {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taprootio/site-authoring",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"description": "Taproot site authoring CLI: sign in once in the browser, then pull, validate, push, preview, approve, and deploy a site from the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "ISC",
|
package/src/api.js
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
CLI_VERSION,
|
|
8
8
|
EXTERNAL_WRITES_SETTING_KEY,
|
|
9
9
|
EXTERNAL_WRITES_SETTING_LOCATION,
|
|
10
|
+
GRPC_NOT_FOUND,
|
|
11
|
+
HTTP_NOT_FOUND,
|
|
10
12
|
LIMITS,
|
|
11
13
|
REFUSAL_CAPABILITY_MISSING,
|
|
12
14
|
REFUSAL_CLI_OUTDATED,
|
|
@@ -101,6 +103,15 @@ export const DEPLOYMENT_STATUSES = Object.freeze([
|
|
|
101
103
|
DEPLOYMENT_STATUS_FAILED,
|
|
102
104
|
]);
|
|
103
105
|
|
|
106
|
+
// DeploySite's admission outcome (TR00839): whether this request created the
|
|
107
|
+
// deployment or coalesced into an already-anchored one.
|
|
108
|
+
export const DEPLOYMENT_REQUEST_OUTCOME_ACCEPTED = "DEPLOYMENT_REQUEST_OUTCOME_ACCEPTED";
|
|
109
|
+
export const DEPLOYMENT_REQUEST_OUTCOME_COALESCED = "DEPLOYMENT_REQUEST_OUTCOME_COALESCED";
|
|
110
|
+
export const DEPLOYMENT_REQUEST_OUTCOMES = Object.freeze([
|
|
111
|
+
DEPLOYMENT_REQUEST_OUTCOME_ACCEPTED,
|
|
112
|
+
DEPLOYMENT_REQUEST_OUTCOME_COALESCED,
|
|
113
|
+
]);
|
|
114
|
+
|
|
104
115
|
export const IMAGE_PROCESSING_STATE_UNKNOWN = "IMAGE_PROCESSING_STATE_UNKNOWN";
|
|
105
116
|
export const IMAGE_PROCESSING_STATE_COMPLETE = "IMAGE_PROCESSING_STATE_COMPLETE";
|
|
106
117
|
export const IMAGE_PROCESSING_STATE_FAILED = "IMAGE_PROCESSING_STATE_FAILED";
|
|
@@ -158,6 +169,7 @@ const AUTHORING_PREVIEW_FIELDS = Object.freeze({
|
|
|
158
169
|
siteCapacity: "AuthoringPreviewCapacity",
|
|
159
170
|
authorityCapacity: "AuthoringPreviewAuthorityCapacity",
|
|
160
171
|
manifest: "AuthoringPreviewManifest",
|
|
172
|
+
snapshot: "AuthoringPreview",
|
|
161
173
|
});
|
|
162
174
|
const AUTHORING_PREVIEW_FIELD_ERRORS = Object.freeze({
|
|
163
175
|
[AUTHORING_PREVIEW_FIELDS.draft]: [
|
|
@@ -348,7 +360,11 @@ const REFUSAL_GUIDANCE = Object.freeze({
|
|
|
348
360
|
[REFUSAL_CREDENTIAL_REJECTED]:
|
|
349
361
|
"The site authoring credential was rejected: it is invalid, revoked, or bound to a different site. "
|
|
350
362
|
+ "Stop and re-issue it; retrying cannot succeed.",
|
|
351
|
-
|
|
363
|
+
// Covers both the per-key request-budget throttle and the durable
|
|
364
|
+
// per-site/per-account deployment request limit (TR00839): both surface as
|
|
365
|
+
// gRPC ResourceExhausted / HTTP 429, and the remedy is identical either way.
|
|
366
|
+
[REFUSAL_THROTTLED]:
|
|
367
|
+
"Too many deployment requests for this site or account. Back off and retry after the delay the server reported.",
|
|
352
368
|
});
|
|
353
369
|
|
|
354
370
|
/**
|
|
@@ -433,6 +449,12 @@ export function announceRefusal(error, onProgress, action = "request") {
|
|
|
433
449
|
}
|
|
434
450
|
const guidance = REFUSAL_GUIDANCE[kind];
|
|
435
451
|
if (guidance) onProgress(guidance);
|
|
452
|
+
// The retry-after trailer (TR00839) is the exact delay the server measured;
|
|
453
|
+
// surface it when the transport captured it rather than leaving the agent
|
|
454
|
+
// to guess a backoff.
|
|
455
|
+
if (kind === REFUSAL_THROTTLED && typeof error.retryAfterSeconds === "number") {
|
|
456
|
+
onProgress(` Retry after: ${error.retryAfterSeconds}s.`);
|
|
457
|
+
}
|
|
436
458
|
}
|
|
437
459
|
|
|
438
460
|
/**
|
|
@@ -1014,6 +1036,9 @@ export function normalizeDeployment(value) {
|
|
|
1014
1036
|
errorMessage: text(deployment.errorMessage),
|
|
1015
1037
|
pageCount: safeCount(deployment.pageCount),
|
|
1016
1038
|
phaseTimings: normalizePhaseTimings(deployment.phaseHistory),
|
|
1039
|
+
// Identical requests coalesced into this deployment inside its settling
|
|
1040
|
+
// window (TR00839). Zero for a deployment that never anchored one.
|
|
1041
|
+
coalescedRequestCount: safeCount(deployment.coalescedRequestCount),
|
|
1017
1042
|
};
|
|
1018
1043
|
}
|
|
1019
1044
|
|
|
@@ -1071,7 +1096,19 @@ export async function deploySite(client, siteId, body) {
|
|
|
1071
1096
|
}
|
|
1072
1097
|
throw error;
|
|
1073
1098
|
}
|
|
1074
|
-
|
|
1099
|
+
const deployment = normalizeDeployment(response.deployment);
|
|
1100
|
+
// `DEPLOYMENT_REQUEST_OUTCOME_ACCEPTED` is the zero-adjacent default: an
|
|
1101
|
+
// older server that omits the field, or the immutable Standard/Docs
|
|
1102
|
+
// branches that never run through the admission seam, both read as this
|
|
1103
|
+
// request creating its own deployment (TR00839).
|
|
1104
|
+
const outcome = enumValue(
|
|
1105
|
+
response.outcome,
|
|
1106
|
+
DEPLOYMENT_REQUEST_OUTCOMES,
|
|
1107
|
+
DEPLOYMENT_REQUEST_OUTCOME_ACCEPTED,
|
|
1108
|
+
"api.deployment_contract",
|
|
1109
|
+
"deployment request outcome",
|
|
1110
|
+
);
|
|
1111
|
+
return { ...deployment, outcome };
|
|
1075
1112
|
}
|
|
1076
1113
|
|
|
1077
1114
|
/**
|
|
@@ -1924,6 +1961,38 @@ export async function claimCliAuthorization(client, deviceCode, requestOptions =
|
|
|
1924
1961
|
}
|
|
1925
1962
|
|
|
1926
1963
|
/** Maps only preview-domain validation fields; authentication/refusal identity stays an ApiError. */
|
|
1964
|
+
/**
|
|
1965
|
+
* Revocation addresses one snapshot, so its refusals are snapshot outcomes.
|
|
1966
|
+
* A NotFound (the page or the snapshot is not available to this caller on
|
|
1967
|
+
* this site) and the server's in-transaction `AuthoringPreview` unavailability
|
|
1968
|
+
* both become `preview.not_found`; the wording never distinguishes another
|
|
1969
|
+
* caller's snapshot from a missing one, mirroring the server. A snapshot that
|
|
1970
|
+
* is already revoked is not an error at all: the server answers REVOKED and
|
|
1971
|
+
* the verb reports that idempotent success. Every other refusal keeps the
|
|
1972
|
+
* shared preview translation (TR00773).
|
|
1973
|
+
*/
|
|
1974
|
+
export function translateAuthoringPreviewRevokeApiError(error) {
|
|
1975
|
+
if (!(error instanceof ApiError) || error.refusalKind() !== REFUSAL_UNCLASSIFIED) return error;
|
|
1976
|
+
if (
|
|
1977
|
+
error.httpStatus === HTTP_NOT_FOUND || error.grpcCode === GRPC_NOT_FOUND
|
|
1978
|
+
|| error.hasField(AUTHORING_PREVIEW_FIELDS.snapshot)
|
|
1979
|
+
) {
|
|
1980
|
+
return new SiteAuthoringError(
|
|
1981
|
+
"preview.not_found",
|
|
1982
|
+
"No authoring preview with that snapshot ID is available for that page on this site. It may have expired "
|
|
1983
|
+
+ "and been cleaned up, or the IDs may belong to another page or site; a snapshot that was already revoked "
|
|
1984
|
+
+ "reports a successful revocation instead.",
|
|
1985
|
+
// A NotFound can name the page as readily as the snapshot, so only the
|
|
1986
|
+
// in-transaction snapshot refusal pins the field a caller should fix.
|
|
1987
|
+
{
|
|
1988
|
+
...(error.hasField(AUTHORING_PREVIEW_FIELDS.snapshot) ? { field: "snapshotId" } : {}),
|
|
1989
|
+
status: error.status,
|
|
1990
|
+
},
|
|
1991
|
+
);
|
|
1992
|
+
}
|
|
1993
|
+
return translateAuthoringPreviewApiError(error);
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1927
1996
|
export function translateAuthoringPreviewApiError(error) {
|
|
1928
1997
|
if (!(error instanceof ApiError) || error.refusalKind() !== REFUSAL_UNCLASSIFIED) return error;
|
|
1929
1998
|
for (const [field, [code, message]] of Object.entries(AUTHORING_PREVIEW_FIELD_ERRORS)) {
|