@contentful/experiences-client 0.4.6 → 0.4.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 CHANGED
@@ -1,3 +1,19 @@
1
+ ## 0.4.8 (2026-09-22)
2
+
3
+ ### 🚀 Features
4
+
5
+ - guard against preview mode with destination fetches [AIS-568] ([#201](https://github.com/contentful/experiences/pull/201))
6
+
7
+ ## 0.4.7 (2026-09-22)
8
+
9
+ ### 🚀 Features
10
+
11
+ - add destination node ID and path resolution to fetchExperience [AIS-567] ([#200](https://github.com/contentful/experiences/pull/200))
12
+
13
+ ### 🧱 Updated Dependencies
14
+
15
+ - Updated core to 0.8.6
16
+
1
17
  ## 0.4.6 (2026-09-22)
2
18
 
3
19
  ### 🧱 Updated Dependencies
package/dist/errors.d.ts CHANGED
@@ -10,17 +10,47 @@
10
10
  * package) is the one exception: it passes through undisturbed so callers
11
11
  * can route it to their framework's 404 idiom, per the existing
12
12
  * distinguishable-404 contract.
13
+ *
14
+ * `environmentId` is `undefined` for the destination-shaped `fetchExperience`
15
+ * branches — the destinations delivery endpoints are space-scoped only, with
16
+ * no environment segment, unlike the by-id path.
13
17
  */
14
18
  declare class ExperienceFetchError extends Error {
15
19
  readonly spaceId: string;
16
- readonly environmentId: string;
20
+ readonly environmentId: string | undefined;
17
21
  readonly experienceId: string;
18
22
  constructor(message: string, options: {
19
23
  spaceId: string;
20
- environmentId: string;
24
+ environmentId?: string;
21
25
  experienceId: string;
22
26
  cause?: unknown;
23
27
  });
24
28
  }
29
+ /**
30
+ * Thrown by `fetchExperience` when `clientOptions.preview` is `true` and
31
+ * `experienceOptions` is destination-shaped (`destinationId` + `nodeId` or
32
+ * `destinationId` + `path`). The Destinations Delivery API has no preview
33
+ * host or preview-token support yet, so this guards against silently hitting the
34
+ * production host with a preview token it doesn't accept.
35
+ *
36
+ * This is a bridge, not a permanent design: revisit once the platform ships
37
+ * preview support for destinations.
38
+ *
39
+ * Only fires for the inline-credentials branch of `ClientOptions`. A
40
+ * caller-supplied `{ client }` already ignores `preview` entirely, per that
41
+ * branch's existing contract.
42
+ */
43
+ declare class DestinationPreviewNotSupportedError extends Error {
44
+ readonly spaceId: string;
45
+ readonly destinationId: string;
46
+ readonly nodeId: string | undefined;
47
+ readonly path: string | undefined;
48
+ constructor(message: string, options: {
49
+ spaceId: string;
50
+ destinationId: string;
51
+ nodeId?: string;
52
+ path?: string;
53
+ });
54
+ }
25
55
 
26
- export { ExperienceFetchError };
56
+ export { DestinationPreviewNotSupportedError, ExperienceFetchError };
package/dist/errors.js CHANGED
@@ -10,7 +10,22 @@ class ExperienceFetchError extends Error {
10
10
  this.experienceId = options.experienceId;
11
11
  }
12
12
  }
13
+ class DestinationPreviewNotSupportedError extends Error {
14
+ spaceId;
15
+ destinationId;
16
+ nodeId;
17
+ path;
18
+ constructor(message, options) {
19
+ super(message);
20
+ this.name = "DestinationPreviewNotSupportedError";
21
+ this.spaceId = options.spaceId;
22
+ this.destinationId = options.destinationId;
23
+ this.nodeId = options.nodeId;
24
+ this.path = options.path;
25
+ }
26
+ }
13
27
  export {
28
+ DestinationPreviewNotSupportedError,
14
29
  ExperienceFetchError
15
30
  };
16
31
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Thrown by `fetchExperience` for a fetch failure that is not \"experience not\n * found\" — network failure, an invalid/expired token, a 5xx from the\n * delivery API, etc. This failure mode is \"surface clearly to the host app,\"\n * unlike the diagnostics `resolveExperience` collects for resolve/render-time\n * issues — there's no partial payload to render around a fetch that never\n * returned one, so a real thrown class is the right shape.\n *\n * `NotFoundError` (the delivery client's class, re-exported from this\n * package) is the one exception: it passes through undisturbed so callers\n * can route it to their framework's 404 idiom, per the existing\n * distinguishable-404 contract.\n */\nexport class ExperienceFetchError extends Error {\n readonly spaceId: string;\n readonly environmentId: string;\n readonly experienceId: string;\n\n constructor(\n message: string,\n options: {\n spaceId: string;\n environmentId: string;\n experienceId: string;\n cause?: unknown;\n }\n ) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = 'ExperienceFetchError';\n this.spaceId = options.spaceId;\n this.environmentId = options.environmentId;\n this.experienceId = options.experienceId;\n }\n}\n"],"mappings":"AAaO,MAAM,6BAA6B,MAAM;AAAA,EACrC;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,eAAe,QAAQ;AAAA,EAC9B;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Thrown by `fetchExperience` for a fetch failure that is not \"experience not\n * found\" — network failure, an invalid/expired token, a 5xx from the\n * delivery API, etc. This failure mode is \"surface clearly to the host app,\"\n * unlike the diagnostics `resolveExperience` collects for resolve/render-time\n * issues — there's no partial payload to render around a fetch that never\n * returned one, so a real thrown class is the right shape.\n *\n * `NotFoundError` (the delivery client's class, re-exported from this\n * package) is the one exception: it passes through undisturbed so callers\n * can route it to their framework's 404 idiom, per the existing\n * distinguishable-404 contract.\n *\n * `environmentId` is `undefined` for the destination-shaped `fetchExperience`\n * branches — the destinations delivery endpoints are space-scoped only, with\n * no environment segment, unlike the by-id path.\n */\nexport class ExperienceFetchError extends Error {\n readonly spaceId: string;\n readonly environmentId: string | undefined;\n readonly experienceId: string;\n\n constructor(\n message: string,\n options: {\n spaceId: string;\n environmentId?: string;\n experienceId: string;\n cause?: unknown;\n }\n ) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = 'ExperienceFetchError';\n this.spaceId = options.spaceId;\n this.environmentId = options.environmentId;\n this.experienceId = options.experienceId;\n }\n}\n\n/**\n * Thrown by `fetchExperience` when `clientOptions.preview` is `true` and\n * `experienceOptions` is destination-shaped (`destinationId` + `nodeId` or\n * `destinationId` + `path`). The Destinations Delivery API has no preview\n * host or preview-token support yet, so this guards against silently hitting the\n * production host with a preview token it doesn't accept.\n *\n * This is a bridge, not a permanent design: revisit once the platform ships\n * preview support for destinations.\n *\n * Only fires for the inline-credentials branch of `ClientOptions`. A\n * caller-supplied `{ client }` already ignores `preview` entirely, per that\n * branch's existing contract.\n */\nexport class DestinationPreviewNotSupportedError extends Error {\n readonly spaceId: string;\n readonly destinationId: string;\n readonly nodeId: string | undefined;\n readonly path: string | undefined;\n\n constructor(\n message: string,\n options: { spaceId: string; destinationId: string; nodeId?: string; path?: string }\n ) {\n super(message);\n this.name = 'DestinationPreviewNotSupportedError';\n this.spaceId = options.spaceId;\n this.destinationId = options.destinationId;\n this.nodeId = options.nodeId;\n this.path = options.path;\n }\n}\n"],"mappings":"AAiBO,MAAM,6BAA6B,MAAM;AAAA,EACrC;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,eAAe,QAAQ;AAAA,EAC9B;AACF;AAgBO,MAAM,4CAA4C,MAAM;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,SACA,SACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,UAAU,QAAQ;AACvB,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,SAAS,QAAQ;AACtB,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;","names":[]}
@@ -1,7 +1,7 @@
1
1
  import { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';
2
2
  import { ResolverConfig, PortableRenderPlan } from '@contentful/experiences-sdk-core';
3
3
 
4
- type ExperienceOptions = {
4
+ type ByIdExperienceOptions = {
5
5
  spaceId: string;
6
6
  environmentId: string;
7
7
  experienceId: string;
@@ -16,6 +16,39 @@ type ExperienceOptions = {
16
16
  */
17
17
  withSourceMap?: boolean;
18
18
  };
19
+ /**
20
+ * Resolve an Experience by the Destination Node instead of `experienceId`
21
+ * The destinations delivery endpoints are space-scoped only and have no locale
22
+ * param, unlike the by-id path.
23
+ */
24
+ type ByDestinationNodeIdExperienceOptions = {
25
+ spaceId: string;
26
+ destinationId: string;
27
+ nodeId: string;
28
+ };
29
+ /**
30
+ * Resolve an Experience by the absolute path wired up to a
31
+ * Destination Node, instead of a node id directly. Same scoping as
32
+ * `ByDestinationNodeIdExperienceOptions` — no `environmentId` or `locale`.
33
+ */
34
+ type ByDestinationPathExperienceOptions = {
35
+ spaceId: string;
36
+ destinationId: string;
37
+ /** Absolute path to resolve. Must start with `/`. */
38
+ path: string;
39
+ };
40
+ type ExperienceOptions = ByIdExperienceOptions | ByDestinationNodeIdExperienceOptions | ByDestinationPathExperienceOptions;
41
+ /**
42
+ * A Destination resolution that the app must act on as control flow — honor
43
+ * it by navigating or re-resolving at the new path — rather than a hydrated
44
+ * Experience to render. Modeled as a normal return value, not a thrown error,
45
+ * per the Destinations delivery API's own framing of a redirect response.
46
+ */
47
+ interface DestinationRedirectResult {
48
+ redirect: {
49
+ path: string;
50
+ };
51
+ }
19
52
  type ClientOptions = {
20
53
  accessToken: string;
21
54
  /**
@@ -61,6 +94,8 @@ type ResolveOptions = {
61
94
  */
62
95
  initialViewportId?: string;
63
96
  };
64
- declare function fetchExperience(experienceOptions: ExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan>;
97
+ declare function fetchExperience(experienceOptions: ByIdExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan>;
98
+ declare function fetchExperience(experienceOptions: ByDestinationNodeIdExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan | DestinationRedirectResult>;
99
+ declare function fetchExperience(experienceOptions: ByDestinationPathExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan | DestinationRedirectResult>;
65
100
 
66
- export { type ClientOptions, type ExperienceOptions, type ResolveOptions, fetchExperience };
101
+ export { type ByDestinationNodeIdExperienceOptions, type ByDestinationPathExperienceOptions, type ByIdExperienceOptions, type ClientOptions, type DestinationRedirectResult, type ExperienceOptions, type ResolveOptions, fetchExperience };
@@ -1,16 +1,24 @@
1
1
  import { ContentfulViewDelivery } from "@contentful/experience-delivery";
2
2
  import { createDebugLogger, resolveExperience } from "@contentful/experiences-sdk-core";
3
3
  import { createClient } from "./create-client.js";
4
- import { ExperienceFetchError } from "./errors.js";
4
+ import { DestinationPreviewNotSupportedError, ExperienceFetchError } from "./errors.js";
5
5
  import { PREVIEW_HOST } from "./hosts.js";
6
6
  import {
7
7
  readSourceMap,
8
- toExperiencePayload
8
+ toExperiencePayload,
9
+ toExperiencePayloadFromDestination
9
10
  } from "./to-experience-payload.js";
10
11
  async function fetchExperience(experienceOptions, clientOptions, resolveOptions) {
11
- const { spaceId, environmentId, experienceId, locale, withSourceMap } = experienceOptions;
12
12
  const { config, metadata, debug, initialViewportId } = resolveOptions;
13
13
  const log = createDebugLogger(debug, "client");
14
+ if (!("client" in clientOptions) && clientOptions.preview && "destinationId" in experienceOptions) {
15
+ const { spaceId: spaceId2, destinationId } = experienceOptions;
16
+ const locator = "nodeId" in experienceOptions ? { nodeId: experienceOptions.nodeId } : { path: experienceOptions.path };
17
+ throw new DestinationPreviewNotSupportedError(
18
+ `fetchExperience() called with preview: true and a destination-shaped experienceOptions (destinationId "${destinationId}"). The Destinations Delivery API does not support preview mode yet \u2014 pass preview: false (or omit it) for destination-based fetches.`,
19
+ { spaceId: spaceId2, destinationId, ...locator }
20
+ );
21
+ }
14
22
  let client;
15
23
  if ("client" in clientOptions) {
16
24
  client = clientOptions.client;
@@ -29,6 +37,25 @@ async function fetchExperience(experienceOptions, clientOptions, resolveOptions)
29
37
  });
30
38
  log.log("created delivery client", { preview: Boolean(preview), host: resolvedHost });
31
39
  }
40
+ if ("nodeId" in experienceOptions) {
41
+ const { spaceId: spaceId2, destinationId, nodeId } = experienceOptions;
42
+ return fetchByDestination(
43
+ { spaceId: spaceId2, destinationId, locator: nodeId },
44
+ () => client.destination.resolveByNodeId(spaceId2, destinationId, nodeId),
45
+ log,
46
+ { config, metadata, debug, initialViewportId }
47
+ );
48
+ }
49
+ if ("path" in experienceOptions) {
50
+ const { spaceId: spaceId2, destinationId, path } = experienceOptions;
51
+ return fetchByDestination(
52
+ { spaceId: spaceId2, destinationId, locator: path },
53
+ () => client.destination.resolveByPath(spaceId2, destinationId, { path }),
54
+ log,
55
+ { config, metadata, debug, initialViewportId }
56
+ );
57
+ }
58
+ const { spaceId, environmentId, experienceId, locale, withSourceMap } = experienceOptions;
32
59
  log.log("fetching experience", {
33
60
  spaceId,
34
61
  environmentId,
@@ -63,6 +90,42 @@ async function fetchExperience(experienceOptions, clientOptions, resolveOptions)
63
90
  sourceMap
64
91
  });
65
92
  }
93
+ async function fetchByDestination(identity, resolve, log, resolveOptions) {
94
+ const { spaceId, destinationId, locator } = identity;
95
+ const { config, metadata, debug, initialViewportId } = resolveOptions;
96
+ log.log("resolving destination experience", { spaceId, destinationId, locator });
97
+ let response;
98
+ try {
99
+ response = await resolve();
100
+ } catch (err) {
101
+ if (err instanceof ContentfulViewDelivery.NotFoundError) {
102
+ throw err;
103
+ }
104
+ const reason = err instanceof Error ? err.message : String(err);
105
+ throw new ExperienceFetchError(
106
+ `Failed to resolve Destination "${destinationId}" at "${locator}" (space "${spaceId}"): ${reason}. Check network connectivity, the access token, and that the space/destination/node-or-path values are correct.`,
107
+ { spaceId, experienceId: locator, cause: err }
108
+ );
109
+ }
110
+ if ("redirect" in response) {
111
+ log.log("destination resolved to a redirect", response.redirect);
112
+ return { redirect: response.redirect };
113
+ }
114
+ const [firstExperience] = response.experiences;
115
+ if (!firstExperience) {
116
+ throw new ExperienceFetchError(
117
+ `Destination "${destinationId}" resolved "${locator}" to zero Experiences (space "${spaceId}"). Expected exactly one hydrated Experience or a redirect.`,
118
+ { spaceId, experienceId: locator }
119
+ );
120
+ }
121
+ const payload = toExperiencePayloadFromDestination(firstExperience.experience);
122
+ log.lazy("received raw payload", () => payload);
123
+ return resolveExperience(payload, config, {
124
+ metadata,
125
+ debug,
126
+ initialViewportId
127
+ });
128
+ }
66
129
  export {
67
130
  fetchExperience
68
131
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/fetch-experience.ts"],"sourcesContent":["import type { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';\nimport { ContentfulViewDelivery } from '@contentful/experience-delivery';\nimport { createDebugLogger, resolveExperience } from '@contentful/experiences-sdk-core';\nimport type { PortableRenderPlan, ResolverConfig } from '@contentful/experiences-sdk-core';\nimport { createClient } from './create-client.js';\nimport { ExperienceFetchError } from './errors.js';\nimport { PREVIEW_HOST } from './hosts.js';\nimport {\n readSourceMap,\n toExperiencePayload,\n type ExperienceResponse,\n} from './to-experience-payload.js';\n\nexport type ExperienceOptions = {\n spaceId: string;\n environmentId: string;\n experienceId: string;\n locale?: string;\n /**\n * Fetch the content source map alongside the experience, onto\n * `PortableRenderPlan.sourceMap`. Defaults to `false` because the map is large.\n *\n * Switches the request from `GET` to `POST` (the opt-in is a request-body\n * field, only accepted by `getWithOverrides`), so it is not CDN-cacheable.\n * Query params, auth, and the response shape are unchanged.\n */\n withSourceMap?: boolean;\n};\n\nexport type ClientOptions =\n | {\n accessToken: string;\n /**\n * Preview access token. Required when calling with `preview: true`.\n */\n previewToken?: string;\n /**\n * Flip between delivery (default) and preview at request time. When\n * `true`, `fetchExperience` uses `previewToken` and the preview host;\n * when `false` or unset, it uses `accessToken` and the delivery host.\n * Ignored when a pre-made `client` is passed instead of inline creds.\n */\n preview?: boolean;\n /**\n * Custom base URL for the delivery client (staging, proxy, per-region).\n * Wins over the `preview`-derived default host — combine `host` with\n * `preview: true` to point preview mode at a non-prod endpoint.\n * Omit for the standard delivery / preview hosts.\n */\n host?: string;\n }\n | { client: ContentfulViewDeliveryClient };\n\nexport type ResolveOptions = {\n config: ResolverConfig;\n /**\n * Arbitrary per-render metadata exposed to every resolver as\n * `ctx.experience.metadata` and readable at render time via the framework\n * adapter's `useExperience()` / `getExperience()`.\n */\n metadata?: Record<string, unknown>;\n /**\n * Observability switch. When on: logs the fetch (host, ids) and the raw\n * payload here, and threads through to `resolveExperience` (resolution steps\n * + `resolveData` timings) and the renderer (visible missing-component box,\n * debug fallback). A single boolean across fetch + resolve + render.\n */\n debug?: boolean;\n /**\n * Per-request fallback viewport for server-side design pre-resolution. Pass\n * the same id you seed the renderer's `initialViewportId` with (e.g. a\n * User-Agent-derived viewport) so SSR paints correct design on first render.\n */\n initialViewportId?: string;\n};\n\nexport async function fetchExperience(\n experienceOptions: ExperienceOptions,\n clientOptions: ClientOptions,\n resolveOptions: ResolveOptions\n): Promise<PortableRenderPlan> {\n const { spaceId, environmentId, experienceId, locale, withSourceMap } = experienceOptions;\n const { config, metadata, debug, initialViewportId } = resolveOptions;\n const log = createDebugLogger(debug, 'client');\n\n let client: ContentfulViewDeliveryClient;\n if ('client' in clientOptions) {\n client = clientOptions.client;\n log.log('using caller-supplied delivery client');\n } else {\n const { accessToken, previewToken, preview, host } = clientOptions;\n if (preview && !previewToken) {\n throw new Error(\n 'fetchExperience() called with preview: true but no previewToken was provided'\n );\n }\n const resolvedHost = host ?? (preview ? PREVIEW_HOST : undefined);\n client = createClient({\n accessToken: preview ? (previewToken as string) : accessToken,\n host: resolvedHost,\n });\n log.log('created delivery client', { preview: Boolean(preview), host: resolvedHost });\n }\n\n log.log('fetching experience', {\n spaceId,\n environmentId,\n experienceId,\n locale,\n withSourceMap: Boolean(withSourceMap),\n });\n\n // Typed as the union of both operations' responses — they declare the same\n // union, but which one runs depends on `withSourceMap` below.\n let response: ExperienceResponse;\n try {\n // Both methods hit the same endpoint; only the POST accepts a body, and\n // `extensions` (the source-map opt-in) lives there. Otherwise identical.\n // The alpha-feature header is sent by the delivery client itself since\n // 1.0.0-dev.7, so a caller-supplied `{ client }` is covered too.\n response = withSourceMap\n ? await client.experience.getWithOverrides(spaceId, environmentId, experienceId, {\n locale,\n extensions: { sourceMap: {} },\n })\n : await client.experience.get(spaceId, environmentId, experienceId, { locale });\n } catch (err) {\n // `NotFoundError` is a distinguishable, expected outcome (draft/unpublished/\n // wrong id) — callers already route it to their framework's 404 idiom, so\n // it passes through as-is. Everything else (network failure, bad/expired\n // token, a 5xx) is unexpected and gets wrapped in an actionable error\n // instead of leaking whatever shape the delivery client happened to throw.\n if (err instanceof ContentfulViewDelivery.NotFoundError) {\n throw err;\n }\n const reason = err instanceof Error ? err.message : String(err);\n throw new ExperienceFetchError(\n `Failed to fetch Experience \"${experienceId}\" (space \"${spaceId}\", environment ` +\n `\"${environmentId}\"): ${reason}. Check network connectivity, the access token, and ` +\n `that the space/environment/experience ids are correct.`,\n { spaceId, environmentId, experienceId, cause: err }\n );\n }\n\n const payload = toExperiencePayload(response);\n const sourceMap = withSourceMap ? readSourceMap(response) : undefined;\n\n log.lazy('received raw payload', () => payload);\n if (withSourceMap && !sourceMap) log.log('source map requested but not returned');\n\n return resolveExperience(payload, config, {\n metadata,\n debug,\n initialViewportId,\n sourceMap,\n });\n}\n"],"mappings":"AACA,SAAS,8BAA8B;AACvC,SAAS,mBAAmB,yBAAyB;AAErD,SAAS,oBAAoB;AAC7B,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAiEP,eAAsB,gBACpB,mBACA,eACA,gBAC6B;AAC7B,QAAM,EAAE,SAAS,eAAe,cAAc,QAAQ,cAAc,IAAI;AACxE,QAAM,EAAE,QAAQ,UAAU,OAAO,kBAAkB,IAAI;AACvD,QAAM,MAAM,kBAAkB,OAAO,QAAQ;AAE7C,MAAI;AACJ,MAAI,YAAY,eAAe;AAC7B,aAAS,cAAc;AACvB,QAAI,IAAI,uCAAuC;AAAA,EACjD,OAAO;AACL,UAAM,EAAE,aAAa,cAAc,SAAS,KAAK,IAAI;AACrD,QAAI,WAAW,CAAC,cAAc;AAC5B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,eAAe,SAAS,UAAU,eAAe;AACvD,aAAS,aAAa;AAAA,MACpB,aAAa,UAAW,eAA0B;AAAA,MAClD,MAAM;AAAA,IACR,CAAC;AACD,QAAI,IAAI,2BAA2B,EAAE,SAAS,QAAQ,OAAO,GAAG,MAAM,aAAa,CAAC;AAAA,EACtF;AAEA,MAAI,IAAI,uBAAuB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,QAAQ,aAAa;AAAA,EACtC,CAAC;AAID,MAAI;AACJ,MAAI;AAKF,eAAW,gBACP,MAAM,OAAO,WAAW,iBAAiB,SAAS,eAAe,cAAc;AAAA,MAC7E;AAAA,MACA,YAAY,EAAE,WAAW,CAAC,EAAE;AAAA,IAC9B,CAAC,IACD,MAAM,OAAO,WAAW,IAAI,SAAS,eAAe,cAAc,EAAE,OAAO,CAAC;AAAA,EAClF,SAAS,KAAK;AAMZ,QAAI,eAAe,uBAAuB,eAAe;AACvD,YAAM;AAAA,IACR;AACA,UAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,UAAM,IAAI;AAAA,MACR,+BAA+B,YAAY,aAAa,OAAO,mBACzD,aAAa,OAAO,MAAM;AAAA,MAEhC,EAAE,SAAS,eAAe,cAAc,OAAO,IAAI;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,UAAU,oBAAoB,QAAQ;AAC5C,QAAM,YAAY,gBAAgB,cAAc,QAAQ,IAAI;AAE5D,MAAI,KAAK,wBAAwB,MAAM,OAAO;AAC9C,MAAI,iBAAiB,CAAC,UAAW,KAAI,IAAI,uCAAuC;AAEhF,SAAO,kBAAkB,SAAS,QAAQ;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../src/fetch-experience.ts"],"sourcesContent":["import type { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';\nimport { ContentfulViewDelivery } from '@contentful/experience-delivery';\nimport { createDebugLogger, resolveExperience } from '@contentful/experiences-sdk-core';\nimport type { PortableRenderPlan, ResolverConfig } from '@contentful/experiences-sdk-core';\nimport { createClient } from './create-client.js';\nimport { DestinationPreviewNotSupportedError, ExperienceFetchError } from './errors.js';\nimport { PREVIEW_HOST } from './hosts.js';\nimport {\n readSourceMap,\n toExperiencePayload,\n toExperiencePayloadFromDestination,\n type ExperienceResponse,\n} from './to-experience-payload.js';\n\nexport type ByIdExperienceOptions = {\n spaceId: string;\n environmentId: string;\n experienceId: string;\n locale?: string;\n /**\n * Fetch the content source map alongside the experience, onto\n * `PortableRenderPlan.sourceMap`. Defaults to `false` because the map is large.\n *\n * Switches the request from `GET` to `POST` (the opt-in is a request-body\n * field, only accepted by `getWithOverrides`), so it is not CDN-cacheable.\n * Query params, auth, and the response shape are unchanged.\n */\n withSourceMap?: boolean;\n};\n\n/**\n * Resolve an Experience by the Destination Node instead of `experienceId`\n * The destinations delivery endpoints are space-scoped only and have no locale\n * param, unlike the by-id path.\n */\nexport type ByDestinationNodeIdExperienceOptions = {\n spaceId: string;\n destinationId: string;\n nodeId: string;\n};\n\n/**\n * Resolve an Experience by the absolute path wired up to a\n * Destination Node, instead of a node id directly. Same scoping as\n * `ByDestinationNodeIdExperienceOptions` — no `environmentId` or `locale`.\n */\nexport type ByDestinationPathExperienceOptions = {\n spaceId: string;\n destinationId: string;\n /** Absolute path to resolve. Must start with `/`. */\n path: string;\n};\n\nexport type ExperienceOptions =\n ByIdExperienceOptions | ByDestinationNodeIdExperienceOptions | ByDestinationPathExperienceOptions;\n\n/**\n * A Destination resolution that the app must act on as control flow — honor\n * it by navigating or re-resolving at the new path — rather than a hydrated\n * Experience to render. Modeled as a normal return value, not a thrown error,\n * per the Destinations delivery API's own framing of a redirect response.\n */\nexport interface DestinationRedirectResult {\n redirect: { path: string };\n}\n\nexport type ClientOptions =\n | {\n accessToken: string;\n /**\n * Preview access token. Required when calling with `preview: true`.\n */\n previewToken?: string;\n /**\n * Flip between delivery (default) and preview at request time. When\n * `true`, `fetchExperience` uses `previewToken` and the preview host;\n * when `false` or unset, it uses `accessToken` and the delivery host.\n * Ignored when a pre-made `client` is passed instead of inline creds.\n */\n preview?: boolean;\n /**\n * Custom base URL for the delivery client (staging, proxy, per-region).\n * Wins over the `preview`-derived default host — combine `host` with\n * `preview: true` to point preview mode at a non-prod endpoint.\n * Omit for the standard delivery / preview hosts.\n */\n host?: string;\n }\n | { client: ContentfulViewDeliveryClient };\n\nexport type ResolveOptions = {\n config: ResolverConfig;\n /**\n * Arbitrary per-render metadata exposed to every resolver as\n * `ctx.experience.metadata` and readable at render time via the framework\n * adapter's `useExperience()` / `getExperience()`.\n */\n metadata?: Record<string, unknown>;\n /**\n * Observability switch. When on: logs the fetch (host, ids) and the raw\n * payload here, and threads through to `resolveExperience` (resolution steps\n * + `resolveData` timings) and the renderer (visible missing-component box,\n * debug fallback). A single boolean across fetch + resolve + render.\n */\n debug?: boolean;\n /**\n * Per-request fallback viewport for server-side design pre-resolution. Pass\n * the same id you seed the renderer's `initialViewportId` with (e.g. a\n * User-Agent-derived viewport) so SSR paints correct design on first render.\n */\n initialViewportId?: string;\n};\n\n// TS overload signatures, not real redeclarations — base ESLint's no-redeclare doesn't know the\n// overload form (@typescript-eslint's own version does), so each repeated signature needs a\n// disable comment.\nexport async function fetchExperience(\n experienceOptions: ByIdExperienceOptions,\n clientOptions: ClientOptions,\n resolveOptions: ResolveOptions\n): Promise<PortableRenderPlan>;\n// eslint-disable-next-line no-redeclare -- see above\nexport async function fetchExperience(\n experienceOptions: ByDestinationNodeIdExperienceOptions,\n clientOptions: ClientOptions,\n resolveOptions: ResolveOptions\n): Promise<PortableRenderPlan | DestinationRedirectResult>;\n// eslint-disable-next-line no-redeclare -- see above\nexport async function fetchExperience(\n experienceOptions: ByDestinationPathExperienceOptions,\n clientOptions: ClientOptions,\n resolveOptions: ResolveOptions\n): Promise<PortableRenderPlan | DestinationRedirectResult>;\n// eslint-disable-next-line no-redeclare -- see above\nexport async function fetchExperience(\n experienceOptions: ExperienceOptions,\n clientOptions: ClientOptions,\n resolveOptions: ResolveOptions\n): Promise<PortableRenderPlan | DestinationRedirectResult> {\n const { config, metadata, debug, initialViewportId } = resolveOptions;\n const log = createDebugLogger(debug, 'client');\n\n if (\n !('client' in clientOptions) &&\n clientOptions.preview &&\n 'destinationId' in experienceOptions\n ) {\n const { spaceId, destinationId } = experienceOptions;\n const locator =\n 'nodeId' in experienceOptions\n ? { nodeId: experienceOptions.nodeId }\n : { path: experienceOptions.path };\n throw new DestinationPreviewNotSupportedError(\n `fetchExperience() called with preview: true and a destination-shaped experienceOptions ` +\n `(destinationId \"${destinationId}\"). The Destinations Delivery API does not support ` +\n `preview mode yet — pass preview: false (or omit it) for destination-based fetches.`,\n { spaceId, destinationId, ...locator }\n );\n }\n\n let client: ContentfulViewDeliveryClient;\n if ('client' in clientOptions) {\n client = clientOptions.client;\n log.log('using caller-supplied delivery client');\n } else {\n const { accessToken, previewToken, preview, host } = clientOptions;\n if (preview && !previewToken) {\n throw new Error(\n 'fetchExperience() called with preview: true but no previewToken was provided'\n );\n }\n const resolvedHost = host ?? (preview ? PREVIEW_HOST : undefined);\n client = createClient({\n accessToken: preview ? (previewToken as string) : accessToken,\n host: resolvedHost,\n });\n log.log('created delivery client', { preview: Boolean(preview), host: resolvedHost });\n }\n\n if ('nodeId' in experienceOptions) {\n const { spaceId, destinationId, nodeId } = experienceOptions;\n return fetchByDestination(\n { spaceId, destinationId, locator: nodeId },\n () => client.destination.resolveByNodeId(spaceId, destinationId, nodeId),\n log,\n { config, metadata, debug, initialViewportId }\n );\n }\n\n if ('path' in experienceOptions) {\n const { spaceId, destinationId, path } = experienceOptions;\n return fetchByDestination(\n { spaceId, destinationId, locator: path },\n () => client.destination.resolveByPath(spaceId, destinationId, { path }),\n log,\n { config, metadata, debug, initialViewportId }\n );\n }\n\n const { spaceId, environmentId, experienceId, locale, withSourceMap } = experienceOptions;\n\n log.log('fetching experience', {\n spaceId,\n environmentId,\n experienceId,\n locale,\n withSourceMap: Boolean(withSourceMap),\n });\n\n // Typed as the union of both operations' responses — they declare the same\n // union, but which one runs depends on `withSourceMap` below.\n let response: ExperienceResponse;\n try {\n // Both methods hit the same endpoint; only the POST accepts a body, and\n // `extensions` (the source-map opt-in) lives there. Otherwise identical.\n // The alpha-feature header is sent by the delivery client itself since\n // 1.0.0-dev.7, so a caller-supplied `{ client }` is covered too.\n response = withSourceMap\n ? await client.experience.getWithOverrides(spaceId, environmentId, experienceId, {\n locale,\n extensions: { sourceMap: {} },\n })\n : await client.experience.get(spaceId, environmentId, experienceId, { locale });\n } catch (err) {\n // `NotFoundError` is a distinguishable, expected outcome (draft/unpublished/\n // wrong id) — callers already route it to their framework's 404 idiom, so\n // it passes through as-is. Everything else (network failure, bad/expired\n // token, a 5xx) is unexpected and gets wrapped in an actionable error\n // instead of leaking whatever shape the delivery client happened to throw.\n if (err instanceof ContentfulViewDelivery.NotFoundError) {\n throw err;\n }\n const reason = err instanceof Error ? err.message : String(err);\n throw new ExperienceFetchError(\n `Failed to fetch Experience \"${experienceId}\" (space \"${spaceId}\", environment ` +\n `\"${environmentId}\"): ${reason}. Check network connectivity, the access token, and ` +\n `that the space/environment/experience ids are correct.`,\n { spaceId, environmentId, experienceId, cause: err }\n );\n }\n\n const payload = toExperiencePayload(response);\n const sourceMap = withSourceMap ? readSourceMap(response) : undefined;\n\n log.lazy('received raw payload', () => payload);\n if (withSourceMap && !sourceMap) log.log('source map requested but not returned');\n\n return resolveExperience(payload, config, {\n metadata,\n debug,\n initialViewportId,\n sourceMap,\n });\n}\n\n/**\n * Shared response-handling for both destination-shaped `fetchExperience`\n * branches (by node id, by path).\n */\nasync function fetchByDestination(\n identity: { spaceId: string; destinationId: string; locator: string },\n resolve: () => Promise<ContentfulViewDelivery.DestinationExperienceResolutionResponse>,\n log: ReturnType<typeof createDebugLogger>,\n resolveOptions: {\n config: ResolverConfig;\n metadata: Record<string, unknown> | undefined;\n debug: boolean | undefined;\n initialViewportId: string | undefined;\n }\n): Promise<PortableRenderPlan | DestinationRedirectResult> {\n const { spaceId, destinationId, locator } = identity;\n const { config, metadata, debug, initialViewportId } = resolveOptions;\n\n log.log('resolving destination experience', { spaceId, destinationId, locator });\n\n let response: ContentfulViewDelivery.DestinationExperienceResolutionResponse;\n try {\n response = await resolve();\n } catch (err) {\n if (err instanceof ContentfulViewDelivery.NotFoundError) {\n throw err;\n }\n const reason = err instanceof Error ? err.message : String(err);\n throw new ExperienceFetchError(\n `Failed to resolve Destination \"${destinationId}\" at \"${locator}\" (space \"${spaceId}\"): ` +\n `${reason}. Check network connectivity, the access token, and that the space/` +\n `destination/node-or-path values are correct.`,\n { spaceId, experienceId: locator, cause: err }\n );\n }\n\n if ('redirect' in response) {\n log.log('destination resolved to a redirect', response.redirect);\n return { redirect: response.redirect };\n }\n\n const [firstExperience] = response.experiences;\n if (!firstExperience) {\n throw new ExperienceFetchError(\n `Destination \"${destinationId}\" resolved \"${locator}\" to zero Experiences ` +\n `(space \"${spaceId}\"). Expected exactly one hydrated Experience or a redirect.`,\n { spaceId, experienceId: locator }\n );\n }\n\n const payload = toExperiencePayloadFromDestination(firstExperience.experience);\n log.lazy('received raw payload', () => payload);\n\n return resolveExperience(payload, config, {\n metadata,\n debug,\n initialViewportId,\n });\n}\n"],"mappings":"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","names":["spaceId"]}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ContentfulViewDelivery } from '@contentful/experience-delivery';
2
2
  export { ContentfulViewDelivery, ContentfulViewDeliveryClient } from '@contentful/experience-delivery';
3
- export { ExperienceFetchError } from './errors.js';
3
+ export { DestinationPreviewNotSupportedError, ExperienceFetchError } from './errors.js';
4
4
  export { CreateClientOptions, createClient } from './create-client.js';
5
- export { ClientOptions, ExperienceOptions, ResolveOptions, fetchExperience } from './fetch-experience.js';
6
- export { ExperienceResponse, readSourceMap, toExperiencePayload } from './to-experience-payload.js';
5
+ export { ByDestinationNodeIdExperienceOptions, ByDestinationPathExperienceOptions, ByIdExperienceOptions, ClientOptions, DestinationRedirectResult, ExperienceOptions, ResolveOptions, fetchExperience } from './fetch-experience.js';
6
+ export { ExperienceResponse, readSourceMap, toExperiencePayload, toExperiencePayloadFromDestination } from './to-experience-payload.js';
7
7
  export { DELIVERY_HOST, PREVIEW_HOST, PREVIEW_WEBSOCKET_HOST } from './hosts.js';
8
8
  import '@contentful/experiences-sdk-core';
9
9
 
package/dist/index.js CHANGED
@@ -4,15 +4,20 @@ import {
4
4
  ContentfulViewDeliveryClient
5
5
  } from "@contentful/experience-delivery";
6
6
  const NotFoundError = ContentfulViewDelivery.NotFoundError;
7
- import { ExperienceFetchError } from "./errors.js";
7
+ import { ExperienceFetchError, DestinationPreviewNotSupportedError } from "./errors.js";
8
8
  import { createClient } from "./create-client.js";
9
9
  import { fetchExperience } from "./fetch-experience.js";
10
- import { readSourceMap, toExperiencePayload } from "./to-experience-payload.js";
10
+ import {
11
+ readSourceMap,
12
+ toExperiencePayload,
13
+ toExperiencePayloadFromDestination
14
+ } from "./to-experience-payload.js";
11
15
  import { DELIVERY_HOST, PREVIEW_HOST, PREVIEW_WEBSOCKET_HOST } from "./hosts.js";
12
16
  export {
13
17
  ContentfulViewDelivery2 as ContentfulViewDelivery,
14
18
  ContentfulViewDeliveryClient,
15
19
  DELIVERY_HOST,
20
+ DestinationPreviewNotSupportedError,
16
21
  ExperienceFetchError,
17
22
  NotFoundError,
18
23
  PREVIEW_HOST,
@@ -20,6 +25,7 @@ export {
20
25
  createClient,
21
26
  fetchExperience,
22
27
  readSourceMap,
23
- toExperiencePayload
28
+ toExperiencePayload,
29
+ toExperiencePayloadFromDestination
24
30
  };
25
31
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { ContentfulViewDelivery } from '@contentful/experience-delivery';\n\nexport {\n ContentfulViewDelivery,\n ContentfulViewDeliveryClient,\n} from '@contentful/experience-delivery';\nexport const NotFoundError = ContentfulViewDelivery.NotFoundError;\n// eslint-disable-next-line no-redeclare -- value + type share a name across separate TS namespaces, not a real redeclaration\nexport type NotFoundError = InstanceType<typeof ContentfulViewDelivery.NotFoundError>;\nexport { ExperienceFetchError } from './errors.js';\nexport { createClient } from './create-client.js';\nexport type { CreateClientOptions } from './create-client.js';\nexport { fetchExperience } from './fetch-experience.js';\nexport { readSourceMap, toExperiencePayload } from './to-experience-payload.js';\nexport type { ExperienceResponse } from './to-experience-payload.js';\nexport type { ExperienceOptions, ClientOptions, ResolveOptions } from './fetch-experience.js';\nexport { DELIVERY_HOST, PREVIEW_HOST, PREVIEW_WEBSOCKET_HOST } from './hosts.js';\n"],"mappings":"AAAA,SAAS,8BAA8B;AAEvC;AAAA,EACE,0BAAAA;AAAA,EACA;AAAA,OACK;AACA,MAAM,gBAAgB,uBAAuB;AAGpD,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAE7B,SAAS,uBAAuB;AAChC,SAAS,eAAe,2BAA2B;AAGnD,SAAS,eAAe,cAAc,8BAA8B;","names":["ContentfulViewDelivery"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { ContentfulViewDelivery } from '@contentful/experience-delivery';\n\nexport {\n ContentfulViewDelivery,\n ContentfulViewDeliveryClient,\n} from '@contentful/experience-delivery';\nexport const NotFoundError = ContentfulViewDelivery.NotFoundError;\n// eslint-disable-next-line no-redeclare -- value + type share a name across separate TS namespaces, not a real redeclaration\nexport type NotFoundError = InstanceType<typeof ContentfulViewDelivery.NotFoundError>;\nexport { ExperienceFetchError, DestinationPreviewNotSupportedError } from './errors.js';\nexport { createClient } from './create-client.js';\nexport type { CreateClientOptions } from './create-client.js';\nexport { fetchExperience } from './fetch-experience.js';\nexport {\n readSourceMap,\n toExperiencePayload,\n toExperiencePayloadFromDestination,\n} from './to-experience-payload.js';\nexport type { ExperienceResponse } from './to-experience-payload.js';\nexport type {\n ExperienceOptions,\n ByIdExperienceOptions,\n ByDestinationNodeIdExperienceOptions,\n ByDestinationPathExperienceOptions,\n ClientOptions,\n ResolveOptions,\n DestinationRedirectResult,\n} from './fetch-experience.js';\nexport { DELIVERY_HOST, PREVIEW_HOST, PREVIEW_WEBSOCKET_HOST } from './hosts.js';\n"],"mappings":"AAAA,SAAS,8BAA8B;AAEvC;AAAA,EACE,0BAAAA;AAAA,EACA;AAAA,OACK;AACA,MAAM,gBAAgB,uBAAuB;AAGpD,SAAS,sBAAsB,2CAA2C;AAC1E,SAAS,oBAAoB;AAE7B,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAWP,SAAS,eAAe,cAAc,8BAA8B;","names":["ContentfulViewDelivery"]}
@@ -19,5 +19,13 @@ type ExperienceResponse = ContentfulViewDelivery.GetExperienceResponse | Content
19
19
  declare function toExperiencePayload(response: ExperienceResponse): ExperiencePayload;
20
20
  /** Read `extensions.sourceMap` off a response. `undefined` when the request did not opt in. */
21
21
  declare function readSourceMap(response: ExperienceResponse): ExperienceSourceMap | undefined;
22
+ /**
23
+ * Narrow a `ResolvedDestinationExperience.experience` to `ExperiencePayload`.
24
+ *
25
+ * Same cast rationale as `toExperiencePayload` above, for the destination
26
+ * resolution endpoints' `HydratedExperience` shape instead of the by-id
27
+ * endpoints' `HydratedExperienceView`.
28
+ */
29
+ declare function toExperiencePayloadFromDestination(experience: ContentfulViewDelivery.HydratedExperience): ExperiencePayload;
22
30
 
23
- export { type ExperienceResponse, readSourceMap, toExperiencePayload };
31
+ export { type ExperienceResponse, readSourceMap, toExperiencePayload, toExperiencePayloadFromDestination };
@@ -5,8 +5,12 @@ function readSourceMap(response) {
5
5
  const extensions = response.extensions;
6
6
  return extensions?.sourceMap;
7
7
  }
8
+ function toExperiencePayloadFromDestination(experience) {
9
+ return experience;
10
+ }
8
11
  export {
9
12
  readSourceMap,
10
- toExperiencePayload
13
+ toExperiencePayload,
14
+ toExperiencePayloadFromDestination
11
15
  };
12
16
  //# sourceMappingURL=to-experience-payload.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/to-experience-payload.ts"],"sourcesContent":["/*\n * Typed narrowing from a delivery-client response to the payload shape the\n * renderer consumes.\n */\n\nimport type { ContentfulViewDelivery } from '@contentful/experience-delivery';\nimport type { ExperiencePayload, ExperienceSourceMap } from '@contentful/experiences-sdk-core';\n\n/** Either shape the experience endpoint can return — `get()` and `getWithOverrides()` share it. */\nexport type ExperienceResponse =\n | ContentfulViewDelivery.GetExperienceResponse\n | ContentfulViewDelivery.GetWithOverridesExperienceResponse;\n\n/**\n * Narrow a delivery response to `ExperiencePayload`.\n *\n * The endpoint types its response as `HydratedView | HydratedExperienceView`.\n * The alpha-feature header the delivery client always sends guarantees the\n * latter, but TypeScript cannot know that, so callers were left casting by hand.\n *\n * `fetchExperience` uses this internally; it is exported for anyone driving the\n * delivery client directly. Type-level only — no validation, no copying.\n *\n * A legacy-shaped response carries `componentType` / `template` links instead;\n * `resolveExperience` reports those through `warnUnrenderableNode`.\n */\nexport function toExperiencePayload(response: ExperienceResponse): ExperiencePayload {\n return response as ContentfulViewDelivery.HydratedExperienceView as ExperiencePayload;\n}\n\n/** Read `extensions.sourceMap` off a response. `undefined` when the request did not opt in. */\nexport function readSourceMap(response: ExperienceResponse): ExperienceSourceMap | undefined {\n const extensions = (response as ContentfulViewDelivery.HydratedExperienceView).extensions;\n return extensions?.sourceMap as ExperienceSourceMap | undefined;\n}\n"],"mappings":"AA0BO,SAAS,oBAAoB,UAAiD;AACnF,SAAO;AACT;AAGO,SAAS,cAAc,UAA+D;AAC3F,QAAM,aAAc,SAA2D;AAC/E,SAAO,YAAY;AACrB;","names":[]}
1
+ {"version":3,"sources":["../src/to-experience-payload.ts"],"sourcesContent":["/*\n * Typed narrowing from a delivery-client response to the payload shape the\n * renderer consumes.\n */\n\nimport type { ContentfulViewDelivery } from '@contentful/experience-delivery';\nimport type { ExperiencePayload, ExperienceSourceMap } from '@contentful/experiences-sdk-core';\n\n/** Either shape the experience endpoint can return — `get()` and `getWithOverrides()` share it. */\nexport type ExperienceResponse =\n | ContentfulViewDelivery.GetExperienceResponse\n | ContentfulViewDelivery.GetWithOverridesExperienceResponse;\n\n/**\n * Narrow a delivery response to `ExperiencePayload`.\n *\n * The endpoint types its response as `HydratedView | HydratedExperienceView`.\n * The alpha-feature header the delivery client always sends guarantees the\n * latter, but TypeScript cannot know that, so callers were left casting by hand.\n *\n * `fetchExperience` uses this internally; it is exported for anyone driving the\n * delivery client directly. Type-level only — no validation, no copying.\n *\n * A legacy-shaped response carries `componentType` / `template` links instead;\n * `resolveExperience` reports those through `warnUnrenderableNode`.\n */\nexport function toExperiencePayload(response: ExperienceResponse): ExperiencePayload {\n return response as ContentfulViewDelivery.HydratedExperienceView as ExperiencePayload;\n}\n\n/** Read `extensions.sourceMap` off a response. `undefined` when the request did not opt in. */\nexport function readSourceMap(response: ExperienceResponse): ExperienceSourceMap | undefined {\n const extensions = (response as ContentfulViewDelivery.HydratedExperienceView).extensions;\n return extensions?.sourceMap as ExperienceSourceMap | undefined;\n}\n\n/**\n * Narrow a `ResolvedDestinationExperience.experience` to `ExperiencePayload`.\n *\n * Same cast rationale as `toExperiencePayload` above, for the destination\n * resolution endpoints' `HydratedExperience` shape instead of the by-id\n * endpoints' `HydratedExperienceView`.\n */\nexport function toExperiencePayloadFromDestination(\n experience: ContentfulViewDelivery.HydratedExperience\n): ExperiencePayload {\n return experience as unknown as ExperiencePayload;\n}\n"],"mappings":"AA0BO,SAAS,oBAAoB,UAAiD;AACnF,SAAO;AACT;AAGO,SAAS,cAAc,UAA+D;AAC3F,QAAM,aAAc,SAA2D;AAC/E,SAAO,YAAY;AACrB;AASO,SAAS,mCACd,YACmB;AACnB,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experiences-client",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
4
4
  "description": "Delivery client + fetchExperience for Contentful Experiences",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "directory": "packages/client"
31
31
  },
32
32
  "dependencies": {
33
- "@contentful/experience-delivery": "1.0.0-dev.7",
34
- "@contentful/experiences-sdk-core": "0.8.5"
33
+ "@contentful/experience-delivery": "1.0.0-dev.8",
34
+ "@contentful/experiences-sdk-core": "0.8.6"
35
35
  }
36
36
  }