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.
- package/README.md +112 -2
- package/dist/adapters/astro/index.js +1 -1
- package/dist/adapters/astro/index.js.map +1 -1
- package/dist/adapters/astro/middleware-entry.js +1 -1
- package/dist/adapters/astro/middleware-entry.js.map +1 -1
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/adapters/nextjs/index.js.map +1 -1
- package/dist/adapters/nuxt/index.js +1 -1
- package/dist/adapters/nuxt/index.js.map +1 -1
- package/dist/adapters/sveltekit/index.js +1 -1
- package/dist/adapters/sveltekit/index.js.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +247 -2
- package/dist/core.d.ts +247 -2
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/doctor-cli.d.ts +34 -0
- package/dist/doctor-cli.js +3 -0
- package/dist/doctor-cli.js.map +1 -0
- package/dist/doctor.d.ts +37 -0
- package/dist/doctor.js +2 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +248 -3
- package/dist/index.d.ts +248 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/probe-tMHdim5y.d.ts +190 -0
- package/package.json +9 -2
package/dist/core.d.cts
CHANGED
|
@@ -1,3 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection state + heartbeat.
|
|
3
|
+
*
|
|
4
|
+
* Tracks whether the runtime is currently receiving updates from a
|
|
5
|
+
* trusted origin and fires a callback when the heartbeat times out.
|
|
6
|
+
*
|
|
7
|
+
* The heartbeat is reset on every valid message and considered dead
|
|
8
|
+
* after `timeoutMs` of silence. The host typically responds by
|
|
9
|
+
* re-sending the `ready` handshake to attempt reconnection.
|
|
10
|
+
*
|
|
11
|
+
* @module @core/state
|
|
12
|
+
*/
|
|
13
|
+
type ConnectionStatus = 'disconnected' | 'connecting' | 'connected';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The shape of a live-preview inspection snapshot.
|
|
17
|
+
*
|
|
18
|
+
* This module is types only. The snapshot is assembled by
|
|
19
|
+
* `LivePreviewRuntime.inspect()` as a plain object literal, because the inline
|
|
20
|
+
* runtime pays for every byte of indirection and the assembly needs access to
|
|
21
|
+
* internal state the runtime does not otherwise expose.
|
|
22
|
+
*
|
|
23
|
+
* A snapshot is a read of what the runtime already holds. It discloses nothing
|
|
24
|
+
* that is not already observable on the page: the trusted origins are inside
|
|
25
|
+
* the injected script, the field names are `data-payload-field` attributes in
|
|
26
|
+
* the DOM, and the counters are derived from those. It is therefore available
|
|
27
|
+
* in production rather than gated to development builds — a preview that
|
|
28
|
+
* misbehaves only on the deployed site is exactly the case where the
|
|
29
|
+
* information is worth having, and a development-only gate would withhold it
|
|
30
|
+
* there.
|
|
31
|
+
*
|
|
32
|
+
* Nothing here is transmitted anywhere. Reading a snapshot performs no I/O.
|
|
33
|
+
*
|
|
34
|
+
* @module @core/inspection/types
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** Origin trust as the runtime currently sees it. */
|
|
38
|
+
interface InspectionOrigins {
|
|
39
|
+
/**
|
|
40
|
+
* Origins the runtime is willing to accept messages from, as configured.
|
|
41
|
+
* An empty list means no explicit allow-list was given, which is the
|
|
42
|
+
* condition under which referrer and localhost heuristics decide instead.
|
|
43
|
+
*/
|
|
44
|
+
readonly trusted: readonly string[];
|
|
45
|
+
/**
|
|
46
|
+
* The origin the runtime locked onto after its first accepted update, or
|
|
47
|
+
* `undefined` while still unlocked. Once locked, every other origin is
|
|
48
|
+
* refused for the rest of the session.
|
|
49
|
+
*/
|
|
50
|
+
readonly locked: string | undefined;
|
|
51
|
+
}
|
|
52
|
+
/** Protocol versions and the capabilities they enable. */
|
|
53
|
+
interface InspectionProtocol {
|
|
54
|
+
/** This library's protocol version. */
|
|
55
|
+
readonly ours: number;
|
|
56
|
+
/** The remote party's version, or `undefined` if it never announced one. */
|
|
57
|
+
readonly theirs: number | undefined;
|
|
58
|
+
/** `min(ours, theirs ?? 1)` — what both sides actually share. */
|
|
59
|
+
readonly negotiated: number;
|
|
60
|
+
/** Capability flags enabled at the negotiated version. */
|
|
61
|
+
readonly capabilities: readonly string[];
|
|
62
|
+
}
|
|
63
|
+
/** Revision accounting for the update pipeline. */
|
|
64
|
+
interface InspectionRevisions {
|
|
65
|
+
/** Updates accepted since the runtime started. */
|
|
66
|
+
readonly accepted: number;
|
|
67
|
+
/**
|
|
68
|
+
* Updates that were still in flight when a newer one arrived and were
|
|
69
|
+
* therefore abandoned. A number that tracks `accepted` closely means the
|
|
70
|
+
* editor is out-typing the pipeline, which is normal; it is only a problem
|
|
71
|
+
* when the last update is among the abandoned ones.
|
|
72
|
+
*/
|
|
73
|
+
readonly superseded: number;
|
|
74
|
+
/** Revision currently in flight, or `undefined` when the pipeline is idle. */
|
|
75
|
+
readonly active: number | undefined;
|
|
76
|
+
}
|
|
77
|
+
/** What the DOM offers the runtime to write into. */
|
|
78
|
+
interface InspectionBindings {
|
|
79
|
+
/** Elements carrying a binding. */
|
|
80
|
+
readonly elements: number;
|
|
81
|
+
/** Distinct field names across those elements. */
|
|
82
|
+
readonly fields: number;
|
|
83
|
+
/** Those field names, sorted. */
|
|
84
|
+
readonly fieldNames: readonly string[];
|
|
85
|
+
/**
|
|
86
|
+
* Field names that arrived in an update but matched no binding, as far as
|
|
87
|
+
* the runtime has observed. This is the list to read when a field refuses
|
|
88
|
+
* to update: a name here is a markup problem, a name absent from here and
|
|
89
|
+
* from `fieldNames` was never sent.
|
|
90
|
+
*/
|
|
91
|
+
readonly orphanFields: readonly string[];
|
|
92
|
+
/** Whether `scopeBindingsByOwner` is active. */
|
|
93
|
+
readonly ownerScoped: boolean;
|
|
94
|
+
/** Distinct document owners currently on the page, sorted. */
|
|
95
|
+
readonly owners: readonly string[];
|
|
96
|
+
}
|
|
97
|
+
/** Scheduler work in progress. */
|
|
98
|
+
interface InspectionScheduler {
|
|
99
|
+
/** Writes buffered for the next flush. */
|
|
100
|
+
readonly pending: number;
|
|
101
|
+
/**
|
|
102
|
+
* Writes held back because their element is offscreen and the binding count
|
|
103
|
+
* is above `visibilityGateThreshold`. These are applied when the element
|
|
104
|
+
* scrolls into view — never, on a page nobody scrolls.
|
|
105
|
+
*/
|
|
106
|
+
readonly deferred: number;
|
|
107
|
+
/** The binding count above which the visibility gate starts deferring. */
|
|
108
|
+
readonly visibilityGateThreshold: number;
|
|
109
|
+
/** Whether the binding count is above that threshold right now. */
|
|
110
|
+
readonly visibilityGateActive: boolean;
|
|
111
|
+
/** Stats of the most recent flush, or `undefined` if none has run. */
|
|
112
|
+
readonly lastFlush: {
|
|
113
|
+
readonly applied: number;
|
|
114
|
+
readonly deferred: number;
|
|
115
|
+
readonly durationMs: number;
|
|
116
|
+
} | undefined;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* A point-in-time read of runtime state, for diagnosing a preview that is not
|
|
120
|
+
* behaving. Every field is a plain value; the snapshot holds no references
|
|
121
|
+
* into runtime internals and does not change after it is returned.
|
|
122
|
+
*/
|
|
123
|
+
interface LivePreviewInspection {
|
|
124
|
+
/** Package version that produced this snapshot. */
|
|
125
|
+
readonly version: string;
|
|
126
|
+
/** Whether the runtime is started, and whether it has been destroyed. */
|
|
127
|
+
readonly started: boolean;
|
|
128
|
+
/** Connection status as reported to the `connect`/`disconnect` events. */
|
|
129
|
+
readonly status: ConnectionStatus;
|
|
130
|
+
readonly origins: InspectionOrigins;
|
|
131
|
+
readonly protocol: InspectionProtocol;
|
|
132
|
+
readonly revisions: InspectionRevisions;
|
|
133
|
+
readonly bindings: InspectionBindings;
|
|
134
|
+
readonly scheduler: InspectionScheduler;
|
|
135
|
+
/** Field types with a registered renderer, sorted. */
|
|
136
|
+
readonly renderers: readonly string[];
|
|
137
|
+
}
|
|
138
|
+
|
|
1
139
|
/**
|
|
2
140
|
* Payload Live Preview message protocol.
|
|
3
141
|
*
|
|
@@ -113,6 +251,101 @@ type PayloadFieldType = 'text' | 'textarea' | 'richText' | 'email' | 'number' |
|
|
|
113
251
|
*/
|
|
114
252
|
type PayloadFieldCondition = (data: unknown, siblingData: unknown) => boolean;
|
|
115
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Stable identifiers for everything the runtime reports.
|
|
256
|
+
*
|
|
257
|
+
* Prose gets reworded; a code does not. A consumer filtering logs, an alert
|
|
258
|
+
* rule, or a bug report referring to `LP0301` keeps meaning the same thing
|
|
259
|
+
* after the sentence around it is rewritten, and a code is greppable in a way
|
|
260
|
+
* that a sentence fragment is not.
|
|
261
|
+
*
|
|
262
|
+
* Codes are grouped by the question they answer:
|
|
263
|
+
*
|
|
264
|
+
* - `LP01xx` — configuration and origin trust: the runtime is running, but it
|
|
265
|
+
* was set up in a way that will bite.
|
|
266
|
+
* - `LP02xx` — bindings and markup: an update had nowhere to land.
|
|
267
|
+
* - `LP03xx` — updates and scheduling: the update landed somewhere other than
|
|
268
|
+
* the DOM, or not yet.
|
|
269
|
+
* - `LP04xx` — rendering: a value reached an element and was refused.
|
|
270
|
+
* - `LP05xx` — protocol and messages: something arrived that was not accepted.
|
|
271
|
+
* - `LP06xx` — consumer callbacks: code the consumer supplied threw.
|
|
272
|
+
* - `LP07xx` — audit findings from `pll doctor`, which reports on a served
|
|
273
|
+
* response rather than on a running runtime.
|
|
274
|
+
*
|
|
275
|
+
* A code is part of the public contract. Codes are never reused for a
|
|
276
|
+
* different meaning and never renumbered; a retired code stays retired.
|
|
277
|
+
* `LP0604` is unassigned: a throwing token validator is deliberately treated
|
|
278
|
+
* as a rejection and reported as `LP0502`, so there is nothing distinct to
|
|
279
|
+
* report yet. The number stays reserved rather than being handed to something
|
|
280
|
+
* else.
|
|
281
|
+
*
|
|
282
|
+
* The runtime writes these as string literals at each reporting site rather
|
|
283
|
+
* than reading them from this record, so the inline build pays for the six
|
|
284
|
+
* characters it prints and nothing more. This record exists so consumers can
|
|
285
|
+
* refer to a code by name instead of copying a literal.
|
|
286
|
+
*
|
|
287
|
+
* @module @core/diagnostic-codes
|
|
288
|
+
*/
|
|
289
|
+
/**
|
|
290
|
+
* Every diagnostic code the runtime can report, by name.
|
|
291
|
+
*
|
|
292
|
+
* ```ts
|
|
293
|
+
* client.events.on('error', (e) => {
|
|
294
|
+
* if (e.code === DIAGNOSTIC_CODES.TransformThrew) reportToSentry(e.error);
|
|
295
|
+
* });
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
declare const DIAGNOSTIC_CODES: Readonly<{
|
|
299
|
+
/** No trusted origin configured in production; nothing will be accepted. */
|
|
300
|
+
readonly NoTrustedOrigin: "LP0101";
|
|
301
|
+
/** Origin trust rests on `document.referrer`, so any framing site is trusted. */
|
|
302
|
+
readonly ReferrerOnlyTrust: "LP0102";
|
|
303
|
+
/** An update named a field with no binding anchor on the page. */
|
|
304
|
+
readonly OrphanField: "LP0201";
|
|
305
|
+
/** Owner scoping is on and the update names no document it could belong to. */
|
|
306
|
+
readonly UnattributableUpdate: "LP0202";
|
|
307
|
+
/** The visibility gate held offscreen writes back until they scroll into view. */
|
|
308
|
+
readonly VisibilityGateDeferred: "LP0301";
|
|
309
|
+
/** A value was refused because the attribute or the value itself is unsafe. */
|
|
310
|
+
readonly UnsafeAttributeWrite: "LP0401";
|
|
311
|
+
/** A text element has structured children, so replacing its text was skipped. */
|
|
312
|
+
readonly TextTargetHasChildren: "LP0402";
|
|
313
|
+
/** A structural container has no array template, so the update was skipped. */
|
|
314
|
+
readonly MissingArrayTemplate: "LP0403";
|
|
315
|
+
/** A message was rejected before it reached the update pipeline. */
|
|
316
|
+
readonly MessageRejected: "LP0501";
|
|
317
|
+
/** A preview token was rejected. */
|
|
318
|
+
readonly TokenRejected: "LP0502";
|
|
319
|
+
/** A consumer event handler threw. */
|
|
320
|
+
readonly HandlerThrew: "LP0601";
|
|
321
|
+
/** A consumer transform threw; the original value was kept. */
|
|
322
|
+
readonly TransformThrew: "LP0602";
|
|
323
|
+
/** A renderer threw while writing a value. */
|
|
324
|
+
readonly RendererThrew: "LP0603";
|
|
325
|
+
/** Runtime startup failed. */
|
|
326
|
+
readonly StartupFailed: "LP0605";
|
|
327
|
+
/** Sending the ready handshake failed. */
|
|
328
|
+
readonly ReadyFailed: "LP0606";
|
|
329
|
+
/** The audit found no runtime in a response that carried preview intent. */
|
|
330
|
+
readonly AuditRuntimeMissing: "LP0701";
|
|
331
|
+
/** The preview response declares no `frame-ancestors`. */
|
|
332
|
+
readonly AuditNoFrameAncestors: "LP0702";
|
|
333
|
+
/** `X-Frame-Options` forbids framing, which no CSP can undo. */
|
|
334
|
+
readonly AuditFrameOptionsBlocks: "LP0703";
|
|
335
|
+
/** Binding attributes are served to anonymous visitors. */
|
|
336
|
+
readonly AuditBindingsExposed: "LP0704";
|
|
337
|
+
/** More bindings than the default visibility gate will write eagerly. */
|
|
338
|
+
readonly AuditGateThresholdExceeded: "LP0705";
|
|
339
|
+
/** Owner markers exist, but some bindings are outside all of them. */
|
|
340
|
+
readonly AuditUnownedBindings: "LP0706";
|
|
341
|
+
/** The preview response carries no bindings at all. */
|
|
342
|
+
readonly AuditNoBindings: "LP0707";
|
|
343
|
+
/** The URL did not return an HTML page, so nothing else can be judged. */
|
|
344
|
+
readonly AuditNotAPage: "LP0708";
|
|
345
|
+
}>;
|
|
346
|
+
/** A diagnostic code, as it appears in log output and on the `error` event. */
|
|
347
|
+
type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[keyof typeof DIAGNOSTIC_CODES];
|
|
348
|
+
|
|
116
349
|
/**
|
|
117
350
|
* Public event payload shapes for the live preview lifecycle.
|
|
118
351
|
*
|
|
@@ -193,11 +426,14 @@ interface LivePreviewEventMap {
|
|
|
193
426
|
/**
|
|
194
427
|
* Fired on errors that the runtime caught but cannot fully recover from.
|
|
195
428
|
*
|
|
196
|
-
* The `context` string identifies where the error originated.
|
|
429
|
+
* The `context` string identifies where the error originated. `code` says
|
|
430
|
+
* the same thing in a form that survives rewording — branch on `code`, read
|
|
431
|
+
* `context` when you want the human-readable origin.
|
|
197
432
|
*/
|
|
198
433
|
readonly error: {
|
|
199
434
|
readonly error: Error;
|
|
200
435
|
readonly context: string;
|
|
436
|
+
readonly code: DiagnosticCode;
|
|
201
437
|
};
|
|
202
438
|
/**
|
|
203
439
|
* Fired during destroy after browser observers and the message listener are
|
|
@@ -657,6 +893,15 @@ declare class LivePreviewClient {
|
|
|
657
893
|
/** Current connection status. */
|
|
658
894
|
get status(): 'disconnected' | 'connecting' | 'connected';
|
|
659
895
|
/** Number of valid updates received so far. */
|
|
896
|
+
/**
|
|
897
|
+
* Point-in-time read of runtime state, for diagnosing a preview that is not
|
|
898
|
+
* updating. Performs no I/O and transmits nothing.
|
|
899
|
+
*
|
|
900
|
+
* Read `bindings.orphanFields` when a field refuses to update, and
|
|
901
|
+
* `scheduler.deferred` together with `scheduler.visibilityGateActive` when
|
|
902
|
+
* updates stop below the fold.
|
|
903
|
+
*/
|
|
904
|
+
inspect(): LivePreviewInspection;
|
|
660
905
|
get updateCount(): number;
|
|
661
906
|
/** `true` once `destroy()` has been called. */
|
|
662
907
|
get destroyed(): boolean;
|
|
@@ -1364,4 +1609,4 @@ declare function createPreviewBindings(options: PreviewBindingsOptions): Preview
|
|
|
1364
1609
|
|
|
1365
1610
|
declare const CORE_ENTRY = true;
|
|
1366
1611
|
|
|
1367
|
-
export { type BindOptions, CORE_ENTRY, type CachedElement, EventEmitter, type EventHandler, type FieldBindingAttributes, type FieldName, type FieldPath, type FieldRenderer, type FieldType, type FrameAncestorsOptions, LIBRARY_PROTOCOL_VERSION, LivePreviewClient, type LivePreviewClientConfig, type LivePreviewEventMap, OriginDetector, type OwnerBindingAttributes, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PayloadLivePreviewMessage, type PreviewBindings, type PreviewBindingsOptions, type ProtocolCapability, type ProtocolNegotiation, type RenderContext, type SanitizerDocument, type SuppressedBinding, type Unsubscribe, VERSION, type ValueAt, bind, bindByPath, buildFrameAncestors, buildScriptSrcWithNonce, createPreviewBindings, detectInitialLocale, escapeHtml, escapeHtmlAttribute, generateCspNonce, hasCapability, initLivePreview, isDevMode, isExternalHttpUrl, isInIframe, isInPopup, isInPreviewContext, isSafeUrl, negotiateProtocol, sanitizeHtml, setCspCrypto, setSanitizerDocument };
|
|
1612
|
+
export { type BindOptions, CORE_ENTRY, type CachedElement, type ConnectionStatus, DIAGNOSTIC_CODES, type DiagnosticCode, EventEmitter, type EventHandler, type FieldBindingAttributes, type FieldName, type FieldPath, type FieldRenderer, type FieldType, type FrameAncestorsOptions, type InspectionBindings, type InspectionOrigins, type InspectionProtocol, type InspectionRevisions, type InspectionScheduler, LIBRARY_PROTOCOL_VERSION, LivePreviewClient, type LivePreviewClientConfig, type LivePreviewEventMap, type LivePreviewInspection, OriginDetector, type OwnerBindingAttributes, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PayloadLivePreviewMessage, type PreviewBindings, type PreviewBindingsOptions, type ProtocolCapability, type ProtocolNegotiation, type RenderContext, type SanitizerDocument, type SuppressedBinding, type Unsubscribe, VERSION, type ValueAt, bind, bindByPath, buildFrameAncestors, buildScriptSrcWithNonce, createPreviewBindings, detectInitialLocale, escapeHtml, escapeHtmlAttribute, generateCspNonce, hasCapability, initLivePreview, isDevMode, isExternalHttpUrl, isInIframe, isInPopup, isInPreviewContext, isSafeUrl, negotiateProtocol, sanitizeHtml, setCspCrypto, setSanitizerDocument };
|
package/dist/core.d.ts
CHANGED
|
@@ -1,3 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection state + heartbeat.
|
|
3
|
+
*
|
|
4
|
+
* Tracks whether the runtime is currently receiving updates from a
|
|
5
|
+
* trusted origin and fires a callback when the heartbeat times out.
|
|
6
|
+
*
|
|
7
|
+
* The heartbeat is reset on every valid message and considered dead
|
|
8
|
+
* after `timeoutMs` of silence. The host typically responds by
|
|
9
|
+
* re-sending the `ready` handshake to attempt reconnection.
|
|
10
|
+
*
|
|
11
|
+
* @module @core/state
|
|
12
|
+
*/
|
|
13
|
+
type ConnectionStatus = 'disconnected' | 'connecting' | 'connected';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The shape of a live-preview inspection snapshot.
|
|
17
|
+
*
|
|
18
|
+
* This module is types only. The snapshot is assembled by
|
|
19
|
+
* `LivePreviewRuntime.inspect()` as a plain object literal, because the inline
|
|
20
|
+
* runtime pays for every byte of indirection and the assembly needs access to
|
|
21
|
+
* internal state the runtime does not otherwise expose.
|
|
22
|
+
*
|
|
23
|
+
* A snapshot is a read of what the runtime already holds. It discloses nothing
|
|
24
|
+
* that is not already observable on the page: the trusted origins are inside
|
|
25
|
+
* the injected script, the field names are `data-payload-field` attributes in
|
|
26
|
+
* the DOM, and the counters are derived from those. It is therefore available
|
|
27
|
+
* in production rather than gated to development builds — a preview that
|
|
28
|
+
* misbehaves only on the deployed site is exactly the case where the
|
|
29
|
+
* information is worth having, and a development-only gate would withhold it
|
|
30
|
+
* there.
|
|
31
|
+
*
|
|
32
|
+
* Nothing here is transmitted anywhere. Reading a snapshot performs no I/O.
|
|
33
|
+
*
|
|
34
|
+
* @module @core/inspection/types
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** Origin trust as the runtime currently sees it. */
|
|
38
|
+
interface InspectionOrigins {
|
|
39
|
+
/**
|
|
40
|
+
* Origins the runtime is willing to accept messages from, as configured.
|
|
41
|
+
* An empty list means no explicit allow-list was given, which is the
|
|
42
|
+
* condition under which referrer and localhost heuristics decide instead.
|
|
43
|
+
*/
|
|
44
|
+
readonly trusted: readonly string[];
|
|
45
|
+
/**
|
|
46
|
+
* The origin the runtime locked onto after its first accepted update, or
|
|
47
|
+
* `undefined` while still unlocked. Once locked, every other origin is
|
|
48
|
+
* refused for the rest of the session.
|
|
49
|
+
*/
|
|
50
|
+
readonly locked: string | undefined;
|
|
51
|
+
}
|
|
52
|
+
/** Protocol versions and the capabilities they enable. */
|
|
53
|
+
interface InspectionProtocol {
|
|
54
|
+
/** This library's protocol version. */
|
|
55
|
+
readonly ours: number;
|
|
56
|
+
/** The remote party's version, or `undefined` if it never announced one. */
|
|
57
|
+
readonly theirs: number | undefined;
|
|
58
|
+
/** `min(ours, theirs ?? 1)` — what both sides actually share. */
|
|
59
|
+
readonly negotiated: number;
|
|
60
|
+
/** Capability flags enabled at the negotiated version. */
|
|
61
|
+
readonly capabilities: readonly string[];
|
|
62
|
+
}
|
|
63
|
+
/** Revision accounting for the update pipeline. */
|
|
64
|
+
interface InspectionRevisions {
|
|
65
|
+
/** Updates accepted since the runtime started. */
|
|
66
|
+
readonly accepted: number;
|
|
67
|
+
/**
|
|
68
|
+
* Updates that were still in flight when a newer one arrived and were
|
|
69
|
+
* therefore abandoned. A number that tracks `accepted` closely means the
|
|
70
|
+
* editor is out-typing the pipeline, which is normal; it is only a problem
|
|
71
|
+
* when the last update is among the abandoned ones.
|
|
72
|
+
*/
|
|
73
|
+
readonly superseded: number;
|
|
74
|
+
/** Revision currently in flight, or `undefined` when the pipeline is idle. */
|
|
75
|
+
readonly active: number | undefined;
|
|
76
|
+
}
|
|
77
|
+
/** What the DOM offers the runtime to write into. */
|
|
78
|
+
interface InspectionBindings {
|
|
79
|
+
/** Elements carrying a binding. */
|
|
80
|
+
readonly elements: number;
|
|
81
|
+
/** Distinct field names across those elements. */
|
|
82
|
+
readonly fields: number;
|
|
83
|
+
/** Those field names, sorted. */
|
|
84
|
+
readonly fieldNames: readonly string[];
|
|
85
|
+
/**
|
|
86
|
+
* Field names that arrived in an update but matched no binding, as far as
|
|
87
|
+
* the runtime has observed. This is the list to read when a field refuses
|
|
88
|
+
* to update: a name here is a markup problem, a name absent from here and
|
|
89
|
+
* from `fieldNames` was never sent.
|
|
90
|
+
*/
|
|
91
|
+
readonly orphanFields: readonly string[];
|
|
92
|
+
/** Whether `scopeBindingsByOwner` is active. */
|
|
93
|
+
readonly ownerScoped: boolean;
|
|
94
|
+
/** Distinct document owners currently on the page, sorted. */
|
|
95
|
+
readonly owners: readonly string[];
|
|
96
|
+
}
|
|
97
|
+
/** Scheduler work in progress. */
|
|
98
|
+
interface InspectionScheduler {
|
|
99
|
+
/** Writes buffered for the next flush. */
|
|
100
|
+
readonly pending: number;
|
|
101
|
+
/**
|
|
102
|
+
* Writes held back because their element is offscreen and the binding count
|
|
103
|
+
* is above `visibilityGateThreshold`. These are applied when the element
|
|
104
|
+
* scrolls into view — never, on a page nobody scrolls.
|
|
105
|
+
*/
|
|
106
|
+
readonly deferred: number;
|
|
107
|
+
/** The binding count above which the visibility gate starts deferring. */
|
|
108
|
+
readonly visibilityGateThreshold: number;
|
|
109
|
+
/** Whether the binding count is above that threshold right now. */
|
|
110
|
+
readonly visibilityGateActive: boolean;
|
|
111
|
+
/** Stats of the most recent flush, or `undefined` if none has run. */
|
|
112
|
+
readonly lastFlush: {
|
|
113
|
+
readonly applied: number;
|
|
114
|
+
readonly deferred: number;
|
|
115
|
+
readonly durationMs: number;
|
|
116
|
+
} | undefined;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* A point-in-time read of runtime state, for diagnosing a preview that is not
|
|
120
|
+
* behaving. Every field is a plain value; the snapshot holds no references
|
|
121
|
+
* into runtime internals and does not change after it is returned.
|
|
122
|
+
*/
|
|
123
|
+
interface LivePreviewInspection {
|
|
124
|
+
/** Package version that produced this snapshot. */
|
|
125
|
+
readonly version: string;
|
|
126
|
+
/** Whether the runtime is started, and whether it has been destroyed. */
|
|
127
|
+
readonly started: boolean;
|
|
128
|
+
/** Connection status as reported to the `connect`/`disconnect` events. */
|
|
129
|
+
readonly status: ConnectionStatus;
|
|
130
|
+
readonly origins: InspectionOrigins;
|
|
131
|
+
readonly protocol: InspectionProtocol;
|
|
132
|
+
readonly revisions: InspectionRevisions;
|
|
133
|
+
readonly bindings: InspectionBindings;
|
|
134
|
+
readonly scheduler: InspectionScheduler;
|
|
135
|
+
/** Field types with a registered renderer, sorted. */
|
|
136
|
+
readonly renderers: readonly string[];
|
|
137
|
+
}
|
|
138
|
+
|
|
1
139
|
/**
|
|
2
140
|
* Payload Live Preview message protocol.
|
|
3
141
|
*
|
|
@@ -113,6 +251,101 @@ type PayloadFieldType = 'text' | 'textarea' | 'richText' | 'email' | 'number' |
|
|
|
113
251
|
*/
|
|
114
252
|
type PayloadFieldCondition = (data: unknown, siblingData: unknown) => boolean;
|
|
115
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Stable identifiers for everything the runtime reports.
|
|
256
|
+
*
|
|
257
|
+
* Prose gets reworded; a code does not. A consumer filtering logs, an alert
|
|
258
|
+
* rule, or a bug report referring to `LP0301` keeps meaning the same thing
|
|
259
|
+
* after the sentence around it is rewritten, and a code is greppable in a way
|
|
260
|
+
* that a sentence fragment is not.
|
|
261
|
+
*
|
|
262
|
+
* Codes are grouped by the question they answer:
|
|
263
|
+
*
|
|
264
|
+
* - `LP01xx` — configuration and origin trust: the runtime is running, but it
|
|
265
|
+
* was set up in a way that will bite.
|
|
266
|
+
* - `LP02xx` — bindings and markup: an update had nowhere to land.
|
|
267
|
+
* - `LP03xx` — updates and scheduling: the update landed somewhere other than
|
|
268
|
+
* the DOM, or not yet.
|
|
269
|
+
* - `LP04xx` — rendering: a value reached an element and was refused.
|
|
270
|
+
* - `LP05xx` — protocol and messages: something arrived that was not accepted.
|
|
271
|
+
* - `LP06xx` — consumer callbacks: code the consumer supplied threw.
|
|
272
|
+
* - `LP07xx` — audit findings from `pll doctor`, which reports on a served
|
|
273
|
+
* response rather than on a running runtime.
|
|
274
|
+
*
|
|
275
|
+
* A code is part of the public contract. Codes are never reused for a
|
|
276
|
+
* different meaning and never renumbered; a retired code stays retired.
|
|
277
|
+
* `LP0604` is unassigned: a throwing token validator is deliberately treated
|
|
278
|
+
* as a rejection and reported as `LP0502`, so there is nothing distinct to
|
|
279
|
+
* report yet. The number stays reserved rather than being handed to something
|
|
280
|
+
* else.
|
|
281
|
+
*
|
|
282
|
+
* The runtime writes these as string literals at each reporting site rather
|
|
283
|
+
* than reading them from this record, so the inline build pays for the six
|
|
284
|
+
* characters it prints and nothing more. This record exists so consumers can
|
|
285
|
+
* refer to a code by name instead of copying a literal.
|
|
286
|
+
*
|
|
287
|
+
* @module @core/diagnostic-codes
|
|
288
|
+
*/
|
|
289
|
+
/**
|
|
290
|
+
* Every diagnostic code the runtime can report, by name.
|
|
291
|
+
*
|
|
292
|
+
* ```ts
|
|
293
|
+
* client.events.on('error', (e) => {
|
|
294
|
+
* if (e.code === DIAGNOSTIC_CODES.TransformThrew) reportToSentry(e.error);
|
|
295
|
+
* });
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
declare const DIAGNOSTIC_CODES: Readonly<{
|
|
299
|
+
/** No trusted origin configured in production; nothing will be accepted. */
|
|
300
|
+
readonly NoTrustedOrigin: "LP0101";
|
|
301
|
+
/** Origin trust rests on `document.referrer`, so any framing site is trusted. */
|
|
302
|
+
readonly ReferrerOnlyTrust: "LP0102";
|
|
303
|
+
/** An update named a field with no binding anchor on the page. */
|
|
304
|
+
readonly OrphanField: "LP0201";
|
|
305
|
+
/** Owner scoping is on and the update names no document it could belong to. */
|
|
306
|
+
readonly UnattributableUpdate: "LP0202";
|
|
307
|
+
/** The visibility gate held offscreen writes back until they scroll into view. */
|
|
308
|
+
readonly VisibilityGateDeferred: "LP0301";
|
|
309
|
+
/** A value was refused because the attribute or the value itself is unsafe. */
|
|
310
|
+
readonly UnsafeAttributeWrite: "LP0401";
|
|
311
|
+
/** A text element has structured children, so replacing its text was skipped. */
|
|
312
|
+
readonly TextTargetHasChildren: "LP0402";
|
|
313
|
+
/** A structural container has no array template, so the update was skipped. */
|
|
314
|
+
readonly MissingArrayTemplate: "LP0403";
|
|
315
|
+
/** A message was rejected before it reached the update pipeline. */
|
|
316
|
+
readonly MessageRejected: "LP0501";
|
|
317
|
+
/** A preview token was rejected. */
|
|
318
|
+
readonly TokenRejected: "LP0502";
|
|
319
|
+
/** A consumer event handler threw. */
|
|
320
|
+
readonly HandlerThrew: "LP0601";
|
|
321
|
+
/** A consumer transform threw; the original value was kept. */
|
|
322
|
+
readonly TransformThrew: "LP0602";
|
|
323
|
+
/** A renderer threw while writing a value. */
|
|
324
|
+
readonly RendererThrew: "LP0603";
|
|
325
|
+
/** Runtime startup failed. */
|
|
326
|
+
readonly StartupFailed: "LP0605";
|
|
327
|
+
/** Sending the ready handshake failed. */
|
|
328
|
+
readonly ReadyFailed: "LP0606";
|
|
329
|
+
/** The audit found no runtime in a response that carried preview intent. */
|
|
330
|
+
readonly AuditRuntimeMissing: "LP0701";
|
|
331
|
+
/** The preview response declares no `frame-ancestors`. */
|
|
332
|
+
readonly AuditNoFrameAncestors: "LP0702";
|
|
333
|
+
/** `X-Frame-Options` forbids framing, which no CSP can undo. */
|
|
334
|
+
readonly AuditFrameOptionsBlocks: "LP0703";
|
|
335
|
+
/** Binding attributes are served to anonymous visitors. */
|
|
336
|
+
readonly AuditBindingsExposed: "LP0704";
|
|
337
|
+
/** More bindings than the default visibility gate will write eagerly. */
|
|
338
|
+
readonly AuditGateThresholdExceeded: "LP0705";
|
|
339
|
+
/** Owner markers exist, but some bindings are outside all of them. */
|
|
340
|
+
readonly AuditUnownedBindings: "LP0706";
|
|
341
|
+
/** The preview response carries no bindings at all. */
|
|
342
|
+
readonly AuditNoBindings: "LP0707";
|
|
343
|
+
/** The URL did not return an HTML page, so nothing else can be judged. */
|
|
344
|
+
readonly AuditNotAPage: "LP0708";
|
|
345
|
+
}>;
|
|
346
|
+
/** A diagnostic code, as it appears in log output and on the `error` event. */
|
|
347
|
+
type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[keyof typeof DIAGNOSTIC_CODES];
|
|
348
|
+
|
|
116
349
|
/**
|
|
117
350
|
* Public event payload shapes for the live preview lifecycle.
|
|
118
351
|
*
|
|
@@ -193,11 +426,14 @@ interface LivePreviewEventMap {
|
|
|
193
426
|
/**
|
|
194
427
|
* Fired on errors that the runtime caught but cannot fully recover from.
|
|
195
428
|
*
|
|
196
|
-
* The `context` string identifies where the error originated.
|
|
429
|
+
* The `context` string identifies where the error originated. `code` says
|
|
430
|
+
* the same thing in a form that survives rewording — branch on `code`, read
|
|
431
|
+
* `context` when you want the human-readable origin.
|
|
197
432
|
*/
|
|
198
433
|
readonly error: {
|
|
199
434
|
readonly error: Error;
|
|
200
435
|
readonly context: string;
|
|
436
|
+
readonly code: DiagnosticCode;
|
|
201
437
|
};
|
|
202
438
|
/**
|
|
203
439
|
* Fired during destroy after browser observers and the message listener are
|
|
@@ -657,6 +893,15 @@ declare class LivePreviewClient {
|
|
|
657
893
|
/** Current connection status. */
|
|
658
894
|
get status(): 'disconnected' | 'connecting' | 'connected';
|
|
659
895
|
/** Number of valid updates received so far. */
|
|
896
|
+
/**
|
|
897
|
+
* Point-in-time read of runtime state, for diagnosing a preview that is not
|
|
898
|
+
* updating. Performs no I/O and transmits nothing.
|
|
899
|
+
*
|
|
900
|
+
* Read `bindings.orphanFields` when a field refuses to update, and
|
|
901
|
+
* `scheduler.deferred` together with `scheduler.visibilityGateActive` when
|
|
902
|
+
* updates stop below the fold.
|
|
903
|
+
*/
|
|
904
|
+
inspect(): LivePreviewInspection;
|
|
660
905
|
get updateCount(): number;
|
|
661
906
|
/** `true` once `destroy()` has been called. */
|
|
662
907
|
get destroyed(): boolean;
|
|
@@ -1364,4 +1609,4 @@ declare function createPreviewBindings(options: PreviewBindingsOptions): Preview
|
|
|
1364
1609
|
|
|
1365
1610
|
declare const CORE_ENTRY = true;
|
|
1366
1611
|
|
|
1367
|
-
export { type BindOptions, CORE_ENTRY, type CachedElement, EventEmitter, type EventHandler, type FieldBindingAttributes, type FieldName, type FieldPath, type FieldRenderer, type FieldType, type FrameAncestorsOptions, LIBRARY_PROTOCOL_VERSION, LivePreviewClient, type LivePreviewClientConfig, type LivePreviewEventMap, OriginDetector, type OwnerBindingAttributes, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PayloadLivePreviewMessage, type PreviewBindings, type PreviewBindingsOptions, type ProtocolCapability, type ProtocolNegotiation, type RenderContext, type SanitizerDocument, type SuppressedBinding, type Unsubscribe, VERSION, type ValueAt, bind, bindByPath, buildFrameAncestors, buildScriptSrcWithNonce, createPreviewBindings, detectInitialLocale, escapeHtml, escapeHtmlAttribute, generateCspNonce, hasCapability, initLivePreview, isDevMode, isExternalHttpUrl, isInIframe, isInPopup, isInPreviewContext, isSafeUrl, negotiateProtocol, sanitizeHtml, setCspCrypto, setSanitizerDocument };
|
|
1612
|
+
export { type BindOptions, CORE_ENTRY, type CachedElement, type ConnectionStatus, DIAGNOSTIC_CODES, type DiagnosticCode, EventEmitter, type EventHandler, type FieldBindingAttributes, type FieldName, type FieldPath, type FieldRenderer, type FieldType, type FrameAncestorsOptions, type InspectionBindings, type InspectionOrigins, type InspectionProtocol, type InspectionRevisions, type InspectionScheduler, LIBRARY_PROTOCOL_VERSION, LivePreviewClient, type LivePreviewClientConfig, type LivePreviewEventMap, type LivePreviewInspection, OriginDetector, type OwnerBindingAttributes, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PayloadLivePreviewMessage, type PreviewBindings, type PreviewBindingsOptions, type ProtocolCapability, type ProtocolNegotiation, type RenderContext, type SanitizerDocument, type SuppressedBinding, type Unsubscribe, VERSION, type ValueAt, bind, bindByPath, buildFrameAncestors, buildScriptSrcWithNonce, createPreviewBindings, detectInitialLocale, escapeHtml, escapeHtmlAttribute, generateCspNonce, hasCapability, initLivePreview, isDevMode, isExternalHttpUrl, isInIframe, isInPopup, isInPreviewContext, isSafeUrl, negotiateProtocol, sanitizeHtml, setCspCrypto, setSanitizerDocument };
|