@contentful/experiences-client 0.10.0 → 0.10.1

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.
@@ -1 +0,0 @@
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` and `fetchDestinationSitemap` when\n * `clientOptions.preview` is `true` for a destination-shaped call\n * (`destinationId` + `nodeId`/`path`, or a sitemap fetch). The Destinations\n * Delivery API has no preview host or preview-token support yet, so this\n * guards against silently hitting the production host with a preview token\n * 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;AAiBO,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,41 +0,0 @@
1
- import { ClientOptions } from './client-resolution.js';
2
- import '@contentful/experience-delivery';
3
- import '@contentful/experiences-sdk-core';
4
-
5
- type FetchDestinationSitemapOptions = {
6
- spaceId: string;
7
- destinationId: string;
8
- };
9
- type FetchDestinationSitemapPaginationOptions = {
10
- /** Maximum number of paths to return. Defaults to `100`, maximum `1000`. */
11
- limit?: number;
12
- /** Cursor from a previous call's `pages.next`. Treat as opaque; don't combine with `pagePrev`. */
13
- pageNext?: string;
14
- /** Cursor from a previous call's `pages.prev`. Treat as opaque; don't combine with `pageNext`. */
15
- pagePrev?: string;
16
- };
17
- type SitemapPathItem = {
18
- /** Path this entry routes. */
19
- path: string;
20
- /** Flat id extracted from the entry's `experienceUrn`. */
21
- experienceId: string;
22
- /** Type of the Destination Node that claims this path, e.g. `"DestinationExperienceNode"`. */
23
- type: string;
24
- };
25
- type DestinationSitemapResult = {
26
- items: SitemapPathItem[];
27
- limit: number;
28
- pages: {
29
- next?: string;
30
- prev?: string;
31
- };
32
- };
33
- /**
34
- * List every routable path in a published Destination. Bulk enumeration —
35
- * pairs with `fetchExperience`'s `destinationId` + `nodeId`/`path` branches,
36
- * which resolve one path at a time. Does not hydrate any Experience itself
37
- * and does not call `fetchExperience` internally.
38
- */
39
- declare function fetchDestinationSitemap(destinationOptions: FetchDestinationSitemapOptions, clientOptions: ClientOptions, paginationOptions?: FetchDestinationSitemapPaginationOptions): Promise<DestinationSitemapResult>;
40
-
41
- export { type DestinationSitemapResult, type FetchDestinationSitemapOptions, type FetchDestinationSitemapPaginationOptions, type SitemapPathItem, fetchDestinationSitemap };
@@ -1,50 +0,0 @@
1
- import { ContentfulViewDelivery } from "@contentful/experience-delivery";
2
- import { createDebugLogger } from "@contentful/experiences-sdk-core";
3
- import { assertDestinationPreviewSupported } from "./destination-guards.js";
4
- import { resolveDeliveryClient } from "./client-resolution.js";
5
- import { ExperienceFetchError } from "./errors.js";
6
- async function fetchDestinationSitemap(destinationOptions, clientOptions, paginationOptions = {}) {
7
- const { spaceId, destinationId } = destinationOptions;
8
- const log = createDebugLogger(false, "client");
9
- if (!("client" in clientOptions)) {
10
- assertDestinationPreviewSupported(clientOptions.preview, { spaceId, destinationId });
11
- }
12
- const client = resolveDeliveryClient(clientOptions, log, "fetchDestinationSitemap");
13
- const { limit, pageNext, pagePrev } = paginationOptions;
14
- let response;
15
- try {
16
- response = await client.destination.sitemap(spaceId, destinationId, {
17
- limit,
18
- pageNext,
19
- pagePrev
20
- });
21
- } catch (err) {
22
- if (err instanceof ContentfulViewDelivery.NotFoundError) {
23
- throw err;
24
- }
25
- const reason = err instanceof Error ? err.message : String(err);
26
- throw new ExperienceFetchError(
27
- `Failed to fetch sitemap for Destination "${destinationId}" (space "${spaceId}"): ${reason}. Check network connectivity, the access token, and that the space/destination ids are correct.`,
28
- { spaceId, experienceId: destinationId, cause: err }
29
- );
30
- }
31
- const result = {
32
- items: response.paths.items.map((item) => ({
33
- path: item.path,
34
- experienceId: extractIdFromUrn(item.experienceUrn),
35
- type: item.sys.type
36
- })),
37
- limit: response.paths.limit,
38
- pages: response.paths.pages
39
- };
40
- log.lazy("received sitemap page", () => result);
41
- return result;
42
- }
43
- function extractIdFromUrn(urn) {
44
- const segments = urn.split("/").filter((s) => s.length > 0);
45
- return segments[segments.length - 1] ?? urn;
46
- }
47
- export {
48
- fetchDestinationSitemap
49
- };
50
- //# sourceMappingURL=fetch-destination-sitemap.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/fetch-destination-sitemap.ts"],"sourcesContent":["import { ContentfulViewDelivery } from '@contentful/experience-delivery';\nimport { createDebugLogger } from '@contentful/experiences-sdk-core';\nimport { assertDestinationPreviewSupported } from './destination-guards.js';\nimport { resolveDeliveryClient, type ClientOptions } from './client-resolution.js';\nimport { ExperienceFetchError } from './errors.js';\n\nexport type FetchDestinationSitemapOptions = {\n spaceId: string;\n destinationId: string;\n};\n\nexport type FetchDestinationSitemapPaginationOptions = {\n /** Maximum number of paths to return. Defaults to `100`, maximum `1000`. */\n limit?: number;\n /** Cursor from a previous call's `pages.next`. Treat as opaque; don't combine with `pagePrev`. */\n pageNext?: string;\n /** Cursor from a previous call's `pages.prev`. Treat as opaque; don't combine with `pageNext`. */\n pagePrev?: string;\n};\n\nexport type SitemapPathItem = {\n /** Path this entry routes. */\n path: string;\n /** Flat id extracted from the entry's `experienceUrn`. */\n experienceId: string;\n /** Type of the Destination Node that claims this path, e.g. `\"DestinationExperienceNode\"`. */\n type: string;\n};\n\nexport type DestinationSitemapResult = {\n items: SitemapPathItem[];\n limit: number;\n pages: { next?: string; prev?: string };\n};\n\n/**\n * List every routable path in a published Destination. Bulk enumeration —\n * pairs with `fetchExperience`'s `destinationId` + `nodeId`/`path` branches,\n * which resolve one path at a time. Does not hydrate any Experience itself\n * and does not call `fetchExperience` internally.\n */\nexport async function fetchDestinationSitemap(\n destinationOptions: FetchDestinationSitemapOptions,\n clientOptions: ClientOptions,\n paginationOptions: FetchDestinationSitemapPaginationOptions = {}\n): Promise<DestinationSitemapResult> {\n const { spaceId, destinationId } = destinationOptions;\n const log = createDebugLogger(false, 'client');\n\n if (!('client' in clientOptions)) {\n assertDestinationPreviewSupported(clientOptions.preview, { spaceId, destinationId });\n }\n\n const client = resolveDeliveryClient(clientOptions, log, 'fetchDestinationSitemap');\n\n const { limit, pageNext, pagePrev } = paginationOptions;\n\n let response: ContentfulViewDelivery.DestinationSitemap;\n try {\n response = await client.destination.sitemap(spaceId, destinationId, {\n limit,\n pageNext,\n pagePrev,\n });\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 fetch sitemap for Destination \"${destinationId}\" (space \"${spaceId}\"): ` +\n `${reason}. Check network connectivity, the access token, and that the space/` +\n `destination ids are correct.`,\n { spaceId, experienceId: destinationId, cause: err }\n );\n }\n\n const result = {\n items: response.paths.items.map((item) => ({\n path: item.path,\n experienceId: extractIdFromUrn(item.experienceUrn),\n type: item.sys.type,\n })),\n limit: response.paths.limit,\n pages: response.paths.pages,\n };\n\n log.lazy('received sitemap page', () => result);\n\n return result;\n}\n\n/**\n * Extract the flat id from an `experienceUrn`. Real shape:\n * crn:contentful:::experience:spaces/$self/environments/$self/experiences/<id>\n *\n * Same one-line logic as the private `extractIdFromUrn` in\n * `packages/core/src/resolve-experience.ts` — not shared across the\n * `core`/`client` package boundary (core stays zero-dep) for one line.\n */\nfunction extractIdFromUrn(urn: string): string {\n const segments = urn.split('/').filter((s) => s.length > 0);\n return segments[segments.length - 1] ?? urn;\n}\n"],"mappings":"AAAA,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAClC,SAAS,yCAAyC;AAClD,SAAS,6BAAiD;AAC1D,SAAS,4BAA4B;AAqCrC,eAAsB,wBACpB,oBACA,eACA,oBAA8D,CAAC,GAC5B;AACnC,QAAM,EAAE,SAAS,cAAc,IAAI;AACnC,QAAM,MAAM,kBAAkB,OAAO,QAAQ;AAE7C,MAAI,EAAE,YAAY,gBAAgB;AAChC,sCAAkC,cAAc,SAAS,EAAE,SAAS,cAAc,CAAC;AAAA,EACrF;AAEA,QAAM,SAAS,sBAAsB,eAAe,KAAK,yBAAyB;AAElF,QAAM,EAAE,OAAO,UAAU,SAAS,IAAI;AAEtC,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,OAAO,YAAY,QAAQ,SAAS,eAAe;AAAA,MAClE;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,QAAI,eAAe,uBAAuB,eAAe;AACvD,YAAM;AAAA,IACR;AACA,UAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,UAAM,IAAI;AAAA,MACR,4CAA4C,aAAa,aAAa,OAAO,OACxE,MAAM;AAAA,MAEX,EAAE,SAAS,cAAc,eAAe,OAAO,IAAI;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,SAAS;AAAA,IACb,OAAO,SAAS,MAAM,MAAM,IAAI,CAAC,UAAU;AAAA,MACzC,MAAM,KAAK;AAAA,MACX,cAAc,iBAAiB,KAAK,aAAa;AAAA,MACjD,MAAM,KAAK,IAAI;AAAA,IACjB,EAAE;AAAA,IACF,OAAO,SAAS,MAAM;AAAA,IACtB,OAAO,SAAS,MAAM;AAAA,EACxB;AAEA,MAAI,KAAK,yBAAyB,MAAM,MAAM;AAE9C,SAAO;AACT;AAUA,SAAS,iBAAiB,KAAqB;AAC7C,QAAM,WAAW,IAAI,MAAM,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC1D,SAAO,SAAS,SAAS,SAAS,CAAC,KAAK;AAC1C;","names":[]}
@@ -1,76 +0,0 @@
1
- import { ContentfulViewDelivery } from '@contentful/experience-delivery';
2
- import { ResolverConfig, PortableRenderPlan } from '@contentful/experiences-sdk-core';
3
- import { ClientOptions } from './client-resolution.js';
4
-
5
- type DeliveryExperienceRequestExtensions = ContentfulViewDelivery.GetWithOverridesExperienceRequestExtensions;
6
- type PersonalizationOptions = NonNullable<DeliveryExperienceRequestExtensions['personalization']>;
7
- type ExperienceRequestExtensions = Omit<DeliveryExperienceRequestExtensions, 'personalization'>;
8
- type ByIdExperienceOptions = {
9
- spaceId: string;
10
- environmentId: string;
11
- experienceId: string;
12
- locale?: string;
13
- /**
14
- * Profile and events used by XDA to personalize the resolved Experience.
15
- */
16
- personalization?: PersonalizationOptions;
17
- /**
18
- * Additional XDA request extensions such as source maps. Supplying a defined
19
- * extension switches the request to POST.
20
- */
21
- extensions?: ExperienceRequestExtensions;
22
- };
23
- /**
24
- * Resolve an Experience by the Destination Node instead of `experienceId`
25
- * The destinations delivery endpoints are space-scoped only and have no locale
26
- * param, unlike the by-id path.
27
- */
28
- type ByDestinationNodeIdExperienceOptions = {
29
- spaceId: string;
30
- destinationId: string;
31
- nodeId: string;
32
- };
33
- /**
34
- * Resolve an Experience by the absolute path wired up to a
35
- * Destination Node, instead of a node id directly. Same scoping as
36
- * `ByDestinationNodeIdExperienceOptions` — no `environmentId` or `locale`.
37
- */
38
- type ByDestinationPathExperienceOptions = {
39
- spaceId: string;
40
- destinationId: string;
41
- /** Absolute path to resolve. Must start with `/`. */
42
- path: string;
43
- };
44
- type ExperienceOptions = ByIdExperienceOptions | ByDestinationNodeIdExperienceOptions | ByDestinationPathExperienceOptions;
45
- /**
46
- * A Destination resolution that the app must act on as control flow — honor
47
- * it by navigating or re-resolving at the new path — rather than a hydrated
48
- * Experience to render. Modeled as a normal return value, not a thrown error,
49
- * per the Destinations delivery API's own framing of a redirect response.
50
- */
51
- interface DestinationRedirectResult {
52
- redirect: {
53
- path: string;
54
- };
55
- }
56
- type ResolveOptions = {
57
- config: ResolverConfig;
58
- /**
59
- * Arbitrary per-render metadata exposed to every resolver as
60
- * `ctx.experience.metadata` and readable at render time via the framework
61
- * adapter's `useExperience()` / `getExperience()`.
62
- */
63
- metadata?: Record<string, unknown>;
64
- /**
65
- * Observability switch. When on: logs the fetch (host, ids) and the raw
66
- * payload here, and threads through to `resolveExperience` (resolution steps
67
- * + `resolveData` timings) and the renderer (visible missing-component box,
68
- * debug fallback). A single boolean across fetch + resolve + render.
69
- */
70
- debug?: boolean;
71
- };
72
- declare function fetchExperience(experienceOptions: ByIdExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan>;
73
- declare function fetchExperience(experienceOptions: ByDestinationNodeIdExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan | DestinationRedirectResult>;
74
- declare function fetchExperience(experienceOptions: ByDestinationPathExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan | DestinationRedirectResult>;
75
-
76
- export { type ByDestinationNodeIdExperienceOptions, type ByDestinationPathExperienceOptions, type ByIdExperienceOptions, ClientOptions, type DestinationRedirectResult, type ExperienceOptions, type ExperienceRequestExtensions, type PersonalizationOptions, type ResolveOptions, fetchExperience };
@@ -1,129 +0,0 @@
1
- import { ContentfulViewDelivery } from "@contentful/experience-delivery";
2
- import { GetWithOverridesExperienceRequestExtensionsPersonalization as personalizationSchema } from "@contentful/experience-delivery/serialization";
3
- import { createDebugLogger, resolveExperience } from "@contentful/experiences-sdk-core";
4
- import { assertDestinationPreviewSupported } from "./destination-guards.js";
5
- import { resolveDeliveryClient } from "./client-resolution.js";
6
- import { ExperienceFetchError } from "./errors.js";
7
- import {
8
- toExperiencePayload,
9
- toExperiencePayloadFromDestination
10
- } from "./to-experience-payload.js";
11
- async function fetchExperience(experienceOptions, clientOptions, resolveOptions) {
12
- const { config, metadata, debug } = resolveOptions;
13
- const log = createDebugLogger(debug, "client");
14
- if (!("client" in clientOptions) && "destinationId" in experienceOptions) {
15
- const { spaceId: spaceId2, destinationId } = experienceOptions;
16
- const locator = "nodeId" in experienceOptions ? { nodeId: experienceOptions.nodeId } : { path: experienceOptions.path };
17
- assertDestinationPreviewSupported(clientOptions.preview, {
18
- spaceId: spaceId2,
19
- destinationId,
20
- ...locator
21
- });
22
- }
23
- const client = resolveDeliveryClient(clientOptions, log, "fetchExperience");
24
- if ("nodeId" in experienceOptions) {
25
- const { spaceId: spaceId2, destinationId, nodeId } = experienceOptions;
26
- return fetchByDestination(
27
- { spaceId: spaceId2, destinationId, locator: nodeId },
28
- () => client.destination.resolveByNodeId(spaceId2, destinationId, nodeId),
29
- log,
30
- { config, metadata, debug }
31
- );
32
- }
33
- if ("path" in experienceOptions) {
34
- const { spaceId: spaceId2, destinationId, path } = experienceOptions;
35
- return fetchByDestination(
36
- { spaceId: spaceId2, destinationId, locator: path },
37
- () => client.destination.resolveByPath(spaceId2, destinationId, { path }),
38
- log,
39
- { config, metadata, debug }
40
- );
41
- }
42
- const { spaceId, environmentId, experienceId, locale, personalization, extensions } = experienceOptions;
43
- log.log("fetching experience", {
44
- spaceId,
45
- environmentId,
46
- experienceId,
47
- locale,
48
- // avoiding log any personalization sensitive data
49
- personalization: personalization !== void 0,
50
- extensions
51
- });
52
- const response = await fetchByExperienceId(client, experienceOptions);
53
- const payload = toExperiencePayload(response);
54
- log.lazy("received raw payload", () => payload);
55
- return resolveExperience(payload, config, { metadata, debug });
56
- }
57
- async function fetchByExperienceId(client, options) {
58
- const { spaceId, environmentId, experienceId, locale, personalization, extensions } = options;
59
- const requestExtensions = { ...extensions };
60
- if (personalization !== void 0) {
61
- try {
62
- requestExtensions.personalization = personalizationSchema.parseOrThrow(personalization, {
63
- unrecognizedObjectKeys: "strip"
64
- });
65
- } catch (cause) {
66
- throw new TypeError("Invalid Experience personalization options", { cause });
67
- }
68
- }
69
- try {
70
- if (hasRequestExtensions(requestExtensions)) {
71
- return await client.experience.getWithOverrides(spaceId, environmentId, experienceId, {
72
- locale,
73
- extensions: requestExtensions
74
- });
75
- }
76
- return await client.experience.get(spaceId, environmentId, experienceId, { locale });
77
- } catch (err) {
78
- if (err instanceof ContentfulViewDelivery.NotFoundError) {
79
- throw err;
80
- }
81
- const reason = err instanceof Error ? err.message : String(err);
82
- throw new ExperienceFetchError(
83
- `Failed to fetch Experience "${experienceId}" (space "${spaceId}", environment "${environmentId}"): ${reason}. Check network connectivity, the access token, and that the space/environment/experience ids are correct.`,
84
- { spaceId, environmentId, experienceId, cause: err }
85
- );
86
- }
87
- }
88
- async function fetchByDestination(identity, resolve, log, resolveOptions) {
89
- const { spaceId, destinationId, locator } = identity;
90
- const { config, metadata, debug } = resolveOptions;
91
- log.log("resolving destination experience", { spaceId, destinationId, locator });
92
- let response;
93
- try {
94
- response = await resolve();
95
- } catch (err) {
96
- if (err instanceof ContentfulViewDelivery.NotFoundError) {
97
- throw err;
98
- }
99
- const reason = err instanceof Error ? err.message : String(err);
100
- throw new ExperienceFetchError(
101
- `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.`,
102
- { spaceId, experienceId: locator, cause: err }
103
- );
104
- }
105
- if ("redirect" in response) {
106
- log.log("destination resolved to a redirect", response.redirect);
107
- return { redirect: response.redirect };
108
- }
109
- const [firstExperience] = response.experiences;
110
- if (!firstExperience) {
111
- throw new ExperienceFetchError(
112
- `Destination "${destinationId}" resolved "${locator}" to zero Experiences (space "${spaceId}"). Expected exactly one hydrated Experience or a redirect.`,
113
- { spaceId, experienceId: locator }
114
- );
115
- }
116
- const payload = toExperiencePayloadFromDestination(firstExperience.experience);
117
- log.lazy("received raw payload", () => payload);
118
- return resolveExperience(payload, config, {
119
- metadata,
120
- debug
121
- });
122
- }
123
- function hasRequestExtensions(extensions) {
124
- return extensions !== void 0 && Object.values(extensions).some((extension) => extension !== void 0);
125
- }
126
- export {
127
- fetchExperience
128
- };
129
- //# sourceMappingURL=fetch-experience.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/fetch-experience.ts"],"sourcesContent":["import type { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';\nimport { ContentfulViewDelivery } from '@contentful/experience-delivery';\nimport { GetWithOverridesExperienceRequestExtensionsPersonalization as personalizationSchema } from '@contentful/experience-delivery/serialization';\nimport { createDebugLogger, resolveExperience } from '@contentful/experiences-sdk-core';\nimport type { PortableRenderPlan, ResolverConfig } from '@contentful/experiences-sdk-core';\nimport { assertDestinationPreviewSupported } from './destination-guards.js';\nimport { resolveDeliveryClient, type ClientOptions } from './client-resolution.js';\nimport { ExperienceFetchError } from './errors.js';\nimport {\n toExperiencePayload,\n toExperiencePayloadFromDestination,\n type ExperienceResponse,\n} from './to-experience-payload.js';\n\nexport type { ClientOptions };\n\ntype DeliveryExperienceRequestExtensions =\n ContentfulViewDelivery.GetWithOverridesExperienceRequestExtensions;\n\nexport type PersonalizationOptions = NonNullable<\n DeliveryExperienceRequestExtensions['personalization']\n>;\n\nexport type ExperienceRequestExtensions = Omit<\n DeliveryExperienceRequestExtensions,\n 'personalization'\n>;\n\nexport type ByIdExperienceOptions = {\n spaceId: string;\n environmentId: string;\n experienceId: string;\n locale?: string;\n /**\n * Profile and events used by XDA to personalize the resolved Experience.\n */\n personalization?: PersonalizationOptions;\n /**\n * Additional XDA request extensions such as source maps. Supplying a defined\n * extension switches the request to POST.\n */\n extensions?: ExperienceRequestExtensions;\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 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\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 } = resolveOptions;\n const log = createDebugLogger(debug, 'client');\n\n if (!('client' in clientOptions) && 'destinationId' in experienceOptions) {\n const { spaceId, destinationId } = experienceOptions;\n const locator =\n 'nodeId' in experienceOptions\n ? { nodeId: experienceOptions.nodeId }\n : { path: experienceOptions.path };\n assertDestinationPreviewSupported(clientOptions.preview, {\n spaceId,\n destinationId,\n ...locator,\n });\n }\n\n const client = resolveDeliveryClient(clientOptions, log, 'fetchExperience');\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 }\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 }\n );\n }\n\n const { spaceId, environmentId, experienceId, locale, personalization, extensions } =\n experienceOptions;\n\n log.log('fetching experience', {\n spaceId,\n environmentId,\n experienceId,\n locale,\n // avoiding log any personalization sensitive data\n personalization: personalization !== undefined,\n extensions,\n });\n\n const response = await fetchByExperienceId(client, experienceOptions);\n\n const payload = toExperiencePayload(response);\n log.lazy('received raw payload', () => payload);\n\n return resolveExperience(payload, config, { metadata, debug });\n}\n\nasync function fetchByExperienceId(\n client: ContentfulViewDeliveryClient,\n options: ByIdExperienceOptions\n): Promise<ExperienceResponse> {\n const { spaceId, environmentId, experienceId, locale, personalization, extensions } = options;\n const requestExtensions: DeliveryExperienceRequestExtensions = { ...extensions };\n if (personalization !== undefined) {\n try {\n // XDA rejects EventBuilder's context.gdpr with HTTP 422. Keep the original\n // events intact and serialize to its generated schema. When upstream XDA and\n // client types accept built events, verify compatibility and remove this if redundant.\n requestExtensions.personalization = personalizationSchema.parseOrThrow(personalization, {\n unrecognizedObjectKeys: 'strip',\n });\n } catch (cause) {\n throw new TypeError('Invalid Experience personalization options', { cause });\n }\n }\n\n try {\n // Both methods hit the same endpoint, but only the POST operation accepts\n // extensions in its request body. Keep the cacheable GET when there are no\n // extensions to evaluate.\n // The generated delivery client owns the alpha-feature header on both\n // paths, including when the caller supplied the client instance.\n //\n // Await inside the try so rejected requests are normalized below.\n if (hasRequestExtensions(requestExtensions)) {\n return await client.experience.getWithOverrides(spaceId, environmentId, experienceId, {\n locale,\n extensions: requestExtensions,\n });\n }\n\n return await client.experience.get(spaceId, environmentId, experienceId, { locale });\n } catch (err) {\n // Preserve expected 404 control flow for framework routers. Other failures\n // are wrapped with stable SDK context instead of exposing transport-specific\n // error shapes.\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\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 }\n): Promise<PortableRenderPlan | DestinationRedirectResult> {\n const { spaceId, destinationId, locator } = identity;\n const { config, metadata, debug } = 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 });\n}\n\nfunction hasRequestExtensions(\n extensions: DeliveryExperienceRequestExtensions | undefined\n): extensions is DeliveryExperienceRequestExtensions {\n return (\n extensions !== undefined &&\n Object.values(extensions).some((extension) => extension !== undefined)\n );\n}\n"],"mappings":"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","names":["spaceId"]}
package/dist/hosts.d.ts DELETED
@@ -1,5 +0,0 @@
1
- declare const DELIVERY_HOST = "https://xdn.contentful.com";
2
- declare const PREVIEW_HOST = "https://preview.xdn.contentful.com";
3
- declare const PREVIEW_WEBSOCKET_HOST = "wss://preview.xdn.contentful.com";
4
-
5
- export { DELIVERY_HOST, PREVIEW_HOST, PREVIEW_WEBSOCKET_HOST };
package/dist/hosts.js DELETED
@@ -1,9 +0,0 @@
1
- const DELIVERY_HOST = "https://xdn.contentful.com";
2
- const PREVIEW_HOST = "https://preview.xdn.contentful.com";
3
- const PREVIEW_WEBSOCKET_HOST = "wss://preview.xdn.contentful.com";
4
- export {
5
- DELIVERY_HOST,
6
- PREVIEW_HOST,
7
- PREVIEW_WEBSOCKET_HOST
8
- };
9
- //# sourceMappingURL=hosts.js.map
package/dist/hosts.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/hosts.ts"],"sourcesContent":["export const DELIVERY_HOST = 'https://xdn.contentful.com';\nexport const PREVIEW_HOST = 'https://preview.xdn.contentful.com';\nexport const PREVIEW_WEBSOCKET_HOST = 'wss://preview.xdn.contentful.com';\n"],"mappings":"AAAO,MAAM,gBAAgB;AACtB,MAAM,eAAe;AACrB,MAAM,yBAAyB;","names":[]}
@@ -1,31 +0,0 @@
1
- import { ContentfulViewDelivery } from '@contentful/experience-delivery';
2
- import { ExperienceSourceMap, ExperiencePayload } from '@contentful/experiences-sdk-core';
3
-
4
- /** Either shape the experience endpoint can return — `get()` and `getWithOverrides()` share it. */
5
- type ExperienceResponse = ContentfulViewDelivery.GetExperienceResponse | ContentfulViewDelivery.GetWithOverridesExperienceResponse;
6
- /**
7
- * Narrow a delivery response to `ExperiencePayload`.
8
- *
9
- * The endpoint types its response as `HydratedView | HydratedExperienceView`.
10
- * The alpha-feature header the delivery client always sends guarantees the
11
- * latter, but TypeScript cannot know that, so callers were left casting by hand.
12
- *
13
- * `fetchExperience` uses this internally; it is exported for anyone driving the
14
- * delivery client directly. Type-level only — no validation, no copying.
15
- *
16
- * A legacy-shaped response carries `componentType` / `template` links instead;
17
- * `resolveExperience` reports those through `warnUnrenderableNode`.
18
- */
19
- declare function toExperiencePayload(response: ExperienceResponse): ExperiencePayload;
20
- /** Read `extensions.sourceMap` off a response. `undefined` when the request did not opt in. */
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;
30
-
31
- export { type ExperienceResponse, readSourceMap, toExperiencePayload, toExperiencePayloadFromDestination };
@@ -1,16 +0,0 @@
1
- function toExperiencePayload(response) {
2
- return response;
3
- }
4
- function readSourceMap(response) {
5
- const extensions = response.extensions;
6
- return extensions?.sourceMap;
7
- }
8
- function toExperiencePayloadFromDestination(experience) {
9
- return experience;
10
- }
11
- export {
12
- readSourceMap,
13
- toExperiencePayload,
14
- toExperiencePayloadFromDestination
15
- };
16
- //# sourceMappingURL=to-experience-payload.js.map
@@ -1 +0,0 @@
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":[]}