payload-live-preview 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.
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Stable identifiers for everything the runtime reports.
3
+ *
4
+ * Prose gets reworded; a code does not. A consumer filtering logs, an alert
5
+ * rule, or a bug report referring to `LP0301` keeps meaning the same thing
6
+ * after the sentence around it is rewritten, and a code is greppable in a way
7
+ * that a sentence fragment is not.
8
+ *
9
+ * Codes are grouped by the question they answer:
10
+ *
11
+ * - `LP01xx` — configuration and origin trust: the runtime is running, but it
12
+ * was set up in a way that will bite.
13
+ * - `LP02xx` — bindings and markup: an update had nowhere to land.
14
+ * - `LP03xx` — updates and scheduling: the update landed somewhere other than
15
+ * the DOM, or not yet.
16
+ * - `LP04xx` — rendering: a value reached an element and was refused.
17
+ * - `LP05xx` — protocol and messages: something arrived that was not accepted.
18
+ * - `LP06xx` — consumer callbacks: code the consumer supplied threw.
19
+ * - `LP07xx` — audit findings from `pll doctor`, which reports on a served
20
+ * response rather than on a running runtime.
21
+ *
22
+ * A code is part of the public contract. Codes are never reused for a
23
+ * different meaning and never renumbered; a retired code stays retired.
24
+ * `LP0604` is unassigned: a throwing token validator is deliberately treated
25
+ * as a rejection and reported as `LP0502`, so there is nothing distinct to
26
+ * report yet. The number stays reserved rather than being handed to something
27
+ * else.
28
+ *
29
+ * The runtime writes these as string literals at each reporting site rather
30
+ * than reading them from this record, so the inline build pays for the six
31
+ * characters it prints and nothing more. This record exists so consumers can
32
+ * refer to a code by name instead of copying a literal.
33
+ *
34
+ * @module @core/diagnostic-codes
35
+ */
36
+ /**
37
+ * Every diagnostic code the runtime can report, by name.
38
+ *
39
+ * ```ts
40
+ * client.events.on('error', (e) => {
41
+ * if (e.code === DIAGNOSTIC_CODES.TransformThrew) reportToSentry(e.error);
42
+ * });
43
+ * ```
44
+ */
45
+ declare const DIAGNOSTIC_CODES: Readonly<{
46
+ /** No trusted origin configured in production; nothing will be accepted. */
47
+ readonly NoTrustedOrigin: "LP0101";
48
+ /** Origin trust rests on `document.referrer`, so any framing site is trusted. */
49
+ readonly ReferrerOnlyTrust: "LP0102";
50
+ /** An update named a field with no binding anchor on the page. */
51
+ readonly OrphanField: "LP0201";
52
+ /** Owner scoping is on and the update names no document it could belong to. */
53
+ readonly UnattributableUpdate: "LP0202";
54
+ /** The visibility gate held offscreen writes back until they scroll into view. */
55
+ readonly VisibilityGateDeferred: "LP0301";
56
+ /** A value was refused because the attribute or the value itself is unsafe. */
57
+ readonly UnsafeAttributeWrite: "LP0401";
58
+ /** A text element has structured children, so replacing its text was skipped. */
59
+ readonly TextTargetHasChildren: "LP0402";
60
+ /** A structural container has no array template, so the update was skipped. */
61
+ readonly MissingArrayTemplate: "LP0403";
62
+ /** A message was rejected before it reached the update pipeline. */
63
+ readonly MessageRejected: "LP0501";
64
+ /** A preview token was rejected. */
65
+ readonly TokenRejected: "LP0502";
66
+ /** A consumer event handler threw. */
67
+ readonly HandlerThrew: "LP0601";
68
+ /** A consumer transform threw; the original value was kept. */
69
+ readonly TransformThrew: "LP0602";
70
+ /** A renderer threw while writing a value. */
71
+ readonly RendererThrew: "LP0603";
72
+ /** Runtime startup failed. */
73
+ readonly StartupFailed: "LP0605";
74
+ /** Sending the ready handshake failed. */
75
+ readonly ReadyFailed: "LP0606";
76
+ /** The audit found no runtime in a response that carried preview intent. */
77
+ readonly AuditRuntimeMissing: "LP0701";
78
+ /** The preview response declares no `frame-ancestors`. */
79
+ readonly AuditNoFrameAncestors: "LP0702";
80
+ /** `X-Frame-Options` forbids framing, which no CSP can undo. */
81
+ readonly AuditFrameOptionsBlocks: "LP0703";
82
+ /** Binding attributes are served to anonymous visitors. */
83
+ readonly AuditBindingsExposed: "LP0704";
84
+ /** More bindings than the default visibility gate will write eagerly. */
85
+ readonly AuditGateThresholdExceeded: "LP0705";
86
+ /** Owner markers exist, but some bindings are outside all of them. */
87
+ readonly AuditUnownedBindings: "LP0706";
88
+ /** The preview response carries no bindings at all. */
89
+ readonly AuditNoBindings: "LP0707";
90
+ /** The URL did not return an HTML page, so nothing else can be judged. */
91
+ readonly AuditNotAPage: "LP0708";
92
+ }>;
93
+ /** A diagnostic code, as it appears in log output and on the `error` event. */
94
+ type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[keyof typeof DIAGNOSTIC_CODES];
95
+
96
+ /**
97
+ * Shapes for the `pll doctor` audit.
98
+ *
99
+ * This module is types only.
100
+ *
101
+ * @module @doctor/types
102
+ */
103
+
104
+ /** How much a finding should worry the reader. */
105
+ type DoctorLevel = 'error' | 'warning' | 'info';
106
+ /** One thing the audit noticed about what the site actually served. */
107
+ interface DoctorFinding {
108
+ readonly code: DiagnosticCode;
109
+ readonly level: DoctorLevel;
110
+ /** One line, the problem itself. */
111
+ readonly title: string;
112
+ /** What was observed, in terms of the actual response. */
113
+ readonly detail: string;
114
+ /** What to change. Empty for informational findings that need no action. */
115
+ readonly remedy: string;
116
+ }
117
+ /**
118
+ * A response as the audit needs to see it. Modelled as plain data rather than
119
+ * a `Response` so the analysis is testable without a network or a fetch
120
+ * implementation.
121
+ */
122
+ interface DoctorResponse {
123
+ readonly status: number;
124
+ /** Header names lowercased. */
125
+ readonly headers: Readonly<Record<string, string>>;
126
+ readonly body: string;
127
+ }
128
+ /** The two fetches the audit compares. */
129
+ interface DoctorProbe {
130
+ /**
131
+ * The page as an ordinary visitor sees it: no preview intent, no admin
132
+ * referer, top-level navigation.
133
+ */
134
+ readonly publicResponse: DoctorResponse;
135
+ /**
136
+ * The same page requested the way the admin's iframe requests it, which is
137
+ * what triggers `'preview-only'` injection.
138
+ */
139
+ readonly previewResponse: DoctorResponse;
140
+ }
141
+ /** What the audit was told about the deployment it is checking. */
142
+ interface DoctorContext {
143
+ /** The page that was probed. */
144
+ readonly url: string;
145
+ /**
146
+ * The admin origin the preview is supposed to be embedded from, when the
147
+ * caller supplied one. Without it the `frame-ancestors` check can only say
148
+ * whether a policy exists, not whether it admits the right origin.
149
+ */
150
+ readonly adminOrigin?: string | undefined;
151
+ }
152
+ /** The complete audit result. */
153
+ interface DoctorReport {
154
+ readonly url: string;
155
+ /** Findings, most severe first. */
156
+ readonly findings: readonly DoctorFinding[];
157
+ /** Counts by level, for the exit code and the summary line. */
158
+ readonly errors: number;
159
+ readonly warnings: number;
160
+ }
161
+
162
+ /** Injectable so tests can drive the audit without a server. */
163
+ type DoctorFetch = (url: string, init: {
164
+ readonly headers: Readonly<Record<string, string>>;
165
+ }) => Promise<DoctorResponse>;
166
+ interface RunDoctorOptions {
167
+ readonly url: string;
168
+ /** Admin origin the preview is meant to be embedded from, when known. */
169
+ readonly adminOrigin?: string | undefined;
170
+ /** Defaults to `globalThis.fetch`. */
171
+ readonly fetchImpl?: DoctorFetch | undefined;
172
+ }
173
+ /**
174
+ * Normalise header names to lowercase.
175
+ *
176
+ * Exported because every header check downstream reads a lowercase key: if
177
+ * this were wrong, `content-security-policy` and `x-frame-options` would both
178
+ * read as absent and the audit would invent findings rather than report them.
179
+ * A silent failure of exactly that shape is worth a test of its own.
180
+ */
181
+ declare function lowercaseHeaders(headers: Headers): Record<string, string>;
182
+ /**
183
+ * Fetch the URL twice — as a visitor and as the admin's iframe — and audit the
184
+ * difference.
185
+ */
186
+ declare function runDoctor(options: RunDoctorOptions): Promise<DoctorReport>;
187
+ /** Render a report for a terminal. */
188
+ declare function formatReport(report: DoctorReport): string;
189
+
190
+ export { type DoctorFetch as D, type RunDoctorOptions as R, type DoctorProbe as a, type DoctorContext as b, type DoctorReport as c, DIAGNOSTIC_CODES as d, type DiagnosticCode as e, type DoctorFinding as f, type DoctorLevel as g, type DoctorResponse as h, formatReport as i, lowercaseHeaders as l, runDoctor as r };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-live-preview",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Live preview for Payload CMS in Astro and any SSR/static frontend (SvelteKit, Nuxt, Next.js, plain HTML). Patches the DOM live, no rebuild.",
5
5
  "author": "relative23",
6
6
  "license": "MIT",
@@ -70,6 +70,12 @@
70
70
  "default": "./dist/codegen-astro.js"
71
71
  }
72
72
  },
73
+ "./doctor": {
74
+ "import": {
75
+ "types": "./dist/doctor.d.ts",
76
+ "default": "./dist/doctor.js"
77
+ }
78
+ },
73
79
  "./payload": {
74
80
  "import": {
75
81
  "types": "./dist/payload.d.ts",
@@ -89,7 +95,8 @@
89
95
  }
90
96
  },
91
97
  "bin": {
92
- "pll-codegen": "./dist/codegen-cli.js"
98
+ "pll-codegen": "./dist/codegen-cli.js",
99
+ "pll": "./dist/doctor-cli.js"
93
100
  },
94
101
  "files": [
95
102
  "dist",