@contentful/experiences-live-preview 0.1.8

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/CHANGELOG.md ADDED
@@ -0,0 +1,68 @@
1
+ ## 0.1.8 (2026-09-22)
2
+
3
+ ### 🧱 Updated Dependencies
4
+
5
+ - Updated client to 0.4.8
6
+
7
+ ## 0.1.7 (2026-09-22)
8
+
9
+ ### 🧱 Updated Dependencies
10
+
11
+ - Updated client to 0.4.7
12
+ - Updated core to 0.8.6
13
+
14
+ ## 0.1.6 (2026-09-22)
15
+
16
+ ### 🩹 Fixes
17
+
18
+ - **live-preview:** accept payloads without viewports [SPA-5272] ([6db6fa7](https://github.com/contentful/experiences/commit/6db6fa7))
19
+
20
+ ### 🧱 Updated Dependencies
21
+
22
+ - Updated client to 0.4.6
23
+ - Updated core to 0.8.5
24
+
25
+ ## 0.1.5 (2026-09-22)
26
+
27
+ ### 🚀 Features
28
+
29
+ - **live-preview:** expose connection errors [SPA-5151] ([#198](https://github.com/contentful/experiences/pull/198))
30
+
31
+ ## 0.1.4 (2026-09-21)
32
+
33
+ ### 🧱 Updated Dependencies
34
+
35
+ - Updated client to 0.4.5
36
+ - Updated core to 0.8.4
37
+
38
+ ## 0.1.3 (2026-09-21)
39
+
40
+ ### 🧱 Updated Dependencies
41
+
42
+ - Updated client to 0.4.4
43
+
44
+ ## 0.1.2 (2026-09-18)
45
+
46
+ ### 🚀 Features
47
+
48
+ - **live-preview:** support resource resolution [SPA-5369] ([#193](https://github.com/contentful/experiences/pull/193))
49
+
50
+ ## 0.1.1 (2026-09-11)
51
+
52
+ ### 🚀 Features
53
+
54
+ - **live-preview:** expose preview status helper [SPA-5289] ([#170](https://github.com/contentful/experiences/pull/170))
55
+
56
+ ### 🧱 Updated Dependencies
57
+
58
+ - Updated core to 0.8.3
59
+
60
+ ## 0.1.0 (2026-09-10)
61
+
62
+ ### 🚀 Features
63
+
64
+ - **live-preview:** add live preview client [SPA-5151] ([#157](https://github.com/contentful/experiences/pull/157))
65
+
66
+ ### 🧱 Updated Dependencies
67
+
68
+ - Updated core to 0.8.2
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # @contentful/experiences-live-preview
2
+
3
+ Optional live preview for Contentful Experiences.
4
+
5
+ ## API
6
+
7
+ ```ts
8
+ type PreviewSessionOptions = {
9
+ spaceId: string;
10
+ environmentId: string;
11
+ previewToken?: string;
12
+ sessionId?: string;
13
+ resourceResolution?: string;
14
+ sessionHost?: string;
15
+ debug?: boolean;
16
+ };
17
+
18
+ type PreviewSessionExperienceOptions = {
19
+ spaceId: string;
20
+ environmentId: string;
21
+ sessionId: string;
22
+ resourceResolution?: string;
23
+ };
24
+
25
+ type PreviewSessionClientOptions = {
26
+ previewToken: string;
27
+ host?: string;
28
+ };
29
+
30
+ type PreviewSessionResolveOptions = {
31
+ config: ResolverConfig;
32
+ metadata?: Record<string, unknown>;
33
+ debug?: boolean;
34
+ initialViewportId?: string;
35
+ };
36
+
37
+ fetchPreviewSession(
38
+ previewSessionOptions: PreviewSessionExperienceOptions,
39
+ clientOptions: PreviewSessionClientOptions,
40
+ resolveOptions: PreviewSessionResolveOptions,
41
+ ): Promise<PortableRenderPlan>;
42
+
43
+ PreviewSessionFetchError;
44
+ LivePreviewConnectionError;
45
+ NotFoundError;
46
+ PREVIEW_WEBSOCKET_HOST;
47
+
48
+ type LivePreviewResult = {
49
+ data: ExperiencePayload | undefined;
50
+ error: Error | undefined;
51
+ };
52
+
53
+ type LivePreviewClient = {
54
+ getResult(): LivePreviewResult;
55
+ subscribe(listener: () => void): () => void;
56
+ subscribeStatus(listener: (status: LivePreviewStatus) => void): () => void;
57
+ };
58
+
59
+ createLivePreviewClient(
60
+ previewSessionOptions: PreviewSessionOptions,
61
+ initialPayload?: ExperiencePayload,
62
+ ): LivePreviewClient;
63
+
64
+ sendPreviewStatus(status: LivePreviewStatus): void;
65
+ ```
66
+
67
+ Use `fetchPreviewSession` for the initial render when the Contentful app
68
+ provides a `preview_session_id`. It fetches the current Preview Session
69
+ snapshot and resolves it into a `PortableRenderPlan`. Use `createLivePreviewClient`
70
+ to receive subsequent WebSocket updates.
71
+
72
+ ```ts
73
+ import { fetchPreviewSession } from '@contentful/experiences-live-preview';
74
+
75
+ const plan = await fetchPreviewSession(
76
+ { spaceId, environmentId, sessionId },
77
+ { previewToken },
78
+ { config: experienceConfig }
79
+ );
80
+ ```
81
+
82
+ The request sends `previewToken` as a Bearer token in the `Authorization`
83
+ header. `host` selects a compatible Preview Session API host and defaults to
84
+ the production host. Pass the same encoded `resourceResolution` value in the
85
+ `previewSessionOptions` passed to `fetchPreviewSession` and
86
+ `createLivePreviewClient` when the session references resources from other
87
+ spaces. A missing session throws `NotFoundError`. Other request and response
88
+ failures throw `PreviewSessionFetchError`.
89
+
90
+ ## Usage
91
+
92
+ `createLivePreviewClient` returns a data source for a Preview Session. It opens
93
+ the socket when the first listener subscribes and publishes each valid `next`
94
+ payload as received. If you pass `initialPayload`, `getResult().data` returns
95
+ it until a valid update arrives. Without `initialPayload`, the data starts as
96
+ `undefined`.
97
+
98
+ `getResult().error` is set when the live-preview connection fails. The last
99
+ valid data remains available in `getResult().data`.
100
+
101
+ A valid payload may omit the deprecated `viewports` field while the APIs migrate
102
+ to flat design-property values.
103
+
104
+ `sessionId` and `previewToken` are optional. The package opens a socket only when
105
+ both values are provided. The caller supplies the session ID through
106
+ `PreviewSessionOptions`.
107
+
108
+ `sessionHost` is an optional WebSocket URL for the Preview Session service. It
109
+ defaults to the production Contentful Session service. The SDK uses the URL as
110
+ supplied, appends the subscription route, and sends `previewToken` as the
111
+ encoded `access_token` query parameter. When provided, `resourceResolution` is
112
+ sent as the encoded `resource_resolution` query parameter.
113
+
114
+ When you use the package directly in a Contentful preview, connect the client's
115
+ status subscription to `sendPreviewStatus`:
116
+
117
+ ```ts
118
+ import { createLivePreviewClient, sendPreviewStatus } from '@contentful/experiences-live-preview';
119
+
120
+ const client = createLivePreviewClient(previewSessionOptions);
121
+ const unsubscribeStatus = client.subscribeStatus(sendPreviewStatus);
122
+ const unsubscribe = client.subscribe(() => {
123
+ const experience = client.getResult().data;
124
+ if (experience) updatePreview(experience);
125
+ });
126
+ ```
127
+
128
+ This tells the Contentful app how to coordinate updates with the SDK. The
129
+ subscription is required for this integration. Framework adapters set it up for
130
+ you. Keep both unsubscribe functions and call them when the preview no longer
131
+ uses the client.
132
+
133
+ A valid `next` message replaces the current data atomically. The client keeps
134
+ the last valid data when it receives malformed messages, server errors, or
135
+ transport interruptions. Unknown message types are ignored. The `next` payload
136
+ contains an `Experience`. Adapters can build on this source and reuse its socket
137
+ and message handling. Other frameworks can use the same framework-neutral
138
+ client.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Thrown by `fetchPreviewSession` for a Preview Session fetch failure other
3
+ * than a missing session.
4
+ */
5
+ declare class PreviewSessionFetchError extends Error {
6
+ readonly spaceId: string;
7
+ readonly environmentId: string;
8
+ readonly sessionId: string;
9
+ constructor(message: string, options: {
10
+ spaceId: string;
11
+ environmentId: string;
12
+ sessionId: string;
13
+ cause?: unknown;
14
+ });
15
+ }
16
+ declare class LivePreviewConnectionError extends Error {
17
+ constructor();
18
+ }
19
+
20
+ export { LivePreviewConnectionError, PreviewSessionFetchError };
package/dist/errors.js ADDED
@@ -0,0 +1,23 @@
1
+ class PreviewSessionFetchError extends Error {
2
+ spaceId;
3
+ environmentId;
4
+ sessionId;
5
+ constructor(message, options) {
6
+ super(message, options.cause !== void 0 ? { cause: options.cause } : void 0);
7
+ this.name = "PreviewSessionFetchError";
8
+ this.spaceId = options.spaceId;
9
+ this.environmentId = options.environmentId;
10
+ this.sessionId = options.sessionId;
11
+ }
12
+ }
13
+ class LivePreviewConnectionError extends Error {
14
+ constructor() {
15
+ super("Live Preview connection failed.");
16
+ this.name = "LivePreviewConnectionError";
17
+ }
18
+ }
19
+ export {
20
+ LivePreviewConnectionError,
21
+ PreviewSessionFetchError
22
+ };
23
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Thrown by `fetchPreviewSession` for a Preview Session fetch failure other\n * than a missing session.\n */\nexport class PreviewSessionFetchError extends Error {\n readonly spaceId: string;\n readonly environmentId: string;\n readonly sessionId: string;\n\n constructor(\n message: string,\n options: {\n spaceId: string;\n environmentId: string;\n sessionId: string;\n cause?: unknown;\n }\n ) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = 'PreviewSessionFetchError';\n this.spaceId = options.spaceId;\n this.environmentId = options.environmentId;\n this.sessionId = options.sessionId;\n }\n}\n\nexport class LivePreviewConnectionError extends Error {\n constructor() {\n super('Live Preview connection failed.');\n this.name = 'LivePreviewConnectionError';\n }\n}\n"],"mappings":"AAIO,MAAM,iCAAiC,MAAM;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,SACA,SAMA;AACA,UAAM,SAAS,QAAQ,UAAU,SAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,MAAS;AACjF,SAAK,OAAO;AACZ,SAAK,UAAU,QAAQ;AACvB,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,YAAY,QAAQ;AAAA,EAC3B;AACF;AAEO,MAAM,mCAAmC,MAAM;AAAA,EACpD,cAAc;AACZ,UAAM,iCAAiC;AACvC,SAAK,OAAO;AAAA,EACd;AACF;","names":[]}
@@ -0,0 +1,7 @@
1
+ import { ExperiencePayload } from '@contentful/experiences-sdk-core';
2
+
3
+ declare function isRecord(value: unknown): value is Record<string, unknown>;
4
+ declare function isExperiencePayload(value: unknown): value is ExperiencePayload;
5
+ declare function isErrorPayload(value: unknown): boolean;
6
+
7
+ export { isErrorPayload, isExperiencePayload, isRecord };
@@ -0,0 +1,20 @@
1
+ function isRecord(value) {
2
+ return typeof value === "object" && value !== null;
3
+ }
4
+ function isExperiencePayload(value) {
5
+ if (!isRecord(value) || !Array.isArray(value.nodes) || value.viewports !== void 0 && !Array.isArray(value.viewports)) {
6
+ return false;
7
+ }
8
+ const sys = value.sys;
9
+ return isRecord(sys) && !Array.isArray(sys) && sys.type === "Experience";
10
+ }
11
+ function isErrorPayload(value) {
12
+ if (!isRecord(value) || !isRecord(value.sys) || Array.isArray(value.sys)) return false;
13
+ return value.sys.type === "Error" && typeof value.sys.id === "string";
14
+ }
15
+ export {
16
+ isErrorPayload,
17
+ isExperiencePayload,
18
+ isRecord
19
+ };
20
+ //# sourceMappingURL=experience-payload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/experience-payload.ts"],"sourcesContent":["import type { ExperiencePayload } from '@contentful/experiences-sdk-core';\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function isExperiencePayload(value: unknown): value is ExperiencePayload {\n if (\n !isRecord(value) ||\n !Array.isArray(value.nodes) ||\n (value.viewports !== undefined && !Array.isArray(value.viewports))\n ) {\n return false;\n }\n\n const sys = value.sys;\n return isRecord(sys) && !Array.isArray(sys) && sys.type === 'Experience';\n}\n\nexport function isErrorPayload(value: unknown): boolean {\n if (!isRecord(value) || !isRecord(value.sys) || Array.isArray(value.sys)) return false;\n return value.sys.type === 'Error' && typeof value.sys.id === 'string';\n}\n"],"mappings":"AAEO,SAAS,SAAS,OAAkD;AACzE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEO,SAAS,oBAAoB,OAA4C;AAC9E,MACE,CAAC,SAAS,KAAK,KACf,CAAC,MAAM,QAAQ,MAAM,KAAK,KACzB,MAAM,cAAc,UAAa,CAAC,MAAM,QAAQ,MAAM,SAAS,GAChE;AACA,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,MAAM;AAClB,SAAO,SAAS,GAAG,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,SAAS;AAC9D;AAEO,SAAS,eAAe,OAAyB;AACtD,MAAI,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,MAAM,GAAG,KAAK,MAAM,QAAQ,MAAM,GAAG,EAAG,QAAO;AACjF,SAAO,MAAM,IAAI,SAAS,WAAW,OAAO,MAAM,IAAI,OAAO;AAC/D;","names":[]}
@@ -0,0 +1,28 @@
1
+ import { ResolverConfig, PortableRenderPlan } from '@contentful/experiences-sdk-core';
2
+
3
+ type PreviewSessionExperienceOptions = {
4
+ spaceId: string;
5
+ environmentId: string;
6
+ sessionId: string;
7
+ /**
8
+ * Opaque encoded resource-resolution value for referenced spaces.
9
+ */
10
+ resourceResolution?: string;
11
+ };
12
+ type PreviewSessionClientOptions = {
13
+ previewToken: string;
14
+ host?: string;
15
+ };
16
+ type PreviewSessionResolveOptions = {
17
+ config: ResolverConfig;
18
+ metadata?: Record<string, unknown>;
19
+ debug?: boolean;
20
+ initialViewportId?: string;
21
+ };
22
+ /**
23
+ * Fetches the current hydrated Experience for a Preview Session and resolves
24
+ * it into the renderer's PortableRenderPlan.
25
+ */
26
+ declare function fetchPreviewSession(previewSessionOptions: PreviewSessionExperienceOptions, clientOptions: PreviewSessionClientOptions, resolveOptions: PreviewSessionResolveOptions): Promise<PortableRenderPlan>;
27
+
28
+ export { type PreviewSessionClientOptions, type PreviewSessionExperienceOptions, type PreviewSessionResolveOptions, fetchPreviewSession };
@@ -0,0 +1,55 @@
1
+ import { createClient, NotFoundError, PREVIEW_HOST } from "@contentful/experiences-client";
2
+ import {
3
+ createDebugLogger,
4
+ resolveExperience
5
+ } from "@contentful/experiences-sdk-core";
6
+ import { PreviewSessionFetchError } from "./errors.js";
7
+ import { isExperiencePayload } from "./experience-payload.js";
8
+ import { previewSessionGetExperienceUrl } from "./preview-session-url.js";
9
+ async function fetchPreviewSession(previewSessionOptions, clientOptions, resolveOptions) {
10
+ const { spaceId, environmentId, sessionId, resourceResolution } = previewSessionOptions;
11
+ const { previewToken, host } = clientOptions;
12
+ const { config, metadata, debug, initialViewportId } = resolveOptions;
13
+ const log = createDebugLogger(debug, "live-preview");
14
+ const client = createClient({
15
+ accessToken: previewToken,
16
+ host: host ?? PREVIEW_HOST
17
+ });
18
+ log.log("fetching preview session experience", { spaceId, environmentId, sessionId });
19
+ let payload;
20
+ try {
21
+ const response = await client.fetch(
22
+ previewSessionGetExperienceUrl({ ...previewSessionOptions, resourceResolution })
23
+ );
24
+ if (response.status === 404) {
25
+ throw new NotFoundError();
26
+ }
27
+ if (!response.ok) {
28
+ throw new Error(`HTTP ${response.status}`);
29
+ }
30
+ const responsePayload = await response.json();
31
+ if (!isExperiencePayload(responsePayload)) {
32
+ throw new Error("Response was not a valid Experience payload");
33
+ }
34
+ payload = responsePayload;
35
+ } catch (error) {
36
+ if (error instanceof NotFoundError) {
37
+ throw error;
38
+ }
39
+ const reason = error instanceof Error ? error.message : String(error);
40
+ throw new PreviewSessionFetchError(
41
+ `Failed to fetch Preview Session "${sessionId}" (space "${spaceId}", environment "${environmentId}"): ${reason}`,
42
+ { spaceId, environmentId, sessionId, cause: error }
43
+ );
44
+ }
45
+ log.lazy("received raw payload", () => payload);
46
+ return resolveExperience(payload, config, {
47
+ metadata,
48
+ debug,
49
+ initialViewportId
50
+ });
51
+ }
52
+ export {
53
+ fetchPreviewSession
54
+ };
55
+ //# sourceMappingURL=fetch-preview-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fetch-preview-session.ts"],"sourcesContent":["import { createClient, NotFoundError, PREVIEW_HOST } from '@contentful/experiences-client';\nimport {\n createDebugLogger,\n resolveExperience,\n type ExperiencePayload,\n type PortableRenderPlan,\n type ResolverConfig,\n} from '@contentful/experiences-sdk-core';\nimport { PreviewSessionFetchError } from './errors.js';\nimport { isExperiencePayload } from './experience-payload.js';\nimport { previewSessionGetExperienceUrl } from './preview-session-url.js';\n\nexport type PreviewSessionExperienceOptions = {\n spaceId: string;\n environmentId: string;\n sessionId: string;\n /**\n * Opaque encoded resource-resolution value for referenced spaces.\n */\n resourceResolution?: string;\n};\n\nexport type PreviewSessionClientOptions = {\n previewToken: string;\n host?: string;\n};\n\nexport type PreviewSessionResolveOptions = {\n config: ResolverConfig;\n metadata?: Record<string, unknown>;\n debug?: boolean;\n initialViewportId?: string;\n};\n\n/**\n * Fetches the current hydrated Experience for a Preview Session and resolves\n * it into the renderer's PortableRenderPlan.\n */\nexport async function fetchPreviewSession(\n previewSessionOptions: PreviewSessionExperienceOptions,\n clientOptions: PreviewSessionClientOptions,\n resolveOptions: PreviewSessionResolveOptions\n): Promise<PortableRenderPlan> {\n const { spaceId, environmentId, sessionId, resourceResolution } = previewSessionOptions;\n const { previewToken, host } = clientOptions;\n const { config, metadata, debug, initialViewportId } = resolveOptions;\n const log = createDebugLogger(debug, 'live-preview');\n const client = createClient({\n accessToken: previewToken,\n host: host ?? PREVIEW_HOST,\n });\n\n log.log('fetching preview session experience', { spaceId, environmentId, sessionId });\n\n let payload: ExperiencePayload;\n try {\n const response = await client.fetch(\n previewSessionGetExperienceUrl({ ...previewSessionOptions, resourceResolution })\n );\n if (response.status === 404) {\n throw new NotFoundError();\n }\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const responsePayload: unknown = await response.json();\n if (!isExperiencePayload(responsePayload)) {\n throw new Error('Response was not a valid Experience payload');\n }\n payload = responsePayload;\n } catch (error) {\n if (error instanceof NotFoundError) {\n throw error;\n }\n const reason = error instanceof Error ? error.message : String(error);\n throw new PreviewSessionFetchError(\n `Failed to fetch Preview Session \"${sessionId}\" (space \"${spaceId}\", environment ` +\n `\"${environmentId}\"): ${reason}`,\n { spaceId, environmentId, sessionId, cause: error }\n );\n }\n\n log.lazy('received raw payload', () => payload);\n\n return resolveExperience(payload, config, {\n metadata,\n debug,\n initialViewportId,\n });\n}\n"],"mappings":"AAAA,SAAS,cAAc,eAAe,oBAAoB;AAC1D;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AACP,SAAS,gCAAgC;AACzC,SAAS,2BAA2B;AACpC,SAAS,sCAAsC;AA4B/C,eAAsB,oBACpB,uBACA,eACA,gBAC6B;AAC7B,QAAM,EAAE,SAAS,eAAe,WAAW,mBAAmB,IAAI;AAClE,QAAM,EAAE,cAAc,KAAK,IAAI;AAC/B,QAAM,EAAE,QAAQ,UAAU,OAAO,kBAAkB,IAAI;AACvD,QAAM,MAAM,kBAAkB,OAAO,cAAc;AACnD,QAAM,SAAS,aAAa;AAAA,IAC1B,aAAa;AAAA,IACb,MAAM,QAAQ;AAAA,EAChB,CAAC;AAED,MAAI,IAAI,uCAAuC,EAAE,SAAS,eAAe,UAAU,CAAC;AAEpF,MAAI;AACJ,MAAI;AACF,UAAM,WAAW,MAAM,OAAO;AAAA,MAC5B,+BAA+B,EAAE,GAAG,uBAAuB,mBAAmB,CAAC;AAAA,IACjF;AACA,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,IAAI,cAAc;AAAA,IAC1B;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,EAAE;AAAA,IAC3C;AAEA,UAAM,kBAA2B,MAAM,SAAS,KAAK;AACrD,QAAI,CAAC,oBAAoB,eAAe,GAAG;AACzC,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,cAAU;AAAA,EACZ,SAAS,OAAO;AACd,QAAI,iBAAiB,eAAe;AAClC,YAAM;AAAA,IACR;AACA,UAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,UAAM,IAAI;AAAA,MACR,oCAAoC,SAAS,aAAa,OAAO,mBAC3D,aAAa,OAAO,MAAM;AAAA,MAChC,EAAE,SAAS,eAAe,WAAW,OAAO,MAAM;AAAA,IACpD;AAAA,EACF;AAEA,MAAI,KAAK,wBAAwB,MAAM,OAAO;AAE9C,SAAO,kBAAkB,SAAS,QAAQ;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;","names":[]}
@@ -0,0 +1,7 @@
1
+ export { LivePreviewClient, LivePreviewResult, LivePreviewStatus, createLivePreviewClient } from './live-preview-client.js';
2
+ export { sendPreviewStatus } from './preview-status.js';
3
+ export { PreviewSessionClientOptions, PreviewSessionExperienceOptions, PreviewSessionResolveOptions, fetchPreviewSession } from './fetch-preview-session.js';
4
+ export { LivePreviewConnectionError, PreviewSessionFetchError } from './errors.js';
5
+ export { NotFoundError, PREVIEW_WEBSOCKET_HOST } from '@contentful/experiences-client';
6
+ export { PreviewSessionOptions } from './preview-session.js';
7
+ import '@contentful/experiences-sdk-core';
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ import { createLivePreviewClient } from "./live-preview-client.js";
2
+ import { sendPreviewStatus } from "./preview-status.js";
3
+ import { fetchPreviewSession } from "./fetch-preview-session.js";
4
+ import { LivePreviewConnectionError, PreviewSessionFetchError } from "./errors.js";
5
+ import { PREVIEW_WEBSOCKET_HOST } from "@contentful/experiences-client";
6
+ import { NotFoundError } from "@contentful/experiences-client";
7
+ export {
8
+ LivePreviewConnectionError,
9
+ NotFoundError,
10
+ PREVIEW_WEBSOCKET_HOST,
11
+ PreviewSessionFetchError,
12
+ createLivePreviewClient,
13
+ fetchPreviewSession,
14
+ sendPreviewStatus
15
+ };
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { createLivePreviewClient } from './live-preview-client.js';\nexport { sendPreviewStatus } from './preview-status.js';\nexport { fetchPreviewSession } from './fetch-preview-session.js';\nexport { LivePreviewConnectionError, PreviewSessionFetchError } from './errors.js';\nexport { PREVIEW_WEBSOCKET_HOST } from '@contentful/experiences-client';\nexport type {\n LivePreviewClient,\n LivePreviewResult,\n LivePreviewStatus,\n} from './live-preview-client.js';\nexport type { PreviewSessionOptions } from './preview-session.js';\nexport type {\n PreviewSessionClientOptions,\n PreviewSessionExperienceOptions,\n PreviewSessionResolveOptions,\n} from './fetch-preview-session.js';\nexport { NotFoundError } from '@contentful/experiences-client';\n"],"mappings":"AAAA,SAAS,+BAA+B;AACxC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,4BAA4B,gCAAgC;AACrE,SAAS,8BAA8B;AAYvC,SAAS,qBAAqB;","names":[]}
@@ -0,0 +1,19 @@
1
+ import { ExperiencePayload } from '@contentful/experiences-sdk-core';
2
+ import { PreviewSessionOptions } from './preview-session.js';
3
+ import './errors.js';
4
+
5
+ type LivePreviewStatus = 'live' | 'static';
6
+ type LivePreviewResult = {
7
+ readonly data: ExperiencePayload | undefined;
8
+ readonly error: Error | undefined;
9
+ };
10
+ type LivePreviewClient = {
11
+ getResult(): LivePreviewResult;
12
+ /** @deprecated Use getResult().data instead. */
13
+ getSnapshot(): ExperiencePayload | undefined;
14
+ subscribe(listener: () => void): () => void;
15
+ subscribeStatus(listener: (status: LivePreviewStatus) => void): () => void;
16
+ };
17
+ declare function createLivePreviewClient(previewSessionOptions: PreviewSessionOptions, initialPayload?: ExperiencePayload): LivePreviewClient;
18
+
19
+ export { type LivePreviewClient, type LivePreviewResult, type LivePreviewStatus, createLivePreviewClient };
@@ -0,0 +1,73 @@
1
+ import { subscribeToPreviewSession } from "./preview-session.js";
2
+ function createLivePreviewClient(previewSessionOptions, initialPayload) {
3
+ const listeners = /* @__PURE__ */ new Set();
4
+ const statusListeners = /* @__PURE__ */ new Set();
5
+ const notifyListeners = () => {
6
+ for (const { handler } of [...listeners]) handler();
7
+ };
8
+ const hasLivePreviewOptions = previewSessionOptions.sessionId !== void 0 && previewSessionOptions.previewToken !== void 0;
9
+ let currentStatus = hasLivePreviewOptions ? void 0 : "static";
10
+ let currentResult = { data: initialPayload, error: void 0 };
11
+ let unsubscribeFromSession;
12
+ const updateData = (data) => {
13
+ currentResult = { ...currentResult, data };
14
+ notifyListeners();
15
+ };
16
+ const updateError = (error) => {
17
+ currentResult = { ...currentResult, error };
18
+ updateStatus("static");
19
+ notifyListeners();
20
+ };
21
+ const updateStatus = (status) => {
22
+ if (status === "live" && currentResult.error !== void 0) {
23
+ currentResult = { ...currentResult, error: void 0 };
24
+ notifyListeners();
25
+ }
26
+ if (currentStatus === status) return;
27
+ currentStatus = status;
28
+ for (const { handler } of [...statusListeners]) handler(status);
29
+ };
30
+ const closeSession = () => {
31
+ unsubscribeFromSession?.();
32
+ unsubscribeFromSession = void 0;
33
+ if (hasLivePreviewOptions) currentStatus = void 0;
34
+ };
35
+ return {
36
+ getResult: () => currentResult,
37
+ getSnapshot: () => currentResult.data,
38
+ subscribe(listener) {
39
+ const subscription = { handler: listener };
40
+ const isFirstSubscriber = listeners.size === 0;
41
+ listeners.add(subscription);
42
+ if (isFirstSubscriber) {
43
+ try {
44
+ unsubscribeFromSession = subscribeToPreviewSession(previewSessionOptions, {
45
+ onOpen: () => updateStatus("live"),
46
+ onError: updateError,
47
+ onUpdate: updateData
48
+ });
49
+ } catch (error) {
50
+ listeners.delete(subscription);
51
+ closeSession();
52
+ throw error;
53
+ }
54
+ }
55
+ return () => {
56
+ if (!listeners.delete(subscription)) return;
57
+ if (listeners.size === 0) closeSession();
58
+ };
59
+ },
60
+ subscribeStatus(listener) {
61
+ const subscription = { handler: listener };
62
+ statusListeners.add(subscription);
63
+ if (currentStatus !== void 0) listener(currentStatus);
64
+ return () => {
65
+ statusListeners.delete(subscription);
66
+ };
67
+ }
68
+ };
69
+ }
70
+ export {
71
+ createLivePreviewClient
72
+ };
73
+ //# sourceMappingURL=live-preview-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/live-preview-client.ts"],"sourcesContent":["import type { ExperiencePayload } from '@contentful/experiences-sdk-core';\nimport { subscribeToPreviewSession, type PreviewSessionOptions } from './preview-session.js';\n\nexport type LivePreviewStatus = 'live' | 'static';\n\nexport type LivePreviewResult = {\n readonly data: ExperiencePayload | undefined;\n readonly error: Error | undefined;\n};\n\nexport type LivePreviewClient = {\n getResult(): LivePreviewResult;\n /** @deprecated Use getResult().data instead. */\n getSnapshot(): ExperiencePayload | undefined;\n subscribe(listener: () => void): () => void;\n subscribeStatus(listener: (status: LivePreviewStatus) => void): () => void;\n};\n\nexport function createLivePreviewClient(\n previewSessionOptions: PreviewSessionOptions,\n initialPayload?: ExperiencePayload\n): LivePreviewClient {\n const listeners = new Set<{ handler: () => void }>();\n const statusListeners = new Set<{ handler: (status: LivePreviewStatus) => void }>();\n const notifyListeners = (): void => {\n for (const { handler } of [...listeners]) handler();\n };\n\n const hasLivePreviewOptions =\n previewSessionOptions.sessionId !== undefined &&\n previewSessionOptions.previewToken !== undefined;\n let currentStatus: LivePreviewStatus | undefined = hasLivePreviewOptions ? undefined : 'static';\n let currentResult: LivePreviewResult = { data: initialPayload, error: undefined };\n let unsubscribeFromSession: (() => void) | undefined;\n\n const updateData = (data: ExperiencePayload): void => {\n currentResult = { ...currentResult, data };\n notifyListeners();\n };\n\n const updateError = (error: Error): void => {\n currentResult = { ...currentResult, error };\n updateStatus('static');\n notifyListeners();\n };\n\n const updateStatus = (status: LivePreviewStatus): void => {\n if (status === 'live' && currentResult.error !== undefined) {\n currentResult = { ...currentResult, error: undefined };\n notifyListeners();\n }\n if (currentStatus === status) return;\n currentStatus = status;\n for (const { handler } of [...statusListeners]) handler(status);\n };\n\n const closeSession = (): void => {\n unsubscribeFromSession?.();\n unsubscribeFromSession = undefined;\n if (hasLivePreviewOptions) currentStatus = undefined;\n };\n\n return {\n getResult: () => currentResult,\n getSnapshot: () => currentResult.data,\n subscribe(listener) {\n const subscription = { handler: listener };\n const isFirstSubscriber = listeners.size === 0;\n listeners.add(subscription);\n if (isFirstSubscriber) {\n try {\n unsubscribeFromSession = subscribeToPreviewSession(previewSessionOptions, {\n onOpen: () => updateStatus('live'),\n onError: updateError,\n onUpdate: updateData,\n });\n } catch (error: unknown) {\n listeners.delete(subscription);\n closeSession();\n throw error;\n }\n }\n\n return () => {\n if (!listeners.delete(subscription)) return;\n if (listeners.size === 0) closeSession();\n };\n },\n subscribeStatus(listener) {\n const subscription = { handler: listener };\n statusListeners.add(subscription);\n if (currentStatus !== undefined) listener(currentStatus);\n\n return () => {\n statusListeners.delete(subscription);\n };\n },\n };\n}\n"],"mappings":"AACA,SAAS,iCAA6D;AAiB/D,SAAS,wBACd,uBACA,gBACmB;AACnB,QAAM,YAAY,oBAAI,IAA6B;AACnD,QAAM,kBAAkB,oBAAI,IAAsD;AAClF,QAAM,kBAAkB,MAAY;AAClC,eAAW,EAAE,QAAQ,KAAK,CAAC,GAAG,SAAS,EAAG,SAAQ;AAAA,EACpD;AAEA,QAAM,wBACJ,sBAAsB,cAAc,UACpC,sBAAsB,iBAAiB;AACzC,MAAI,gBAA+C,wBAAwB,SAAY;AACvF,MAAI,gBAAmC,EAAE,MAAM,gBAAgB,OAAO,OAAU;AAChF,MAAI;AAEJ,QAAM,aAAa,CAAC,SAAkC;AACpD,oBAAgB,EAAE,GAAG,eAAe,KAAK;AACzC,oBAAgB;AAAA,EAClB;AAEA,QAAM,cAAc,CAAC,UAAuB;AAC1C,oBAAgB,EAAE,GAAG,eAAe,MAAM;AAC1C,iBAAa,QAAQ;AACrB,oBAAgB;AAAA,EAClB;AAEA,QAAM,eAAe,CAAC,WAAoC;AACxD,QAAI,WAAW,UAAU,cAAc,UAAU,QAAW;AAC1D,sBAAgB,EAAE,GAAG,eAAe,OAAO,OAAU;AACrD,sBAAgB;AAAA,IAClB;AACA,QAAI,kBAAkB,OAAQ;AAC9B,oBAAgB;AAChB,eAAW,EAAE,QAAQ,KAAK,CAAC,GAAG,eAAe,EAAG,SAAQ,MAAM;AAAA,EAChE;AAEA,QAAM,eAAe,MAAY;AAC/B,6BAAyB;AACzB,6BAAyB;AACzB,QAAI,sBAAuB,iBAAgB;AAAA,EAC7C;AAEA,SAAO;AAAA,IACL,WAAW,MAAM;AAAA,IACjB,aAAa,MAAM,cAAc;AAAA,IACjC,UAAU,UAAU;AAClB,YAAM,eAAe,EAAE,SAAS,SAAS;AACzC,YAAM,oBAAoB,UAAU,SAAS;AAC7C,gBAAU,IAAI,YAAY;AAC1B,UAAI,mBAAmB;AACrB,YAAI;AACF,mCAAyB,0BAA0B,uBAAuB;AAAA,YACxE,QAAQ,MAAM,aAAa,MAAM;AAAA,YACjC,SAAS;AAAA,YACT,UAAU;AAAA,UACZ,CAAC;AAAA,QACH,SAAS,OAAgB;AACvB,oBAAU,OAAO,YAAY;AAC7B,uBAAa;AACb,gBAAM;AAAA,QACR;AAAA,MACF;AAEA,aAAO,MAAM;AACX,YAAI,CAAC,UAAU,OAAO,YAAY,EAAG;AACrC,YAAI,UAAU,SAAS,EAAG,cAAa;AAAA,MACzC;AAAA,IACF;AAAA,IACA,gBAAgB,UAAU;AACxB,YAAM,eAAe,EAAE,SAAS,SAAS;AACzC,sBAAgB,IAAI,YAAY;AAChC,UAAI,kBAAkB,OAAW,UAAS,aAAa;AAEvD,aAAO,MAAM;AACX,wBAAgB,OAAO,YAAY;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,15 @@
1
+ type PreviewSessionRouteOptions = {
2
+ spaceId: string;
3
+ environmentId: string;
4
+ sessionId: string;
5
+ };
6
+ declare function previewSessionGetExperienceUrl({ resourceResolution, ...options }: PreviewSessionRouteOptions & {
7
+ resourceResolution?: string;
8
+ }): string;
9
+ declare function previewSessionSubscribeUrl({ spaceId, environmentId, sessionId, sessionHost, previewToken, resourceResolution, }: PreviewSessionRouteOptions & {
10
+ sessionHost?: string;
11
+ previewToken: string;
12
+ resourceResolution?: string;
13
+ }): string;
14
+
15
+ export { previewSessionGetExperienceUrl, previewSessionSubscribeUrl };
@@ -0,0 +1,44 @@
1
+ import { PREVIEW_WEBSOCKET_HOST } from "@contentful/experiences-client";
2
+ function previewSessionPath(options) {
3
+ return [
4
+ "spaces",
5
+ encodeURIComponent(options.spaceId),
6
+ "environments",
7
+ encodeURIComponent(options.environmentId),
8
+ "preview_sessions",
9
+ encodeURIComponent(options.sessionId)
10
+ ].join("/");
11
+ }
12
+ function previewSessionGetExperienceUrl({
13
+ resourceResolution,
14
+ ...options
15
+ }) {
16
+ const path = `/${previewSessionPath(options)}/experience`;
17
+ if (resourceResolution === void 0) return path;
18
+ const searchParams = new globalThis.URLSearchParams({
19
+ resource_resolution: resourceResolution
20
+ });
21
+ return `${path}?${searchParams.toString()}`;
22
+ }
23
+ function previewSessionSubscribeUrl({
24
+ spaceId,
25
+ environmentId,
26
+ sessionId,
27
+ sessionHost,
28
+ previewToken,
29
+ resourceResolution
30
+ }) {
31
+ const url = new globalThis.URL(sessionHost ?? PREVIEW_WEBSOCKET_HOST);
32
+ const basePath = url.pathname.replace(/\/+$/, "");
33
+ url.pathname = `${basePath}/${previewSessionPath({ spaceId, environmentId, sessionId })}/subscribe`;
34
+ url.searchParams.set("access_token", previewToken);
35
+ if (resourceResolution !== void 0) {
36
+ url.searchParams.set("resource_resolution", resourceResolution);
37
+ }
38
+ return url.toString();
39
+ }
40
+ export {
41
+ previewSessionGetExperienceUrl,
42
+ previewSessionSubscribeUrl
43
+ };
44
+ //# sourceMappingURL=preview-session-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/preview-session-url.ts"],"sourcesContent":["import { PREVIEW_WEBSOCKET_HOST } from '@contentful/experiences-client';\n\ntype PreviewSessionRouteOptions = {\n spaceId: string;\n environmentId: string;\n sessionId: string;\n};\n\nfunction previewSessionPath(options: PreviewSessionRouteOptions): string {\n return [\n 'spaces',\n encodeURIComponent(options.spaceId),\n 'environments',\n encodeURIComponent(options.environmentId),\n 'preview_sessions',\n encodeURIComponent(options.sessionId),\n ].join('/');\n}\n\nexport function previewSessionGetExperienceUrl({\n resourceResolution,\n ...options\n}: PreviewSessionRouteOptions & { resourceResolution?: string }): string {\n const path = `/${previewSessionPath(options)}/experience`;\n if (resourceResolution === undefined) return path;\n\n const searchParams = new globalThis.URLSearchParams({\n resource_resolution: resourceResolution,\n });\n return `${path}?${searchParams.toString()}`;\n}\n\nexport function previewSessionSubscribeUrl({\n spaceId,\n environmentId,\n sessionId,\n sessionHost,\n previewToken,\n resourceResolution,\n}: PreviewSessionRouteOptions & {\n sessionHost?: string;\n previewToken: string;\n resourceResolution?: string;\n}): string {\n const url = new globalThis.URL(sessionHost ?? PREVIEW_WEBSOCKET_HOST);\n const basePath = url.pathname.replace(/\\/+$/, '');\n url.pathname = `${basePath}/${previewSessionPath({ spaceId, environmentId, sessionId })}/subscribe`;\n url.searchParams.set('access_token', previewToken);\n if (resourceResolution !== undefined) {\n url.searchParams.set('resource_resolution', resourceResolution);\n }\n\n return url.toString();\n}\n"],"mappings":"AAAA,SAAS,8BAA8B;AAQvC,SAAS,mBAAmB,SAA6C;AACvE,SAAO;AAAA,IACL;AAAA,IACA,mBAAmB,QAAQ,OAAO;AAAA,IAClC;AAAA,IACA,mBAAmB,QAAQ,aAAa;AAAA,IACxC;AAAA,IACA,mBAAmB,QAAQ,SAAS;AAAA,EACtC,EAAE,KAAK,GAAG;AACZ;AAEO,SAAS,+BAA+B;AAAA,EAC7C;AAAA,EACA,GAAG;AACL,GAAyE;AACvE,QAAM,OAAO,IAAI,mBAAmB,OAAO,CAAC;AAC5C,MAAI,uBAAuB,OAAW,QAAO;AAE7C,QAAM,eAAe,IAAI,WAAW,gBAAgB;AAAA,IAClD,qBAAqB;AAAA,EACvB,CAAC;AACD,SAAO,GAAG,IAAI,IAAI,aAAa,SAAS,CAAC;AAC3C;AAEO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAIW;AACT,QAAM,MAAM,IAAI,WAAW,IAAI,eAAe,sBAAsB;AACpE,QAAM,WAAW,IAAI,SAAS,QAAQ,QAAQ,EAAE;AAChD,MAAI,WAAW,GAAG,QAAQ,IAAI,mBAAmB,EAAE,SAAS,eAAe,UAAU,CAAC,CAAC;AACvF,MAAI,aAAa,IAAI,gBAAgB,YAAY;AACjD,MAAI,uBAAuB,QAAW;AACpC,QAAI,aAAa,IAAI,uBAAuB,kBAAkB;AAAA,EAChE;AAEA,SAAO,IAAI,SAAS;AACtB;","names":[]}
@@ -0,0 +1,27 @@
1
+ import { ExperiencePayload } from '@contentful/experiences-sdk-core';
2
+ import { LivePreviewConnectionError } from './errors.js';
3
+
4
+ type PreviewSessionOptions = {
5
+ spaceId: string;
6
+ environmentId: string;
7
+ previewToken?: string;
8
+ sessionId?: string;
9
+ /**
10
+ * Opaque encoded resource-resolution value for referenced spaces.
11
+ */
12
+ resourceResolution?: string;
13
+ /**
14
+ * Custom WebSocket URL for Preview Session subscriptions (staging, proxy, per-region).
15
+ * Omit to use the production Preview Session WebSocket host.
16
+ */
17
+ sessionHost?: string;
18
+ debug?: boolean;
19
+ };
20
+ type PreviewSessionHandlers = {
21
+ onUpdate: (experience: ExperiencePayload) => void;
22
+ onOpen?: () => void;
23
+ onError?: (error: LivePreviewConnectionError) => void;
24
+ };
25
+ declare function subscribeToPreviewSession(options: PreviewSessionOptions, handlers: PreviewSessionHandlers): () => void;
26
+
27
+ export { type PreviewSessionOptions, subscribeToPreviewSession };
@@ -0,0 +1,74 @@
1
+ import { createDebugLogger } from "@contentful/experiences-sdk-core";
2
+ import { isErrorPayload, isExperiencePayload, isRecord } from "./experience-payload.js";
3
+ import { createWebSocketConnection } from "./websocket.js";
4
+ import { previewSessionSubscribeUrl } from "./preview-session-url.js";
5
+ import { LivePreviewConnectionError } from "./errors.js";
6
+ const RETRY_DELAYS_MS = [100, 500, 1e3];
7
+ function parseMessage(data) {
8
+ let message = data;
9
+ if (typeof data === "string") {
10
+ try {
11
+ message = JSON.parse(data);
12
+ } catch {
13
+ return { kind: "invalid" };
14
+ }
15
+ }
16
+ if (!isRecord(message) || typeof message.type !== "string") {
17
+ return { kind: "invalid" };
18
+ }
19
+ if (message.type === "next") {
20
+ return isExperiencePayload(message.data) ? { kind: "next", payload: message.data } : { kind: "invalid" };
21
+ }
22
+ if (message.type === "error") {
23
+ return isErrorPayload(message.data) ? { kind: "error" } : { kind: "invalid" };
24
+ }
25
+ return { kind: "unknown" };
26
+ }
27
+ function isSessionEnded(event) {
28
+ if (event.code !== 1e3) return false;
29
+ const reason = event.reason.trim().toLowerCase();
30
+ return reason === "deleted" || reason === "expired";
31
+ }
32
+ function subscribeToPreviewSession(options, handlers) {
33
+ const log = createDebugLogger(options.debug, "live-preview");
34
+ const { sessionId, previewToken } = options;
35
+ const { onError, onOpen, onUpdate } = handlers;
36
+ if (sessionId === void 0 || previewToken === void 0) return () => void 0;
37
+ const connection = createWebSocketConnection({
38
+ url: previewSessionSubscribeUrl({ ...options, sessionId, previewToken }),
39
+ retry: (failureCount, event) => {
40
+ const sessionEnded = isSessionEnded(event);
41
+ const hasExhaustedRetries = failureCount >= RETRY_DELAYS_MS.length;
42
+ const shouldRetry = !hasExhaustedRetries && !sessionEnded;
43
+ if (hasExhaustedRetries || sessionEnded) {
44
+ onError?.(new LivePreviewConnectionError());
45
+ }
46
+ return shouldRetry;
47
+ },
48
+ retryDelay: (retryAttempt) => RETRY_DELAYS_MS[retryAttempt] ?? RETRY_DELAYS_MS[RETRY_DELAYS_MS.length - 1] ?? 0,
49
+ onFailure: () => onError?.(new LivePreviewConnectionError())
50
+ });
51
+ const unsubscribeFromOpen = onOpen ? connection.onopen(() => onOpen()) : void 0;
52
+ const unsubscribe = connection.onmessage((event) => {
53
+ const message = parseMessage(event.data);
54
+ if (message.kind === "unknown") return;
55
+ if (message.kind === "error") {
56
+ log.log("Preview Session returned an error");
57
+ return;
58
+ }
59
+ if (message.kind === "invalid") {
60
+ log.log("ignored invalid Preview Session message");
61
+ return;
62
+ }
63
+ onUpdate(message.payload);
64
+ });
65
+ return () => {
66
+ unsubscribeFromOpen?.();
67
+ unsubscribe();
68
+ connection.close();
69
+ };
70
+ }
71
+ export {
72
+ subscribeToPreviewSession
73
+ };
74
+ //# sourceMappingURL=preview-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/preview-session.ts"],"sourcesContent":["import { createDebugLogger, type ExperiencePayload } from '@contentful/experiences-sdk-core';\nimport { isErrorPayload, isExperiencePayload, isRecord } from './experience-payload.js';\nimport { createWebSocketConnection, type WebSocketCloseEvent } from './websocket.js';\nimport { previewSessionSubscribeUrl } from './preview-session-url.js';\nimport { LivePreviewConnectionError } from './errors.js';\n\nconst RETRY_DELAYS_MS: readonly number[] = [100, 500, 1000];\n\nexport type PreviewSessionOptions = {\n spaceId: string;\n environmentId: string;\n previewToken?: string;\n sessionId?: string;\n /**\n * Opaque encoded resource-resolution value for referenced spaces.\n */\n resourceResolution?: string;\n /**\n * Custom WebSocket URL for Preview Session subscriptions (staging, proxy, per-region).\n * Omit to use the production Preview Session WebSocket host.\n */\n sessionHost?: string;\n debug?: boolean;\n};\n\ntype SessionMessage =\n | { kind: 'next'; payload: ExperiencePayload }\n | { kind: 'error' }\n | { kind: 'unknown' }\n | { kind: 'invalid' };\n\ntype PreviewSessionHandlers = {\n onUpdate: (experience: ExperiencePayload) => void;\n onOpen?: () => void;\n onError?: (error: LivePreviewConnectionError) => void;\n};\n\nfunction parseMessage(data: unknown): SessionMessage {\n let message: unknown = data;\n\n if (typeof data === 'string') {\n try {\n message = JSON.parse(data);\n } catch {\n return { kind: 'invalid' };\n }\n }\n\n if (!isRecord(message) || typeof message.type !== 'string') {\n return { kind: 'invalid' };\n }\n\n if (message.type === 'next') {\n return isExperiencePayload(message.data)\n ? { kind: 'next', payload: message.data }\n : { kind: 'invalid' };\n }\n\n if (message.type === 'error') {\n return isErrorPayload(message.data) ? { kind: 'error' } : { kind: 'invalid' };\n }\n\n return { kind: 'unknown' };\n}\n\nfunction isSessionEnded(event: WebSocketCloseEvent): boolean {\n if (event.code !== 1000) return false;\n const reason = event.reason.trim().toLowerCase();\n return reason === 'deleted' || reason === 'expired';\n}\n\nexport function subscribeToPreviewSession(\n options: PreviewSessionOptions,\n handlers: PreviewSessionHandlers\n): () => void {\n const log = createDebugLogger(options.debug, 'live-preview');\n const { sessionId, previewToken } = options;\n const { onError, onOpen, onUpdate } = handlers;\n if (sessionId === undefined || previewToken === undefined) return () => undefined;\n\n const connection = createWebSocketConnection({\n url: previewSessionSubscribeUrl({ ...options, sessionId, previewToken }),\n retry: (failureCount, event) => {\n const sessionEnded = isSessionEnded(event);\n const hasExhaustedRetries = failureCount >= RETRY_DELAYS_MS.length;\n const shouldRetry = !hasExhaustedRetries && !sessionEnded;\n if (hasExhaustedRetries || sessionEnded) {\n onError?.(new LivePreviewConnectionError());\n }\n return shouldRetry;\n },\n retryDelay: (retryAttempt) =>\n RETRY_DELAYS_MS[retryAttempt] ?? RETRY_DELAYS_MS[RETRY_DELAYS_MS.length - 1] ?? 0,\n onFailure: () => onError?.(new LivePreviewConnectionError()),\n });\n\n const unsubscribeFromOpen = onOpen ? connection.onopen(() => onOpen()) : undefined;\n const unsubscribe = connection.onmessage((event) => {\n const message = parseMessage(event.data);\n\n if (message.kind === 'unknown') return;\n if (message.kind === 'error') {\n log.log('Preview Session returned an error');\n return;\n }\n if (message.kind === 'invalid') {\n log.log('ignored invalid Preview Session message');\n return;\n }\n\n onUpdate(message.payload);\n });\n\n return () => {\n unsubscribeFromOpen?.();\n unsubscribe();\n connection.close();\n };\n}\n"],"mappings":"AAAA,SAAS,yBAAiD;AAC1D,SAAS,gBAAgB,qBAAqB,gBAAgB;AAC9D,SAAS,iCAA2D;AACpE,SAAS,kCAAkC;AAC3C,SAAS,kCAAkC;AAE3C,MAAM,kBAAqC,CAAC,KAAK,KAAK,GAAI;AA+B1D,SAAS,aAAa,MAA+B;AACnD,MAAI,UAAmB;AAEvB,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI;AACF,gBAAU,KAAK,MAAM,IAAI;AAAA,IAC3B,QAAQ;AACN,aAAO,EAAE,MAAM,UAAU;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,OAAO,KAAK,OAAO,QAAQ,SAAS,UAAU;AAC1D,WAAO,EAAE,MAAM,UAAU;AAAA,EAC3B;AAEA,MAAI,QAAQ,SAAS,QAAQ;AAC3B,WAAO,oBAAoB,QAAQ,IAAI,IACnC,EAAE,MAAM,QAAQ,SAAS,QAAQ,KAAK,IACtC,EAAE,MAAM,UAAU;AAAA,EACxB;AAEA,MAAI,QAAQ,SAAS,SAAS;AAC5B,WAAO,eAAe,QAAQ,IAAI,IAAI,EAAE,MAAM,QAAQ,IAAI,EAAE,MAAM,UAAU;AAAA,EAC9E;AAEA,SAAO,EAAE,MAAM,UAAU;AAC3B;AAEA,SAAS,eAAe,OAAqC;AAC3D,MAAI,MAAM,SAAS,IAAM,QAAO;AAChC,QAAM,SAAS,MAAM,OAAO,KAAK,EAAE,YAAY;AAC/C,SAAO,WAAW,aAAa,WAAW;AAC5C;AAEO,SAAS,0BACd,SACA,UACY;AACZ,QAAM,MAAM,kBAAkB,QAAQ,OAAO,cAAc;AAC3D,QAAM,EAAE,WAAW,aAAa,IAAI;AACpC,QAAM,EAAE,SAAS,QAAQ,SAAS,IAAI;AACtC,MAAI,cAAc,UAAa,iBAAiB,OAAW,QAAO,MAAM;AAExE,QAAM,aAAa,0BAA0B;AAAA,IAC3C,KAAK,2BAA2B,EAAE,GAAG,SAAS,WAAW,aAAa,CAAC;AAAA,IACvE,OAAO,CAAC,cAAc,UAAU;AAC9B,YAAM,eAAe,eAAe,KAAK;AACzC,YAAM,sBAAsB,gBAAgB,gBAAgB;AAC5D,YAAM,cAAc,CAAC,uBAAuB,CAAC;AAC7C,UAAI,uBAAuB,cAAc;AACvC,kBAAU,IAAI,2BAA2B,CAAC;AAAA,MAC5C;AACA,aAAO;AAAA,IACT;AAAA,IACA,YAAY,CAAC,iBACX,gBAAgB,YAAY,KAAK,gBAAgB,gBAAgB,SAAS,CAAC,KAAK;AAAA,IAClF,WAAW,MAAM,UAAU,IAAI,2BAA2B,CAAC;AAAA,EAC7D,CAAC;AAED,QAAM,sBAAsB,SAAS,WAAW,OAAO,MAAM,OAAO,CAAC,IAAI;AACzE,QAAM,cAAc,WAAW,UAAU,CAAC,UAAU;AAClD,UAAM,UAAU,aAAa,MAAM,IAAI;AAEvC,QAAI,QAAQ,SAAS,UAAW;AAChC,QAAI,QAAQ,SAAS,SAAS;AAC5B,UAAI,IAAI,mCAAmC;AAC3C;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,WAAW;AAC9B,UAAI,IAAI,yCAAyC;AACjD;AAAA,IACF;AAEA,aAAS,QAAQ,OAAO;AAAA,EAC1B,CAAC;AAED,SAAO,MAAM;AACX,0BAAsB;AACtB,gBAAY;AACZ,eAAW,MAAM;AAAA,EACnB;AACF;","names":[]}
@@ -0,0 +1,8 @@
1
+ import { LivePreviewStatus } from './live-preview-client.js';
2
+ import '@contentful/experiences-sdk-core';
3
+ import './preview-session.js';
4
+ import './errors.js';
5
+
6
+ declare function sendPreviewStatus(status: LivePreviewStatus): void;
7
+
8
+ export { sendPreviewStatus };
@@ -0,0 +1,18 @@
1
+ const PREVIEW_STATUS_MESSAGE = {
2
+ source: "experiences/live-preview",
3
+ type: "status"
4
+ };
5
+ function sendPreviewStatus(status) {
6
+ if (typeof window === "undefined") return;
7
+ window.parent?.postMessage(
8
+ {
9
+ ...PREVIEW_STATUS_MESSAGE,
10
+ status
11
+ },
12
+ "*"
13
+ );
14
+ }
15
+ export {
16
+ sendPreviewStatus
17
+ };
18
+ //# sourceMappingURL=preview-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/preview-status.ts"],"sourcesContent":["import type { LivePreviewStatus } from './live-preview-client.js';\n\nconst PREVIEW_STATUS_MESSAGE = {\n source: 'experiences/live-preview',\n type: 'status',\n} as const;\n\nexport function sendPreviewStatus(status: LivePreviewStatus): void {\n if (typeof window === 'undefined') return;\n\n window.parent?.postMessage(\n {\n ...PREVIEW_STATUS_MESSAGE,\n status,\n },\n '*'\n );\n}\n"],"mappings":"AAEA,MAAM,yBAAyB;AAAA,EAC7B,QAAQ;AAAA,EACR,MAAM;AACR;AAEO,SAAS,kBAAkB,QAAiC;AACjE,MAAI,OAAO,WAAW,YAAa;AAEnC,SAAO,QAAQ;AAAA,IACb;AAAA,MACE,GAAG;AAAA,MACH;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,31 @@
1
+ type WebSocketCloseEvent = {
2
+ readonly code: number;
3
+ readonly reason: string;
4
+ };
5
+ type WebSocketOpenEvent = {
6
+ readonly type: string;
7
+ };
8
+ type WebSocketMessageEvent = {
9
+ readonly data: unknown;
10
+ };
11
+ type WebSocket = {
12
+ onopen: ((event: WebSocketOpenEvent) => void) | null;
13
+ onclose: ((event: WebSocketCloseEvent) => void) | null;
14
+ onmessage: ((event: WebSocketMessageEvent) => void) | null;
15
+ close(): void;
16
+ };
17
+ type WebSocketConstructor = new (url: string) => WebSocket;
18
+ type WebSocketConnection = {
19
+ close(): void;
20
+ onopen(handler: (event: WebSocketOpenEvent) => void): () => void;
21
+ onmessage(handler: (event: WebSocketMessageEvent) => void): () => void;
22
+ };
23
+ declare function createWebSocketConnection(options: {
24
+ url: string;
25
+ retry?: number | ((failureCount: number, event: WebSocketCloseEvent) => boolean);
26
+ retryDelay?: number | ((retryAttempt: number, event: WebSocketCloseEvent) => number);
27
+ WebSocket?: WebSocketConstructor;
28
+ onFailure?: (error: unknown) => void;
29
+ }): WebSocketConnection;
30
+
31
+ export { type WebSocketCloseEvent, type WebSocketMessageEvent, type WebSocketOpenEvent, createWebSocketConnection };
@@ -0,0 +1,128 @@
1
+ function createWebSocketConnection(options) {
2
+ const WS = options.WebSocket ?? globalThis.WebSocket;
3
+ if (!WS) throw new Error("WebSocket constructor is not available in this runtime.");
4
+ let websocket;
5
+ let retryTimer;
6
+ let retryCount = 0;
7
+ let closed = false;
8
+ const openHandlers = /* @__PURE__ */ new Set();
9
+ const messageHandlers = /* @__PURE__ */ new Set();
10
+ const clearRetryTimer = () => {
11
+ if (retryTimer === void 0) return;
12
+ clearTimeout(retryTimer);
13
+ retryTimer = void 0;
14
+ };
15
+ const clearHandlers = () => {
16
+ openHandlers.clear();
17
+ messageHandlers.clear();
18
+ };
19
+ const detachSocketHandlers = (currentSocket) => {
20
+ currentSocket.onopen = null;
21
+ currentSocket.onmessage = null;
22
+ currentSocket.onclose = null;
23
+ };
24
+ const shouldRetry = (event) => {
25
+ if (closed) return false;
26
+ if (typeof options.retry === "number") return retryCount < options.retry;
27
+ if (typeof options.retry === "function") return options.retry(retryCount, event);
28
+ return false;
29
+ };
30
+ const getRetryDelay = (event) => {
31
+ if (typeof options.retryDelay === "function") {
32
+ return options.retryDelay(retryCount, event);
33
+ }
34
+ return options.retryDelay ?? 0;
35
+ };
36
+ const handleClose = (currentSocket, event) => {
37
+ if (websocket !== currentSocket) return;
38
+ websocket = void 0;
39
+ detachSocketHandlers(currentSocket);
40
+ if (closed || !shouldRetry(event)) {
41
+ closed = true;
42
+ clearHandlers();
43
+ return;
44
+ }
45
+ const delay = getRetryDelay(event);
46
+ retryCount += 1;
47
+ retryTimer = setTimeout(() => {
48
+ retryTimer = void 0;
49
+ if (closed) return;
50
+ try {
51
+ connect();
52
+ } catch (error) {
53
+ closed = true;
54
+ clearHandlers();
55
+ options.onFailure?.(error);
56
+ }
57
+ }, delay);
58
+ };
59
+ const connect = () => {
60
+ if (closed || websocket !== void 0 || retryTimer !== void 0) return;
61
+ const ws = new WS(options.url);
62
+ websocket = ws;
63
+ ws.onclose = (event) => handleClose(ws, event);
64
+ ws.onopen = (event) => {
65
+ if (websocket !== ws || closed) return;
66
+ let handlerError;
67
+ let hasHandlerError = false;
68
+ for (const handler of [...openHandlers]) {
69
+ try {
70
+ handler(event);
71
+ } catch (error) {
72
+ if (!hasHandlerError) handlerError = error;
73
+ hasHandlerError = true;
74
+ }
75
+ }
76
+ if (hasHandlerError) throw handlerError;
77
+ };
78
+ ws.onmessage = (event) => {
79
+ if (websocket !== ws || closed) return;
80
+ let handlerError;
81
+ let hasHandlerError = false;
82
+ for (const handler of [...messageHandlers]) {
83
+ try {
84
+ handler(event);
85
+ } catch (error) {
86
+ if (!hasHandlerError) handlerError = error;
87
+ hasHandlerError = true;
88
+ }
89
+ }
90
+ if (hasHandlerError) throw handlerError;
91
+ };
92
+ };
93
+ const connection = {
94
+ close() {
95
+ if (closed) return;
96
+ closed = true;
97
+ clearRetryTimer();
98
+ const currentSocket = websocket;
99
+ if (!currentSocket) {
100
+ clearHandlers();
101
+ return;
102
+ }
103
+ detachSocketHandlers(currentSocket);
104
+ clearHandlers();
105
+ currentSocket.close();
106
+ },
107
+ onopen(handler) {
108
+ if (closed) return () => void 0;
109
+ openHandlers.add(handler);
110
+ return () => {
111
+ openHandlers.delete(handler);
112
+ };
113
+ },
114
+ onmessage(handler) {
115
+ if (closed) return () => void 0;
116
+ messageHandlers.add(handler);
117
+ return () => {
118
+ messageHandlers.delete(handler);
119
+ };
120
+ }
121
+ };
122
+ connect();
123
+ return connection;
124
+ }
125
+ export {
126
+ createWebSocketConnection
127
+ };
128
+ //# sourceMappingURL=websocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/websocket.ts"],"sourcesContent":["export type WebSocketCloseEvent = {\n readonly code: number;\n readonly reason: string;\n};\n\nexport type WebSocketOpenEvent = {\n readonly type: string;\n};\n\nexport type WebSocketMessageEvent = {\n readonly data: unknown;\n};\n\ntype WebSocket = {\n onopen: ((event: WebSocketOpenEvent) => void) | null;\n onclose: ((event: WebSocketCloseEvent) => void) | null;\n onmessage: ((event: WebSocketMessageEvent) => void) | null;\n close(): void;\n};\n\ntype WebSocketConstructor = new (url: string) => WebSocket;\n\ntype WebSocketConnection = {\n close(): void;\n onopen(handler: (event: WebSocketOpenEvent) => void): () => void;\n onmessage(handler: (event: WebSocketMessageEvent) => void): () => void;\n};\n\nexport function createWebSocketConnection(options: {\n url: string;\n retry?: number | ((failureCount: number, event: WebSocketCloseEvent) => boolean);\n retryDelay?: number | ((retryAttempt: number, event: WebSocketCloseEvent) => number);\n WebSocket?: WebSocketConstructor;\n onFailure?: (error: unknown) => void;\n}): WebSocketConnection {\n const WS = options.WebSocket ?? (globalThis.WebSocket as WebSocketConstructor | undefined);\n if (!WS) throw new Error('WebSocket constructor is not available in this runtime.');\n\n let websocket: WebSocket | undefined;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n let retryCount = 0;\n let closed = false;\n\n const openHandlers = new Set<(event: WebSocketOpenEvent) => void>();\n const messageHandlers = new Set<(event: WebSocketMessageEvent) => void>();\n\n const clearRetryTimer = () => {\n if (retryTimer === undefined) return;\n clearTimeout(retryTimer);\n retryTimer = undefined;\n };\n\n const clearHandlers = () => {\n openHandlers.clear();\n messageHandlers.clear();\n };\n\n const detachSocketHandlers = (currentSocket: WebSocket) => {\n currentSocket.onopen = null;\n currentSocket.onmessage = null;\n currentSocket.onclose = null;\n };\n\n const shouldRetry = (event: WebSocketCloseEvent) => {\n if (closed) return false;\n if (typeof options.retry === 'number') return retryCount < options.retry;\n if (typeof options.retry === 'function') return options.retry(retryCount, event);\n return false;\n };\n\n const getRetryDelay = (event: WebSocketCloseEvent) => {\n if (typeof options.retryDelay === 'function') {\n return options.retryDelay(retryCount, event);\n }\n return options.retryDelay ?? 0;\n };\n\n const handleClose = (currentSocket: WebSocket, event: WebSocketCloseEvent) => {\n if (websocket !== currentSocket) return;\n\n websocket = undefined;\n detachSocketHandlers(currentSocket);\n\n if (closed || !shouldRetry(event)) {\n closed = true;\n clearHandlers();\n return;\n }\n\n const delay = getRetryDelay(event);\n retryCount += 1;\n retryTimer = setTimeout(() => {\n retryTimer = undefined;\n if (closed) return;\n try {\n connect();\n } catch (error: unknown) {\n closed = true;\n clearHandlers();\n options.onFailure?.(error);\n }\n }, delay);\n };\n\n const connect = () => {\n if (closed || websocket !== undefined || retryTimer !== undefined) return;\n\n const ws = new WS(options.url);\n websocket = ws;\n ws.onclose = (event) => handleClose(ws, event);\n ws.onopen = (event) => {\n if (websocket !== ws || closed) return;\n\n let handlerError: unknown;\n let hasHandlerError = false;\n\n for (const handler of [...openHandlers]) {\n try {\n handler(event);\n } catch (error: unknown) {\n if (!hasHandlerError) handlerError = error;\n hasHandlerError = true;\n }\n }\n\n if (hasHandlerError) throw handlerError;\n };\n ws.onmessage = (event) => {\n if (websocket !== ws || closed) return;\n\n let handlerError: unknown;\n let hasHandlerError = false;\n\n for (const handler of [...messageHandlers]) {\n try {\n handler(event);\n } catch (error: unknown) {\n if (!hasHandlerError) handlerError = error;\n hasHandlerError = true;\n }\n }\n\n if (hasHandlerError) throw handlerError;\n };\n };\n\n const connection: WebSocketConnection = {\n close() {\n if (closed) return;\n closed = true;\n clearRetryTimer();\n\n const currentSocket = websocket;\n if (!currentSocket) {\n clearHandlers();\n return;\n }\n\n detachSocketHandlers(currentSocket);\n clearHandlers();\n currentSocket.close();\n },\n onopen(handler) {\n if (closed) return () => undefined;\n\n openHandlers.add(handler);\n return () => {\n openHandlers.delete(handler);\n };\n },\n onmessage(handler) {\n if (closed) return () => undefined;\n\n messageHandlers.add(handler);\n return () => {\n messageHandlers.delete(handler);\n };\n },\n };\n\n connect();\n return connection;\n}\n"],"mappings":"AA4BO,SAAS,0BAA0B,SAMlB;AACtB,QAAM,KAAK,QAAQ,aAAc,WAAW;AAC5C,MAAI,CAAC,GAAI,OAAM,IAAI,MAAM,yDAAyD;AAElF,MAAI;AACJ,MAAI;AACJ,MAAI,aAAa;AACjB,MAAI,SAAS;AAEb,QAAM,eAAe,oBAAI,IAAyC;AAClE,QAAM,kBAAkB,oBAAI,IAA4C;AAExE,QAAM,kBAAkB,MAAM;AAC5B,QAAI,eAAe,OAAW;AAC9B,iBAAa,UAAU;AACvB,iBAAa;AAAA,EACf;AAEA,QAAM,gBAAgB,MAAM;AAC1B,iBAAa,MAAM;AACnB,oBAAgB,MAAM;AAAA,EACxB;AAEA,QAAM,uBAAuB,CAAC,kBAA6B;AACzD,kBAAc,SAAS;AACvB,kBAAc,YAAY;AAC1B,kBAAc,UAAU;AAAA,EAC1B;AAEA,QAAM,cAAc,CAAC,UAA+B;AAClD,QAAI,OAAQ,QAAO;AACnB,QAAI,OAAO,QAAQ,UAAU,SAAU,QAAO,aAAa,QAAQ;AACnE,QAAI,OAAO,QAAQ,UAAU,WAAY,QAAO,QAAQ,MAAM,YAAY,KAAK;AAC/E,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,CAAC,UAA+B;AACpD,QAAI,OAAO,QAAQ,eAAe,YAAY;AAC5C,aAAO,QAAQ,WAAW,YAAY,KAAK;AAAA,IAC7C;AACA,WAAO,QAAQ,cAAc;AAAA,EAC/B;AAEA,QAAM,cAAc,CAAC,eAA0B,UAA+B;AAC5E,QAAI,cAAc,cAAe;AAEjC,gBAAY;AACZ,yBAAqB,aAAa;AAElC,QAAI,UAAU,CAAC,YAAY,KAAK,GAAG;AACjC,eAAS;AACT,oBAAc;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,cAAc,KAAK;AACjC,kBAAc;AACd,iBAAa,WAAW,MAAM;AAC5B,mBAAa;AACb,UAAI,OAAQ;AACZ,UAAI;AACF,gBAAQ;AAAA,MACV,SAAS,OAAgB;AACvB,iBAAS;AACT,sBAAc;AACd,gBAAQ,YAAY,KAAK;AAAA,MAC3B;AAAA,IACF,GAAG,KAAK;AAAA,EACV;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,UAAU,cAAc,UAAa,eAAe,OAAW;AAEnE,UAAM,KAAK,IAAI,GAAG,QAAQ,GAAG;AAC7B,gBAAY;AACZ,OAAG,UAAU,CAAC,UAAU,YAAY,IAAI,KAAK;AAC7C,OAAG,SAAS,CAAC,UAAU;AACrB,UAAI,cAAc,MAAM,OAAQ;AAEhC,UAAI;AACJ,UAAI,kBAAkB;AAEtB,iBAAW,WAAW,CAAC,GAAG,YAAY,GAAG;AACvC,YAAI;AACF,kBAAQ,KAAK;AAAA,QACf,SAAS,OAAgB;AACvB,cAAI,CAAC,gBAAiB,gBAAe;AACrC,4BAAkB;AAAA,QACpB;AAAA,MACF;AAEA,UAAI,gBAAiB,OAAM;AAAA,IAC7B;AACA,OAAG,YAAY,CAAC,UAAU;AACxB,UAAI,cAAc,MAAM,OAAQ;AAEhC,UAAI;AACJ,UAAI,kBAAkB;AAEtB,iBAAW,WAAW,CAAC,GAAG,eAAe,GAAG;AAC1C,YAAI;AACF,kBAAQ,KAAK;AAAA,QACf,SAAS,OAAgB;AACvB,cAAI,CAAC,gBAAiB,gBAAe;AACrC,4BAAkB;AAAA,QACpB;AAAA,MACF;AAEA,UAAI,gBAAiB,OAAM;AAAA,IAC7B;AAAA,EACF;AAEA,QAAM,aAAkC;AAAA,IACtC,QAAQ;AACN,UAAI,OAAQ;AACZ,eAAS;AACT,sBAAgB;AAEhB,YAAM,gBAAgB;AACtB,UAAI,CAAC,eAAe;AAClB,sBAAc;AACd;AAAA,MACF;AAEA,2BAAqB,aAAa;AAClC,oBAAc;AACd,oBAAc,MAAM;AAAA,IACtB;AAAA,IACA,OAAO,SAAS;AACd,UAAI,OAAQ,QAAO,MAAM;AAEzB,mBAAa,IAAI,OAAO;AACxB,aAAO,MAAM;AACX,qBAAa,OAAO,OAAO;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,UAAU,SAAS;AACjB,UAAI,OAAQ,QAAO,MAAM;AAEzB,sBAAgB,IAAI,OAAO;AAC3B,aAAO,MAAM;AACX,wBAAgB,OAAO,OAAO;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAEA,UAAQ;AACR,SAAO;AACT;","names":[]}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@contentful/experiences-live-preview",
3
+ "version": "0.1.8",
4
+ "description": "Optional live preview for Contentful Experiences",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "sideEffects": false,
10
+ "exports": {
11
+ ".": {
12
+ "import": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "CHANGELOG.md"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/contentful/experiences.git",
30
+ "directory": "packages/live-preview"
31
+ },
32
+ "dependencies": {
33
+ "@contentful/experiences-client": "0.4.8",
34
+ "@contentful/experiences-sdk-core": "0.8.6"
35
+ }
36
+ }