payload-live-preview 1.8.0 → 2.0.0-beta.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 +301 -93
- package/dist/adapters/astro/PreviewBoundary.astro +66 -0
- package/dist/adapters/astro/RichText.astro +6 -0
- package/dist/adapters/astro/index.d.ts +165 -134
- package/dist/adapters/astro/index.js +1 -1
- package/dist/adapters/astro/index.js.map +1 -1
- package/dist/adapters/astro/middleware-entry.d.ts +4 -9
- package/dist/adapters/astro/middleware-entry.js +1 -1
- package/dist/adapters/astro/middleware-entry.js.map +1 -1
- package/dist/adapters/nextjs/index.d.ts +13 -80
- package/dist/adapters/nextjs/index.js +1 -1
- package/dist/adapters/nextjs/index.js.map +1 -1
- package/dist/adapters/nuxt/index.d.ts +46 -106
- package/dist/adapters/nuxt/index.js +1 -1
- package/dist/adapters/nuxt/index.js.map +1 -1
- package/dist/adapters/sveltekit/index.d.ts +10 -75
- package/dist/adapters/sveltekit/index.js +1 -1
- package/dist/adapters/sveltekit/index.js.map +1 -1
- package/dist/client.cjs +2 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +747 -0
- package/dist/client.d.ts +747 -0
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -0
- package/dist/codegen-astro.d.ts +5 -27
- package/dist/codegen-astro.js +1 -1
- package/dist/codegen-astro.js.map +1 -1
- package/dist/codegen-cli.d.ts +3 -16
- package/dist/codegen-cli.js +1 -1
- package/dist/codegen-cli.js.map +1 -1
- package/dist/codegen.cjs +1 -1
- package/dist/codegen.cjs.map +1 -1
- package/dist/codegen.d.cts +37 -124
- package/dist/codegen.d.ts +37 -124
- package/dist/codegen.js +1 -1
- package/dist/codegen.js.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +647 -1100
- package/dist/core.d.ts +647 -1100
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/doctor-cli.d.ts +3 -28
- package/dist/doctor-cli.js +1 -1
- package/dist/doctor-cli.js.map +1 -1
- package/dist/doctor.d.ts +16 -32
- package/dist/doctor.js +1 -1
- package/dist/doctor.js.map +1 -1
- package/dist/fragment.cjs +2 -0
- package/dist/fragment.cjs.map +1 -0
- package/dist/fragment.d.cts +333 -0
- package/dist/fragment.d.ts +333 -0
- package/dist/fragment.js +2 -0
- package/dist/fragment.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +885 -1531
- package/dist/index.d.ts +885 -1531
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lexical.cjs +2 -0
- package/dist/lexical.cjs.map +1 -0
- package/dist/lexical.d.cts +90 -0
- package/dist/lexical.d.ts +90 -0
- package/dist/lexical.js +2 -0
- package/dist/lexical.js.map +1 -0
- package/dist/middleware-CEPsY1P7.d.ts +40 -0
- package/dist/migrate.d.ts +73 -0
- package/dist/migrate.js +2 -0
- package/dist/migrate.js.map +1 -0
- package/dist/options-CEzzfHJu.d.ts +197 -0
- package/dist/payload.cjs +1 -1
- package/dist/payload.cjs.map +1 -1
- package/dist/payload.d.cts +11 -80
- package/dist/payload.d.ts +11 -80
- package/dist/payload.js +1 -1
- package/dist/payload.js.map +1 -1
- package/dist/plugins.cjs +2 -0
- package/dist/plugins.cjs.map +1 -0
- package/dist/plugins.d.cts +509 -0
- package/dist/plugins.d.ts +509 -0
- package/dist/plugins.js +2 -0
- package/dist/plugins.js.map +1 -0
- package/dist/{probe-tMHdim5y.d.ts → probe-CYtvj_Lm.d.ts} +43 -77
- package/dist/server.cjs +2 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +435 -0
- package/dist/server.d.ts +435 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/dist/structural.cjs +3 -0
- package/dist/structural.cjs.map +1 -0
- package/dist/structural.d.cts +243 -0
- package/dist/structural.d.ts +243 -0
- package/dist/structural.js +3 -0
- package/dist/structural.js.map +1 -0
- package/package.json +86 -7
- package/dist/middleware-DD4Hwomt.d.ts +0 -189
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/** Payload's `DocumentEvent` shape (admin `providers/DocumentEvents`). */
|
|
2
|
+
interface PayloadDocumentEventDetail {
|
|
3
|
+
readonly entitySlug: string;
|
|
4
|
+
readonly operation?: 'create' | 'update';
|
|
5
|
+
readonly id?: string | number;
|
|
6
|
+
readonly updatedAt?: string;
|
|
7
|
+
readonly [extra: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
/** A validated update as events expose it. */
|
|
10
|
+
interface PayloadLivePreviewData {
|
|
11
|
+
readonly fields: Record<string, unknown>;
|
|
12
|
+
readonly schema?: readonly PayloadFieldSchema[];
|
|
13
|
+
readonly globalSlug?: string;
|
|
14
|
+
readonly collectionSlug?: string;
|
|
15
|
+
readonly locale?: string;
|
|
16
|
+
}
|
|
17
|
+
/** The subset of Payload's field schema the runtime reads; extra properties are kept opaquely. */
|
|
18
|
+
interface PayloadFieldSchema {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly type: PayloadFieldType;
|
|
21
|
+
readonly label?: string;
|
|
22
|
+
readonly required?: boolean;
|
|
23
|
+
readonly localized?: boolean;
|
|
24
|
+
readonly fields?: readonly PayloadFieldSchema[];
|
|
25
|
+
readonly blocks?: readonly PayloadBlockSchema[];
|
|
26
|
+
readonly relationTo?: string | readonly string[];
|
|
27
|
+
readonly hasMany?: boolean;
|
|
28
|
+
readonly admin?: {
|
|
29
|
+
readonly condition?: PayloadFieldCondition;
|
|
30
|
+
};
|
|
31
|
+
readonly [extra: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
interface PayloadBlockSchema {
|
|
34
|
+
readonly slug: string;
|
|
35
|
+
readonly fields: readonly PayloadFieldSchema[];
|
|
36
|
+
readonly [extra: string]: unknown;
|
|
37
|
+
}
|
|
38
|
+
/** Payload's core field types. `tabs` is a structural container; `group` flattens. */
|
|
39
|
+
type PayloadFieldType = 'text' | 'textarea' | 'richText' | 'email' | 'number' | 'checkbox' | 'date' | 'select' | 'radio' | 'array' | 'blocks' | 'group' | 'tabs' | 'row' | 'collapsible' | 'relationship' | 'upload' | 'point' | 'json' | 'code' | 'ui';
|
|
40
|
+
/** `admin.condition` is a function in source and cannot cross `postMessage`; modelled, not consumed. */
|
|
41
|
+
type PayloadFieldCondition = (data: unknown, siblingData: unknown) => boolean;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Every diagnostic code the runtime and tools emit, so a consumer can branch
|
|
45
|
+
* on `e.code` instead of matching message text. A code is never reused for a
|
|
46
|
+
* different meaning; a retired one stays reserved.
|
|
47
|
+
*
|
|
48
|
+
* Browser-side reporting sites write the literal (`code: 'LP0603'`) rather than
|
|
49
|
+
* reading it from this record: the frozen table would then ship in the inline
|
|
50
|
+
* runtime for the sake of six characters. Server-side tools may import it.
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* Every diagnostic code the runtime can report, by name.
|
|
54
|
+
*
|
|
55
|
+
* ```ts
|
|
56
|
+
* client.events.on('error', (e) => {
|
|
57
|
+
* if (e.code === DIAGNOSTIC_CODES.TransformThrew) reportToSentry(e.error);
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare const DIAGNOSTIC_CODES: Readonly<{
|
|
62
|
+
/** No trusted origin configured in production; nothing will be accepted. */
|
|
63
|
+
readonly NoTrustedOrigin: "LP0101";
|
|
64
|
+
/** Origin trust rests on `document.referrer`, so any framing site is trusted. */
|
|
65
|
+
readonly ReferrerOnlyTrust: "LP0102";
|
|
66
|
+
/** A plugin declares a runtime range this runtime does not satisfy; it was refused. */
|
|
67
|
+
readonly PluginIncompatible: "LP0103";
|
|
68
|
+
/** An update named a field with no binding anchor on the page. */
|
|
69
|
+
readonly OrphanField: "LP0201";
|
|
70
|
+
/** Owner scoping is on and the update names no document it could belong to. */
|
|
71
|
+
readonly UnattributableUpdate: "LP0202";
|
|
72
|
+
/** The visibility gate held offscreen writes back until they scroll into view. */
|
|
73
|
+
readonly VisibilityGateDeferred: "LP0301";
|
|
74
|
+
/** A value was refused because the attribute or the value itself is unsafe. */
|
|
75
|
+
readonly UnsafeAttributeWrite: "LP0401";
|
|
76
|
+
/** A text element has structured children, so replacing its text was skipped. */
|
|
77
|
+
readonly TextTargetHasChildren: "LP0402";
|
|
78
|
+
/** A structural container has no array template, so the update was skipped. */
|
|
79
|
+
readonly MissingArrayTemplate: "LP0403";
|
|
80
|
+
/** A structural item has no `id`; it pairs positionally, so an insert re-renders every row after it. */
|
|
81
|
+
readonly StructuralItemUnkeyed: "LP0404";
|
|
82
|
+
/** Two structural items share a key; later ones pair positionally. */
|
|
83
|
+
readonly StructuralDuplicateKey: "LP0405";
|
|
84
|
+
/** Every structural key changed while the length did not; the source generates keys per message. */
|
|
85
|
+
readonly StructuralUnstableKeys: "LP0406";
|
|
86
|
+
/** A binding asks for a delivery strategy this release does not have; it is left unchanged. */
|
|
87
|
+
readonly UnsupportedStrategy: "LP0407";
|
|
88
|
+
/** A message was rejected before it reached the update pipeline. */
|
|
89
|
+
readonly MessageRejected: "LP0501";
|
|
90
|
+
/** A preview token was rejected. */
|
|
91
|
+
readonly TokenRejected: "LP0502";
|
|
92
|
+
/** A consumer event handler threw. */
|
|
93
|
+
readonly HandlerThrew: "LP0601";
|
|
94
|
+
/** A consumer transform threw; the original value was kept. */
|
|
95
|
+
readonly TransformThrew: "LP0602";
|
|
96
|
+
/** A renderer threw while writing a value. */
|
|
97
|
+
readonly RendererThrew: "LP0603";
|
|
98
|
+
/** Runtime startup failed. */
|
|
99
|
+
readonly StartupFailed: "LP0605";
|
|
100
|
+
/** Sending the ready handshake failed. */
|
|
101
|
+
readonly ReadyFailed: "LP0606";
|
|
102
|
+
/** The audit found no runtime in a response that carried preview intent. */
|
|
103
|
+
readonly AuditRuntimeMissing: "LP0701";
|
|
104
|
+
/** The preview response declares no `frame-ancestors`. */
|
|
105
|
+
readonly AuditNoFrameAncestors: "LP0702";
|
|
106
|
+
/** `X-Frame-Options` forbids framing, which no CSP can undo. */
|
|
107
|
+
readonly AuditFrameOptionsBlocks: "LP0703";
|
|
108
|
+
/** Binding attributes are served to anonymous visitors. */
|
|
109
|
+
readonly AuditBindingsExposed: "LP0704";
|
|
110
|
+
/** More bindings than the default visibility gate will write eagerly. */
|
|
111
|
+
readonly AuditGateThresholdExceeded: "LP0705";
|
|
112
|
+
/** Owner markers exist, but some bindings are outside all of them. */
|
|
113
|
+
readonly AuditUnownedBindings: "LP0706";
|
|
114
|
+
/** The preview response carries no bindings at all. */
|
|
115
|
+
readonly AuditNoBindings: "LP0707";
|
|
116
|
+
/** The URL did not return an HTML page, so nothing else can be judged. */
|
|
117
|
+
readonly AuditNotAPage: "LP0708";
|
|
118
|
+
/** A fragment request failed (network, timeout, server error); the boundary was patched instead. */
|
|
119
|
+
readonly FragmentRequestFailed: "LP0801";
|
|
120
|
+
/** The fragment response had the wrong content type or shape; the boundary was patched instead. */
|
|
121
|
+
readonly FragmentResponseInvalid: "LP0802";
|
|
122
|
+
/** The fragment endpoint refused the preview (not authorized); the boundary was patched instead. */
|
|
123
|
+
readonly FragmentUnauthorized: "LP0803";
|
|
124
|
+
/** A fragment response arrived for a revision that was already superseded and was discarded. */
|
|
125
|
+
readonly FragmentSuperseded: "LP0804";
|
|
126
|
+
/** A route refresh was requested again for the same revision; the loop guard stopped it. */
|
|
127
|
+
readonly RouteRefreshLoop: "LP0805";
|
|
128
|
+
/** A boundary asks for the fragment strategy but no fragment handler is configured; it is patched. */
|
|
129
|
+
readonly FragmentStrategyUnavailable: "LP0806";
|
|
130
|
+
/** A readiness row is not yet at its 2.0 value; `pll doctor --v2` reports it. */
|
|
131
|
+
readonly V2ReadinessGap: "LP0709";
|
|
132
|
+
/** The preview runtime is served to anonymous visitors, not only inside the admin frame. */
|
|
133
|
+
readonly RuntimeOnPublicPage: "LP0710";
|
|
134
|
+
}>;
|
|
135
|
+
/** A diagnostic code, as it appears in log output and on the `error` event. */
|
|
136
|
+
type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[keyof typeof DIAGNOSTIC_CODES];
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* How a bound region is brought up to date: the runtime patches it, a server
|
|
140
|
+
* renders a `data-payload-fragment` boundary from the unsaved form state, or
|
|
141
|
+
* the whole route refreshes. Core carries only the seam — which boundaries a
|
|
142
|
+
* strategy owns and what it may do — so a patch-only page pays for nothing
|
|
143
|
+
* more; the orchestration lives in `payload-live-preview/fragment`.
|
|
144
|
+
*/
|
|
145
|
+
|
|
146
|
+
/** What produced an update: the runtime's DOM patching, a server-rendered fragment, or a route refresh. */
|
|
147
|
+
type UpdateSource = 'patch' | 'fragment' | 'route';
|
|
148
|
+
|
|
149
|
+
/** Types shared by the runtime primitives. */
|
|
150
|
+
|
|
151
|
+
/** Payload's field set plus the DOM-binding categories `html`, `url`, `image` and `structural-array`. */
|
|
152
|
+
type FieldType = PayloadFieldType | 'html' | 'url' | 'image' | 'structural-array';
|
|
153
|
+
/** A namespaced project renderer key, so a typo of a built-in type can never become one. */
|
|
154
|
+
type CustomRendererKey = `${string}:${string}`;
|
|
155
|
+
/** What a renderer may be registered under and an element may ask for. */
|
|
156
|
+
type RendererKey = FieldType | CustomRendererKey;
|
|
157
|
+
/**
|
|
158
|
+
* A project rich-text renderer, shared by SSR and preview. Its output goes
|
|
159
|
+
* through the sanitizer; call the same `sanitizeHtml()` server-side for byte equality.
|
|
160
|
+
*/
|
|
161
|
+
type RichTextRenderer = (value: unknown, context: {
|
|
162
|
+
readonly fieldName: string;
|
|
163
|
+
readonly element: Element;
|
|
164
|
+
readonly locale: string | undefined;
|
|
165
|
+
}) => string;
|
|
166
|
+
/** One registered binding. Several may share a field name when it renders in several places. */
|
|
167
|
+
interface CachedElement {
|
|
168
|
+
/** The bound DOM element. */
|
|
169
|
+
readonly element: Element;
|
|
170
|
+
/** Payload field path, e.g., `title` or `hero.subtitle`. */
|
|
171
|
+
readonly fieldName: string;
|
|
172
|
+
/** Resolved from attributes and tag heuristics; the schema may override it unless explicit. */
|
|
173
|
+
readonly fieldType: RendererKey;
|
|
174
|
+
/** Whether `data-payload-type` set the type, in which case the schema must not override it. */
|
|
175
|
+
readonly explicitFieldType?: boolean;
|
|
176
|
+
/** Fields this binding depends on (`data-payload-depends`); a change in any re-applies it under `skipUnchanged`. */
|
|
177
|
+
readonly dependsOn?: readonly string[];
|
|
178
|
+
/** Raw `data-payload-strategy` value. */
|
|
179
|
+
readonly strategy?: string;
|
|
180
|
+
/** How the runtime brings this binding up to date; `'unknown'` for an unrecognised strategy. Resolved by the cache. */
|
|
181
|
+
readonly strategyKind?: UpdateSource | 'unknown';
|
|
182
|
+
/** Nearest enclosing `data-payload-fragment` boundary. Resolved by the cache. */
|
|
183
|
+
readonly fragmentBoundary?: Element;
|
|
184
|
+
/** `data-payload-boundary`: an anchor that hides itself while its field is empty. */
|
|
185
|
+
readonly boundary?: boolean;
|
|
186
|
+
/** Write the value into this attribute instead of the content; policed writes. */
|
|
187
|
+
readonly targetAttribute?: string;
|
|
188
|
+
/** Optional sibling-field path bound to the element's `href` attribute. */
|
|
189
|
+
readonly hrefField?: string;
|
|
190
|
+
/** Optional sibling-field path bound to the element's `src` attribute. */
|
|
191
|
+
readonly srcField?: string;
|
|
192
|
+
/** Optional sibling-field path bound to the element's `alt` attribute. */
|
|
193
|
+
readonly altField?: string;
|
|
194
|
+
/** Optional inline template for array/blocks rendering. */
|
|
195
|
+
readonly arrayTemplate?: string;
|
|
196
|
+
/** Optional separator for primitive-array stringification. */
|
|
197
|
+
readonly arraySeparator?: string;
|
|
198
|
+
/** Optional locale code locked onto this element (overrides the global locale). */
|
|
199
|
+
readonly locale?: string;
|
|
200
|
+
/** The document this binding belongs to, from the nearest `data-payload-owner`. */
|
|
201
|
+
readonly owner?: string;
|
|
202
|
+
}
|
|
203
|
+
/** What a renderer is given; `allFields` lets it resolve a sibling field. */
|
|
204
|
+
interface RenderContext {
|
|
205
|
+
/** Full field map for the current update — used for sibling lookups. */
|
|
206
|
+
readonly allFields: Record<string, unknown>;
|
|
207
|
+
/** Active locale, or `undefined` when none is established. */
|
|
208
|
+
readonly locale: string | undefined;
|
|
209
|
+
/** Optional schema descriptor for the field, when available. */
|
|
210
|
+
readonly schema: PayloadFieldSchema | undefined;
|
|
211
|
+
/** The project's rich-text renderer, when the client was configured with one. */
|
|
212
|
+
readonly renderRichText?: RichTextRenderer;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* A renderer writes one value into its element. It must not throw: one bad
|
|
216
|
+
* field may not stop an update. The result stays `void` — the internal
|
|
217
|
+
* no-write sentinel is not part of the contract.
|
|
218
|
+
*/
|
|
219
|
+
interface FieldRenderer {
|
|
220
|
+
readonly name: RendererKey;
|
|
221
|
+
render(target: CachedElement, value: unknown, context: RenderContext): void;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Shape of the `inspect()` snapshot. It only re-reads what the page already
|
|
226
|
+
* shows — origins from the injected script, field names from the DOM,
|
|
227
|
+
* counters derived from both — so it stays available in production, where a
|
|
228
|
+
* misbehaving preview is exactly the case worth diagnosing. Reading one
|
|
229
|
+
* performs no I/O and transmits nothing.
|
|
230
|
+
*/
|
|
231
|
+
|
|
232
|
+
/** One plugin as `inspect().plugins` reports it. */
|
|
233
|
+
interface PluginInspection {
|
|
234
|
+
readonly name: string;
|
|
235
|
+
readonly version: string | undefined;
|
|
236
|
+
/** `initializing` while `init` runs, `active` afterwards, `tearing-down` while `destroy` runs. */
|
|
237
|
+
readonly state: 'initializing' | 'active' | 'tearing-down';
|
|
238
|
+
/** Live registrations owned by the plugin's scope, by kind. */
|
|
239
|
+
readonly registrations: {
|
|
240
|
+
readonly transforms: number;
|
|
241
|
+
readonly renderers: number;
|
|
242
|
+
readonly subscriptions: number;
|
|
243
|
+
readonly cleanups: number;
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Public event payloads. The map keys are the valid event names; `EventEmitter` is generic over it. */
|
|
248
|
+
|
|
249
|
+
interface LivePreviewEventMap {
|
|
250
|
+
/** Once per startup attempt, after observers, cache and message listening are active. A rolled-back attempt emits it again on retry. */
|
|
251
|
+
readonly init: {
|
|
252
|
+
readonly timestamp: number;
|
|
253
|
+
};
|
|
254
|
+
/** The first accepted data-bearing update from a trusted origin. */
|
|
255
|
+
readonly connect: {
|
|
256
|
+
readonly origin: string;
|
|
257
|
+
readonly timestamp: number;
|
|
258
|
+
};
|
|
259
|
+
/** The heartbeat timed out, the runtime was destroyed, or the page was suspended for navigation (`'unload'`). */
|
|
260
|
+
readonly disconnect: {
|
|
261
|
+
readonly reason: 'timeout' | 'destroy' | 'unload';
|
|
262
|
+
readonly timestamp: number;
|
|
263
|
+
};
|
|
264
|
+
/** Before the DOM is mutated for an update; `cancel()` skips exactly this revision. */
|
|
265
|
+
readonly beforeUpdate: {
|
|
266
|
+
readonly data: PayloadLivePreviewData;
|
|
267
|
+
readonly revision?: number;
|
|
268
|
+
/** When the runtime accepted the message, Unix milliseconds. */
|
|
269
|
+
readonly receivedAt?: number;
|
|
270
|
+
/** The strategy that produced the update. */
|
|
271
|
+
readonly source?: UpdateSource;
|
|
272
|
+
readonly cancel: () => void;
|
|
273
|
+
};
|
|
274
|
+
/** After each applied, still-current batch. Visibility replay may emit another for the same revision; cancelled, obsolete and deferred-only batches emit none. */
|
|
275
|
+
readonly afterUpdate: {
|
|
276
|
+
readonly data: PayloadLivePreviewData;
|
|
277
|
+
readonly updatedCount: number;
|
|
278
|
+
readonly durationMs: number;
|
|
279
|
+
readonly revision?: number;
|
|
280
|
+
readonly receivedAt?: number;
|
|
281
|
+
readonly source?: UpdateSource;
|
|
282
|
+
};
|
|
283
|
+
/** Each successful, still-current element write. */
|
|
284
|
+
readonly elementUpdate: {
|
|
285
|
+
readonly element: Element;
|
|
286
|
+
readonly fieldName: string;
|
|
287
|
+
readonly previousValue: unknown;
|
|
288
|
+
readonly nextValue: unknown;
|
|
289
|
+
readonly revision?: number;
|
|
290
|
+
readonly receivedAt?: number;
|
|
291
|
+
readonly source?: UpdateSource;
|
|
292
|
+
};
|
|
293
|
+
/** The element cache was rebuilt (initial scan or mutation). */
|
|
294
|
+
readonly cacheRefresh: {
|
|
295
|
+
readonly elementCount: number;
|
|
296
|
+
readonly fieldCount: number;
|
|
297
|
+
readonly durationMs: number;
|
|
298
|
+
};
|
|
299
|
+
/** Once per fragment boundary and revision: rendered by the server, or failed (with the LP08xx code) and patched instead. */
|
|
300
|
+
readonly fragmentRender: {
|
|
301
|
+
readonly element: Element;
|
|
302
|
+
readonly id: string;
|
|
303
|
+
readonly key: string | undefined;
|
|
304
|
+
readonly status: 'rendered' | 'failed';
|
|
305
|
+
readonly code?: DiagnosticCode;
|
|
306
|
+
readonly revision: number;
|
|
307
|
+
readonly receivedAt: number;
|
|
308
|
+
};
|
|
309
|
+
/** A `payload-document-event` message arrived (document save). */
|
|
310
|
+
readonly documentSave: {
|
|
311
|
+
readonly timestamp: number;
|
|
312
|
+
};
|
|
313
|
+
/** A data update carried `externallyUpdatedRelationship`: a related document changed in an admin drawer, so the update re-renders unconditionally. */
|
|
314
|
+
readonly relationshipUpdate: {
|
|
315
|
+
readonly detail: PayloadDocumentEventDetail;
|
|
316
|
+
readonly timestamp: number;
|
|
317
|
+
};
|
|
318
|
+
/** An error the runtime caught but cannot fully recover from. Branch on `code`; `context` is the human-readable origin. */
|
|
319
|
+
readonly error: {
|
|
320
|
+
readonly error: Error;
|
|
321
|
+
readonly context: string;
|
|
322
|
+
readonly code: DiagnosticCode;
|
|
323
|
+
};
|
|
324
|
+
/** During destroy, after observers and the message listener are removed; listeners are released by the owning client afterwards. */
|
|
325
|
+
readonly destroy: {
|
|
326
|
+
readonly timestamp: number;
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
/** Handlers may return a promise; they are awaited in registration order, which `beforeUpdate.cancel()` relies on. */
|
|
330
|
+
type EventHandler<TPayload> = (payload: TPayload) => void | Promise<void>;
|
|
331
|
+
type Unsubscribe = () => void;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Per-instance typed emitter: handlers run sequentially in registration order,
|
|
335
|
+
* may be async, and a throwing one is logged and isolated. See ADR 0002.
|
|
336
|
+
*/
|
|
337
|
+
|
|
338
|
+
declare class EventEmitter<TMap extends object = LivePreviewEventMap> {
|
|
339
|
+
#private;
|
|
340
|
+
on<E extends keyof TMap>(event: E, handler: EventHandler<TMap[E]>): Unsubscribe;
|
|
341
|
+
once<E extends keyof TMap>(event: E, handler: EventHandler<TMap[E]>): Unsubscribe;
|
|
342
|
+
off<E extends keyof TMap>(event: E, handler: EventHandler<TMap[E]>): void;
|
|
343
|
+
/** Dispatch to every handler: regular ones first, then `once` handlers. */
|
|
344
|
+
emit<E extends keyof TMap>(event: E, payload: TMap[E]): Promise<void>;
|
|
345
|
+
/**
|
|
346
|
+
* Dispatch while `shouldContinue()` holds — checked around every handler, so
|
|
347
|
+
* an obsolete transaction cannot resume across an await.
|
|
348
|
+
* @internal
|
|
349
|
+
*/
|
|
350
|
+
emitWhile<E extends keyof TMap>(event: E, payload: TMap[E], shouldContinue: () => boolean): Promise<boolean>;
|
|
351
|
+
/** Registered handlers for `event`, `on` and `once` together. */
|
|
352
|
+
listenerCount(event: keyof TMap): number;
|
|
353
|
+
/** Remove every handler, or only those of `event`. */
|
|
354
|
+
removeAllListeners(event?: keyof TMap): void;
|
|
355
|
+
/** Event names with at least one handler. */
|
|
356
|
+
eventNames(): (keyof TMap)[];
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Plugin compatibility claims. The range grammar is the subset a plugin
|
|
361
|
+
* author writes (`*`, `1.2.3`, `^`, `~`, `>=`, `>`, `<`, `<=`, space-joined
|
|
362
|
+
* conjunctions, `||` alternatives); prerelease tags are ignored.
|
|
363
|
+
*/
|
|
364
|
+
interface PluginCompatibility {
|
|
365
|
+
/** A semver range the runtime's `VERSION` must satisfy, e.g. `>=2.0.0`. */
|
|
366
|
+
readonly runtime?: string;
|
|
367
|
+
/** The highest postMessage protocol version the plugin understands. */
|
|
368
|
+
readonly protocol?: number;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/** Plugin contract: a scoped, per-instance context for renderers, transforms and events. */
|
|
372
|
+
|
|
373
|
+
/** Idempotent handle that releases one plugin-owned resource. */
|
|
374
|
+
type PluginDisposer = () => void;
|
|
375
|
+
/** The client's event surface scoped to one registration: bulk removal and introspection see only this plugin's listeners. */
|
|
376
|
+
interface PluginEvents {
|
|
377
|
+
readonly on: <E extends keyof LivePreviewEventMap>(event: E, handler: EventHandler<LivePreviewEventMap[E]>) => Unsubscribe;
|
|
378
|
+
readonly once: <E extends keyof LivePreviewEventMap>(event: E, handler: EventHandler<LivePreviewEventMap[E]>) => Unsubscribe;
|
|
379
|
+
readonly off: <E extends keyof LivePreviewEventMap>(event: E, handler: EventHandler<LivePreviewEventMap[E]>) => void;
|
|
380
|
+
/** Emit through the owning client's event channel. */
|
|
381
|
+
readonly emit: <E extends keyof LivePreviewEventMap>(event: E, payload: LivePreviewEventMap[E]) => Promise<void>;
|
|
382
|
+
/** Guarded emit; dispatch stops when the predicate turns false or this registration is removed. */
|
|
383
|
+
readonly emitWhile: <E extends keyof LivePreviewEventMap>(event: E, payload: LivePreviewEventMap[E], shouldContinue: () => boolean) => Promise<boolean>;
|
|
384
|
+
readonly listenerCount: (event: keyof LivePreviewEventMap) => number;
|
|
385
|
+
readonly removeAllListeners: (event?: keyof LivePreviewEventMap) => void;
|
|
386
|
+
readonly eventNames: () => (keyof LivePreviewEventMap)[];
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Synchronous value transform run in registration order; returning a thenable
|
|
390
|
+
* is a contract error (`LP0602`) that dispatches the untransformed value.
|
|
391
|
+
*/
|
|
392
|
+
type FieldTransform = (value: unknown, context: {
|
|
393
|
+
readonly fieldName: string;
|
|
394
|
+
readonly element: Element;
|
|
395
|
+
readonly allFields: Record<string, unknown>;
|
|
396
|
+
}) => unknown;
|
|
397
|
+
interface PluginContext {
|
|
398
|
+
readonly events: PluginEvents;
|
|
399
|
+
/** Register a renderer layer owned by this registration. */
|
|
400
|
+
readonly registerFieldRenderer: (renderer: FieldRenderer) => void;
|
|
401
|
+
/** Register an ordered transform owned by this registration. */
|
|
402
|
+
readonly registerTransform: (fieldName: string, transform: FieldTransform) => void;
|
|
403
|
+
/** Register a synchronous cleanup run on rollback, `unuse()` and client destruction. */
|
|
404
|
+
readonly registerCleanup?: (cleanup: PluginDisposer) => void;
|
|
405
|
+
readonly getConfig: () => Readonly<Record<string, unknown>>;
|
|
406
|
+
readonly log: (...args: unknown[]) => void;
|
|
407
|
+
}
|
|
408
|
+
/** `init` runs once per registration, `destroy` on removal; both may return a promise. */
|
|
409
|
+
interface LivePreviewPlugin {
|
|
410
|
+
readonly name: string;
|
|
411
|
+
readonly version?: string;
|
|
412
|
+
/** Checked at registration; a plugin this runtime does not fit is refused (`LP0103`). */
|
|
413
|
+
readonly compat?: PluginCompatibility;
|
|
414
|
+
readonly init: (context: PluginContext) => void | Promise<void>;
|
|
415
|
+
readonly destroy?: () => void | Promise<void>;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Per-instance plugin manager. Mutations run through one call-order queue;
|
|
420
|
+
* while a queue-held hook is pending, a requested mutation takes the direct
|
|
421
|
+
* path because that hook may be awaiting it. See ADR 0005.
|
|
422
|
+
*/
|
|
423
|
+
|
|
424
|
+
interface PluginManagerOptions {
|
|
425
|
+
readonly events: EventEmitter;
|
|
426
|
+
readonly config: Readonly<Record<string, unknown>>;
|
|
427
|
+
/** Add one renderer layer to the host; may return the layer's disposer. */
|
|
428
|
+
readonly registerFieldRenderer: (renderer: FieldRenderer) => void;
|
|
429
|
+
/** Receives transform contract failures for the runtime's `error` event. */
|
|
430
|
+
readonly onTransformError?: (error: Error) => unknown;
|
|
431
|
+
readonly log: (...args: unknown[]) => void;
|
|
432
|
+
}
|
|
433
|
+
declare class PluginManager {
|
|
434
|
+
#private;
|
|
435
|
+
constructor(options: PluginManagerOptions);
|
|
436
|
+
/** Register a plugin transactionally; concurrent mutations run in call order. */
|
|
437
|
+
register(plugin: LivePreviewPlugin): Promise<void>;
|
|
438
|
+
/** Remove one plugin and every resource its registration created. */
|
|
439
|
+
unregister(name: string): Promise<void>;
|
|
440
|
+
/** Destroy every registration; one failure never strands another. */
|
|
441
|
+
destroyAll(): Promise<void>;
|
|
442
|
+
/** Apply active transforms in registration order; a failure returns the original value. */
|
|
443
|
+
applyTransforms(fieldName: string, value: unknown, context: {
|
|
444
|
+
readonly element: Element;
|
|
445
|
+
readonly allFields: Record<string, unknown>;
|
|
446
|
+
}, isCurrent?: () => boolean): unknown;
|
|
447
|
+
list(): readonly string[];
|
|
448
|
+
/** Every plugin with its state and live registrations (`inspect().plugins`). */
|
|
449
|
+
snapshot(): readonly PluginInspection[];
|
|
450
|
+
get size(): number;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* `highlight` plugin: flashes an outline on updated elements. Respects
|
|
455
|
+
* `prefers-reduced-motion`; the stylesheet is shared per document across
|
|
456
|
+
* clients through a lease (ADR 0002).
|
|
457
|
+
*/
|
|
458
|
+
|
|
459
|
+
declare const highlightPlugin: LivePreviewPlugin;
|
|
460
|
+
|
|
461
|
+
/** `debug` plugin: logs every lifecycle event through the plugin context. */
|
|
462
|
+
|
|
463
|
+
declare const debugPlugin: LivePreviewPlugin;
|
|
464
|
+
|
|
465
|
+
/** `analytics` plugin: running totals over the update stream, read through `getStats()`. */
|
|
466
|
+
|
|
467
|
+
interface AnalyticsSnapshot {
|
|
468
|
+
readonly updateCount: number;
|
|
469
|
+
readonly totalElements: number;
|
|
470
|
+
readonly totalDurationMs: number;
|
|
471
|
+
readonly averageDurationMs: number;
|
|
472
|
+
}
|
|
473
|
+
declare function createAnalyticsPlugin(): LivePreviewPlugin & {
|
|
474
|
+
readonly getStats: () => AnalyticsSnapshot;
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* `documentSave` plugin: what to do when Payload saves the document.
|
|
479
|
+
* `'silent'` (default) emits only; `'reload'` reloads and restores the scroll
|
|
480
|
+
* position; `'revalidate'` POSTs to a revalidation endpoint; `'fetch'` runs
|
|
481
|
+
* a custom handler.
|
|
482
|
+
*/
|
|
483
|
+
|
|
484
|
+
type DocumentSaveStrategy = 'silent' | 'reload' | 'revalidate' | 'fetch';
|
|
485
|
+
/** Handler for the `fetch` strategy; the signal aborts when the plugin is removed. */
|
|
486
|
+
type DocumentSaveHandler = {
|
|
487
|
+
bivarianceHack(signal?: AbortSignal): void | Promise<void>;
|
|
488
|
+
}['bivarianceHack'];
|
|
489
|
+
interface DocumentSavePluginOptions {
|
|
490
|
+
/** Default `'silent'`. */
|
|
491
|
+
readonly strategy?: DocumentSaveStrategy;
|
|
492
|
+
/**
|
|
493
|
+
* `'revalidate'` endpoint, default `/api/revalidate`; the body is
|
|
494
|
+
* `{ source: 'payload-live-preview' }`. The request is a plain `fetch` from
|
|
495
|
+
* the preview page: cookies travel with it, there is no CSRF token, and a
|
|
496
|
+
* bearer secret in `revalidateHeaders` would sit in page JavaScript. The
|
|
497
|
+
* endpoint must authorise on its own (session cookie, same-origin check).
|
|
498
|
+
*/
|
|
499
|
+
readonly revalidateUrl?: string;
|
|
500
|
+
/** Extra request headers for `'revalidate'`; `Content-Type` is set already. */
|
|
501
|
+
readonly revalidateHeaders?: Readonly<Record<string, string>>;
|
|
502
|
+
/** `'fetch'` handler; rejections are logged, never thrown. */
|
|
503
|
+
readonly handler?: DocumentSaveHandler;
|
|
504
|
+
/** `'reload'` hard-refreshes when the revalidate request fails or returns non-2xx. */
|
|
505
|
+
readonly onRevalidateFailure?: 'silent' | 'reload';
|
|
506
|
+
}
|
|
507
|
+
declare function documentSavePlugin(options?: DocumentSavePluginOptions): LivePreviewPlugin;
|
|
508
|
+
|
|
509
|
+
export { type AnalyticsSnapshot, type CachedElement, type CustomRendererKey, DIAGNOSTIC_CODES, type DiagnosticCode, type DocumentSaveHandler, type DocumentSavePluginOptions, type DocumentSaveStrategy, EventEmitter, type EventHandler, type FieldRenderer, type FieldTransform, type FieldType, type LivePreviewEventMap, type LivePreviewPlugin, type PayloadBlockSchema, type PayloadDocumentEventDetail, type PayloadFieldCondition, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PluginCompatibility, type PluginContext, type PluginDisposer, type PluginEvents, type PluginInspection, PluginManager, type PluginManagerOptions, type RenderContext, type RendererKey, type RichTextRenderer, type Unsubscribe, type UpdateSource, createAnalyticsPlugin, debugPlugin, documentSavePlugin, highlightPlugin };
|