payload-live-preview 1.0.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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +389 -0
  3. package/dist/adapters/astro/RichText.astro +55 -0
  4. package/dist/adapters/astro/index.cjs +370 -0
  5. package/dist/adapters/astro/index.cjs.map +1 -0
  6. package/dist/adapters/astro/index.d.cts +105 -0
  7. package/dist/adapters/astro/index.d.ts +105 -0
  8. package/dist/adapters/astro/index.js +364 -0
  9. package/dist/adapters/astro/index.js.map +1 -0
  10. package/dist/adapters/astro/middleware-entry.cjs +303 -0
  11. package/dist/adapters/astro/middleware-entry.cjs.map +1 -0
  12. package/dist/adapters/astro/middleware-entry.d.cts +15 -0
  13. package/dist/adapters/astro/middleware-entry.d.ts +15 -0
  14. package/dist/adapters/astro/middleware-entry.js +297 -0
  15. package/dist/adapters/astro/middleware-entry.js.map +1 -0
  16. package/dist/adapters/nextjs/index.cjs +309 -0
  17. package/dist/adapters/nextjs/index.cjs.map +1 -0
  18. package/dist/adapters/nextjs/index.d.cts +75 -0
  19. package/dist/adapters/nextjs/index.d.ts +75 -0
  20. package/dist/adapters/nextjs/index.js +306 -0
  21. package/dist/adapters/nextjs/index.js.map +1 -0
  22. package/dist/adapters/nuxt/index.cjs +299 -0
  23. package/dist/adapters/nuxt/index.cjs.map +1 -0
  24. package/dist/adapters/nuxt/index.d.cts +126 -0
  25. package/dist/adapters/nuxt/index.d.ts +126 -0
  26. package/dist/adapters/nuxt/index.js +294 -0
  27. package/dist/adapters/nuxt/index.js.map +1 -0
  28. package/dist/adapters/sveltekit/index.cjs +275 -0
  29. package/dist/adapters/sveltekit/index.cjs.map +1 -0
  30. package/dist/adapters/sveltekit/index.d.cts +80 -0
  31. package/dist/adapters/sveltekit/index.d.ts +80 -0
  32. package/dist/adapters/sveltekit/index.js +273 -0
  33. package/dist/adapters/sveltekit/index.js.map +1 -0
  34. package/dist/bind-BSgxoQhN.d.cts +1137 -0
  35. package/dist/bind-BSgxoQhN.d.ts +1137 -0
  36. package/dist/codegen-astro.cjs +612 -0
  37. package/dist/codegen-astro.cjs.map +1 -0
  38. package/dist/codegen-astro.d.cts +54 -0
  39. package/dist/codegen-astro.d.ts +54 -0
  40. package/dist/codegen-astro.js +610 -0
  41. package/dist/codegen-astro.js.map +1 -0
  42. package/dist/codegen-cli.cjs +669 -0
  43. package/dist/codegen-cli.cjs.map +1 -0
  44. package/dist/codegen-cli.d.cts +19 -0
  45. package/dist/codegen-cli.d.ts +19 -0
  46. package/dist/codegen-cli.js +667 -0
  47. package/dist/codegen-cli.js.map +1 -0
  48. package/dist/codegen.cjs +551 -0
  49. package/dist/codegen.cjs.map +1 -0
  50. package/dist/codegen.d.cts +162 -0
  51. package/dist/codegen.d.ts +162 -0
  52. package/dist/codegen.js +547 -0
  53. package/dist/codegen.js.map +1 -0
  54. package/dist/core.cjs +3684 -0
  55. package/dist/core.cjs.map +1 -0
  56. package/dist/core.d.cts +24 -0
  57. package/dist/core.d.ts +24 -0
  58. package/dist/core.js +3657 -0
  59. package/dist/core.js.map +1 -0
  60. package/dist/index.cjs +4083 -0
  61. package/dist/index.cjs.map +1 -0
  62. package/dist/index.d.cts +472 -0
  63. package/dist/index.d.ts +472 -0
  64. package/dist/index.js +4040 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/middleware-BwIlf0jW.d.cts +168 -0
  67. package/dist/middleware-BwIlf0jW.d.ts +168 -0
  68. package/dist/payload.cjs +31 -0
  69. package/dist/payload.cjs.map +1 -0
  70. package/dist/payload.d.cts +87 -0
  71. package/dist/payload.d.ts +87 -0
  72. package/dist/payload.js +29 -0
  73. package/dist/payload.js.map +1 -0
  74. package/dist/preview-request-DAvxm18T.d.cts +68 -0
  75. package/dist/preview-request-DAvxm18T.d.ts +68 -0
  76. package/package.json +186 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Public types for the Astro adapter.
3
+ *
4
+ * @module @adapters/astro/types
5
+ */
6
+ interface LivePreviewAstroOptions {
7
+ /**
8
+ * How the integration wires the preview:
9
+ *
10
+ * - `'inline'` (default) — bake the runtime into every page at
11
+ * build time. For `output: 'static'` projects.
12
+ * - `'middleware'` — auto-register the preview middleware:
13
+ * request-time injection into preview requests only, plus
14
+ * `frame-ancestors` CSP management. For `output: 'server'`.
15
+ * (`shouldInject` is unsupported here — options serialize into
16
+ * the build.)
17
+ */
18
+ readonly mode?: 'inline' | 'middleware';
19
+ /**
20
+ * Trusted Payload admin origin(s). Required in production unless
21
+ * `document.referrer` reliably exposes the parent origin.
22
+ */
23
+ readonly allowedOrigins?: readonly string[];
24
+ /**
25
+ * Payload server origin, e.g. `https://cms.example.com`. When set,
26
+ * incoming updates are re-fetched through the Payload REST API so
27
+ * relationship/upload fields render populated instead of as bare
28
+ * IDs. Strongly recommended for Payload 3.x.
29
+ */
30
+ readonly serverURL?: string;
31
+ /** REST API route prefix used with `serverURL`. Defaults to `/api`. */
32
+ readonly apiRoute?: string;
33
+ /** Population depth used with `serverURL`. Defaults to `1`. */
34
+ readonly mergeDepth?: number;
35
+ /**
36
+ * Auto-inject the inline preview script. Default `true`. Disable to
37
+ * embed the script manually via `renderLivePreviewScript()`.
38
+ */
39
+ readonly autoInject?: boolean;
40
+ /**
41
+ * When the middleware injects the script (integration-based
42
+ * injection is always build-time and unaffected):
43
+ *
44
+ * - `'preview-only'` (default) — only into responses that look
45
+ * like preview requests (`?preview=true` / `?draft=true` query,
46
+ * `Sec-Fetch-Dest: iframe`, or a referer from `allowedOrigins`).
47
+ * Normal production traffic passes through untouched.
48
+ * - `'always'` — into every HTML response.
49
+ */
50
+ readonly inject?: 'preview-only' | 'always';
51
+ /**
52
+ * Query parameters that mark a request as a preview (values `true`
53
+ * or `1`). Default: `['preview', 'draft', 'livePreview']`.
54
+ */
55
+ readonly previewQueryParams?: readonly string[];
56
+ /**
57
+ * Which signals count as a preview request. Default: all three
58
+ * (`query`, `fetch-dest`, `referer`). Restrict to `['query']` when
59
+ * an unsolicited iframe load must never trigger preview handling
60
+ * (e.g. sites that serve `frame-ancestors 'none'` and only allow
61
+ * preview via the explicit `?preview=true` URL).
62
+ */
63
+ readonly previewSignals?: readonly ('query' | 'fetch-dest' | 'referer')[];
64
+ /**
65
+ * Restrict auto-inject to requests where this function returns
66
+ * `true`. Applied on top of the `inject` mode.
67
+ */
68
+ readonly shouldInject?: (request: Request) => boolean;
69
+ /**
70
+ * Content-Security-Policy management on preview responses:
71
+ *
72
+ * - `'frame-ancestors'` (default) — merge a `frame-ancestors`
73
+ * directive allowing the admin origins to embed the page.
74
+ * Existing CSP directives are preserved (union merge).
75
+ * - `'full'` — additionally manage `script-src` with a
76
+ * per-request nonce. Only useful when your whole page is
77
+ * nonce-disciplined; see `strictDynamic`.
78
+ * - `false` — never touch CSP headers.
79
+ *
80
+ * `true` is accepted as a legacy alias for `'frame-ancestors'`.
81
+ */
82
+ readonly manageCsp?: boolean | 'frame-ancestors' | 'full';
83
+ /**
84
+ * Add `'strict-dynamic'` to the managed `script-src` (only with
85
+ * `manageCsp: 'full'`). ⚠️ Under CSP 3 this makes browsers ignore
86
+ * `'self'` and host sources — every script on the page must then
87
+ * carry the nonce or be loaded by a nonce-carrying script. Astro's
88
+ * own hydration scripts do NOT carry it, so leave this off unless
89
+ * you know your page is fully nonce-disciplined. Default `false`.
90
+ */
91
+ readonly strictDynamic?: boolean;
92
+ /**
93
+ * Extra `frame-ancestors` sources to merge with the auto-detected
94
+ * ones. Always includes `'self'` and every entry in `allowedOrigins`.
95
+ */
96
+ readonly frameAncestorsExtra?: readonly string[];
97
+ /**
98
+ * Extra `script-src` sources (e.g., a CDN) appended after the nonce
99
+ * (only with `manageCsp: 'full'`).
100
+ */
101
+ readonly scriptSrcExtra?: readonly string[];
102
+ /**
103
+ * Enable verbose debug logging in the injected client. Default: dev mode.
104
+ */
105
+ readonly debug?: boolean;
106
+ /**
107
+ * Debounce window for incoming updates. Default: 50 ms.
108
+ */
109
+ readonly debounceMs?: number;
110
+ /**
111
+ * Heartbeat timeout in ms. Default `0` (disabled — the Payload admin
112
+ * sends no keepalive, so an idle timeout would cause false
113
+ * disconnects).
114
+ */
115
+ readonly heartbeatMs?: number;
116
+ }
117
+
118
+ /**
119
+ * Astro middleware for Payload Live Preview.
120
+ *
121
+ * Responsibilities (per request):
122
+ *
123
+ * 1. Generate a per-response CSP nonce and stash it on
124
+ * `Astro.locals.livePreviewNonce` so consumers can reference it.
125
+ * 2. On **preview requests only** (see `isPreviewRequest`), rewrite
126
+ * the HTML response to inject the live-preview `<script>` tag.
127
+ * Normal production traffic streams through untouched — no
128
+ * buffering, no extra bytes.
129
+ * 3. On preview requests, merge `frame-ancestors` into the
130
+ * `Content-Security-Policy` header so the Payload admin may embed
131
+ * the page. Full `script-src` nonce management is opt-in via
132
+ * `manageCsp: 'full'`.
133
+ *
134
+ * Prerendered pages are skipped entirely: Astro runs middleware at
135
+ * build time for those, where per-request nonces and response headers
136
+ * are meaningless.
137
+ *
138
+ * @module @adapters/astro/middleware
139
+ */
140
+
141
+ type MiddlewareNext = () => Promise<Response>;
142
+ interface MiddlewareContext {
143
+ readonly request: Request;
144
+ readonly locals: Record<string, unknown>;
145
+ /** Present in Astro ≥ 5: `true` while prerendering at build time. */
146
+ readonly isPrerendered?: boolean;
147
+ }
148
+ type LivePreviewMiddleware = (context: MiddlewareContext, next: MiddlewareNext) => Promise<Response>;
149
+ /**
150
+ * Key on `Astro.locals` carrying the request-scoped nonce. Consumers
151
+ * can read `Astro.locals.livePreviewNonce` from `.astro` templates to
152
+ * set the `nonce` attribute on their own scripts.
153
+ */
154
+ declare const NONCE_LOCALS_KEY = "livePreviewNonce";
155
+ /**
156
+ * Build the Astro-compatible middleware. Register it in
157
+ * `src/middleware.ts`:
158
+ *
159
+ * ```ts
160
+ * import { createLivePreviewMiddleware } from 'payload-live-preview/astro';
161
+ * export const onRequest = createLivePreviewMiddleware({
162
+ * allowedOrigins: [import.meta.env.PUBLIC_PAYLOAD_ADMIN_ORIGIN],
163
+ * });
164
+ * ```
165
+ */
166
+ declare function createLivePreviewMiddleware(options?: LivePreviewAstroOptions): LivePreviewMiddleware;
167
+
168
+ export { type LivePreviewAstroOptions as L, NONCE_LOCALS_KEY as N, type LivePreviewMiddleware as a, createLivePreviewMiddleware as c };
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Public types for the Astro adapter.
3
+ *
4
+ * @module @adapters/astro/types
5
+ */
6
+ interface LivePreviewAstroOptions {
7
+ /**
8
+ * How the integration wires the preview:
9
+ *
10
+ * - `'inline'` (default) — bake the runtime into every page at
11
+ * build time. For `output: 'static'` projects.
12
+ * - `'middleware'` — auto-register the preview middleware:
13
+ * request-time injection into preview requests only, plus
14
+ * `frame-ancestors` CSP management. For `output: 'server'`.
15
+ * (`shouldInject` is unsupported here — options serialize into
16
+ * the build.)
17
+ */
18
+ readonly mode?: 'inline' | 'middleware';
19
+ /**
20
+ * Trusted Payload admin origin(s). Required in production unless
21
+ * `document.referrer` reliably exposes the parent origin.
22
+ */
23
+ readonly allowedOrigins?: readonly string[];
24
+ /**
25
+ * Payload server origin, e.g. `https://cms.example.com`. When set,
26
+ * incoming updates are re-fetched through the Payload REST API so
27
+ * relationship/upload fields render populated instead of as bare
28
+ * IDs. Strongly recommended for Payload 3.x.
29
+ */
30
+ readonly serverURL?: string;
31
+ /** REST API route prefix used with `serverURL`. Defaults to `/api`. */
32
+ readonly apiRoute?: string;
33
+ /** Population depth used with `serverURL`. Defaults to `1`. */
34
+ readonly mergeDepth?: number;
35
+ /**
36
+ * Auto-inject the inline preview script. Default `true`. Disable to
37
+ * embed the script manually via `renderLivePreviewScript()`.
38
+ */
39
+ readonly autoInject?: boolean;
40
+ /**
41
+ * When the middleware injects the script (integration-based
42
+ * injection is always build-time and unaffected):
43
+ *
44
+ * - `'preview-only'` (default) — only into responses that look
45
+ * like preview requests (`?preview=true` / `?draft=true` query,
46
+ * `Sec-Fetch-Dest: iframe`, or a referer from `allowedOrigins`).
47
+ * Normal production traffic passes through untouched.
48
+ * - `'always'` — into every HTML response.
49
+ */
50
+ readonly inject?: 'preview-only' | 'always';
51
+ /**
52
+ * Query parameters that mark a request as a preview (values `true`
53
+ * or `1`). Default: `['preview', 'draft', 'livePreview']`.
54
+ */
55
+ readonly previewQueryParams?: readonly string[];
56
+ /**
57
+ * Which signals count as a preview request. Default: all three
58
+ * (`query`, `fetch-dest`, `referer`). Restrict to `['query']` when
59
+ * an unsolicited iframe load must never trigger preview handling
60
+ * (e.g. sites that serve `frame-ancestors 'none'` and only allow
61
+ * preview via the explicit `?preview=true` URL).
62
+ */
63
+ readonly previewSignals?: readonly ('query' | 'fetch-dest' | 'referer')[];
64
+ /**
65
+ * Restrict auto-inject to requests where this function returns
66
+ * `true`. Applied on top of the `inject` mode.
67
+ */
68
+ readonly shouldInject?: (request: Request) => boolean;
69
+ /**
70
+ * Content-Security-Policy management on preview responses:
71
+ *
72
+ * - `'frame-ancestors'` (default) — merge a `frame-ancestors`
73
+ * directive allowing the admin origins to embed the page.
74
+ * Existing CSP directives are preserved (union merge).
75
+ * - `'full'` — additionally manage `script-src` with a
76
+ * per-request nonce. Only useful when your whole page is
77
+ * nonce-disciplined; see `strictDynamic`.
78
+ * - `false` — never touch CSP headers.
79
+ *
80
+ * `true` is accepted as a legacy alias for `'frame-ancestors'`.
81
+ */
82
+ readonly manageCsp?: boolean | 'frame-ancestors' | 'full';
83
+ /**
84
+ * Add `'strict-dynamic'` to the managed `script-src` (only with
85
+ * `manageCsp: 'full'`). ⚠️ Under CSP 3 this makes browsers ignore
86
+ * `'self'` and host sources — every script on the page must then
87
+ * carry the nonce or be loaded by a nonce-carrying script. Astro's
88
+ * own hydration scripts do NOT carry it, so leave this off unless
89
+ * you know your page is fully nonce-disciplined. Default `false`.
90
+ */
91
+ readonly strictDynamic?: boolean;
92
+ /**
93
+ * Extra `frame-ancestors` sources to merge with the auto-detected
94
+ * ones. Always includes `'self'` and every entry in `allowedOrigins`.
95
+ */
96
+ readonly frameAncestorsExtra?: readonly string[];
97
+ /**
98
+ * Extra `script-src` sources (e.g., a CDN) appended after the nonce
99
+ * (only with `manageCsp: 'full'`).
100
+ */
101
+ readonly scriptSrcExtra?: readonly string[];
102
+ /**
103
+ * Enable verbose debug logging in the injected client. Default: dev mode.
104
+ */
105
+ readonly debug?: boolean;
106
+ /**
107
+ * Debounce window for incoming updates. Default: 50 ms.
108
+ */
109
+ readonly debounceMs?: number;
110
+ /**
111
+ * Heartbeat timeout in ms. Default `0` (disabled — the Payload admin
112
+ * sends no keepalive, so an idle timeout would cause false
113
+ * disconnects).
114
+ */
115
+ readonly heartbeatMs?: number;
116
+ }
117
+
118
+ /**
119
+ * Astro middleware for Payload Live Preview.
120
+ *
121
+ * Responsibilities (per request):
122
+ *
123
+ * 1. Generate a per-response CSP nonce and stash it on
124
+ * `Astro.locals.livePreviewNonce` so consumers can reference it.
125
+ * 2. On **preview requests only** (see `isPreviewRequest`), rewrite
126
+ * the HTML response to inject the live-preview `<script>` tag.
127
+ * Normal production traffic streams through untouched — no
128
+ * buffering, no extra bytes.
129
+ * 3. On preview requests, merge `frame-ancestors` into the
130
+ * `Content-Security-Policy` header so the Payload admin may embed
131
+ * the page. Full `script-src` nonce management is opt-in via
132
+ * `manageCsp: 'full'`.
133
+ *
134
+ * Prerendered pages are skipped entirely: Astro runs middleware at
135
+ * build time for those, where per-request nonces and response headers
136
+ * are meaningless.
137
+ *
138
+ * @module @adapters/astro/middleware
139
+ */
140
+
141
+ type MiddlewareNext = () => Promise<Response>;
142
+ interface MiddlewareContext {
143
+ readonly request: Request;
144
+ readonly locals: Record<string, unknown>;
145
+ /** Present in Astro ≥ 5: `true` while prerendering at build time. */
146
+ readonly isPrerendered?: boolean;
147
+ }
148
+ type LivePreviewMiddleware = (context: MiddlewareContext, next: MiddlewareNext) => Promise<Response>;
149
+ /**
150
+ * Key on `Astro.locals` carrying the request-scoped nonce. Consumers
151
+ * can read `Astro.locals.livePreviewNonce` from `.astro` templates to
152
+ * set the `nonce` attribute on their own scripts.
153
+ */
154
+ declare const NONCE_LOCALS_KEY = "livePreviewNonce";
155
+ /**
156
+ * Build the Astro-compatible middleware. Register it in
157
+ * `src/middleware.ts`:
158
+ *
159
+ * ```ts
160
+ * import { createLivePreviewMiddleware } from 'payload-live-preview/astro';
161
+ * export const onRequest = createLivePreviewMiddleware({
162
+ * allowedOrigins: [import.meta.env.PUBLIC_PAYLOAD_ADMIN_ORIGIN],
163
+ * });
164
+ * ```
165
+ */
166
+ declare function createLivePreviewMiddleware(options?: LivePreviewAstroOptions): LivePreviewMiddleware;
167
+
168
+ export { type LivePreviewAstroOptions as L, NONCE_LOCALS_KEY as N, type LivePreviewMiddleware as a, createLivePreviewMiddleware as c };
@@ -0,0 +1,31 @@
1
+ 'use strict';
2
+
3
+ // src/payload/index.ts
4
+ function buildLivePreviewUrl(options) {
5
+ const base = options.baseUrl.replace(/\/+$/, "");
6
+ const fallback = options.fallback ?? "/";
7
+ const previewParam = options.previewParam === void 0 ? "preview" : options.previewParam;
8
+ return (args) => {
9
+ const locale = normaliseLocale(args.locale);
10
+ const context = { data: args.data, locale };
11
+ const resolver = (args.collectionConfig !== void 0 ? options.collections?.[args.collectionConfig.slug] : void 0) ?? (args.globalConfig !== void 0 ? options.globals?.[args.globalConfig.slug] : void 0);
12
+ let path = fallback;
13
+ if (resolver !== void 0) {
14
+ const resolved = typeof resolver === "function" ? resolver(context) : resolver;
15
+ if (resolved.length > 0) path = resolved;
16
+ }
17
+ if (!path.startsWith("/")) path = `/${path}`;
18
+ if (previewParam === null) return `${base}${path}`;
19
+ const separator = path.includes("?") ? "&" : "?";
20
+ return `${base}${path}${separator}${previewParam}=true`;
21
+ };
22
+ }
23
+ function normaliseLocale(locale) {
24
+ if (locale === void 0) return void 0;
25
+ if (typeof locale === "string") return locale.length > 0 ? locale : void 0;
26
+ return locale.code.length > 0 ? locale.code : void 0;
27
+ }
28
+
29
+ exports.buildLivePreviewUrl = buildLivePreviewUrl;
30
+ //# sourceMappingURL=payload.cjs.map
31
+ //# sourceMappingURL=payload.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/payload/index.ts"],"names":[],"mappings":";;;AAmFO,SAAS,oBACd,OAAA,EACsC;AACtC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,GAAA;AACrC,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,YAAA,KAAiB,MAAA,GAAY,YAAY,OAAA,CAAQ,YAAA;AAE9E,EAAA,OAAO,CAAC,IAAA,KAAS;AACf,IAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAA;AAC1C,IAAA,MAAM,OAAA,GAA+B,EAAE,IAAA,EAAM,IAAA,CAAK,MAAM,MAAA,EAAO;AAE/D,IAAA,MAAM,YACH,IAAA,CAAK,gBAAA,KAAqB,SACvB,OAAA,CAAQ,WAAA,GAAc,KAAK,gBAAA,CAAiB,IAAI,IAChD,MAAA,MACH,IAAA,CAAK,iBAAiB,MAAA,GAAY,OAAA,CAAQ,UAAU,IAAA,CAAK,YAAA,CAAa,IAAI,CAAA,GAAI,MAAA,CAAA;AAEjF,IAAA,IAAI,IAAA,GAAO,QAAA;AACX,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,MAAM,WAAW,OAAO,QAAA,KAAa,UAAA,GAAa,QAAA,CAAS,OAAO,CAAA,GAAI,QAAA;AACtE,MAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,IAAA,GAAO,QAAA;AAAA,IAClC;AACA,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA;AAE1C,IAAA,IAAI,iBAAiB,IAAA,EAAM,OAAO,CAAA,EAAG,IAAI,GAAG,IAAI,CAAA,CAAA;AAChD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,QAAA,CAAS,GAAG,IAAI,GAAA,GAAM,GAAA;AAC7C,IAAA,OAAO,GAAG,IAAI,CAAA,EAAG,IAAI,CAAA,EAAG,SAAS,GAAG,YAAY,CAAA,KAAA,CAAA;AAAA,EAClD,CAAA;AACF;AAEA,SAAS,gBAAgB,MAAA,EAA0D;AACjF,EAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AACjC,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,SAAiB,MAAA,CAAO,MAAA,GAAS,IAAI,MAAA,GAAS,MAAA;AACpE,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,OAAO,IAAA,GAAO,MAAA;AAChD","file":"payload.cjs","sourcesContent":["/**\n * Backend-side helpers for `payload.config.ts`.\n *\n * Payload's `admin.livePreview.url` callback maps the document being\n * edited to the frontend URL that should be shown in the preview\n * iframe. In practice every project hand-writes the same lookup-table\n * boilerplate (global → path, collection → localized route, fallback\n * when a new draft has no slug yet). `buildLivePreviewUrl` packages\n * that pattern.\n *\n * This module is dependency-free and framework-agnostic — it does not\n * import `payload`, it just produces a function with the documented\n * callback shape.\n *\n * ```ts\n * // payload.config.ts\n * import { buildLivePreviewUrl } from 'payload-live-preview/payload';\n *\n * admin: {\n * livePreview: {\n * url: buildLivePreviewUrl({\n * baseUrl: process.env.FRONTEND_URL ?? 'http://localhost:4321',\n * collections: {\n * services: ({ data, locale }) => `/${locale}/services/${String(data.slug ?? '')}`,\n * posts: ({ data }) => `/blog/${String(data.slug ?? '')}`,\n * },\n * globals: {\n * homepage: '/',\n * contact: ({ locale }) => `/${locale}/contact`,\n * },\n * fallback: '/',\n * }),\n * collections: ['services', 'posts'],\n * globals: ['homepage', 'contact'],\n * },\n * }\n * ```\n *\n * @module @payload\n */\n\n/** Arguments Payload passes to `admin.livePreview.url`. */\nexport interface LivePreviewUrlArgs {\n readonly data: Record<string, unknown>;\n readonly locale?: string | { readonly code: string };\n readonly collectionConfig?: { readonly slug: string };\n readonly globalConfig?: { readonly slug: string };\n readonly [extra: string]: unknown;\n}\n\n/** Context handed to per-slug path resolvers. */\nexport interface PathResolverContext {\n readonly data: Record<string, unknown>;\n /** Normalised locale code (string), or `undefined`. */\n readonly locale: string | undefined;\n}\n\nexport type PathResolver = string | ((context: PathResolverContext) => string);\n\nexport interface BuildLivePreviewUrlOptions {\n /** Frontend origin, e.g. `https://site.example` (no trailing slash needed). */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. */\n readonly collections?: Readonly<Record<string, PathResolver>>;\n /** Per-global path resolvers keyed by global slug. */\n readonly globals?: Readonly<Record<string, PathResolver>>;\n /**\n * Path used when no resolver matches, or when a resolver returns an\n * empty string (e.g. a brand-new draft without a slug). Default `/`.\n */\n readonly fallback?: string;\n /**\n * Query parameter appended so the frontend can recognise the request\n * as a preview (`isPreviewRequest` checks it). Set `null` to disable.\n * Default `'preview'` → `?preview=true`.\n */\n readonly previewParam?: string | null;\n}\n\n/**\n * Build an `admin.livePreview.url` callback from declarative slug →\n * path mappings.\n */\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlOptions,\n): (args: LivePreviewUrlArgs) => string {\n const base = options.baseUrl.replace(/\\/+$/, '');\n const fallback = options.fallback ?? '/';\n const previewParam = options.previewParam === undefined ? 'preview' : options.previewParam;\n\n return (args) => {\n const locale = normaliseLocale(args.locale);\n const context: PathResolverContext = { data: args.data, locale };\n\n const resolver =\n (args.collectionConfig !== undefined\n ? options.collections?.[args.collectionConfig.slug]\n : undefined) ??\n (args.globalConfig !== undefined ? options.globals?.[args.globalConfig.slug] : undefined);\n\n let path = fallback;\n if (resolver !== undefined) {\n const resolved = typeof resolver === 'function' ? resolver(context) : resolver;\n if (resolved.length > 0) path = resolved;\n }\n if (!path.startsWith('/')) path = `/${path}`;\n\n if (previewParam === null) return `${base}${path}`;\n const separator = path.includes('?') ? '&' : '?';\n return `${base}${path}${separator}${previewParam}=true`;\n };\n}\n\nfunction normaliseLocale(locale: LivePreviewUrlArgs['locale']): string | undefined {\n if (locale === undefined) return undefined;\n if (typeof locale === 'string') return locale.length > 0 ? locale : undefined;\n return locale.code.length > 0 ? locale.code : undefined;\n}\n"]}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Backend-side helpers for `payload.config.ts`.
3
+ *
4
+ * Payload's `admin.livePreview.url` callback maps the document being
5
+ * edited to the frontend URL that should be shown in the preview
6
+ * iframe. In practice every project hand-writes the same lookup-table
7
+ * boilerplate (global → path, collection → localized route, fallback
8
+ * when a new draft has no slug yet). `buildLivePreviewUrl` packages
9
+ * that pattern.
10
+ *
11
+ * This module is dependency-free and framework-agnostic — it does not
12
+ * import `payload`, it just produces a function with the documented
13
+ * callback shape.
14
+ *
15
+ * ```ts
16
+ * // payload.config.ts
17
+ * import { buildLivePreviewUrl } from 'payload-live-preview/payload';
18
+ *
19
+ * admin: {
20
+ * livePreview: {
21
+ * url: buildLivePreviewUrl({
22
+ * baseUrl: process.env.FRONTEND_URL ?? 'http://localhost:4321',
23
+ * collections: {
24
+ * services: ({ data, locale }) => `/${locale}/services/${String(data.slug ?? '')}`,
25
+ * posts: ({ data }) => `/blog/${String(data.slug ?? '')}`,
26
+ * },
27
+ * globals: {
28
+ * homepage: '/',
29
+ * contact: ({ locale }) => `/${locale}/contact`,
30
+ * },
31
+ * fallback: '/',
32
+ * }),
33
+ * collections: ['services', 'posts'],
34
+ * globals: ['homepage', 'contact'],
35
+ * },
36
+ * }
37
+ * ```
38
+ *
39
+ * @module @payload
40
+ */
41
+ /** Arguments Payload passes to `admin.livePreview.url`. */
42
+ interface LivePreviewUrlArgs {
43
+ readonly data: Record<string, unknown>;
44
+ readonly locale?: string | {
45
+ readonly code: string;
46
+ };
47
+ readonly collectionConfig?: {
48
+ readonly slug: string;
49
+ };
50
+ readonly globalConfig?: {
51
+ readonly slug: string;
52
+ };
53
+ readonly [extra: string]: unknown;
54
+ }
55
+ /** Context handed to per-slug path resolvers. */
56
+ interface PathResolverContext {
57
+ readonly data: Record<string, unknown>;
58
+ /** Normalised locale code (string), or `undefined`. */
59
+ readonly locale: string | undefined;
60
+ }
61
+ type PathResolver = string | ((context: PathResolverContext) => string);
62
+ interface BuildLivePreviewUrlOptions {
63
+ /** Frontend origin, e.g. `https://site.example` (no trailing slash needed). */
64
+ readonly baseUrl: string;
65
+ /** Per-collection path resolvers keyed by collection slug. */
66
+ readonly collections?: Readonly<Record<string, PathResolver>>;
67
+ /** Per-global path resolvers keyed by global slug. */
68
+ readonly globals?: Readonly<Record<string, PathResolver>>;
69
+ /**
70
+ * Path used when no resolver matches, or when a resolver returns an
71
+ * empty string (e.g. a brand-new draft without a slug). Default `/`.
72
+ */
73
+ readonly fallback?: string;
74
+ /**
75
+ * Query parameter appended so the frontend can recognise the request
76
+ * as a preview (`isPreviewRequest` checks it). Set `null` to disable.
77
+ * Default `'preview'` → `?preview=true`.
78
+ */
79
+ readonly previewParam?: string | null;
80
+ }
81
+ /**
82
+ * Build an `admin.livePreview.url` callback from declarative slug →
83
+ * path mappings.
84
+ */
85
+ declare function buildLivePreviewUrl(options: BuildLivePreviewUrlOptions): (args: LivePreviewUrlArgs) => string;
86
+
87
+ export { type BuildLivePreviewUrlOptions, type LivePreviewUrlArgs, type PathResolver, type PathResolverContext, buildLivePreviewUrl };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Backend-side helpers for `payload.config.ts`.
3
+ *
4
+ * Payload's `admin.livePreview.url` callback maps the document being
5
+ * edited to the frontend URL that should be shown in the preview
6
+ * iframe. In practice every project hand-writes the same lookup-table
7
+ * boilerplate (global → path, collection → localized route, fallback
8
+ * when a new draft has no slug yet). `buildLivePreviewUrl` packages
9
+ * that pattern.
10
+ *
11
+ * This module is dependency-free and framework-agnostic — it does not
12
+ * import `payload`, it just produces a function with the documented
13
+ * callback shape.
14
+ *
15
+ * ```ts
16
+ * // payload.config.ts
17
+ * import { buildLivePreviewUrl } from 'payload-live-preview/payload';
18
+ *
19
+ * admin: {
20
+ * livePreview: {
21
+ * url: buildLivePreviewUrl({
22
+ * baseUrl: process.env.FRONTEND_URL ?? 'http://localhost:4321',
23
+ * collections: {
24
+ * services: ({ data, locale }) => `/${locale}/services/${String(data.slug ?? '')}`,
25
+ * posts: ({ data }) => `/blog/${String(data.slug ?? '')}`,
26
+ * },
27
+ * globals: {
28
+ * homepage: '/',
29
+ * contact: ({ locale }) => `/${locale}/contact`,
30
+ * },
31
+ * fallback: '/',
32
+ * }),
33
+ * collections: ['services', 'posts'],
34
+ * globals: ['homepage', 'contact'],
35
+ * },
36
+ * }
37
+ * ```
38
+ *
39
+ * @module @payload
40
+ */
41
+ /** Arguments Payload passes to `admin.livePreview.url`. */
42
+ interface LivePreviewUrlArgs {
43
+ readonly data: Record<string, unknown>;
44
+ readonly locale?: string | {
45
+ readonly code: string;
46
+ };
47
+ readonly collectionConfig?: {
48
+ readonly slug: string;
49
+ };
50
+ readonly globalConfig?: {
51
+ readonly slug: string;
52
+ };
53
+ readonly [extra: string]: unknown;
54
+ }
55
+ /** Context handed to per-slug path resolvers. */
56
+ interface PathResolverContext {
57
+ readonly data: Record<string, unknown>;
58
+ /** Normalised locale code (string), or `undefined`. */
59
+ readonly locale: string | undefined;
60
+ }
61
+ type PathResolver = string | ((context: PathResolverContext) => string);
62
+ interface BuildLivePreviewUrlOptions {
63
+ /** Frontend origin, e.g. `https://site.example` (no trailing slash needed). */
64
+ readonly baseUrl: string;
65
+ /** Per-collection path resolvers keyed by collection slug. */
66
+ readonly collections?: Readonly<Record<string, PathResolver>>;
67
+ /** Per-global path resolvers keyed by global slug. */
68
+ readonly globals?: Readonly<Record<string, PathResolver>>;
69
+ /**
70
+ * Path used when no resolver matches, or when a resolver returns an
71
+ * empty string (e.g. a brand-new draft without a slug). Default `/`.
72
+ */
73
+ readonly fallback?: string;
74
+ /**
75
+ * Query parameter appended so the frontend can recognise the request
76
+ * as a preview (`isPreviewRequest` checks it). Set `null` to disable.
77
+ * Default `'preview'` → `?preview=true`.
78
+ */
79
+ readonly previewParam?: string | null;
80
+ }
81
+ /**
82
+ * Build an `admin.livePreview.url` callback from declarative slug →
83
+ * path mappings.
84
+ */
85
+ declare function buildLivePreviewUrl(options: BuildLivePreviewUrlOptions): (args: LivePreviewUrlArgs) => string;
86
+
87
+ export { type BuildLivePreviewUrlOptions, type LivePreviewUrlArgs, type PathResolver, type PathResolverContext, buildLivePreviewUrl };
@@ -0,0 +1,29 @@
1
+ // src/payload/index.ts
2
+ function buildLivePreviewUrl(options) {
3
+ const base = options.baseUrl.replace(/\/+$/, "");
4
+ const fallback = options.fallback ?? "/";
5
+ const previewParam = options.previewParam === void 0 ? "preview" : options.previewParam;
6
+ return (args) => {
7
+ const locale = normaliseLocale(args.locale);
8
+ const context = { data: args.data, locale };
9
+ const resolver = (args.collectionConfig !== void 0 ? options.collections?.[args.collectionConfig.slug] : void 0) ?? (args.globalConfig !== void 0 ? options.globals?.[args.globalConfig.slug] : void 0);
10
+ let path = fallback;
11
+ if (resolver !== void 0) {
12
+ const resolved = typeof resolver === "function" ? resolver(context) : resolver;
13
+ if (resolved.length > 0) path = resolved;
14
+ }
15
+ if (!path.startsWith("/")) path = `/${path}`;
16
+ if (previewParam === null) return `${base}${path}`;
17
+ const separator = path.includes("?") ? "&" : "?";
18
+ return `${base}${path}${separator}${previewParam}=true`;
19
+ };
20
+ }
21
+ function normaliseLocale(locale) {
22
+ if (locale === void 0) return void 0;
23
+ if (typeof locale === "string") return locale.length > 0 ? locale : void 0;
24
+ return locale.code.length > 0 ? locale.code : void 0;
25
+ }
26
+
27
+ export { buildLivePreviewUrl };
28
+ //# sourceMappingURL=payload.js.map
29
+ //# sourceMappingURL=payload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/payload/index.ts"],"names":[],"mappings":";AAmFO,SAAS,oBACd,OAAA,EACsC;AACtC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,IAAY,GAAA;AACrC,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,YAAA,KAAiB,MAAA,GAAY,YAAY,OAAA,CAAQ,YAAA;AAE9E,EAAA,OAAO,CAAC,IAAA,KAAS;AACf,IAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAA;AAC1C,IAAA,MAAM,OAAA,GAA+B,EAAE,IAAA,EAAM,IAAA,CAAK,MAAM,MAAA,EAAO;AAE/D,IAAA,MAAM,YACH,IAAA,CAAK,gBAAA,KAAqB,SACvB,OAAA,CAAQ,WAAA,GAAc,KAAK,gBAAA,CAAiB,IAAI,IAChD,MAAA,MACH,IAAA,CAAK,iBAAiB,MAAA,GAAY,OAAA,CAAQ,UAAU,IAAA,CAAK,YAAA,CAAa,IAAI,CAAA,GAAI,MAAA,CAAA;AAEjF,IAAA,IAAI,IAAA,GAAO,QAAA;AACX,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,MAAM,WAAW,OAAO,QAAA,KAAa,UAAA,GAAa,QAAA,CAAS,OAAO,CAAA,GAAI,QAAA;AACtE,MAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,IAAA,GAAO,QAAA;AAAA,IAClC;AACA,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA;AAE1C,IAAA,IAAI,iBAAiB,IAAA,EAAM,OAAO,CAAA,EAAG,IAAI,GAAG,IAAI,CAAA,CAAA;AAChD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,QAAA,CAAS,GAAG,IAAI,GAAA,GAAM,GAAA;AAC7C,IAAA,OAAO,GAAG,IAAI,CAAA,EAAG,IAAI,CAAA,EAAG,SAAS,GAAG,YAAY,CAAA,KAAA,CAAA;AAAA,EAClD,CAAA;AACF;AAEA,SAAS,gBAAgB,MAAA,EAA0D;AACjF,EAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AACjC,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,SAAiB,MAAA,CAAO,MAAA,GAAS,IAAI,MAAA,GAAS,MAAA;AACpE,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,OAAO,IAAA,GAAO,MAAA;AAChD","file":"payload.js","sourcesContent":["/**\n * Backend-side helpers for `payload.config.ts`.\n *\n * Payload's `admin.livePreview.url` callback maps the document being\n * edited to the frontend URL that should be shown in the preview\n * iframe. In practice every project hand-writes the same lookup-table\n * boilerplate (global → path, collection → localized route, fallback\n * when a new draft has no slug yet). `buildLivePreviewUrl` packages\n * that pattern.\n *\n * This module is dependency-free and framework-agnostic — it does not\n * import `payload`, it just produces a function with the documented\n * callback shape.\n *\n * ```ts\n * // payload.config.ts\n * import { buildLivePreviewUrl } from 'payload-live-preview/payload';\n *\n * admin: {\n * livePreview: {\n * url: buildLivePreviewUrl({\n * baseUrl: process.env.FRONTEND_URL ?? 'http://localhost:4321',\n * collections: {\n * services: ({ data, locale }) => `/${locale}/services/${String(data.slug ?? '')}`,\n * posts: ({ data }) => `/blog/${String(data.slug ?? '')}`,\n * },\n * globals: {\n * homepage: '/',\n * contact: ({ locale }) => `/${locale}/contact`,\n * },\n * fallback: '/',\n * }),\n * collections: ['services', 'posts'],\n * globals: ['homepage', 'contact'],\n * },\n * }\n * ```\n *\n * @module @payload\n */\n\n/** Arguments Payload passes to `admin.livePreview.url`. */\nexport interface LivePreviewUrlArgs {\n readonly data: Record<string, unknown>;\n readonly locale?: string | { readonly code: string };\n readonly collectionConfig?: { readonly slug: string };\n readonly globalConfig?: { readonly slug: string };\n readonly [extra: string]: unknown;\n}\n\n/** Context handed to per-slug path resolvers. */\nexport interface PathResolverContext {\n readonly data: Record<string, unknown>;\n /** Normalised locale code (string), or `undefined`. */\n readonly locale: string | undefined;\n}\n\nexport type PathResolver = string | ((context: PathResolverContext) => string);\n\nexport interface BuildLivePreviewUrlOptions {\n /** Frontend origin, e.g. `https://site.example` (no trailing slash needed). */\n readonly baseUrl: string;\n /** Per-collection path resolvers keyed by collection slug. */\n readonly collections?: Readonly<Record<string, PathResolver>>;\n /** Per-global path resolvers keyed by global slug. */\n readonly globals?: Readonly<Record<string, PathResolver>>;\n /**\n * Path used when no resolver matches, or when a resolver returns an\n * empty string (e.g. a brand-new draft without a slug). Default `/`.\n */\n readonly fallback?: string;\n /**\n * Query parameter appended so the frontend can recognise the request\n * as a preview (`isPreviewRequest` checks it). Set `null` to disable.\n * Default `'preview'` → `?preview=true`.\n */\n readonly previewParam?: string | null;\n}\n\n/**\n * Build an `admin.livePreview.url` callback from declarative slug →\n * path mappings.\n */\nexport function buildLivePreviewUrl(\n options: BuildLivePreviewUrlOptions,\n): (args: LivePreviewUrlArgs) => string {\n const base = options.baseUrl.replace(/\\/+$/, '');\n const fallback = options.fallback ?? '/';\n const previewParam = options.previewParam === undefined ? 'preview' : options.previewParam;\n\n return (args) => {\n const locale = normaliseLocale(args.locale);\n const context: PathResolverContext = { data: args.data, locale };\n\n const resolver =\n (args.collectionConfig !== undefined\n ? options.collections?.[args.collectionConfig.slug]\n : undefined) ??\n (args.globalConfig !== undefined ? options.globals?.[args.globalConfig.slug] : undefined);\n\n let path = fallback;\n if (resolver !== undefined) {\n const resolved = typeof resolver === 'function' ? resolver(context) : resolver;\n if (resolved.length > 0) path = resolved;\n }\n if (!path.startsWith('/')) path = `/${path}`;\n\n if (previewParam === null) return `${base}${path}`;\n const separator = path.includes('?') ? '&' : '?';\n return `${base}${path}${separator}${previewParam}=true`;\n };\n}\n\nfunction normaliseLocale(locale: LivePreviewUrlArgs['locale']): string | undefined {\n if (locale === undefined) return undefined;\n if (typeof locale === 'string') return locale.length > 0 ? locale : undefined;\n return locale.code.length > 0 ? locale.code : undefined;\n}\n"]}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Server-side preview-request detection.
3
+ *
4
+ * The live-preview runtime only ever activates inside the Payload
5
+ * admin's iframe, but the *server* still has to decide whether to
6
+ * inject the (sizeable) inline script into a given HTML response.
7
+ * Injecting it into every page for every visitor buffers every
8
+ * response and ships dead bytes to production traffic — so adapters
9
+ * gate injection on this predicate by default, and consumers with
10
+ * hand-rolled middleware can import it directly.
11
+ *
12
+ * A request counts as a preview when any of these hold:
13
+ *
14
+ * 1. A preview query parameter is present (`?preview=true`,
15
+ * `?draft=true`, `?livePreview=true` — configurable).
16
+ * 2. `Sec-Fetch-Dest: iframe` — the document is being loaded as an
17
+ * iframe, which is exactly how the Payload admin embeds it.
18
+ * (Sent by all evergreen browsers; absence never *excludes* a
19
+ * request, presence includes it.)
20
+ * 3. The `Referer` points at one of the given admin origins.
21
+ *
22
+ * @module @adapters/shared/preview-request
23
+ */
24
+ /** The individual signals the predicate can consider. */
25
+ type PreviewSignal = 'query' | 'fetch-dest' | 'referer';
26
+ interface PreviewRequestOptions {
27
+ /**
28
+ * Which signals count as "this is a preview request". Default: all
29
+ * three. High-security setups that must never relax framing headers
30
+ * for unsolicited iframe loads can restrict to `['query']` — then
31
+ * only an explicit `?preview=true` (e.g. from `buildLivePreviewUrl`)
32
+ * activates preview handling.
33
+ */
34
+ readonly signals?: readonly PreviewSignal[];
35
+ /**
36
+ * Query parameters (with values `true` or `1`) that mark a request
37
+ * as a preview. Default: `['preview', 'draft', 'livePreview']`.
38
+ */
39
+ readonly queryParams?: readonly string[];
40
+ /**
41
+ * Treat `Sec-Fetch-Dest: iframe` as a preview signal. Default `true`.
42
+ * Legacy alias for excluding `'fetch-dest'` from `signals`.
43
+ */
44
+ readonly checkFetchDest?: boolean;
45
+ /**
46
+ * Admin origins whose `Referer` marks a request as a preview,
47
+ * e.g. `['https://cms.example.com']`.
48
+ */
49
+ readonly adminOrigins?: readonly string[];
50
+ }
51
+ /**
52
+ * The minimal request surface the predicate needs. The standard
53
+ * `Request` satisfies it structurally, and server frameworks without
54
+ * fetch-style requests (e.g. Nitro/H3) can supply a tiny shim.
55
+ */
56
+ interface PreviewRequestLike {
57
+ readonly url: string;
58
+ readonly headers: {
59
+ get(name: string): string | null;
60
+ };
61
+ }
62
+ /**
63
+ * Decide whether `request` is a live-preview request. See the module
64
+ * docblock for the exact signals.
65
+ */
66
+ declare function isPreviewRequest(request: PreviewRequestLike, options?: PreviewRequestOptions): boolean;
67
+
68
+ export { type PreviewRequestLike as P, type PreviewRequestOptions as a, isPreviewRequest as i };