@contentful/experiences-client 0.10.0 → 0.10.2
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 +20 -0
- package/README.md +19 -5
- package/dist/index.cjs +327 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +251 -0
- package/dist/index.d.mts +251 -0
- package/dist/index.d.ts +246 -10
- package/dist/index.js +310 -16
- package/dist/index.js.map +1 -1
- package/package.json +10 -5
- package/dist/client-resolution.d.ts +0 -34
- package/dist/client-resolution.js +0 -23
- package/dist/client-resolution.js.map +0 -1
- package/dist/create-delivery-client.d.ts +0 -15
- package/dist/create-delivery-client.js +0 -13
- package/dist/create-delivery-client.js.map +0 -1
- package/dist/destination-guards.d.ts +0 -16
- package/dist/destination-guards.js +0 -14
- package/dist/destination-guards.js.map +0 -1
- package/dist/errors.d.ts +0 -57
- package/dist/errors.js +0 -31
- package/dist/errors.js.map +0 -1
- package/dist/fetch-destination-sitemap.d.ts +0 -41
- package/dist/fetch-destination-sitemap.js +0 -50
- package/dist/fetch-destination-sitemap.js.map +0 -1
- package/dist/fetch-experience.d.ts +0 -76
- package/dist/fetch-experience.js +0 -129
- package/dist/fetch-experience.js.map +0 -1
- package/dist/hosts.d.ts +0 -5
- package/dist/hosts.js +0 -9
- package/dist/hosts.js.map +0 -1
- package/dist/to-experience-payload.d.ts +0 -31
- package/dist/to-experience-payload.js +0 -16
- package/dist/to-experience-payload.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,251 @@
|
|
|
1
|
-
import { ContentfulViewDelivery } from '@contentful/experience-delivery';
|
|
1
|
+
import { ContentfulViewDeliveryClient, ContentfulViewDelivery } from '@contentful/experience-delivery';
|
|
2
2
|
export { ContentfulViewDelivery, ContentfulViewDeliveryClient } from '@contentful/experience-delivery';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
import { ResolverConfig, PortableRenderPlan, ExperienceSourceMap, ExperiencePayload } from '@contentful/experiences-sdk-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Thrown by `fetchExperience` for a fetch failure that is not "experience not
|
|
7
|
+
* found" — network failure, an invalid/expired token, a 5xx from the
|
|
8
|
+
* delivery API, etc. This failure mode is "surface clearly to the host app,"
|
|
9
|
+
* unlike the diagnostics `resolveExperience` collects for resolve/render-time
|
|
10
|
+
* issues — there's no partial payload to render around a fetch that never
|
|
11
|
+
* returned one, so a real thrown class is the right shape.
|
|
12
|
+
*
|
|
13
|
+
* `NotFoundError` (the delivery client's class, re-exported from this
|
|
14
|
+
* package) is the one exception: it passes through undisturbed so callers
|
|
15
|
+
* can route it to their framework's 404 idiom, per the existing
|
|
16
|
+
* distinguishable-404 contract.
|
|
17
|
+
*
|
|
18
|
+
* `environmentId` is `undefined` for the destination-shaped `fetchExperience`
|
|
19
|
+
* branches — the destinations delivery endpoints are space-scoped only, with
|
|
20
|
+
* no environment segment, unlike the by-id path.
|
|
21
|
+
*/
|
|
22
|
+
declare class ExperienceFetchError extends Error {
|
|
23
|
+
readonly spaceId: string;
|
|
24
|
+
readonly environmentId: string | undefined;
|
|
25
|
+
readonly experienceId: string;
|
|
26
|
+
constructor(message: string, options: {
|
|
27
|
+
spaceId: string;
|
|
28
|
+
environmentId?: string;
|
|
29
|
+
experienceId: string;
|
|
30
|
+
cause?: unknown;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Thrown by `fetchExperience` and `fetchDestinationSitemap` when
|
|
35
|
+
* `clientOptions.preview` is `true` for a destination-shaped call
|
|
36
|
+
* (`destinationId` + `nodeId`/`path`, or a sitemap fetch). The Destinations
|
|
37
|
+
* Delivery API has no preview host or preview-token support yet, so this
|
|
38
|
+
* guards against silently hitting the production host with a preview token
|
|
39
|
+
* it doesn't accept.
|
|
40
|
+
*
|
|
41
|
+
* This is a bridge, not a permanent design: revisit once the platform ships
|
|
42
|
+
* preview support for destinations.
|
|
43
|
+
*
|
|
44
|
+
* Only fires for the inline-credentials branch of `ClientOptions`. A
|
|
45
|
+
* caller-supplied `{ client }` already ignores `preview` entirely, per that
|
|
46
|
+
* branch's existing contract.
|
|
47
|
+
*/
|
|
48
|
+
declare class DestinationPreviewNotSupportedError extends Error {
|
|
49
|
+
readonly spaceId: string;
|
|
50
|
+
readonly destinationId: string;
|
|
51
|
+
readonly nodeId: string | undefined;
|
|
52
|
+
readonly path: string | undefined;
|
|
53
|
+
constructor(message: string, options: {
|
|
54
|
+
spaceId: string;
|
|
55
|
+
destinationId: string;
|
|
56
|
+
nodeId?: string;
|
|
57
|
+
path?: string;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Options for the legacy functional Delivery client constructor. */
|
|
62
|
+
type CreateClientOptions = {
|
|
63
|
+
accessToken: string;
|
|
64
|
+
/**
|
|
65
|
+
* Base URL for the delivery client. Defaults to `DELIVERY_HOST` when omitted.
|
|
66
|
+
* Pass `PREVIEW_HOST` for preview mode, or any custom URL (staging, proxy,
|
|
67
|
+
* per-region). Both constants are exported from this package.
|
|
68
|
+
*/
|
|
69
|
+
host?: string;
|
|
70
|
+
} & Omit<ContentfulViewDeliveryClient.Options, 'token' | 'baseUrl'>;
|
|
71
|
+
declare function createClient(options: CreateClientOptions): ContentfulViewDeliveryClient;
|
|
72
|
+
|
|
73
|
+
type ClientOptions = {
|
|
74
|
+
accessToken: string;
|
|
75
|
+
/**
|
|
76
|
+
* Preview access token. Required when calling with `preview: true`.
|
|
77
|
+
*/
|
|
78
|
+
previewToken?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Flip between delivery (default) and preview at request time. When
|
|
81
|
+
* `true`, uses `previewToken` and the preview host; when `false` or
|
|
82
|
+
* unset, uses `accessToken` and the delivery host. Ignored when a
|
|
83
|
+
* pre-made `client` is passed instead of inline creds.
|
|
84
|
+
*/
|
|
85
|
+
preview?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Custom base URL for the delivery client (staging, proxy, per-region).
|
|
88
|
+
* Wins over the `preview`-derived default host — combine `host` with
|
|
89
|
+
* `preview: true` to point preview mode at a non-prod endpoint.
|
|
90
|
+
* Omit for the standard delivery / preview hosts.
|
|
91
|
+
*/
|
|
92
|
+
host?: string;
|
|
93
|
+
} | {
|
|
94
|
+
client: ContentfulViewDeliveryClient;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/** One collection order path; `-` selects descending order. Delivery validates the path. */
|
|
98
|
+
type ExperienceParameterOrder = `fields.${string}` | `sys.${string}` | `-fields.${string}` | `-sys.${string}`;
|
|
99
|
+
/** Runtime values for one Record parameter. Nested records and arrays are not supported. */
|
|
100
|
+
type ExperienceParameterRecord = Record<string, string | number>;
|
|
101
|
+
type ExperienceParameterValue = string | number | ExperienceParameterRecord;
|
|
102
|
+
/** Unprefixed IDs declared in Experience.parameters and referenced as `$parameters/<id>`. */
|
|
103
|
+
type ExperienceParameters = Record<string, ExperienceParameterValue>;
|
|
104
|
+
|
|
105
|
+
type DeliveryExperienceRequestExtensions = ContentfulViewDelivery.GetWithOverridesExperienceRequestExtensions;
|
|
106
|
+
type PersonalizationOptions = NonNullable<DeliveryExperienceRequestExtensions['personalization']>;
|
|
107
|
+
type ExperienceRequestExtensions = Omit<DeliveryExperienceRequestExtensions, 'personalization'>;
|
|
108
|
+
type ByIdExperienceOptions = {
|
|
109
|
+
spaceId: string;
|
|
110
|
+
environmentId: string;
|
|
111
|
+
experienceId: string;
|
|
112
|
+
locale?: string;
|
|
113
|
+
/** Values for declared Experience parameters. Refetch with new values to swap content. */
|
|
114
|
+
parameters?: ExperienceParameters;
|
|
115
|
+
/**
|
|
116
|
+
* Profile and events used by XDA to personalize the resolved Experience.
|
|
117
|
+
*/
|
|
118
|
+
personalization?: PersonalizationOptions;
|
|
119
|
+
/**
|
|
120
|
+
* Additional XDA request extensions such as source maps. Supplying a defined
|
|
121
|
+
* extension switches the request to POST.
|
|
122
|
+
*/
|
|
123
|
+
extensions?: ExperienceRequestExtensions;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Resolve an Experience by the Destination Node instead of `experienceId`
|
|
127
|
+
* The destinations delivery endpoints are space-scoped only and have no locale
|
|
128
|
+
* param, unlike the by-id path.
|
|
129
|
+
*/
|
|
130
|
+
type ByDestinationNodeIdExperienceOptions = {
|
|
131
|
+
spaceId: string;
|
|
132
|
+
destinationId: string;
|
|
133
|
+
nodeId: string;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Resolve an Experience by the absolute path wired up to a
|
|
137
|
+
* Destination Node, instead of a node id directly. Same scoping as
|
|
138
|
+
* `ByDestinationNodeIdExperienceOptions` — no `environmentId` or `locale`.
|
|
139
|
+
*/
|
|
140
|
+
type ByDestinationPathExperienceOptions = {
|
|
141
|
+
spaceId: string;
|
|
142
|
+
destinationId: string;
|
|
143
|
+
/** Absolute path to resolve. Must start with `/`. */
|
|
144
|
+
path: string;
|
|
145
|
+
};
|
|
146
|
+
type ExperienceOptions = ByIdExperienceOptions | ByDestinationNodeIdExperienceOptions | ByDestinationPathExperienceOptions;
|
|
147
|
+
/**
|
|
148
|
+
* A Destination resolution that the app must act on as control flow — honor
|
|
149
|
+
* it by navigating or re-resolving at the new path — rather than a hydrated
|
|
150
|
+
* Experience to render. Modeled as a normal return value, not a thrown error,
|
|
151
|
+
* per the Destinations delivery API's own framing of a redirect response.
|
|
152
|
+
*/
|
|
153
|
+
interface DestinationRedirectResult {
|
|
154
|
+
redirect: {
|
|
155
|
+
path: string;
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
type ResolveOptions = {
|
|
159
|
+
config: ResolverConfig;
|
|
160
|
+
/**
|
|
161
|
+
* Arbitrary per-render metadata exposed to every resolver as
|
|
162
|
+
* `ctx.experience.metadata` and readable at render time via the framework
|
|
163
|
+
* adapter's `useExperience()` / `getExperience()`.
|
|
164
|
+
*/
|
|
165
|
+
metadata?: Record<string, unknown>;
|
|
166
|
+
/**
|
|
167
|
+
* Observability switch. When on: logs the fetch (host, ids) and the raw
|
|
168
|
+
* payload here, and threads through to `resolveExperience` (resolution steps
|
|
169
|
+
* + `resolveData` timings) and the renderer (visible missing-component box,
|
|
170
|
+
* debug fallback). A single boolean across fetch + resolve + render.
|
|
171
|
+
*/
|
|
172
|
+
debug?: boolean;
|
|
173
|
+
};
|
|
174
|
+
declare function fetchExperience(experienceOptions: ByIdExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan>;
|
|
175
|
+
declare function fetchExperience(experienceOptions: ByDestinationNodeIdExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan | DestinationRedirectResult>;
|
|
176
|
+
declare function fetchExperience(experienceOptions: ByDestinationPathExperienceOptions, clientOptions: ClientOptions, resolveOptions: ResolveOptions): Promise<PortableRenderPlan | DestinationRedirectResult>;
|
|
177
|
+
|
|
178
|
+
type FetchDestinationSitemapOptions = {
|
|
179
|
+
spaceId: string;
|
|
180
|
+
destinationId: string;
|
|
181
|
+
};
|
|
182
|
+
type FetchDestinationSitemapPaginationOptions = {
|
|
183
|
+
/** Maximum number of paths to return. Defaults to `100`, maximum `1000`. */
|
|
184
|
+
limit?: number;
|
|
185
|
+
/** Cursor from a previous call's `pages.next`. Treat as opaque; don't combine with `pagePrev`. */
|
|
186
|
+
pageNext?: string;
|
|
187
|
+
/** Cursor from a previous call's `pages.prev`. Treat as opaque; don't combine with `pageNext`. */
|
|
188
|
+
pagePrev?: string;
|
|
189
|
+
};
|
|
190
|
+
type SitemapPathItem = {
|
|
191
|
+
/** Path this entry routes. */
|
|
192
|
+
path: string;
|
|
193
|
+
/** Flat id extracted from the entry's `experienceUrn`. */
|
|
194
|
+
experienceId: string;
|
|
195
|
+
/** Type of the Destination Node that claims this path, e.g. `"DestinationExperienceNode"`. */
|
|
196
|
+
type: string;
|
|
197
|
+
};
|
|
198
|
+
type DestinationSitemapResult = {
|
|
199
|
+
items: SitemapPathItem[];
|
|
200
|
+
limit: number;
|
|
201
|
+
pages: {
|
|
202
|
+
next?: string;
|
|
203
|
+
prev?: string;
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* List every routable path in a published Destination. Bulk enumeration —
|
|
208
|
+
* pairs with `fetchExperience`'s `destinationId` + `nodeId`/`path` branches,
|
|
209
|
+
* which resolve one path at a time. Does not hydrate any Experience itself
|
|
210
|
+
* and does not call `fetchExperience` internally.
|
|
211
|
+
*/
|
|
212
|
+
declare function fetchDestinationSitemap(destinationOptions: FetchDestinationSitemapOptions, clientOptions: ClientOptions, paginationOptions?: FetchDestinationSitemapPaginationOptions): Promise<DestinationSitemapResult>;
|
|
213
|
+
|
|
214
|
+
/** Either shape the experience endpoint can return — `get()` and `getWithOverrides()` share it. */
|
|
215
|
+
type ExperienceResponse = ContentfulViewDelivery.GetExperienceResponse | ContentfulViewDelivery.GetWithOverridesExperienceResponse;
|
|
216
|
+
/**
|
|
217
|
+
* Narrow a delivery response to `ExperiencePayload`.
|
|
218
|
+
*
|
|
219
|
+
* The endpoint types its response as `HydratedView | HydratedExperienceView`.
|
|
220
|
+
* The alpha-feature header the delivery client always sends guarantees the
|
|
221
|
+
* latter, but TypeScript cannot know that, so callers were left casting by hand.
|
|
222
|
+
*
|
|
223
|
+
* `fetchExperience` uses this internally; it is exported for anyone driving the
|
|
224
|
+
* delivery client directly. Type-level only — no validation, no copying.
|
|
225
|
+
*
|
|
226
|
+
* A legacy-shaped response carries `componentType` / `template` links instead;
|
|
227
|
+
* `resolveExperience` reports those through `warnUnrenderableNode`.
|
|
228
|
+
*/
|
|
229
|
+
declare function toExperiencePayload(response: ExperienceResponse): ExperiencePayload;
|
|
230
|
+
/** Read `extensions.sourceMap` off a response. `undefined` when the request did not opt in. */
|
|
231
|
+
declare function readSourceMap(response: ExperienceResponse): ExperienceSourceMap | undefined;
|
|
232
|
+
/**
|
|
233
|
+
* Narrow a `ResolvedDestinationExperience.experience` to `ExperiencePayload`.
|
|
234
|
+
*
|
|
235
|
+
* Same cast rationale as `toExperiencePayload` above, for the destination
|
|
236
|
+
* resolution endpoints' `HydratedExperience` shape instead of the by-id
|
|
237
|
+
* endpoints' `HydratedExperienceView`.
|
|
238
|
+
*/
|
|
239
|
+
declare function toExperiencePayloadFromDestination(experience: ContentfulViewDelivery.HydratedExperience): ExperiencePayload;
|
|
240
|
+
|
|
241
|
+
declare const DELIVERY_HOST = "https://xdn.contentful.com";
|
|
242
|
+
declare const PREVIEW_HOST = "https://preview.xdn.contentful.com";
|
|
243
|
+
declare const PREVIEW_WEBSOCKET_HOST = "wss://preview.xdn.contentful.com";
|
|
244
|
+
|
|
245
|
+
/** Validate and serialize events to the generated XDA request contract. */
|
|
246
|
+
declare function serializePersonalization(personalization: unknown): PersonalizationOptions;
|
|
11
247
|
|
|
12
248
|
declare const NotFoundError: typeof ContentfulViewDelivery.NotFoundError;
|
|
13
249
|
type NotFoundError = InstanceType<typeof ContentfulViewDelivery.NotFoundError>;
|
|
14
250
|
|
|
15
|
-
export { NotFoundError };
|
|
251
|
+
export { type ByDestinationNodeIdExperienceOptions, type ByDestinationPathExperienceOptions, type ByIdExperienceOptions, type ClientOptions, type CreateClientOptions, DELIVERY_HOST, DestinationPreviewNotSupportedError, type DestinationRedirectResult, type DestinationSitemapResult, ExperienceFetchError, type ExperienceOptions, type ExperienceParameterOrder, type ExperienceParameterRecord, type ExperienceParameterValue, type ExperienceParameters, type ExperienceRequestExtensions, type ExperienceResponse, type FetchDestinationSitemapOptions, type FetchDestinationSitemapPaginationOptions, NotFoundError, PREVIEW_HOST, PREVIEW_WEBSOCKET_HOST, type PersonalizationOptions, type ResolveOptions, type SitemapPathItem, createClient, fetchDestinationSitemap, fetchExperience, readSourceMap, serializePersonalization, toExperiencePayload, toExperiencePayloadFromDestination };
|
package/dist/index.js
CHANGED
|
@@ -1,22 +1,315 @@
|
|
|
1
|
-
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { ContentfulViewDelivery as ContentfulViewDelivery3 } from "@contentful/experience-delivery";
|
|
2
3
|
import {
|
|
3
|
-
ContentfulViewDelivery as
|
|
4
|
-
ContentfulViewDeliveryClient
|
|
4
|
+
ContentfulViewDelivery as ContentfulViewDelivery4,
|
|
5
|
+
ContentfulViewDeliveryClient as ContentfulViewDeliveryClient2
|
|
5
6
|
} from "@contentful/experience-delivery";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
|
|
8
|
+
// src/errors.ts
|
|
9
|
+
var ExperienceFetchError = class extends Error {
|
|
10
|
+
spaceId;
|
|
11
|
+
environmentId;
|
|
12
|
+
experienceId;
|
|
13
|
+
constructor(message, options) {
|
|
14
|
+
super(message, options.cause !== void 0 ? { cause: options.cause } : void 0);
|
|
15
|
+
this.name = "ExperienceFetchError";
|
|
16
|
+
this.spaceId = options.spaceId;
|
|
17
|
+
this.environmentId = options.environmentId;
|
|
18
|
+
this.experienceId = options.experienceId;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var DestinationPreviewNotSupportedError = class extends Error {
|
|
22
|
+
spaceId;
|
|
23
|
+
destinationId;
|
|
24
|
+
nodeId;
|
|
25
|
+
path;
|
|
26
|
+
constructor(message, options) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "DestinationPreviewNotSupportedError";
|
|
29
|
+
this.spaceId = options.spaceId;
|
|
30
|
+
this.destinationId = options.destinationId;
|
|
31
|
+
this.nodeId = options.nodeId;
|
|
32
|
+
this.path = options.path;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// src/create-delivery-client.ts
|
|
37
|
+
import { ContentfulViewDeliveryClient } from "@contentful/experience-delivery";
|
|
38
|
+
function createClient(options) {
|
|
39
|
+
const { accessToken, host, ...rest } = options;
|
|
40
|
+
return new ContentfulViewDeliveryClient({
|
|
41
|
+
...rest,
|
|
42
|
+
token: accessToken,
|
|
43
|
+
baseUrl: host
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/fetch-experience.ts
|
|
48
|
+
import { ContentfulViewDelivery } from "@contentful/experience-delivery";
|
|
49
|
+
|
|
50
|
+
// src/personalization.ts
|
|
51
|
+
import { GetWithOverridesExperienceRequestExtensionsPersonalization as personalizationSchema } from "@contentful/experience-delivery/serialization";
|
|
52
|
+
function serializePersonalization(personalization) {
|
|
53
|
+
try {
|
|
54
|
+
return personalizationSchema.parseOrThrow(personalization, {
|
|
55
|
+
unrecognizedObjectKeys: "strip"
|
|
56
|
+
});
|
|
57
|
+
} catch (cause) {
|
|
58
|
+
throw new TypeError("Invalid Experience personalization options", { cause });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/fetch-experience.ts
|
|
63
|
+
import { createDebugLogger, resolveExperience } from "@contentful/experiences-sdk-core";
|
|
64
|
+
|
|
65
|
+
// src/destination-guards.ts
|
|
66
|
+
function assertDestinationPreviewSupported(isPreview, destination) {
|
|
67
|
+
if (!isPreview) return;
|
|
68
|
+
const { spaceId, destinationId, nodeId, path } = destination;
|
|
69
|
+
const locator = nodeId !== void 0 ? `nodeId "${nodeId}"` : `path "${path}"`;
|
|
70
|
+
throw new DestinationPreviewNotSupportedError(
|
|
71
|
+
`preview: true was combined with a destination-shaped call (destinationId "${destinationId}", ${locator}). The Destinations Delivery API does not support preview mode yet \u2014 pass preview: false (or omit it) for destination-based fetches.`,
|
|
72
|
+
{ spaceId, destinationId, nodeId, path }
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/hosts.ts
|
|
77
|
+
var DELIVERY_HOST = "https://xdn.contentful.com";
|
|
78
|
+
var PREVIEW_HOST = "https://preview.xdn.contentful.com";
|
|
79
|
+
var PREVIEW_WEBSOCKET_HOST = "wss://preview.xdn.contentful.com";
|
|
80
|
+
|
|
81
|
+
// src/client-resolution.ts
|
|
82
|
+
function resolveDeliveryClient(clientOptions, log, callerName) {
|
|
83
|
+
if ("client" in clientOptions) {
|
|
84
|
+
log.log("using caller-supplied delivery client");
|
|
85
|
+
return clientOptions.client;
|
|
86
|
+
}
|
|
87
|
+
const { accessToken, previewToken, preview, host } = clientOptions;
|
|
88
|
+
if (preview && !previewToken) {
|
|
89
|
+
throw new Error(`${callerName}() called with preview: true but no previewToken was provided`);
|
|
90
|
+
}
|
|
91
|
+
const resolvedHost = host ?? (preview ? PREVIEW_HOST : void 0);
|
|
92
|
+
const client = createClient({
|
|
93
|
+
accessToken: preview ? previewToken : accessToken,
|
|
94
|
+
host: resolvedHost
|
|
95
|
+
});
|
|
96
|
+
log.log("created delivery client", { preview: Boolean(preview), host: resolvedHost });
|
|
97
|
+
return client;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/experience-parameters.ts
|
|
101
|
+
function parameterQuery(parameters) {
|
|
102
|
+
const entries = [];
|
|
103
|
+
for (const [id, value] of Object.entries(parameters ?? {})) {
|
|
104
|
+
if (id.includes(".")) return void 0;
|
|
105
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
106
|
+
entries.push([`parameter.${id}`, value]);
|
|
107
|
+
} else {
|
|
108
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
109
|
+
const leaves = Object.entries(value);
|
|
110
|
+
if (leaves.length === 0) return void 0;
|
|
111
|
+
for (const [field, leaf] of leaves) {
|
|
112
|
+
if (field.includes(".")) return void 0;
|
|
113
|
+
if (typeof leaf !== "string" && typeof leaf !== "number") return void 0;
|
|
114
|
+
entries.push([`parameter.${id}.${field}`, leaf]);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return Object.fromEntries(entries);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/to-experience-payload.ts
|
|
122
|
+
function toExperiencePayload(response) {
|
|
123
|
+
return response;
|
|
124
|
+
}
|
|
125
|
+
function readSourceMap(response) {
|
|
126
|
+
const extensions = response.extensions;
|
|
127
|
+
return extensions?.sourceMap;
|
|
128
|
+
}
|
|
129
|
+
function toExperiencePayloadFromDestination(experience) {
|
|
130
|
+
return experience;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/fetch-experience.ts
|
|
134
|
+
async function fetchExperience(experienceOptions, clientOptions, resolveOptions) {
|
|
135
|
+
const { config, metadata, debug } = resolveOptions;
|
|
136
|
+
const log = createDebugLogger(debug, "client");
|
|
137
|
+
if (!("client" in clientOptions) && "destinationId" in experienceOptions) {
|
|
138
|
+
const { spaceId: spaceId2, destinationId } = experienceOptions;
|
|
139
|
+
const locator = "nodeId" in experienceOptions ? { nodeId: experienceOptions.nodeId } : { path: experienceOptions.path };
|
|
140
|
+
assertDestinationPreviewSupported(clientOptions.preview, {
|
|
141
|
+
spaceId: spaceId2,
|
|
142
|
+
destinationId,
|
|
143
|
+
...locator
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const client = resolveDeliveryClient(clientOptions, log, "fetchExperience");
|
|
147
|
+
if ("nodeId" in experienceOptions) {
|
|
148
|
+
const { spaceId: spaceId2, destinationId, nodeId } = experienceOptions;
|
|
149
|
+
return fetchByDestination(
|
|
150
|
+
{ spaceId: spaceId2, destinationId, locator: nodeId },
|
|
151
|
+
() => client.destination.resolveByNodeId(spaceId2, destinationId, nodeId),
|
|
152
|
+
log,
|
|
153
|
+
{ config, metadata, debug }
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
if ("path" in experienceOptions) {
|
|
157
|
+
const { spaceId: spaceId2, destinationId, path } = experienceOptions;
|
|
158
|
+
return fetchByDestination(
|
|
159
|
+
{ spaceId: spaceId2, destinationId, locator: path },
|
|
160
|
+
() => client.destination.resolveByPath(spaceId2, destinationId, { path }),
|
|
161
|
+
log,
|
|
162
|
+
{ config, metadata, debug }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
const { spaceId, environmentId, experienceId, locale, personalization, extensions } = experienceOptions;
|
|
166
|
+
log.log("fetching experience", {
|
|
167
|
+
spaceId,
|
|
168
|
+
environmentId,
|
|
169
|
+
experienceId,
|
|
170
|
+
locale,
|
|
171
|
+
// avoiding log any personalization sensitive data
|
|
172
|
+
personalization: personalization !== void 0,
|
|
173
|
+
extensions
|
|
174
|
+
});
|
|
175
|
+
const response = await fetchByExperienceId(client, experienceOptions);
|
|
176
|
+
const payload = toExperiencePayload(response);
|
|
177
|
+
log.lazy("received raw payload", () => payload);
|
|
178
|
+
return resolveExperience(payload, config, { metadata, debug });
|
|
179
|
+
}
|
|
180
|
+
async function fetchByExperienceId(client, options) {
|
|
181
|
+
const { spaceId, environmentId, experienceId, locale, parameters, personalization, extensions } = options;
|
|
182
|
+
const requestExtensions = { ...extensions };
|
|
183
|
+
if (personalization !== void 0) {
|
|
184
|
+
requestExtensions.personalization = serializePersonalization(personalization);
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const queryParams = parameterQuery(parameters);
|
|
188
|
+
if (hasRequestExtensions(requestExtensions) || queryParams === void 0) {
|
|
189
|
+
const request = {
|
|
190
|
+
locale,
|
|
191
|
+
extensions: requestExtensions,
|
|
192
|
+
...parameters === void 0 ? {} : { parameters }
|
|
193
|
+
};
|
|
194
|
+
return await client.experience.getWithOverrides(
|
|
195
|
+
spaceId,
|
|
196
|
+
environmentId,
|
|
197
|
+
experienceId,
|
|
198
|
+
request
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
if (Object.keys(queryParams).length > 0) {
|
|
202
|
+
return await client.experience.get(
|
|
203
|
+
spaceId,
|
|
204
|
+
environmentId,
|
|
205
|
+
experienceId,
|
|
206
|
+
{ locale },
|
|
207
|
+
{
|
|
208
|
+
queryParams
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
return await client.experience.get(spaceId, environmentId, experienceId, { locale });
|
|
213
|
+
} catch (err) {
|
|
214
|
+
if (err instanceof ContentfulViewDelivery.NotFoundError) {
|
|
215
|
+
throw err;
|
|
216
|
+
}
|
|
217
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
218
|
+
throw new ExperienceFetchError(
|
|
219
|
+
`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.`,
|
|
220
|
+
{ spaceId, environmentId, experienceId, cause: err }
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async function fetchByDestination(identity, resolve, log, resolveOptions) {
|
|
225
|
+
const { spaceId, destinationId, locator } = identity;
|
|
226
|
+
const { config, metadata, debug } = resolveOptions;
|
|
227
|
+
log.log("resolving destination experience", { spaceId, destinationId, locator });
|
|
228
|
+
let response;
|
|
229
|
+
try {
|
|
230
|
+
response = await resolve();
|
|
231
|
+
} catch (err) {
|
|
232
|
+
if (err instanceof ContentfulViewDelivery.NotFoundError) {
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
235
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
236
|
+
throw new ExperienceFetchError(
|
|
237
|
+
`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.`,
|
|
238
|
+
{ spaceId, experienceId: locator, cause: err }
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
if ("redirect" in response) {
|
|
242
|
+
log.log("destination resolved to a redirect", response.redirect);
|
|
243
|
+
return { redirect: response.redirect };
|
|
244
|
+
}
|
|
245
|
+
const [firstExperience] = response.experiences;
|
|
246
|
+
if (!firstExperience) {
|
|
247
|
+
throw new ExperienceFetchError(
|
|
248
|
+
`Destination "${destinationId}" resolved "${locator}" to zero Experiences (space "${spaceId}"). Expected exactly one hydrated Experience or a redirect.`,
|
|
249
|
+
{ spaceId, experienceId: locator }
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
const payload = toExperiencePayloadFromDestination(firstExperience.experience);
|
|
253
|
+
log.lazy("received raw payload", () => payload);
|
|
254
|
+
return resolveExperience(payload, config, {
|
|
255
|
+
metadata,
|
|
256
|
+
debug
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
function hasRequestExtensions(extensions) {
|
|
260
|
+
return extensions !== void 0 && Object.values(extensions).some((extension) => extension !== void 0);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// src/fetch-destination-sitemap.ts
|
|
264
|
+
import { ContentfulViewDelivery as ContentfulViewDelivery2 } from "@contentful/experience-delivery";
|
|
265
|
+
import { createDebugLogger as createDebugLogger2 } from "@contentful/experiences-sdk-core";
|
|
266
|
+
async function fetchDestinationSitemap(destinationOptions, clientOptions, paginationOptions = {}) {
|
|
267
|
+
const { spaceId, destinationId } = destinationOptions;
|
|
268
|
+
const log = createDebugLogger2(false, "client");
|
|
269
|
+
if (!("client" in clientOptions)) {
|
|
270
|
+
assertDestinationPreviewSupported(clientOptions.preview, { spaceId, destinationId });
|
|
271
|
+
}
|
|
272
|
+
const client = resolveDeliveryClient(clientOptions, log, "fetchDestinationSitemap");
|
|
273
|
+
const { limit, pageNext, pagePrev } = paginationOptions;
|
|
274
|
+
let response;
|
|
275
|
+
try {
|
|
276
|
+
response = await client.destination.sitemap(spaceId, destinationId, {
|
|
277
|
+
limit,
|
|
278
|
+
pageNext,
|
|
279
|
+
pagePrev
|
|
280
|
+
});
|
|
281
|
+
} catch (err) {
|
|
282
|
+
if (err instanceof ContentfulViewDelivery2.NotFoundError) {
|
|
283
|
+
throw err;
|
|
284
|
+
}
|
|
285
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
286
|
+
throw new ExperienceFetchError(
|
|
287
|
+
`Failed to fetch sitemap for Destination "${destinationId}" (space "${spaceId}"): ${reason}. Check network connectivity, the access token, and that the space/destination ids are correct.`,
|
|
288
|
+
{ spaceId, experienceId: destinationId, cause: err }
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
const result = {
|
|
292
|
+
items: response.paths.items.map((item) => ({
|
|
293
|
+
path: item.path,
|
|
294
|
+
experienceId: extractIdFromUrn(item.experienceUrn),
|
|
295
|
+
type: item.sys.type
|
|
296
|
+
})),
|
|
297
|
+
limit: response.paths.limit,
|
|
298
|
+
pages: response.paths.pages
|
|
299
|
+
};
|
|
300
|
+
log.lazy("received sitemap page", () => result);
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
function extractIdFromUrn(urn) {
|
|
304
|
+
const segments = urn.split("/").filter((s) => s.length > 0);
|
|
305
|
+
return segments[segments.length - 1] ?? urn;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// src/index.ts
|
|
309
|
+
var NotFoundError = ContentfulViewDelivery3.NotFoundError;
|
|
17
310
|
export {
|
|
18
|
-
|
|
19
|
-
ContentfulViewDeliveryClient,
|
|
311
|
+
ContentfulViewDelivery4 as ContentfulViewDelivery,
|
|
312
|
+
ContentfulViewDeliveryClient2 as ContentfulViewDeliveryClient,
|
|
20
313
|
DELIVERY_HOST,
|
|
21
314
|
DestinationPreviewNotSupportedError,
|
|
22
315
|
ExperienceFetchError,
|
|
@@ -27,6 +320,7 @@ export {
|
|
|
27
320
|
fetchDestinationSitemap,
|
|
28
321
|
fetchExperience,
|
|
29
322
|
readSourceMap,
|
|
323
|
+
serializePersonalization,
|
|
30
324
|
toExperiencePayload,
|
|
31
325
|
toExperiencePayloadFromDestination
|
|
32
326
|
};
|