@contentful/experiences-client 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.7.0 (2026-09-30)
2
+
3
+ ### 🚀 Features
4
+
5
+ - ⚠️ add event-triggering methods to runtimes ([#209](https://github.com/contentful/experiences/pull/209))
6
+
7
+ ### ⚠️ Breaking Changes
8
+
9
+ - add event-triggering methods to runtimes ([#209](https://github.com/contentful/experiences/pull/209))
10
+
1
11
  ## 0.6.0 (2026-09-30)
2
12
 
3
13
  ### 🚀 Features
package/README.md CHANGED
@@ -16,35 +16,81 @@ remain supported for adapter and application integration.
16
16
 
17
17
  `ContentfulExperiences` is an internal shared runtime contract for the public
18
18
  Node/Web SDKs. Construct it with a space, environment, resolver configuration,
19
- a delivery client source, and an `eventBuilder` config with an explicit
20
- `channel`; optionally provide a preview client source. It retains those clients,
21
- merges configured resolve defaults with per-call options, and exposes
22
- `resolveExperience` and by-id/destination `fetchExperience` methods. Calling
23
- `fetchExperience` with `preview: true` requires the optional preview client.
24
-
25
- The Client transport configuration is trusted: its bearer token is sent to the
26
- selected endpoint. `environmentId` is the Contentful environment identifier
27
- passed to by-ID Experience requests; it is not the generated delivery client's
28
- optional `environment` endpoint setting. For a Client-created transport,
29
- Experiences' `host` is passed through as the generated client's `baseUrl`.
30
- Callers that construct a raw `ContentfulViewDeliveryClient` may configure
31
- `baseUrl` directly. This is how both public leaves can use trusted custom
32
- endpoints (for example, a proxy, staging service, or regional endpoint).
33
- Endpoint precedence is explicit `host`/raw-client `baseUrl`, then the generated
34
- client's `environment`, then the delivery or preview default.
19
+ a delivery configuration, and an `eventBuilder` config with an explicit
20
+ `channel`; optionally provide a preview configuration. It constructs and retains
21
+ those clients, merges configured resolve defaults with per-call options, and
22
+ exposes `resolveExperience` and by-id/destination `fetchExperience` methods.
23
+ Calling `fetchExperience` with `preview: true` requires preview configuration.
24
+
25
+ The runtime-owned Delivery and Preview clients support two security models. For
26
+ direct API access, provide an `accessToken`; it may be a supplier and is sent to
27
+ the selected endpoint. For a trusted application proxy that adds the upstream
28
+ token itself, omit `accessToken` and provide an explicit `host`; the runtime
29
+ disables generated bearer authentication. `environmentId` is the Contentful
30
+ environment identifier passed to by-ID requests, not the generated delivery
31
+ client's optional endpoint-valued `environment`. Endpoint precedence is
32
+ explicit `host`, then generated-client `environment`, then the delivery or
33
+ preview default.
34
+
35
+ Direct browser tokens are credentials but are intentionally browser-visible
36
+ when an application's scope and CORS policy permit that model. Proxy mode keeps
37
+ the upstream token server-side. In either mode, treat custom endpoints as
38
+ trusted configuration.
35
39
 
36
40
  The optional preview client enables direct CPA fetches by Experience ID through
37
41
  the same shared runtime. It is separate from `@contentful/experiences-live-preview`,
38
42
  which owns Preview Session HTTP loading, WebSocket subscription, and update state.
39
43
  Destination operations continue to use the delivery client.
40
44
 
41
- The runtime constructs and owns one `EventBuilder`. The caller supplies its
42
- channel, while the runtime retains this SDK's default library identity and the
43
- runtime locale unless overridden. This is the owner of event construction for
44
- the lower layer, rather than Core.
45
+ The runtime constructs and owns one `EventBuilder` and one Optimization API
46
+ client. The caller supplies the event channel, while the runtime retains this
47
+ SDK's default library identity and the runtime locale unless overridden. This
48
+ package owns event construction and direct transport for the lower layer,
49
+ rather than Core. It exposes a protected binding point used by the public Node
50
+ and Web leaves; Client itself does not retain a mutable event profile.
51
+
52
+ By default the Optimization client uses the runtime's `spaceId` and maps its
53
+ Contentful `environmentId` to the Optimization client's `environment` option.
54
+ This is the same Contentful environment identifier passed to by-ID delivery
55
+ requests, not the generated delivery client's endpoint-valued `environment`
56
+ setting. The optional `optimization` configuration can provide API-specific
57
+ endpoint, feature, and fetch overrides; the runtime always constructs and owns
58
+ the Optimization client. Custom Optimization base URLs receive complete event
59
+ and profile payloads, so treat them as sensitive-data destinations and use only
60
+ trusted HTTPS origins outside explicit local development.
61
+
62
+ The bound event methods normally send immediately: `identify`, `page`, and
63
+ `track` upsert a profile through the Personalization API; view, click, hover,
64
+ and flag-view events send a one-event batch through Analytics. Queues, durable
65
+ profile persistence, consent gating, lifecycle/beacon delivery, automatic
66
+ interaction tracking, and Live Preview integration are intentionally absent.
67
+ The Node leaf additionally has a request-scoped, one-shot handoff journal for
68
+ paired browser replay; it is not an SDK queue or persistence mechanism. Because
69
+ calls are not serialized, callers must await profile-producing calls before
70
+ starting another profile-producing or Analytics call on the same bound runtime.
71
+
72
+ ### Server-to-browser event handoff contract
73
+
74
+ `RuntimeEventHandoff` is the internal replay payload between Node and Web. Node
75
+ alone chooses direct `commit` or paired-browser `handoff` delivery per request.
76
+ The handoff holds a version, Contentful scope, optional initial profile, ordered
77
+ Personalization/Analytics event bodies, and an optional initial-page route key. Its
78
+ internal serialized-payload cap is 64 KiB. Node can preflight the initial
79
+ Personalization sequence as one batch; individual Personalization methods remain
80
+ cumulative and Analytics methods stage without transport. Web validates the
81
+ payload, admits page-bearing journals only for a matching browser route,
82
+ batches compatible adjacent Personalization entries, preserves locale and Analytics
83
+ ordering boundaries, and chains each resulting profile.
84
+
85
+ The payload is browser-visible sensitive data. Application integration must use
86
+ escaped serialization in a private, no-store response and exclude secrets and
87
+ server-only traits. Do not cache, log, or persist it. Replay may partially
88
+ commit, has no automatic retry or distributed exactly-once guarantee, and is
89
+ independent from Live Preview. A failed replay rejects its receipt but releases
90
+ later direct Web calls. See the root [paired replay guide](../../README.md#paired-server-to-browser-replay).
45
91
 
46
92
  This package's direct dependencies are the generated delivery client,
47
- `@contentful/optimization-api-client` (event schemas and logger), `es-toolkit`
93
+ `@contentful/optimization-api-client` (event schemas, logger, and transport), `es-toolkit`
48
94
  (event-property merging), and `zod` (event argument schemas), in addition to
49
95
  Core. None of those dependencies are introduced into Core.
50
96
 
@@ -201,7 +247,7 @@ const client = new ContentfulViewDeliveryClient({
201
247
  - Do not import `@contentful/experience-delivery` from anywhere except this package.
202
248
  - Re-export only what framework adapters need to surface to their users.
203
249
  - Keep `fetchExperience` thin — fetch + cast + resolve. Business logic belongs in `packages/core`.
204
- - Name mappings between SDK options and delivery-client options live in `create-client.ts` — one place to change.
250
+ - Name mappings between SDK options and delivery-client options live in `create-delivery-client.ts` — one place to change.
205
251
 
206
252
  ## License
207
253
 
@@ -1,14 +1,14 @@
1
- import { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';
2
1
  import { ExperiencePayload, PortableRenderPlan, ResolverConfig } from '@contentful/experiences-sdk-core';
3
2
  import EventBuilder, { EventBuilderConfig } from './event-builder.js';
3
+ import { RuntimeDeliveryClientOptions } from './create-delivery-client.js';
4
4
  import { PersonalizationOptions, ExperienceRequestExtensions, DestinationRedirectResult } from './fetch-experience.js';
5
- import { CreateClientOptions } from './create-client.js';
5
+ import { RuntimeOptimizationConfig } from './create-optimization-client.js';
6
+ import { RuntimeOptimizationApiClient, RuntimeEventBindings, RuntimeEventDispatch, RuntimeEventMethods } from './runtime-event-methods.js';
6
7
  import '@contentful/optimization-api-client/api-schemas';
7
8
  import 'zod/mini';
9
+ import '@contentful/experience-delivery';
10
+ import '@contentful/optimization-api-client';
8
11
 
9
- type RuntimeClientSource = CreateClientOptions | {
10
- client: ContentfulViewDeliveryClient;
11
- };
12
12
  type RuntimeResolveOptions = {
13
13
  metadata?: Record<string, unknown>;
14
14
  debug?: boolean;
@@ -49,8 +49,12 @@ type ContentfulExperiencesConfig = {
49
49
  environmentId: string;
50
50
  locale?: string;
51
51
  resolverConfig: ResolverConfig;
52
- delivery: RuntimeClientSource;
53
- preview?: RuntimeClientSource;
52
+ /** Configuration for the runtime-owned Content Delivery API client. */
53
+ delivery: RuntimeDeliveryClientOptions;
54
+ /** Optional configuration for the runtime-owned Content Preview API client. */
55
+ preview?: RuntimeDeliveryClientOptions;
56
+ /** Overrides for the runtime-owned Personalization and Analytics event transport. */
57
+ optimization?: RuntimeOptimizationConfig;
54
58
  resolveDefaults?: Pick<RuntimeResolveOptions, 'metadata' | 'debug'>;
55
59
  eventBuilder: RuntimeEventBuilderConfig;
56
60
  };
@@ -59,12 +63,14 @@ declare class ContentfulExperiences implements ExperienceRuntime {
59
63
  readonly spaceId: string;
60
64
  readonly environmentId: string;
61
65
  readonly eventBuilder: EventBuilder;
66
+ protected readonly optimizationApi: RuntimeOptimizationApiClient;
62
67
  constructor(config: ContentfulExperiencesConfig);
63
68
  get locale(): string | undefined;
69
+ protected createEventMethods(bindings: RuntimeEventBindings, dispatch?: RuntimeEventDispatch): RuntimeEventMethods;
64
70
  resolveExperience(payload: ExperiencePayload, resolveOptions?: RuntimeResolveOptions): Promise<PortableRenderPlan>;
65
71
  fetchExperience(options: RuntimeFetchExperienceOptions, resolveOptions?: RuntimeResolveOptions): Promise<PortableRenderPlan>;
66
72
  fetchByDestinationNode(options: RuntimeFetchByDestinationNodeOptions, resolveOptions?: RuntimeResolveOptions): Promise<PortableRenderPlan | DestinationRedirectResult>;
67
73
  fetchByDestinationPath(options: RuntimeFetchByDestinationPathOptions, resolveOptions?: RuntimeResolveOptions): Promise<PortableRenderPlan | DestinationRedirectResult>;
68
74
  }
69
75
 
70
- export { ContentfulExperiences, type ContentfulExperiencesConfig, type ExperienceRuntime, type RuntimeClientSource, type RuntimeEventBuilderConfig, type RuntimeFetchByDestinationNodeOptions, type RuntimeFetchByDestinationPathOptions, type RuntimeFetchExperienceOptions, type RuntimeResolveOptions };
76
+ export { ContentfulExperiences, type ContentfulExperiencesConfig, type ExperienceRuntime, type RuntimeEventBuilderConfig, type RuntimeFetchByDestinationNodeOptions, type RuntimeFetchByDestinationPathOptions, type RuntimeFetchExperienceOptions, type RuntimeResolveOptions };
@@ -1,11 +1,19 @@
1
1
  import { resolveExperience as resolveCoreExperience } from "@contentful/experiences-sdk-core";
2
2
  import EventBuilder from "./event-builder.js";
3
- import { createClient } from "./create-client.js";
3
+ import {
4
+ createRuntimeDeliveryClient
5
+ } from "./create-delivery-client.js";
4
6
  import {
5
7
  fetchExperience
6
8
  } from "./fetch-experience.js";
9
+ import {
10
+ createRuntimeOptimizationClient
11
+ } from "./create-optimization-client.js";
7
12
  import { PREVIEW_HOST } from "./hosts.js";
8
13
  import { DEFAULT_EVENT_CONTEXT_LIBRARY } from "./sdk-info.js";
14
+ import {
15
+ createRuntimeEventMethods
16
+ } from "./runtime-event-methods.js";
9
17
  class ContentfulExperiences {
10
18
  spaceId;
11
19
  environmentId;
@@ -14,14 +22,20 @@ class ContentfulExperiences {
14
22
  #resolverConfig;
15
23
  #deliveryClient;
16
24
  #previewClient;
25
+ optimizationApi;
17
26
  #resolveDefaults;
18
27
  constructor(config) {
19
28
  this.spaceId = config.spaceId;
20
29
  this.environmentId = config.environmentId;
21
30
  this.#locale = config.locale;
22
31
  this.#resolverConfig = config.resolverConfig;
23
- this.#deliveryClient = resolveClient(config.delivery);
24
- this.#previewClient = config.preview === void 0 ? void 0 : resolveClient(config.preview, PREVIEW_HOST);
32
+ this.#deliveryClient = createRuntimeDeliveryClient(config.delivery);
33
+ this.#previewClient = config.preview === void 0 ? void 0 : createRuntimeDeliveryClient(config.preview, PREVIEW_HOST);
34
+ this.optimizationApi = createRuntimeOptimizationClient({
35
+ spaceId: config.spaceId,
36
+ environmentId: config.environmentId,
37
+ ...config.optimization
38
+ });
25
39
  this.#resolveDefaults = config.resolveDefaults ?? {};
26
40
  this.eventBuilder = new EventBuilder({
27
41
  ...config.eventBuilder,
@@ -32,6 +46,9 @@ class ContentfulExperiences {
32
46
  get locale() {
33
47
  return this.#locale;
34
48
  }
49
+ createEventMethods(bindings, dispatch) {
50
+ return createRuntimeEventMethods(this.optimizationApi, this.eventBuilder, bindings, dispatch);
51
+ }
35
52
  resolveExperience(payload, resolveOptions) {
36
53
  return resolveCoreExperience(
37
54
  payload,
@@ -82,13 +99,6 @@ class ContentfulExperiences {
82
99
  };
83
100
  }
84
101
  }
85
- function resolveClient(source, defaultHost) {
86
- if ("client" in source) return source.client;
87
- return createClient({
88
- ...source,
89
- host: source.host ?? (source.environment === void 0 ? defaultHost : void 0)
90
- });
91
- }
92
102
  export {
93
103
  ContentfulExperiences
94
104
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/contentful-experiences.ts"],"sourcesContent":["import type { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';\nimport { resolveExperience as resolveCoreExperience } from '@contentful/experiences-sdk-core';\nimport type {\n ExperiencePayload,\n PortableRenderPlan,\n ResolverConfig,\n} from '@contentful/experiences-sdk-core';\nimport EventBuilder from './event-builder.js';\nimport type { EventBuilderConfig } from './event-builder.js';\nimport { createClient } from './create-client.js';\nimport {\n fetchExperience,\n type DestinationRedirectResult,\n type ExperienceRequestExtensions,\n type PersonalizationOptions,\n} from './fetch-experience.js';\nimport type { CreateClientOptions } from './create-client.js';\nimport { PREVIEW_HOST } from './hosts.js';\nimport { DEFAULT_EVENT_CONTEXT_LIBRARY } from './sdk-info.js';\n\nexport type RuntimeClientSource = CreateClientOptions | { client: ContentfulViewDeliveryClient };\n\nexport type RuntimeResolveOptions = {\n metadata?: Record<string, unknown>;\n debug?: boolean;\n initialViewportId?: string;\n};\n\nexport type RuntimeEventBuilderConfig = Omit<EventBuilderConfig, 'channel' | 'library'> & {\n channel: EventBuilderConfig['channel'];\n library?: Partial<EventBuilderConfig['library']>;\n};\n\nexport type RuntimeFetchExperienceOptions = {\n experienceId: string;\n locale?: string;\n personalization?: PersonalizationOptions;\n extensions?: ExperienceRequestExtensions;\n preview?: boolean;\n};\n\nexport type RuntimeFetchByDestinationNodeOptions = {\n destinationId: string;\n nodeId: string;\n};\n\nexport type RuntimeFetchByDestinationPathOptions = {\n destinationId: string;\n path: string;\n};\n\n/** Structural contract implemented by the Client runtime. */\nexport interface ExperienceRuntime {\n readonly spaceId: string;\n readonly environmentId: string;\n readonly locale: string | undefined;\n readonly eventBuilder: EventBuilder;\n resolveExperience(\n payload: ExperiencePayload,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan>;\n fetchExperience(\n options: RuntimeFetchExperienceOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan>;\n fetchByDestinationNode(\n options: RuntimeFetchByDestinationNodeOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan | DestinationRedirectResult>;\n fetchByDestinationPath(\n options: RuntimeFetchByDestinationPathOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan | DestinationRedirectResult>;\n}\n\nexport type ContentfulExperiencesConfig = {\n spaceId: string;\n environmentId: string;\n locale?: string;\n resolverConfig: ResolverConfig;\n delivery: RuntimeClientSource;\n preview?: RuntimeClientSource;\n resolveDefaults?: Pick<RuntimeResolveOptions, 'metadata' | 'debug'>;\n eventBuilder: RuntimeEventBuilderConfig;\n};\n\nexport class ContentfulExperiences implements ExperienceRuntime {\n readonly spaceId: string;\n readonly environmentId: string;\n readonly eventBuilder: EventBuilder;\n\n readonly #locale: string | undefined;\n readonly #resolverConfig: ResolverConfig;\n readonly #deliveryClient: ContentfulViewDeliveryClient;\n readonly #previewClient: ContentfulViewDeliveryClient | undefined;\n readonly #resolveDefaults: Pick<RuntimeResolveOptions, 'metadata' | 'debug'>;\n\n constructor(config: ContentfulExperiencesConfig) {\n this.spaceId = config.spaceId;\n this.environmentId = config.environmentId;\n this.#locale = config.locale;\n this.#resolverConfig = config.resolverConfig;\n this.#deliveryClient = resolveClient(config.delivery);\n this.#previewClient =\n config.preview === undefined ? undefined : resolveClient(config.preview, PREVIEW_HOST);\n this.#resolveDefaults = config.resolveDefaults ?? {};\n\n this.eventBuilder = new EventBuilder({\n ...config.eventBuilder,\n library: { ...DEFAULT_EVENT_CONTEXT_LIBRARY, ...config.eventBuilder.library },\n getLocale: config.eventBuilder.getLocale ?? (() => this.locale),\n });\n }\n\n get locale(): string | undefined {\n return this.#locale;\n }\n\n resolveExperience(\n payload: ExperiencePayload,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan> {\n return resolveCoreExperience(\n payload,\n this.#resolverConfig,\n this.#mergeResolveOptions(resolveOptions)\n );\n }\n\n fetchExperience(\n options: RuntimeFetchExperienceOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan> {\n if (options.preview === true && this.#previewClient === undefined) {\n throw new Error(\n 'fetchExperience() called with preview: true but this runtime has no preview client'\n );\n }\n return fetchExperience(\n {\n spaceId: this.spaceId,\n environmentId: this.environmentId,\n experienceId: options.experienceId,\n locale: options.locale ?? this.locale,\n personalization: options.personalization,\n extensions: options.extensions,\n },\n {\n client: options.preview\n ? (this.#previewClient as ContentfulViewDeliveryClient)\n : this.#deliveryClient,\n },\n { config: this.#resolverConfig, ...this.#mergeResolveOptions(resolveOptions) }\n );\n }\n\n fetchByDestinationNode(\n options: RuntimeFetchByDestinationNodeOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan | DestinationRedirectResult> {\n return fetchExperience(\n { spaceId: this.spaceId, destinationId: options.destinationId, nodeId: options.nodeId },\n { client: this.#deliveryClient },\n { config: this.#resolverConfig, ...this.#mergeResolveOptions(resolveOptions) }\n );\n }\n\n fetchByDestinationPath(\n options: RuntimeFetchByDestinationPathOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan | DestinationRedirectResult> {\n return fetchExperience(\n { spaceId: this.spaceId, destinationId: options.destinationId, path: options.path },\n { client: this.#deliveryClient },\n { config: this.#resolverConfig, ...this.#mergeResolveOptions(resolveOptions) }\n );\n }\n\n #mergeResolveOptions(options: RuntimeResolveOptions | undefined): RuntimeResolveOptions {\n return {\n metadata: { ...this.#resolveDefaults.metadata, ...options?.metadata },\n debug: options?.debug ?? this.#resolveDefaults.debug,\n initialViewportId: options?.initialViewportId,\n };\n }\n}\n\nfunction resolveClient(\n source: RuntimeClientSource,\n defaultHost?: string\n): ContentfulViewDeliveryClient {\n if ('client' in source) return source.client;\n\n return createClient({\n ...source,\n host: source.host ?? (source.environment === undefined ? defaultHost : undefined),\n });\n}\n"],"mappings":"AACA,SAAS,qBAAqB,6BAA6B;AAM3D,OAAO,kBAAkB;AAEzB,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,OAIK;AAEP,SAAS,oBAAoB;AAC7B,SAAS,qCAAqC;AAoEvC,MAAM,sBAAmD;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAqC;AAC/C,SAAK,UAAU,OAAO;AACtB,SAAK,gBAAgB,OAAO;AAC5B,SAAK,UAAU,OAAO;AACtB,SAAK,kBAAkB,OAAO;AAC9B,SAAK,kBAAkB,cAAc,OAAO,QAAQ;AACpD,SAAK,iBACH,OAAO,YAAY,SAAY,SAAY,cAAc,OAAO,SAAS,YAAY;AACvF,SAAK,mBAAmB,OAAO,mBAAmB,CAAC;AAEnD,SAAK,eAAe,IAAI,aAAa;AAAA,MACnC,GAAG,OAAO;AAAA,MACV,SAAS,EAAE,GAAG,+BAA+B,GAAG,OAAO,aAAa,QAAQ;AAAA,MAC5E,WAAW,OAAO,aAAa,cAAc,MAAM,KAAK;AAAA,IAC1D,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,SAA6B;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBACE,SACA,gBAC6B;AAC7B,WAAO;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL,KAAK,qBAAqB,cAAc;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,gBACE,SACA,gBAC6B;AAC7B,QAAI,QAAQ,YAAY,QAAQ,KAAK,mBAAmB,QAAW;AACjE,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,QACE,SAAS,KAAK;AAAA,QACd,eAAe,KAAK;AAAA,QACpB,cAAc,QAAQ;AAAA,QACtB,QAAQ,QAAQ,UAAU,KAAK;AAAA,QAC/B,iBAAiB,QAAQ;AAAA,QACzB,YAAY,QAAQ;AAAA,MACtB;AAAA,MACA;AAAA,QACE,QAAQ,QAAQ,UACX,KAAK,iBACN,KAAK;AAAA,MACX;AAAA,MACA,EAAE,QAAQ,KAAK,iBAAiB,GAAG,KAAK,qBAAqB,cAAc,EAAE;AAAA,IAC/E;AAAA,EACF;AAAA,EAEA,uBACE,SACA,gBACyD;AACzD,WAAO;AAAA,MACL,EAAE,SAAS,KAAK,SAAS,eAAe,QAAQ,eAAe,QAAQ,QAAQ,OAAO;AAAA,MACtF,EAAE,QAAQ,KAAK,gBAAgB;AAAA,MAC/B,EAAE,QAAQ,KAAK,iBAAiB,GAAG,KAAK,qBAAqB,cAAc,EAAE;AAAA,IAC/E;AAAA,EACF;AAAA,EAEA,uBACE,SACA,gBACyD;AACzD,WAAO;AAAA,MACL,EAAE,SAAS,KAAK,SAAS,eAAe,QAAQ,eAAe,MAAM,QAAQ,KAAK;AAAA,MAClF,EAAE,QAAQ,KAAK,gBAAgB;AAAA,MAC/B,EAAE,QAAQ,KAAK,iBAAiB,GAAG,KAAK,qBAAqB,cAAc,EAAE;AAAA,IAC/E;AAAA,EACF;AAAA,EAEA,qBAAqB,SAAmE;AACtF,WAAO;AAAA,MACL,UAAU,EAAE,GAAG,KAAK,iBAAiB,UAAU,GAAG,SAAS,SAAS;AAAA,MACpE,OAAO,SAAS,SAAS,KAAK,iBAAiB;AAAA,MAC/C,mBAAmB,SAAS;AAAA,IAC9B;AAAA,EACF;AACF;AAEA,SAAS,cACP,QACA,aAC8B;AAC9B,MAAI,YAAY,OAAQ,QAAO,OAAO;AAEtC,SAAO,aAAa;AAAA,IAClB,GAAG;AAAA,IACH,MAAM,OAAO,SAAS,OAAO,gBAAgB,SAAY,cAAc;AAAA,EACzE,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../src/contentful-experiences.ts"],"sourcesContent":["import type { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';\nimport { resolveExperience as resolveCoreExperience } from '@contentful/experiences-sdk-core';\nimport type {\n ExperiencePayload,\n PortableRenderPlan,\n ResolverConfig,\n} from '@contentful/experiences-sdk-core';\nimport EventBuilder from './event-builder.js';\nimport type { EventBuilderConfig } from './event-builder.js';\nimport {\n createRuntimeDeliveryClient,\n type RuntimeDeliveryClientOptions,\n} from './create-delivery-client.js';\nimport {\n fetchExperience,\n type DestinationRedirectResult,\n type ExperienceRequestExtensions,\n type PersonalizationOptions,\n} from './fetch-experience.js';\nimport {\n createRuntimeOptimizationClient,\n type RuntimeOptimizationConfig,\n} from './create-optimization-client.js';\nimport { PREVIEW_HOST } from './hosts.js';\nimport { DEFAULT_EVENT_CONTEXT_LIBRARY } from './sdk-info.js';\nimport {\n createRuntimeEventMethods,\n type RuntimeEventBindings,\n type RuntimeEventDispatch,\n type RuntimeEventMethods,\n type RuntimeOptimizationApiClient,\n} from './runtime-event-methods.js';\n\nexport type RuntimeResolveOptions = {\n metadata?: Record<string, unknown>;\n debug?: boolean;\n initialViewportId?: string;\n};\n\nexport type RuntimeEventBuilderConfig = Omit<EventBuilderConfig, 'channel' | 'library'> & {\n channel: EventBuilderConfig['channel'];\n library?: Partial<EventBuilderConfig['library']>;\n};\n\nexport type RuntimeFetchExperienceOptions = {\n experienceId: string;\n locale?: string;\n personalization?: PersonalizationOptions;\n extensions?: ExperienceRequestExtensions;\n preview?: boolean;\n};\n\nexport type RuntimeFetchByDestinationNodeOptions = {\n destinationId: string;\n nodeId: string;\n};\n\nexport type RuntimeFetchByDestinationPathOptions = {\n destinationId: string;\n path: string;\n};\n\n/** Structural contract implemented by the Client runtime. */\nexport interface ExperienceRuntime {\n readonly spaceId: string;\n readonly environmentId: string;\n readonly locale: string | undefined;\n readonly eventBuilder: EventBuilder;\n resolveExperience(\n payload: ExperiencePayload,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan>;\n fetchExperience(\n options: RuntimeFetchExperienceOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan>;\n fetchByDestinationNode(\n options: RuntimeFetchByDestinationNodeOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan | DestinationRedirectResult>;\n fetchByDestinationPath(\n options: RuntimeFetchByDestinationPathOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan | DestinationRedirectResult>;\n}\n\nexport type ContentfulExperiencesConfig = {\n spaceId: string;\n environmentId: string;\n locale?: string;\n resolverConfig: ResolverConfig;\n /** Configuration for the runtime-owned Content Delivery API client. */\n delivery: RuntimeDeliveryClientOptions;\n /** Optional configuration for the runtime-owned Content Preview API client. */\n preview?: RuntimeDeliveryClientOptions;\n /** Overrides for the runtime-owned Personalization and Analytics event transport. */\n optimization?: RuntimeOptimizationConfig;\n resolveDefaults?: Pick<RuntimeResolveOptions, 'metadata' | 'debug'>;\n eventBuilder: RuntimeEventBuilderConfig;\n};\n\nexport class ContentfulExperiences implements ExperienceRuntime {\n readonly spaceId: string;\n readonly environmentId: string;\n readonly eventBuilder: EventBuilder;\n\n readonly #locale: string | undefined;\n readonly #resolverConfig: ResolverConfig;\n readonly #deliveryClient: ContentfulViewDeliveryClient;\n readonly #previewClient: ContentfulViewDeliveryClient | undefined;\n protected readonly optimizationApi: RuntimeOptimizationApiClient;\n readonly #resolveDefaults: Pick<RuntimeResolveOptions, 'metadata' | 'debug'>;\n\n constructor(config: ContentfulExperiencesConfig) {\n this.spaceId = config.spaceId;\n this.environmentId = config.environmentId;\n this.#locale = config.locale;\n this.#resolverConfig = config.resolverConfig;\n this.#deliveryClient = createRuntimeDeliveryClient(config.delivery);\n this.#previewClient =\n config.preview === undefined\n ? undefined\n : createRuntimeDeliveryClient(config.preview, PREVIEW_HOST);\n this.optimizationApi = createRuntimeOptimizationClient({\n spaceId: config.spaceId,\n environmentId: config.environmentId,\n ...config.optimization,\n });\n this.#resolveDefaults = config.resolveDefaults ?? {};\n\n this.eventBuilder = new EventBuilder({\n ...config.eventBuilder,\n library: { ...DEFAULT_EVENT_CONTEXT_LIBRARY, ...config.eventBuilder.library },\n getLocale: config.eventBuilder.getLocale ?? (() => this.locale),\n });\n }\n\n get locale(): string | undefined {\n return this.#locale;\n }\n\n protected createEventMethods(\n bindings: RuntimeEventBindings,\n dispatch?: RuntimeEventDispatch\n ): RuntimeEventMethods {\n return createRuntimeEventMethods(this.optimizationApi, this.eventBuilder, bindings, dispatch);\n }\n\n resolveExperience(\n payload: ExperiencePayload,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan> {\n return resolveCoreExperience(\n payload,\n this.#resolverConfig,\n this.#mergeResolveOptions(resolveOptions)\n );\n }\n\n fetchExperience(\n options: RuntimeFetchExperienceOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan> {\n if (options.preview === true && this.#previewClient === undefined) {\n throw new Error(\n 'fetchExperience() called with preview: true but this runtime has no preview client'\n );\n }\n return fetchExperience(\n {\n spaceId: this.spaceId,\n environmentId: this.environmentId,\n experienceId: options.experienceId,\n locale: options.locale ?? this.locale,\n personalization: options.personalization,\n extensions: options.extensions,\n },\n {\n client: options.preview\n ? (this.#previewClient as ContentfulViewDeliveryClient)\n : this.#deliveryClient,\n },\n { config: this.#resolverConfig, ...this.#mergeResolveOptions(resolveOptions) }\n );\n }\n\n fetchByDestinationNode(\n options: RuntimeFetchByDestinationNodeOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan | DestinationRedirectResult> {\n return fetchExperience(\n { spaceId: this.spaceId, destinationId: options.destinationId, nodeId: options.nodeId },\n { client: this.#deliveryClient },\n { config: this.#resolverConfig, ...this.#mergeResolveOptions(resolveOptions) }\n );\n }\n\n fetchByDestinationPath(\n options: RuntimeFetchByDestinationPathOptions,\n resolveOptions?: RuntimeResolveOptions\n ): Promise<PortableRenderPlan | DestinationRedirectResult> {\n return fetchExperience(\n { spaceId: this.spaceId, destinationId: options.destinationId, path: options.path },\n { client: this.#deliveryClient },\n { config: this.#resolverConfig, ...this.#mergeResolveOptions(resolveOptions) }\n );\n }\n\n #mergeResolveOptions(options: RuntimeResolveOptions | undefined): RuntimeResolveOptions {\n return {\n metadata: { ...this.#resolveDefaults.metadata, ...options?.metadata },\n debug: options?.debug ?? this.#resolveDefaults.debug,\n initialViewportId: options?.initialViewportId,\n };\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,29 @@
1
+ import { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';
2
+
3
+ /** Options for the legacy functional Delivery client constructor. */
4
+ type CreateClientOptions = {
5
+ accessToken: string;
6
+ /**
7
+ * Base URL for the delivery client. Defaults to `DELIVERY_HOST` when omitted.
8
+ * Pass `PREVIEW_HOST` for preview mode, or any custom URL (staging, proxy,
9
+ * per-region). Both constants are exported from this package.
10
+ */
11
+ host?: string;
12
+ } & Omit<ContentfulViewDeliveryClient.Options, 'token' | 'baseUrl'>;
13
+ type RuntimeDeliveryClientBaseOptions = Omit<ContentfulViewDeliveryClient.Options, 'token' | 'baseUrl'>;
14
+ /** Configuration for a Delivery or Preview client owned by a runtime. */
15
+ type RuntimeDeliveryClientOptions = RuntimeDeliveryClientBaseOptions & ({
16
+ /** Bearer token or token supplier used for direct Delivery/Preview API access. */
17
+ accessToken: ContentfulViewDeliveryClient.Options['token'];
18
+ /** Optional endpoint override or endpoint supplier. */
19
+ host?: ContentfulViewDeliveryClient.Options['baseUrl'];
20
+ } | {
21
+ accessToken?: never;
22
+ /** Explicit proxy endpoint that owns upstream authentication. */
23
+ host: NonNullable<ContentfulViewDeliveryClient.Options['baseUrl']>;
24
+ });
25
+ declare function createClient(options: CreateClientOptions): ContentfulViewDeliveryClient;
26
+ /** Constructs a runtime-owned client, disabling generated auth for a tokenless proxy. */
27
+ declare function createRuntimeDeliveryClient(options: RuntimeDeliveryClientOptions, defaultHost?: NonNullable<ContentfulViewDeliveryClient.Options['baseUrl']>): ContentfulViewDeliveryClient;
28
+
29
+ export { type CreateClientOptions, type RuntimeDeliveryClientOptions, createClient, createRuntimeDeliveryClient };
@@ -0,0 +1,27 @@
1
+ import { ContentfulViewDeliveryClient } from "@contentful/experience-delivery";
2
+ function createClient(options) {
3
+ const { accessToken, host, ...rest } = options;
4
+ return new ContentfulViewDeliveryClient({
5
+ ...rest,
6
+ token: accessToken,
7
+ baseUrl: host
8
+ });
9
+ }
10
+ function createRuntimeDeliveryClient(options, defaultHost) {
11
+ const { accessToken, host, ...rest } = options;
12
+ if (accessToken === void 0 && host === void 0) {
13
+ throw new Error(
14
+ "Runtime delivery configuration requires accessToken unless an explicit proxy host is provided"
15
+ );
16
+ }
17
+ const baseUrl = host ?? (rest.environment === void 0 ? defaultHost : void 0);
18
+ const clientOptions = accessToken === void 0 ? { ...rest, auth: rest.auth ?? false, baseUrl } : { ...rest, token: accessToken, baseUrl };
19
+ return new ContentfulViewDeliveryClient(
20
+ clientOptions
21
+ );
22
+ }
23
+ export {
24
+ createClient,
25
+ createRuntimeDeliveryClient
26
+ };
27
+ //# sourceMappingURL=create-delivery-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/create-delivery-client.ts"],"sourcesContent":["import { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';\n\n/** Options for the legacy functional Delivery client constructor. */\nexport type CreateClientOptions = {\n accessToken: string;\n /**\n * Base URL for the delivery client. Defaults to `DELIVERY_HOST` when omitted.\n * Pass `PREVIEW_HOST` for preview mode, or any custom URL (staging, proxy,\n * per-region). Both constants are exported from this package.\n */\n host?: string;\n} & Omit<ContentfulViewDeliveryClient.Options, 'token' | 'baseUrl'>;\n\ntype RuntimeDeliveryClientBaseOptions = Omit<\n ContentfulViewDeliveryClient.Options,\n 'token' | 'baseUrl'\n>;\n\n/** Configuration for a Delivery or Preview client owned by a runtime. */\nexport type RuntimeDeliveryClientOptions = RuntimeDeliveryClientBaseOptions &\n (\n | {\n /** Bearer token or token supplier used for direct Delivery/Preview API access. */\n accessToken: ContentfulViewDeliveryClient.Options['token'];\n /** Optional endpoint override or endpoint supplier. */\n host?: ContentfulViewDeliveryClient.Options['baseUrl'];\n }\n | {\n accessToken?: never;\n /** Explicit proxy endpoint that owns upstream authentication. */\n host: NonNullable<ContentfulViewDeliveryClient.Options['baseUrl']>;\n }\n );\n\nexport function createClient(options: CreateClientOptions): ContentfulViewDeliveryClient {\n const { accessToken, host, ...rest } = options;\n return new ContentfulViewDeliveryClient({\n ...rest,\n token: accessToken,\n baseUrl: host,\n });\n}\n\n/** Constructs a runtime-owned client, disabling generated auth for a tokenless proxy. */\nexport function createRuntimeDeliveryClient(\n options: RuntimeDeliveryClientOptions,\n defaultHost?: NonNullable<ContentfulViewDeliveryClient.Options['baseUrl']>\n): ContentfulViewDeliveryClient {\n const { accessToken, host, ...rest } = options;\n if (accessToken === undefined && host === undefined) {\n throw new Error(\n 'Runtime delivery configuration requires accessToken unless an explicit proxy host is provided'\n );\n }\n\n const baseUrl = host ?? (rest.environment === undefined ? defaultHost : undefined);\n const clientOptions =\n accessToken === undefined\n ? { ...rest, auth: rest.auth ?? false, baseUrl }\n : { ...rest, token: accessToken, baseUrl };\n\n return new ContentfulViewDeliveryClient(\n clientOptions as unknown as ContentfulViewDeliveryClient.Options\n );\n}\n"],"mappings":"AAAA,SAAS,oCAAoC;AAkCtC,SAAS,aAAa,SAA4D;AACvF,QAAM,EAAE,aAAa,MAAM,GAAG,KAAK,IAAI;AACvC,SAAO,IAAI,6BAA6B;AAAA,IACtC,GAAG;AAAA,IACH,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AACH;AAGO,SAAS,4BACd,SACA,aAC8B;AAC9B,QAAM,EAAE,aAAa,MAAM,GAAG,KAAK,IAAI;AACvC,MAAI,gBAAgB,UAAa,SAAS,QAAW;AACnD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,SAAS,KAAK,gBAAgB,SAAY,cAAc;AACxE,QAAM,gBACJ,gBAAgB,SACZ,EAAE,GAAG,MAAM,MAAM,KAAK,QAAQ,OAAO,QAAQ,IAC7C,EAAE,GAAG,MAAM,OAAO,aAAa,QAAQ;AAE7C,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,20 @@
1
+ import { ExperienceApiClientConfig, InsightsApiClientConfig, ApiClientConfig } from '@contentful/optimization-api-client';
2
+ import { RuntimeOptimizationApiClient } from './runtime-event-methods.js';
3
+ import '@contentful/optimization-api-client/api-schemas';
4
+ import './event-builder.js';
5
+ import 'zod/mini';
6
+
7
+ /** Stable configuration for the runtime-owned Optimization API client. */
8
+ type RuntimeOptimizationConfig = {
9
+ personalizationBaseUrl?: ExperienceApiClientConfig['baseUrl'];
10
+ analyticsBaseUrl?: InsightsApiClientConfig['baseUrl'];
11
+ personalizationEnabledFeatures?: ExperienceApiClientConfig['enabledFeatures'];
12
+ fetchOptions?: ApiClientConfig['fetchOptions'];
13
+ };
14
+ type CreateRuntimeOptimizationClientOptions = RuntimeOptimizationConfig & {
15
+ spaceId: string;
16
+ environmentId: string;
17
+ };
18
+ declare function createRuntimeOptimizationClient({ spaceId, environmentId, personalizationBaseUrl, analyticsBaseUrl, personalizationEnabledFeatures, fetchOptions, }: CreateRuntimeOptimizationClientOptions): RuntimeOptimizationApiClient;
19
+
20
+ export { type RuntimeOptimizationConfig, createRuntimeOptimizationClient };
@@ -0,0 +1,30 @@
1
+ import {
2
+ ApiClient as OptimizationApiClient
3
+ } from "@contentful/optimization-api-client";
4
+ function createRuntimeOptimizationClient({
5
+ spaceId,
6
+ environmentId,
7
+ personalizationBaseUrl,
8
+ analyticsBaseUrl,
9
+ personalizationEnabledFeatures,
10
+ fetchOptions
11
+ }) {
12
+ const client = new OptimizationApiClient({
13
+ spaceId,
14
+ environment: environmentId,
15
+ fetchOptions,
16
+ experience: {
17
+ baseUrl: personalizationBaseUrl,
18
+ enabledFeatures: personalizationEnabledFeatures
19
+ },
20
+ insights: { baseUrl: analyticsBaseUrl }
21
+ });
22
+ return {
23
+ personalization: client.experience,
24
+ analytics: client.insights
25
+ };
26
+ }
27
+ export {
28
+ createRuntimeOptimizationClient
29
+ };
30
+ //# sourceMappingURL=create-optimization-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/create-optimization-client.ts"],"sourcesContent":["import {\n ApiClient as OptimizationApiClient,\n type ApiClientConfig as OptimizationApiClientConfig,\n type ExperienceApiClientConfig as PersonalizationApiClientConfig,\n type InsightsApiClientConfig as AnalyticsApiClientConfig,\n} from '@contentful/optimization-api-client';\nimport type { RuntimeOptimizationApiClient } from './runtime-event-methods.js';\n\n/** Stable configuration for the runtime-owned Optimization API client. */\nexport type RuntimeOptimizationConfig = {\n personalizationBaseUrl?: PersonalizationApiClientConfig['baseUrl'];\n analyticsBaseUrl?: AnalyticsApiClientConfig['baseUrl'];\n personalizationEnabledFeatures?: PersonalizationApiClientConfig['enabledFeatures'];\n fetchOptions?: OptimizationApiClientConfig['fetchOptions'];\n};\n\ntype CreateRuntimeOptimizationClientOptions = RuntimeOptimizationConfig & {\n spaceId: string;\n environmentId: string;\n};\n\nexport function createRuntimeOptimizationClient({\n spaceId,\n environmentId,\n personalizationBaseUrl,\n analyticsBaseUrl,\n personalizationEnabledFeatures,\n fetchOptions,\n}: CreateRuntimeOptimizationClientOptions): RuntimeOptimizationApiClient {\n const client = new OptimizationApiClient({\n spaceId,\n environment: environmentId,\n fetchOptions,\n experience: {\n baseUrl: personalizationBaseUrl,\n enabledFeatures: personalizationEnabledFeatures,\n },\n insights: { baseUrl: analyticsBaseUrl },\n });\n\n return {\n personalization: client.experience,\n analytics: client.insights,\n };\n}\n"],"mappings":"AAAA;AAAA,EACE,aAAa;AAAA,OAIR;AAgBA,SAAS,gCAAgC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyE;AACvE,QAAM,SAAS,IAAI,sBAAsB;AAAA,IACvC;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA,YAAY;AAAA,MACV,SAAS;AAAA,MACT,iBAAiB;AAAA,IACnB;AAAA,IACA,UAAU,EAAE,SAAS,iBAAiB;AAAA,EACxC,CAAC;AAED,SAAO;AAAA,IACL,iBAAiB,OAAO;AAAA,IACxB,WAAW,OAAO;AAAA,EACpB;AACF;","names":[]}
@@ -1,18 +1,18 @@
1
1
  import {
2
- Campaign,
3
- ExoEntityKind,
4
- GeoLocation,
5
- Page,
6
- PageEventContext,
7
- parseWithFriendlyError,
8
- Properties,
9
- Screen,
10
- Traits
2
+ Campaign as OptimizationCampaign,
3
+ ExoEntityKind as OptimizationExoEntityKind,
4
+ GeoLocation as OptimizationGeoLocation,
5
+ Page as OptimizationPage,
6
+ PageEventContext as OptimizationPageEventContext,
7
+ parseWithFriendlyError as parseOptimizationSchema,
8
+ Properties as OptimizationProperties,
9
+ Screen as OptimizationScreen,
10
+ Traits as OptimizationTraits
11
11
  } from "@contentful/optimization-api-client/api-schemas";
12
- import { createScopedLogger } from "@contentful/optimization-api-client/logger";
12
+ import { createScopedLogger as createOptimizationScopedLogger } from "@contentful/optimization-api-client/logger";
13
13
  import { merge } from "es-toolkit/object";
14
14
  import * as z from "zod/mini";
15
- const eventBuilderLogger = createScopedLogger("Experiences:EventBuilder");
15
+ const eventBuilderLogger = createOptimizationScopedLogger("Experiences:EventBuilder");
16
16
  const UTM_CAMPAIGN_PARAMETERS = [
17
17
  ["utm_campaign", "name"],
18
18
  ["utm_source", "source"],
@@ -37,16 +37,16 @@ function extractCampaignFromUrl(url) {
37
37
  }
38
38
  }
39
39
  const UniversalEventBuilderArgs = z.object({
40
- campaign: z.optional(Campaign),
40
+ campaign: z.optional(OptimizationCampaign),
41
41
  locale: z.optional(z.string()),
42
- location: z.optional(GeoLocation),
43
- page: z.optional(Page),
44
- screen: z.optional(Screen),
42
+ location: z.optional(OptimizationGeoLocation),
43
+ page: z.optional(OptimizationPage),
44
+ screen: z.optional(OptimizationScreen),
45
45
  userAgent: z.optional(z.string())
46
46
  });
47
47
  const InteractionBuilderArgsBase = z.extend(UniversalEventBuilderArgs, {
48
48
  entityId: z.string(),
49
- entityKind: ExoEntityKind,
49
+ entityKind: OptimizationExoEntityKind,
50
50
  entityKindId: z.optional(z.string()),
51
51
  entryIds: z.optional(z.array(z.string())),
52
52
  optimizationId: z.optional(z.string()),
@@ -74,15 +74,15 @@ const FlagViewBuilderArgs = z.extend(FlagInteractionBuilderArgsBase, {
74
74
  viewDurationMs: z.optional(z.number())
75
75
  });
76
76
  const IdentifyBuilderArgs = z.extend(UniversalEventBuilderArgs, {
77
- traits: z.optional(Traits),
77
+ traits: z.optional(OptimizationTraits),
78
78
  userId: z.string()
79
79
  });
80
80
  const PageViewBuilderArgs = z.extend(UniversalEventBuilderArgs, {
81
- properties: z.optional(z.partial(Page))
81
+ properties: z.optional(z.partial(OptimizationPage))
82
82
  });
83
83
  const TrackBuilderArgs = z.extend(UniversalEventBuilderArgs, {
84
84
  event: z.string(),
85
- properties: z.optional(z.prefault(Properties, {}))
85
+ properties: z.optional(z.prefault(OptimizationProperties, {}))
86
86
  });
87
87
  const PAGE_CONTEXT_CONFLICT_KEYS = ["path", "query", "search", "url"];
88
88
  function warnIfPageContextConflicts(explicitPage, properties) {
@@ -167,7 +167,7 @@ class EventBuilder {
167
167
  };
168
168
  }
169
169
  buildView(args) {
170
- const { viewId, viewDurationMs, ...interaction } = parseWithFriendlyError(
170
+ const { viewId, viewDurationMs, ...interaction } = parseOptimizationSchema(
171
171
  ViewBuilderArgs,
172
172
  args
173
173
  );
@@ -179,14 +179,14 @@ class EventBuilder {
179
179
  };
180
180
  }
181
181
  buildClick(args) {
182
- const interaction = parseWithFriendlyError(ClickBuilderArgs, args);
182
+ const interaction = parseOptimizationSchema(ClickBuilderArgs, args);
183
183
  return {
184
184
  ...this.buildInteractionBase(interaction),
185
185
  type: "exo_node_click"
186
186
  };
187
187
  }
188
188
  buildHover(args) {
189
- const { hoverId, hoverDurationMs, ...interaction } = parseWithFriendlyError(
189
+ const { hoverId, hoverDurationMs, ...interaction } = parseOptimizationSchema(
190
190
  HoverBuilderArgs,
191
191
  args
192
192
  );
@@ -198,7 +198,7 @@ class EventBuilder {
198
198
  };
199
199
  }
200
200
  buildFlagView(args) {
201
- const { componentId, experienceId, variantIndex, viewId, viewDurationMs, ...universal } = parseWithFriendlyError(FlagViewBuilderArgs, args);
201
+ const { componentId, experienceId, variantIndex, viewId, viewDurationMs, ...universal } = parseOptimizationSchema(FlagViewBuilderArgs, args);
202
202
  return {
203
203
  ...this.buildUniversalEventProperties(universal),
204
204
  ...viewDurationMs === void 0 ? {} : { viewDurationMs },
@@ -211,7 +211,11 @@ class EventBuilder {
211
211
  };
212
212
  }
213
213
  buildIdentify(args) {
214
- const { traits = {}, userId, ...universal } = parseWithFriendlyError(IdentifyBuilderArgs, args);
214
+ const {
215
+ traits = {},
216
+ userId,
217
+ ...universal
218
+ } = parseOptimizationSchema(IdentifyBuilderArgs, args);
215
219
  return {
216
220
  ...this.buildUniversalEventProperties(universal),
217
221
  type: "identify",
@@ -220,7 +224,7 @@ class EventBuilder {
220
224
  };
221
225
  }
222
226
  buildPageView(args = {}) {
223
- const { properties = {}, ...universal } = parseWithFriendlyError(PageViewBuilderArgs, args);
227
+ const { properties = {}, ...universal } = parseOptimizationSchema(PageViewBuilderArgs, args);
224
228
  const propertiesCampaign = extractCampaignFromUrl(properties.url);
225
229
  const pageProperties = this.getPageProperties();
226
230
  const merged = merge(
@@ -239,7 +243,7 @@ class EventBuilder {
239
243
  campaign: universal.campaign ?? propertiesCampaign,
240
244
  page: universal.page ?? merged
241
245
  });
242
- const context = parseWithFriendlyError(PageEventContext, universalContext);
246
+ const context = parseOptimizationSchema(OptimizationPageEventContext, universalContext);
243
247
  return {
244
248
  ...universalProperties,
245
249
  context,
@@ -248,7 +252,11 @@ class EventBuilder {
248
252
  };
249
253
  }
250
254
  buildTrack(args) {
251
- const { event, properties = {}, ...universal } = parseWithFriendlyError(TrackBuilderArgs, args);
255
+ const {
256
+ event,
257
+ properties = {},
258
+ ...universal
259
+ } = parseOptimizationSchema(TrackBuilderArgs, args);
252
260
  return {
253
261
  ...this.buildUniversalEventProperties(universal),
254
262
  type: "track",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/event-builder.ts"],"sourcesContent":["/* eslint-disable no-redeclare */\n\nimport {\n type App,\n Campaign,\n type Channel,\n type ExoClickEvent,\n ExoEntityKind,\n type ExoHoverEvent,\n type ExoViewEvent,\n GeoLocation,\n type IdentifyEvent,\n type Library,\n Page,\n PageEventContext,\n type PageViewEvent,\n parseWithFriendlyError,\n Properties,\n Screen,\n type TrackEvent,\n Traits,\n UniversalEventProperties,\n type ViewEvent,\n} from '@contentful/optimization-api-client/api-schemas';\nimport { createScopedLogger } from '@contentful/optimization-api-client/logger';\nimport { merge } from 'es-toolkit/object';\nimport * as z from 'zod/mini';\n\nconst eventBuilderLogger = createScopedLogger('Experiences:EventBuilder');\n\nconst UTM_CAMPAIGN_PARAMETERS = [\n ['utm_campaign', 'name'],\n ['utm_source', 'source'],\n ['utm_medium', 'medium'],\n ['utm_term', 'term'],\n ['utm_content', 'content'],\n] as const;\n\nfunction extractCampaignFromUrl(url: string | undefined): Campaign | undefined {\n if (url === undefined) return undefined;\n\n try {\n const { searchParams } = new URL(url);\n const campaign: Campaign = {};\n let hasCampaignParameter = false;\n\n for (const [parameter, property] of UTM_CAMPAIGN_PARAMETERS) {\n if (!searchParams.has(parameter)) continue;\n\n campaign[property] = searchParams.get(parameter) ?? '';\n hasCampaignParameter = true;\n }\n\n return hasCampaignParameter ? campaign : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface EventBuilderConfig {\n app?: App;\n channel: Channel;\n library: Library;\n getLocale?: () => string | undefined;\n getPageProperties?: () => Page;\n getUserAgent?: () => string | undefined;\n getConsent?: () => boolean | undefined;\n}\n\nexport const UniversalEventBuilderArgs = z.object({\n campaign: z.optional(Campaign),\n locale: z.optional(z.string()),\n location: z.optional(GeoLocation),\n page: z.optional(Page),\n screen: z.optional(Screen),\n userAgent: z.optional(z.string()),\n});\n\nexport type UniversalEventBuilderArgs = z.infer<typeof UniversalEventBuilderArgs>;\n\nexport const InteractionBuilderArgsBase = z.extend(UniversalEventBuilderArgs, {\n entityId: z.string(),\n entityKind: ExoEntityKind,\n entityKindId: z.optional(z.string()),\n entryIds: z.optional(z.array(z.string())),\n optimizationId: z.optional(z.string()),\n parameters: z.optional(z.record(z.string(), z.json())),\n parentExperienceId: z.optional(z.string()),\n variantId: z.optional(z.string()),\n variantIndex: z.optional(z.number()),\n});\n\nexport type InteractionBuilderArgsBase = z.infer<typeof InteractionBuilderArgsBase>;\n\nexport const ViewBuilderArgs = z.extend(InteractionBuilderArgsBase, {\n viewId: z.string(),\n viewDurationMs: z.int().check(z.minimum(0)),\n});\n\nexport type ViewBuilderArgs = z.infer<typeof ViewBuilderArgs>;\n\nexport const ClickBuilderArgs = InteractionBuilderArgsBase;\n\nexport type ClickBuilderArgs = z.infer<typeof ClickBuilderArgs>;\n\nexport const HoverBuilderArgs = z.extend(InteractionBuilderArgsBase, {\n hoverId: z.string(),\n hoverDurationMs: z.int().check(z.minimum(0)),\n});\n\nexport type HoverBuilderArgs = z.infer<typeof HoverBuilderArgs>;\n\nconst FlagInteractionBuilderArgsBase = z.extend(UniversalEventBuilderArgs, {\n componentId: z.string(),\n experienceId: z.optional(z.string()),\n variantIndex: z.optional(z.number()),\n});\n\nexport const FlagViewBuilderArgs = z.extend(FlagInteractionBuilderArgsBase, {\n viewId: z.optional(z.string()),\n viewDurationMs: z.optional(z.number()),\n});\n\nexport type FlagViewBuilderArgs = z.infer<typeof FlagViewBuilderArgs>;\n\nexport const IdentifyBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n traits: z.optional(Traits),\n userId: z.string(),\n});\n\nexport type IdentifyBuilderArgs = z.infer<typeof IdentifyBuilderArgs>;\n\nexport const PageViewBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n properties: z.optional(z.partial(Page)),\n});\n\nexport type PageViewBuilderArgs = z.infer<typeof PageViewBuilderArgs>;\n\nexport const TrackBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n event: z.string(),\n properties: z.optional(z.prefault(Properties, {})),\n});\n\nexport type TrackBuilderArgs = z.infer<typeof TrackBuilderArgs>;\n\nconst PAGE_CONTEXT_CONFLICT_KEYS = ['path', 'query', 'search', 'url'] as const;\n\nfunction warnIfPageContextConflicts(explicitPage: Page | undefined, properties: Page): void {\n if (!explicitPage) return;\n\n const conflictingKeys = PAGE_CONTEXT_CONFLICT_KEYS.filter((key) => {\n const { [key]: explicitValue } = explicitPage;\n const { [key]: propertyValue } = properties;\n return JSON.stringify(explicitValue) !== JSON.stringify(propertyValue);\n });\n\n if (conflictingKeys.length === 0) return;\n\n eventBuilderLogger.warn(\n `Explicit page context differs from page event properties for: ${conflictingKeys.join(', ')}`\n );\n}\n\nexport const DEFAULT_PAGE_PROPERTIES: Page = {\n path: '',\n query: {},\n referrer: '',\n search: '',\n title: '',\n url: '',\n};\n\nclass EventBuilder {\n app?: App;\n channel: Channel;\n library: Library;\n getLocale: () => string | undefined;\n getPageProperties: () => Page;\n getUserAgent: () => string | undefined;\n getConsent: () => boolean | undefined;\n\n constructor(config: EventBuilderConfig) {\n const { app, channel, library, getLocale, getPageProperties, getUserAgent, getConsent } =\n config;\n this.app = app;\n this.channel = channel;\n this.library = library;\n this.getLocale = getLocale ?? (() => 'en-US');\n this.getPageProperties = getPageProperties ?? (() => DEFAULT_PAGE_PROPERTIES);\n this.getUserAgent = getUserAgent ?? (() => undefined);\n this.getConsent = getConsent ?? (() => undefined);\n }\n\n protected buildUniversalEventProperties({\n campaign,\n locale,\n location,\n page,\n screen,\n userAgent,\n }: UniversalEventBuilderArgs): UniversalEventProperties {\n const timestamp = new Date().toISOString();\n const resolvedPage = page ?? this.getPageProperties();\n\n return {\n channel: this.channel,\n context: {\n app: this.app,\n campaign: campaign ?? extractCampaignFromUrl(resolvedPage.url) ?? {},\n gdpr: { isConsentGiven: this.getConsent() === true },\n library: this.library,\n locale: locale ?? this.getLocale() ?? 'en-US',\n location,\n page: resolvedPage,\n screen,\n userAgent: userAgent ?? this.getUserAgent(),\n },\n messageId: crypto.randomUUID(),\n originalTimestamp: timestamp,\n sentAt: timestamp,\n timestamp,\n };\n }\n\n private buildInteractionBase(\n args: InteractionBuilderArgsBase\n ): UniversalEventProperties & InteractionBuilderArgsBase {\n const { campaign, locale, location, page, screen, userAgent, ...interactionProperties } = args;\n\n return {\n ...this.buildUniversalEventProperties({\n campaign,\n locale,\n location,\n page,\n screen,\n userAgent,\n }),\n ...interactionProperties,\n };\n }\n\n buildView(args: ViewBuilderArgs): ExoViewEvent {\n const { viewId, viewDurationMs, ...interaction } = parseWithFriendlyError(\n ViewBuilderArgs,\n args\n );\n\n return {\n ...this.buildInteractionBase(interaction),\n type: 'exo_node_view',\n viewId,\n viewDurationMs,\n };\n }\n\n buildClick(args: ClickBuilderArgs): ExoClickEvent {\n const interaction = parseWithFriendlyError(ClickBuilderArgs, args);\n\n return {\n ...this.buildInteractionBase(interaction),\n type: 'exo_node_click',\n };\n }\n\n buildHover(args: HoverBuilderArgs): ExoHoverEvent {\n const { hoverId, hoverDurationMs, ...interaction } = parseWithFriendlyError(\n HoverBuilderArgs,\n args\n );\n\n return {\n ...this.buildInteractionBase(interaction),\n type: 'exo_node_hover',\n hoverId,\n hoverDurationMs,\n };\n }\n\n buildFlagView(args: FlagViewBuilderArgs): ViewEvent {\n const { componentId, experienceId, variantIndex, viewId, viewDurationMs, ...universal } =\n parseWithFriendlyError(FlagViewBuilderArgs, args);\n\n return {\n ...this.buildUniversalEventProperties(universal),\n ...(viewDurationMs === undefined ? {} : { viewDurationMs }),\n ...(viewId === undefined ? {} : { viewId }),\n type: 'component',\n componentType: 'Variable',\n componentId,\n experienceId,\n variantIndex: variantIndex ?? 0,\n };\n }\n\n buildIdentify(args: IdentifyBuilderArgs): IdentifyEvent {\n const { traits = {}, userId, ...universal } = parseWithFriendlyError(IdentifyBuilderArgs, args);\n\n return {\n ...this.buildUniversalEventProperties(universal),\n type: 'identify',\n traits,\n userId,\n };\n }\n\n buildPageView(args: PageViewBuilderArgs = {}): PageViewEvent {\n const { properties = {}, ...universal } = parseWithFriendlyError(PageViewBuilderArgs, args);\n const propertiesCampaign = extractCampaignFromUrl(properties.url);\n const pageProperties = this.getPageProperties();\n const merged = merge(\n {\n ...pageProperties,\n title: pageProperties.title ?? DEFAULT_PAGE_PROPERTIES.title,\n },\n properties\n );\n\n warnIfPageContextConflicts(universal.page, merged);\n\n const {\n context: { screen: _, ...universalContext },\n ...universalProperties\n } = this.buildUniversalEventProperties({\n ...universal,\n campaign: universal.campaign ?? propertiesCampaign,\n page: universal.page ?? merged,\n });\n\n const context = parseWithFriendlyError(PageEventContext, universalContext);\n\n return {\n ...universalProperties,\n context,\n type: 'page',\n properties: merged,\n };\n }\n\n buildTrack(args: TrackBuilderArgs): TrackEvent {\n const { event, properties = {}, ...universal } = parseWithFriendlyError(TrackBuilderArgs, args);\n\n return {\n ...this.buildUniversalEventProperties(universal),\n type: 'track',\n event,\n properties,\n };\n }\n}\n\nexport default EventBuilder;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/event-builder.ts"],"sourcesContent":["/* eslint-disable no-redeclare */\n\nimport {\n type App as OptimizationApp,\n Campaign as OptimizationCampaign,\n type Channel as OptimizationChannel,\n type ExoClickEvent as OptimizationExoClickEvent,\n ExoEntityKind as OptimizationExoEntityKind,\n type ExoHoverEvent as OptimizationExoHoverEvent,\n type ExoViewEvent as OptimizationExoViewEvent,\n GeoLocation as OptimizationGeoLocation,\n type IdentifyEvent as OptimizationIdentifyEvent,\n type Library as OptimizationLibrary,\n Page as OptimizationPage,\n PageEventContext as OptimizationPageEventContext,\n type PageViewEvent as OptimizationPageViewEvent,\n parseWithFriendlyError as parseOptimizationSchema,\n Properties as OptimizationProperties,\n Screen as OptimizationScreen,\n type TrackEvent as OptimizationTrackEvent,\n Traits as OptimizationTraits,\n UniversalEventProperties as OptimizationUniversalEventProperties,\n type ViewEvent as OptimizationViewEvent,\n} from '@contentful/optimization-api-client/api-schemas';\nimport { createScopedLogger as createOptimizationScopedLogger } from '@contentful/optimization-api-client/logger';\nimport { merge } from 'es-toolkit/object';\nimport * as z from 'zod/mini';\n\nconst eventBuilderLogger = createOptimizationScopedLogger('Experiences:EventBuilder');\n\nconst UTM_CAMPAIGN_PARAMETERS = [\n ['utm_campaign', 'name'],\n ['utm_source', 'source'],\n ['utm_medium', 'medium'],\n ['utm_term', 'term'],\n ['utm_content', 'content'],\n] as const;\n\nfunction extractCampaignFromUrl(url: string | undefined): OptimizationCampaign | undefined {\n if (url === undefined) return undefined;\n\n try {\n const { searchParams } = new URL(url);\n const campaign: OptimizationCampaign = {};\n let hasCampaignParameter = false;\n\n for (const [parameter, property] of UTM_CAMPAIGN_PARAMETERS) {\n if (!searchParams.has(parameter)) continue;\n\n campaign[property] = searchParams.get(parameter) ?? '';\n hasCampaignParameter = true;\n }\n\n return hasCampaignParameter ? campaign : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface EventBuilderConfig {\n app?: OptimizationApp;\n channel: OptimizationChannel;\n library: OptimizationLibrary;\n getLocale?: () => string | undefined;\n getPageProperties?: () => OptimizationPage;\n getUserAgent?: () => string | undefined;\n getConsent?: () => boolean | undefined;\n}\n\nexport const UniversalEventBuilderArgs = z.object({\n campaign: z.optional(OptimizationCampaign),\n locale: z.optional(z.string()),\n location: z.optional(OptimizationGeoLocation),\n page: z.optional(OptimizationPage),\n screen: z.optional(OptimizationScreen),\n userAgent: z.optional(z.string()),\n});\n\nexport type UniversalEventBuilderArgs = z.infer<typeof UniversalEventBuilderArgs>;\n\nexport const InteractionBuilderArgsBase = z.extend(UniversalEventBuilderArgs, {\n entityId: z.string(),\n entityKind: OptimizationExoEntityKind,\n entityKindId: z.optional(z.string()),\n entryIds: z.optional(z.array(z.string())),\n optimizationId: z.optional(z.string()),\n parameters: z.optional(z.record(z.string(), z.json())),\n parentExperienceId: z.optional(z.string()),\n variantId: z.optional(z.string()),\n variantIndex: z.optional(z.number()),\n});\n\nexport type InteractionBuilderArgsBase = z.infer<typeof InteractionBuilderArgsBase>;\n\nexport const ViewBuilderArgs = z.extend(InteractionBuilderArgsBase, {\n viewId: z.string(),\n viewDurationMs: z.int().check(z.minimum(0)),\n});\n\nexport type ViewBuilderArgs = z.infer<typeof ViewBuilderArgs>;\n\nexport const ClickBuilderArgs = InteractionBuilderArgsBase;\n\nexport type ClickBuilderArgs = z.infer<typeof ClickBuilderArgs>;\n\nexport const HoverBuilderArgs = z.extend(InteractionBuilderArgsBase, {\n hoverId: z.string(),\n hoverDurationMs: z.int().check(z.minimum(0)),\n});\n\nexport type HoverBuilderArgs = z.infer<typeof HoverBuilderArgs>;\n\nconst FlagInteractionBuilderArgsBase = z.extend(UniversalEventBuilderArgs, {\n componentId: z.string(),\n experienceId: z.optional(z.string()),\n variantIndex: z.optional(z.number()),\n});\n\nexport const FlagViewBuilderArgs = z.extend(FlagInteractionBuilderArgsBase, {\n viewId: z.optional(z.string()),\n viewDurationMs: z.optional(z.number()),\n});\n\nexport type FlagViewBuilderArgs = z.infer<typeof FlagViewBuilderArgs>;\n\nexport const IdentifyBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n traits: z.optional(OptimizationTraits),\n userId: z.string(),\n});\n\nexport type IdentifyBuilderArgs = z.infer<typeof IdentifyBuilderArgs>;\n\nexport const PageViewBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n properties: z.optional(z.partial(OptimizationPage)),\n});\n\nexport type PageViewBuilderArgs = z.infer<typeof PageViewBuilderArgs>;\n\nexport const TrackBuilderArgs = z.extend(UniversalEventBuilderArgs, {\n event: z.string(),\n properties: z.optional(z.prefault(OptimizationProperties, {})),\n});\n\nexport type TrackBuilderArgs = z.infer<typeof TrackBuilderArgs>;\n\nconst PAGE_CONTEXT_CONFLICT_KEYS = ['path', 'query', 'search', 'url'] as const;\n\nfunction warnIfPageContextConflicts(\n explicitPage: OptimizationPage | undefined,\n properties: OptimizationPage\n): void {\n if (!explicitPage) return;\n\n const conflictingKeys = PAGE_CONTEXT_CONFLICT_KEYS.filter((key) => {\n const { [key]: explicitValue } = explicitPage;\n const { [key]: propertyValue } = properties;\n return JSON.stringify(explicitValue) !== JSON.stringify(propertyValue);\n });\n\n if (conflictingKeys.length === 0) return;\n\n eventBuilderLogger.warn(\n `Explicit page context differs from page event properties for: ${conflictingKeys.join(', ')}`\n );\n}\n\nexport const DEFAULT_PAGE_PROPERTIES: OptimizationPage = {\n path: '',\n query: {},\n referrer: '',\n search: '',\n title: '',\n url: '',\n};\n\nclass EventBuilder {\n app?: OptimizationApp;\n channel: OptimizationChannel;\n library: OptimizationLibrary;\n getLocale: () => string | undefined;\n getPageProperties: () => OptimizationPage;\n getUserAgent: () => string | undefined;\n getConsent: () => boolean | undefined;\n\n constructor(config: EventBuilderConfig) {\n const { app, channel, library, getLocale, getPageProperties, getUserAgent, getConsent } =\n config;\n this.app = app;\n this.channel = channel;\n this.library = library;\n this.getLocale = getLocale ?? (() => 'en-US');\n this.getPageProperties = getPageProperties ?? (() => DEFAULT_PAGE_PROPERTIES);\n this.getUserAgent = getUserAgent ?? (() => undefined);\n this.getConsent = getConsent ?? (() => undefined);\n }\n\n protected buildUniversalEventProperties({\n campaign,\n locale,\n location,\n page,\n screen,\n userAgent,\n }: UniversalEventBuilderArgs): OptimizationUniversalEventProperties {\n const timestamp = new Date().toISOString();\n const resolvedPage = page ?? this.getPageProperties();\n\n return {\n channel: this.channel,\n context: {\n app: this.app,\n campaign: campaign ?? extractCampaignFromUrl(resolvedPage.url) ?? {},\n gdpr: { isConsentGiven: this.getConsent() === true },\n library: this.library,\n locale: locale ?? this.getLocale() ?? 'en-US',\n location,\n page: resolvedPage,\n screen,\n userAgent: userAgent ?? this.getUserAgent(),\n },\n messageId: crypto.randomUUID(),\n originalTimestamp: timestamp,\n sentAt: timestamp,\n timestamp,\n };\n }\n\n private buildInteractionBase(\n args: InteractionBuilderArgsBase\n ): OptimizationUniversalEventProperties & InteractionBuilderArgsBase {\n const { campaign, locale, location, page, screen, userAgent, ...interactionProperties } = args;\n\n return {\n ...this.buildUniversalEventProperties({\n campaign,\n locale,\n location,\n page,\n screen,\n userAgent,\n }),\n ...interactionProperties,\n };\n }\n\n buildView(args: ViewBuilderArgs): OptimizationExoViewEvent {\n const { viewId, viewDurationMs, ...interaction } = parseOptimizationSchema(\n ViewBuilderArgs,\n args\n );\n\n return {\n ...this.buildInteractionBase(interaction),\n type: 'exo_node_view',\n viewId,\n viewDurationMs,\n };\n }\n\n buildClick(args: ClickBuilderArgs): OptimizationExoClickEvent {\n const interaction = parseOptimizationSchema(ClickBuilderArgs, args);\n\n return {\n ...this.buildInteractionBase(interaction),\n type: 'exo_node_click',\n };\n }\n\n buildHover(args: HoverBuilderArgs): OptimizationExoHoverEvent {\n const { hoverId, hoverDurationMs, ...interaction } = parseOptimizationSchema(\n HoverBuilderArgs,\n args\n );\n\n return {\n ...this.buildInteractionBase(interaction),\n type: 'exo_node_hover',\n hoverId,\n hoverDurationMs,\n };\n }\n\n buildFlagView(args: FlagViewBuilderArgs): OptimizationViewEvent {\n const { componentId, experienceId, variantIndex, viewId, viewDurationMs, ...universal } =\n parseOptimizationSchema(FlagViewBuilderArgs, args);\n\n return {\n ...this.buildUniversalEventProperties(universal),\n ...(viewDurationMs === undefined ? {} : { viewDurationMs }),\n ...(viewId === undefined ? {} : { viewId }),\n type: 'component',\n componentType: 'Variable',\n componentId,\n experienceId,\n variantIndex: variantIndex ?? 0,\n };\n }\n\n buildIdentify(args: IdentifyBuilderArgs): OptimizationIdentifyEvent {\n const {\n traits = {},\n userId,\n ...universal\n } = parseOptimizationSchema(IdentifyBuilderArgs, args);\n\n return {\n ...this.buildUniversalEventProperties(universal),\n type: 'identify',\n traits,\n userId,\n };\n }\n\n buildPageView(args: PageViewBuilderArgs = {}): OptimizationPageViewEvent {\n const { properties = {}, ...universal } = parseOptimizationSchema(PageViewBuilderArgs, args);\n const propertiesCampaign = extractCampaignFromUrl(properties.url);\n const pageProperties = this.getPageProperties();\n const merged = merge(\n {\n ...pageProperties,\n title: pageProperties.title ?? DEFAULT_PAGE_PROPERTIES.title,\n },\n properties\n );\n\n warnIfPageContextConflicts(universal.page, merged);\n\n const {\n context: { screen: _, ...universalContext },\n ...universalProperties\n } = this.buildUniversalEventProperties({\n ...universal,\n campaign: universal.campaign ?? propertiesCampaign,\n page: universal.page ?? merged,\n });\n\n const context = parseOptimizationSchema(OptimizationPageEventContext, universalContext);\n\n return {\n ...universalProperties,\n context,\n type: 'page',\n properties: merged,\n };\n }\n\n buildTrack(args: TrackBuilderArgs): OptimizationTrackEvent {\n const {\n event,\n properties = {},\n ...universal\n } = parseOptimizationSchema(TrackBuilderArgs, args);\n\n return {\n ...this.buildUniversalEventProperties(universal),\n type: 'track',\n event,\n properties,\n };\n }\n}\n\nexport default EventBuilder;\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import { ContentfulViewDelivery } from "@contentful/experience-delivery";
2
2
  import { createDebugLogger, resolveExperience } from "@contentful/experiences-sdk-core";
3
- import { createClient } from "./create-client.js";
3
+ import { createClient } from "./create-delivery-client.js";
4
4
  import { DestinationPreviewNotSupportedError, ExperienceFetchError } from "./errors.js";
5
5
  import { PREVIEW_HOST } from "./hosts.js";
6
6
  import {
@@ -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 { 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\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 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, 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 const sourceMap = extensions?.sourceMap !== undefined ? readSourceMap(response) : undefined;\n\n log.lazy('received raw payload', () => payload);\n\n return resolveExperience(payload, config, {\n metadata,\n debug,\n initialViewportId,\n sourceMap,\n });\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 = {\n ...extensions,\n ...(personalization === undefined ? {} : { personalization }),\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 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\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":"AACA,SAAS,8BAA8B;AACvC,SAAS,mBAAmB,yBAAyB;AAErD,SAAS,oBAAoB;AAC7B,SAAS,qCAAqC,4BAA4B;AAC1E,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAsIP,eAAsB,gBACpB,mBACA,eACA,gBACyD;AACzD,QAAM,EAAE,QAAQ,UAAU,OAAO,kBAAkB,IAAI;AACvD,QAAM,MAAM,kBAAkB,OAAO,QAAQ;AAE7C,MACE,EAAE,YAAY,kBACd,cAAc,WACd,mBAAmB,mBACnB;AACA,UAAM,EAAE,SAAAA,UAAS,cAAc,IAAI;AACnC,UAAM,UACJ,YAAY,oBACR,EAAE,QAAQ,kBAAkB,OAAO,IACnC,EAAE,MAAM,kBAAkB,KAAK;AACrC,UAAM,IAAI;AAAA,MACR,0GACqB,aAAa;AAAA,MAElC,EAAE,SAAAA,UAAS,eAAe,GAAG,QAAQ;AAAA,IACvC;AAAA,EACF;AAEA,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,YAAY,mBAAmB;AACjC,UAAM,EAAE,SAAAA,UAAS,eAAe,OAAO,IAAI;AAC3C,WAAO;AAAA,MACL,EAAE,SAAAA,UAAS,eAAe,SAAS,OAAO;AAAA,MAC1C,MAAM,OAAO,YAAY,gBAAgBA,UAAS,eAAe,MAAM;AAAA,MACvE;AAAA,MACA,EAAE,QAAQ,UAAU,OAAO,kBAAkB;AAAA,IAC/C;AAAA,EACF;AAEA,MAAI,UAAU,mBAAmB;AAC/B,UAAM,EAAE,SAAAA,UAAS,eAAe,KAAK,IAAI;AACzC,WAAO;AAAA,MACL,EAAE,SAAAA,UAAS,eAAe,SAAS,KAAK;AAAA,MACxC,MAAM,OAAO,YAAY,cAAcA,UAAS,eAAe,EAAE,KAAK,CAAC;AAAA,MACvE;AAAA,MACA,EAAE,QAAQ,UAAU,OAAO,kBAAkB;AAAA,IAC/C;AAAA,EACF;AAEA,QAAM,EAAE,SAAS,eAAe,cAAc,QAAQ,iBAAiB,WAAW,IAChF;AAEF,MAAI,IAAI,uBAAuB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA,iBAAiB,oBAAoB;AAAA,IACrC;AAAA,EACF,CAAC;AAED,QAAM,WAAW,MAAM,oBAAoB,QAAQ,iBAAiB;AAEpE,QAAM,UAAU,oBAAoB,QAAQ;AAC5C,QAAM,YAAY,YAAY,cAAc,SAAY,cAAc,QAAQ,IAAI;AAElF,MAAI,KAAK,wBAAwB,MAAM,OAAO;AAE9C,SAAO,kBAAkB,SAAS,QAAQ;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,eAAe,oBACb,QACA,SAC6B;AAC7B,QAAM,EAAE,SAAS,eAAe,cAAc,QAAQ,iBAAiB,WAAW,IAAI;AACtF,QAAM,oBAAyD;AAAA,IAC7D,GAAG;AAAA,IACH,GAAI,oBAAoB,SAAY,CAAC,IAAI,EAAE,gBAAgB;AAAA,EAC7D;AAEA,MAAI;AAQF,QAAI,qBAAqB,iBAAiB,GAAG;AAC3C,aAAO,MAAM,OAAO,WAAW,iBAAiB,SAAS,eAAe,cAAc;AAAA,QACpF;AAAA,QACA,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,WAAO,MAAM,OAAO,WAAW,IAAI,SAAS,eAAe,cAAc,EAAE,OAAO,CAAC;AAAA,EACrF,SAAS,KAAK;AAIZ,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;AACF;AAMA,eAAe,mBACb,UACA,SACA,KACA,gBAMyD;AACzD,QAAM,EAAE,SAAS,eAAe,QAAQ,IAAI;AAC5C,QAAM,EAAE,QAAQ,UAAU,OAAO,kBAAkB,IAAI;AAEvD,MAAI,IAAI,oCAAoC,EAAE,SAAS,eAAe,QAAQ,CAAC;AAE/E,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,QAAQ;AAAA,EAC3B,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,kCAAkC,aAAa,SAAS,OAAO,aAAa,OAAO,OAC9E,MAAM;AAAA,MAEX,EAAE,SAAS,cAAc,SAAS,OAAO,IAAI;AAAA,IAC/C;AAAA,EACF;AAEA,MAAI,cAAc,UAAU;AAC1B,QAAI,IAAI,sCAAsC,SAAS,QAAQ;AAC/D,WAAO,EAAE,UAAU,SAAS,SAAS;AAAA,EACvC;AAEA,QAAM,CAAC,eAAe,IAAI,SAAS;AACnC,MAAI,CAAC,iBAAiB;AACpB,UAAM,IAAI;AAAA,MACR,gBAAgB,aAAa,eAAe,OAAO,iCACtC,OAAO;AAAA,MACpB,EAAE,SAAS,cAAc,QAAQ;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,UAAU,mCAAmC,gBAAgB,UAAU;AAC7E,MAAI,KAAK,wBAAwB,MAAM,OAAO;AAE9C,SAAO,kBAAkB,SAAS,QAAQ;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,SAAS,qBACP,YACmD;AACnD,SACE,eAAe,UACf,OAAO,OAAO,UAAU,EAAE,KAAK,CAAC,cAAc,cAAc,MAAS;AAEzE;","names":["spaceId"]}
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-delivery-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\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 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, 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 const sourceMap = extensions?.sourceMap !== undefined ? readSourceMap(response) : undefined;\n\n log.lazy('received raw payload', () => payload);\n\n return resolveExperience(payload, config, {\n metadata,\n debug,\n initialViewportId,\n sourceMap,\n });\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 = {\n ...extensions,\n ...(personalization === undefined ? {} : { personalization }),\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 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\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/index.d.ts CHANGED
@@ -1,13 +1,17 @@
1
1
  import { ContentfulViewDelivery } from '@contentful/experience-delivery';
2
2
  export { ContentfulViewDelivery, ContentfulViewDeliveryClient } from '@contentful/experience-delivery';
3
3
  export { DestinationPreviewNotSupportedError, ExperienceFetchError } from './errors.js';
4
- export { CreateClientOptions, createClient } from './create-client.js';
4
+ export { CreateClientOptions, RuntimeDeliveryClientOptions, createClient } from './create-delivery-client.js';
5
+ export { RuntimeOptimizationConfig } from './create-optimization-client.js';
5
6
  export { ClickBuilderArgs, DEFAULT_PAGE_PROPERTIES, default as EventBuilder, EventBuilderConfig, FlagViewBuilderArgs, HoverBuilderArgs, IdentifyBuilderArgs, InteractionBuilderArgsBase, PageViewBuilderArgs, TrackBuilderArgs, UniversalEventBuilderArgs, ViewBuilderArgs } from './event-builder.js';
6
7
  export { ByDestinationNodeIdExperienceOptions, ByDestinationPathExperienceOptions, ByIdExperienceOptions, ClientOptions, DestinationRedirectResult, ExperienceOptions, ExperienceRequestExtensions, PersonalizationOptions, ResolveOptions, fetchExperience } from './fetch-experience.js';
7
- export { ContentfulExperiences, ContentfulExperiencesConfig, ExperienceRuntime, RuntimeClientSource, RuntimeEventBuilderConfig, RuntimeFetchByDestinationNodeOptions, RuntimeFetchByDestinationPathOptions, RuntimeFetchExperienceOptions, RuntimeResolveOptions } from './contentful-experiences.js';
8
+ export { ContentfulExperiences, ContentfulExperiencesConfig, ExperienceRuntime, RuntimeEventBuilderConfig, RuntimeFetchByDestinationNodeOptions, RuntimeFetchByDestinationPathOptions, RuntimeFetchExperienceOptions, RuntimeResolveOptions } from './contentful-experiences.js';
9
+ export { AnalyticsEventMethod, EventProfileRequiredError, PersonalizationEventMethod, RuntimeEventBindings, RuntimeEventMethods } from './runtime-event-methods.js';
10
+ export { RUNTIME_EVENT_HANDOFF_VERSION, RuntimeEventHandoff, RuntimeEventHandoffEvent, RuntimeEventHandoffReceipt, RuntimeServerEventDelivery, assertRuntimeEventHandoffSize, parseRuntimeEventHandoff } from './runtime-event-handoff.js';
8
11
  export { ExperienceResponse, readSourceMap, toExperiencePayload, toExperiencePayloadFromDestination } from './to-experience-payload.js';
9
12
  export { DELIVERY_HOST, PREVIEW_HOST, PREVIEW_WEBSOCKET_HOST } from './hosts.js';
10
- import '@contentful/optimization-api-client/api-schemas';
13
+ export { OptimizationData as EventOptimizationData, PartialProfile as EventProfile } from '@contentful/optimization-api-client/api-schemas';
14
+ import '@contentful/optimization-api-client';
11
15
  import 'zod/mini';
12
16
  import '@contentful/experiences-sdk-core';
13
17
 
package/dist/index.js CHANGED
@@ -5,11 +5,17 @@ import {
5
5
  } from "@contentful/experience-delivery";
6
6
  const NotFoundError = ContentfulViewDelivery.NotFoundError;
7
7
  import { ExperienceFetchError, DestinationPreviewNotSupportedError } from "./errors.js";
8
- import { createClient } from "./create-client.js";
8
+ import { createClient } from "./create-delivery-client.js";
9
9
  import { default as default2 } from "./event-builder.js";
10
10
  export * from "./event-builder.js";
11
11
  import { fetchExperience } from "./fetch-experience.js";
12
12
  import { ContentfulExperiences } from "./contentful-experiences.js";
13
+ import { EventProfileRequiredError } from "./runtime-event-methods.js";
14
+ import {
15
+ assertRuntimeEventHandoffSize,
16
+ parseRuntimeEventHandoff,
17
+ RUNTIME_EVENT_HANDOFF_VERSION
18
+ } from "./runtime-event-handoff.js";
13
19
  import {
14
20
  readSourceMap,
15
21
  toExperiencePayload,
@@ -23,12 +29,16 @@ export {
23
29
  DELIVERY_HOST,
24
30
  DestinationPreviewNotSupportedError,
25
31
  default2 as EventBuilder,
32
+ EventProfileRequiredError,
26
33
  ExperienceFetchError,
27
34
  NotFoundError,
28
35
  PREVIEW_HOST,
29
36
  PREVIEW_WEBSOCKET_HOST,
37
+ RUNTIME_EVENT_HANDOFF_VERSION,
38
+ assertRuntimeEventHandoffSize,
30
39
  createClient,
31
40
  fetchExperience,
41
+ parseRuntimeEventHandoff,
32
42
  readSourceMap,
33
43
  toExperiencePayload,
34
44
  toExperiencePayloadFromDestination
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, DestinationPreviewNotSupportedError } from './errors.js';\nexport { createClient } from './create-client.js';\nexport type { CreateClientOptions } from './create-client.js';\nexport { default as EventBuilder } from './event-builder.js';\nexport * from './event-builder.js';\nexport { fetchExperience } from './fetch-experience.js';\nexport { ContentfulExperiences } from './contentful-experiences.js';\nexport type {\n ContentfulExperiencesConfig,\n ExperienceRuntime,\n RuntimeFetchExperienceOptions,\n RuntimeFetchByDestinationNodeOptions,\n RuntimeFetchByDestinationPathOptions,\n RuntimeClientSource,\n RuntimeEventBuilderConfig,\n RuntimeResolveOptions,\n} from './contentful-experiences.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 ExperienceRequestExtensions,\n PersonalizationOptions,\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,SAAoB,WAAXC,gBAA+B;AACxC,cAAc;AACd,SAAS,uBAAuB;AAChC,SAAS,6BAA6B;AAWtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAaP,SAAS,eAAe,cAAc,8BAA8B;","names":["ContentfulViewDelivery","default"]}
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-delivery-client.js';\nexport type {\n CreateClientOptions,\n RuntimeDeliveryClientOptions,\n} from './create-delivery-client.js';\nexport type { RuntimeOptimizationConfig } from './create-optimization-client.js';\nexport { default as EventBuilder } from './event-builder.js';\nexport * from './event-builder.js';\nexport { fetchExperience } from './fetch-experience.js';\nexport { ContentfulExperiences } from './contentful-experiences.js';\nexport type {\n ContentfulExperiencesConfig,\n ExperienceRuntime,\n RuntimeFetchExperienceOptions,\n RuntimeFetchByDestinationNodeOptions,\n RuntimeFetchByDestinationPathOptions,\n RuntimeEventBuilderConfig,\n RuntimeResolveOptions,\n} from './contentful-experiences.js';\nexport { EventProfileRequiredError } from './runtime-event-methods.js';\nexport type {\n EventOptimizationData,\n EventProfile,\n AnalyticsEventMethod,\n PersonalizationEventMethod,\n RuntimeEventBindings,\n RuntimeEventMethods,\n} from './runtime-event-methods.js';\nexport {\n assertRuntimeEventHandoffSize,\n parseRuntimeEventHandoff,\n RUNTIME_EVENT_HANDOFF_VERSION,\n} from './runtime-event-handoff.js';\nexport type {\n RuntimeEventHandoff,\n RuntimeEventHandoffEvent,\n RuntimeEventHandoffReceipt,\n RuntimeServerEventDelivery,\n} from './runtime-event-handoff.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 ExperienceRequestExtensions,\n PersonalizationOptions,\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;AAM7B,SAAoB,WAAXC,gBAA+B;AACxC,cAAc;AACd,SAAS,uBAAuB;AAChC,SAAS,6BAA6B;AAUtC,SAAS,iCAAiC;AAS1C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAOP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAaP,SAAS,eAAe,cAAc,8BAA8B;","names":["ContentfulViewDelivery","default"]}
@@ -0,0 +1,33 @@
1
+ import { ExperienceEvent, InsightsEvent } from '@contentful/optimization-api-client/api-schemas';
2
+
3
+ declare const RUNTIME_EVENT_HANDOFF_VERSION: 1;
4
+ /** Server-only delivery choice. Browser runtimes always commit received handoffs. */
5
+ type RuntimeServerEventDelivery = 'commit' | 'handoff';
6
+ type RuntimeEventHandoffEvent = {
7
+ readonly transport: 'personalization';
8
+ readonly event: ExperienceEvent;
9
+ } | {
10
+ readonly transport: 'analytics';
11
+ readonly event: InsightsEvent;
12
+ };
13
+ /** Plain JSON passed from one Node request to its paired Web runtime. */
14
+ interface RuntimeEventHandoff {
15
+ readonly version: typeof RUNTIME_EVENT_HANDOFF_VERSION;
16
+ readonly spaceId: string;
17
+ readonly environmentId: string;
18
+ /** Profile known before any preflight event was evaluated. */
19
+ readonly initialProfileId?: string;
20
+ readonly events: readonly RuntimeEventHandoffEvent[];
21
+ /** App-defined route identity for a successfully staged initial page event. */
22
+ readonly initialPageRouteKey?: string;
23
+ }
24
+ /** Returned only after the complete Web replay succeeds. */
25
+ interface RuntimeEventHandoffReceipt {
26
+ readonly initialPageRouteKey?: string;
27
+ }
28
+ /** Enforces the private response payload cap without parsing trusted Node data. */
29
+ declare function assertRuntimeEventHandoffSize(input: unknown): void;
30
+ /** Validates an untrusted serialized handoff before Web starts any transport. */
31
+ declare function parseRuntimeEventHandoff(input: unknown): RuntimeEventHandoff;
32
+
33
+ export { RUNTIME_EVENT_HANDOFF_VERSION, type RuntimeEventHandoff, type RuntimeEventHandoffEvent, type RuntimeEventHandoffReceipt, type RuntimeServerEventDelivery, assertRuntimeEventHandoffSize, parseRuntimeEventHandoff };
@@ -0,0 +1,68 @@
1
+ import {
2
+ ExperienceEvent as PersonalizationEventSchema,
3
+ InsightsEvent as AnalyticsEventSchema,
4
+ parseWithFriendlyError as parseOptimizationSchema
5
+ } from "@contentful/optimization-api-client/api-schemas";
6
+ import * as z from "zod/mini";
7
+ const RUNTIME_EVENT_HANDOFF_VERSION = 1;
8
+ const RUNTIME_EVENT_HANDOFF_MAX_BYTES = 64 * 1024;
9
+ const encoder = new globalThis.TextEncoder();
10
+ const RuntimeEventHandoffSchema = z.object({
11
+ version: z.literal(RUNTIME_EVENT_HANDOFF_VERSION),
12
+ spaceId: z.string(),
13
+ environmentId: z.string(),
14
+ initialProfileId: z.optional(z.string()),
15
+ events: z.array(
16
+ z.discriminatedUnion("transport", [
17
+ z.object({
18
+ transport: z.literal("personalization"),
19
+ event: PersonalizationEventSchema
20
+ }),
21
+ z.object({
22
+ transport: z.literal("analytics"),
23
+ event: AnalyticsEventSchema
24
+ })
25
+ ])
26
+ ),
27
+ initialPageRouteKey: z.optional(z.string())
28
+ });
29
+ function assertRuntimeEventHandoffSize(input) {
30
+ let serialized;
31
+ try {
32
+ serialized = JSON.stringify(input);
33
+ } catch (error) {
34
+ throw new TypeError("Runtime event handoff must be JSON serializable", { cause: error });
35
+ }
36
+ if (serialized === void 0) throw new TypeError("Runtime event handoff is not serializable");
37
+ if (encoder.encode(serialized).byteLength > RUNTIME_EVENT_HANDOFF_MAX_BYTES) {
38
+ throw new TypeError(
39
+ `Runtime event handoff exceeds ${RUNTIME_EVENT_HANDOFF_MAX_BYTES} serialized bytes`
40
+ );
41
+ }
42
+ }
43
+ function parseRuntimeEventHandoff(input) {
44
+ assertRuntimeEventHandoffSize(input);
45
+ const handoff = parseOptimizationSchema(RuntimeEventHandoffSchema, input);
46
+ if (handoff.initialPageRouteKey !== void 0 && !handoff.events.some(
47
+ (entry) => entry.transport === "personalization" && entry.event.type === "page"
48
+ )) {
49
+ throw new TypeError("Runtime event handoff initial page requires a staged page event");
50
+ }
51
+ let hasProfile = handoff.initialProfileId !== void 0;
52
+ for (const entry of handoff.events) {
53
+ if (entry.transport === "personalization") {
54
+ hasProfile = true;
55
+ } else if (!hasProfile) {
56
+ throw new TypeError(
57
+ "Runtime event handoff Analytics events require an initial or preceding Personalization profile"
58
+ );
59
+ }
60
+ }
61
+ return handoff;
62
+ }
63
+ export {
64
+ RUNTIME_EVENT_HANDOFF_VERSION,
65
+ assertRuntimeEventHandoffSize,
66
+ parseRuntimeEventHandoff
67
+ };
68
+ //# sourceMappingURL=runtime-event-handoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime-event-handoff.ts"],"sourcesContent":["import {\n ExperienceEvent as PersonalizationEventSchema,\n InsightsEvent as AnalyticsEventSchema,\n parseWithFriendlyError as parseOptimizationSchema,\n type ExperienceEvent as PersonalizationEvent,\n type InsightsEvent as AnalyticsEvent,\n} from '@contentful/optimization-api-client/api-schemas';\nimport * as z from 'zod/mini';\n\nexport const RUNTIME_EVENT_HANDOFF_VERSION = 1 as const;\n\nconst RUNTIME_EVENT_HANDOFF_MAX_BYTES = 64 * 1024;\nconst encoder = new globalThis.TextEncoder();\nconst RuntimeEventHandoffSchema = z.object({\n version: z.literal(RUNTIME_EVENT_HANDOFF_VERSION),\n spaceId: z.string(),\n environmentId: z.string(),\n initialProfileId: z.optional(z.string()),\n events: z.array(\n z.discriminatedUnion('transport', [\n z.object({\n transport: z.literal('personalization'),\n event: PersonalizationEventSchema,\n }),\n z.object({\n transport: z.literal('analytics'),\n event: AnalyticsEventSchema,\n }),\n ])\n ),\n initialPageRouteKey: z.optional(z.string()),\n});\n\n/** Server-only delivery choice. Browser runtimes always commit received handoffs. */\nexport type RuntimeServerEventDelivery = 'commit' | 'handoff';\n\nexport type RuntimeEventHandoffEvent =\n | { readonly transport: 'personalization'; readonly event: PersonalizationEvent }\n | { readonly transport: 'analytics'; readonly event: AnalyticsEvent };\n\n/** Plain JSON passed from one Node request to its paired Web runtime. */\nexport interface RuntimeEventHandoff {\n readonly version: typeof RUNTIME_EVENT_HANDOFF_VERSION;\n readonly spaceId: string;\n readonly environmentId: string;\n /** Profile known before any preflight event was evaluated. */\n readonly initialProfileId?: string;\n readonly events: readonly RuntimeEventHandoffEvent[];\n /** App-defined route identity for a successfully staged initial page event. */\n readonly initialPageRouteKey?: string;\n}\n\n/** Returned only after the complete Web replay succeeds. */\nexport interface RuntimeEventHandoffReceipt {\n readonly initialPageRouteKey?: string;\n}\n\n/** Enforces the private response payload cap without parsing trusted Node data. */\nexport function assertRuntimeEventHandoffSize(input: unknown): void {\n let serialized: string | undefined;\n try {\n serialized = JSON.stringify(input);\n } catch (error) {\n throw new TypeError('Runtime event handoff must be JSON serializable', { cause: error });\n }\n if (serialized === undefined) throw new TypeError('Runtime event handoff is not serializable');\n if (encoder.encode(serialized).byteLength > RUNTIME_EVENT_HANDOFF_MAX_BYTES) {\n throw new TypeError(\n `Runtime event handoff exceeds ${RUNTIME_EVENT_HANDOFF_MAX_BYTES} serialized bytes`\n );\n }\n}\n\n/** Validates an untrusted serialized handoff before Web starts any transport. */\nexport function parseRuntimeEventHandoff(input: unknown): RuntimeEventHandoff {\n assertRuntimeEventHandoffSize(input);\n const handoff = parseOptimizationSchema(RuntimeEventHandoffSchema, input);\n\n if (\n handoff.initialPageRouteKey !== undefined &&\n !handoff.events.some(\n (entry) => entry.transport === 'personalization' && entry.event.type === 'page'\n )\n ) {\n throw new TypeError('Runtime event handoff initial page requires a staged page event');\n }\n\n let hasProfile = handoff.initialProfileId !== undefined;\n for (const entry of handoff.events) {\n if (entry.transport === 'personalization') {\n hasProfile = true;\n } else if (!hasProfile) {\n throw new TypeError(\n 'Runtime event handoff Analytics events require an initial or preceding Personalization profile'\n );\n }\n }\n\n return handoff;\n}\n"],"mappings":"AAAA;AAAA,EACE,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,0BAA0B;AAAA,OAGrB;AACP,YAAY,OAAO;AAEZ,MAAM,gCAAgC;AAE7C,MAAM,kCAAkC,KAAK;AAC7C,MAAM,UAAU,IAAI,WAAW,YAAY;AAC3C,MAAM,4BAA4B,EAAE,OAAO;AAAA,EACzC,SAAS,EAAE,QAAQ,6BAA6B;AAAA,EAChD,SAAS,EAAE,OAAO;AAAA,EAClB,eAAe,EAAE,OAAO;AAAA,EACxB,kBAAkB,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EACvC,QAAQ,EAAE;AAAA,IACR,EAAE,mBAAmB,aAAa;AAAA,MAChC,EAAE,OAAO;AAAA,QACP,WAAW,EAAE,QAAQ,iBAAiB;AAAA,QACtC,OAAO;AAAA,MACT,CAAC;AAAA,MACD,EAAE,OAAO;AAAA,QACP,WAAW,EAAE,QAAQ,WAAW;AAAA,QAChC,OAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EACA,qBAAqB,EAAE,SAAS,EAAE,OAAO,CAAC;AAC5C,CAAC;AA2BM,SAAS,8BAA8B,OAAsB;AAClE,MAAI;AACJ,MAAI;AACF,iBAAa,KAAK,UAAU,KAAK;AAAA,EACnC,SAAS,OAAO;AACd,UAAM,IAAI,UAAU,mDAAmD,EAAE,OAAO,MAAM,CAAC;AAAA,EACzF;AACA,MAAI,eAAe,OAAW,OAAM,IAAI,UAAU,2CAA2C;AAC7F,MAAI,QAAQ,OAAO,UAAU,EAAE,aAAa,iCAAiC;AAC3E,UAAM,IAAI;AAAA,MACR,iCAAiC,+BAA+B;AAAA,IAClE;AAAA,EACF;AACF;AAGO,SAAS,yBAAyB,OAAqC;AAC5E,gCAA8B,KAAK;AACnC,QAAM,UAAU,wBAAwB,2BAA2B,KAAK;AAExE,MACE,QAAQ,wBAAwB,UAChC,CAAC,QAAQ,OAAO;AAAA,IACd,CAAC,UAAU,MAAM,cAAc,qBAAqB,MAAM,MAAM,SAAS;AAAA,EAC3E,GACA;AACA,UAAM,IAAI,UAAU,iEAAiE;AAAA,EACvF;AAEA,MAAI,aAAa,QAAQ,qBAAqB;AAC9C,aAAW,SAAS,QAAQ,QAAQ;AAClC,QAAI,MAAM,cAAc,mBAAmB;AACzC,mBAAa;AAAA,IACf,WAAW,CAAC,YAAY;AACtB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
@@ -0,0 +1,52 @@
1
+ import { ExperienceApiClient, InsightsApiClient } from '@contentful/optimization-api-client';
2
+ import { PartialProfile, ExperienceEvent, OptimizationData, InsightsEvent } from '@contentful/optimization-api-client/api-schemas';
3
+ export { OptimizationData as EventOptimizationData, PartialProfile as EventProfile } from '@contentful/optimization-api-client/api-schemas';
4
+ import EventBuilder, { UniversalEventBuilderArgs, IdentifyBuilderArgs, PageViewBuilderArgs, TrackBuilderArgs, ViewBuilderArgs, ClickBuilderArgs, HoverBuilderArgs, FlagViewBuilderArgs } from './event-builder.js';
5
+ import 'zod/mini';
6
+
7
+ type PersonalizationEventMethod = 'identify' | 'page' | 'track';
8
+ type AnalyticsEventMethod = 'trackView' | 'trackClick' | 'trackHover' | 'trackFlagView';
9
+ /** The Optimization API surface used by the shared runtime. */
10
+ interface RuntimeOptimizationApiClient {
11
+ readonly personalization: Pick<ExperienceApiClient, 'upsertProfile'>;
12
+ readonly analytics: Pick<InsightsApiClient, 'sendBatchEvents'>;
13
+ }
14
+ /** Internal strategy used by a runtime to commit or stage built events. */
15
+ interface RuntimeEventDispatch {
16
+ personalization(event: ExperienceEvent, profile: PartialProfile | undefined): Promise<OptimizationData>;
17
+ analytics(event: InsightsEvent, profile: PartialProfile): Promise<boolean>;
18
+ }
19
+ /** Runtime-owned state and context used to bind otherwise stateless event methods. */
20
+ interface RuntimeEventBindings {
21
+ getProfile: () => PartialProfile | undefined;
22
+ setProfile: (profile: PartialProfile) => void;
23
+ /** Changes when an external session boundary must invalidate an in-flight profile response. */
24
+ getProfileRevision?: () => number;
25
+ getEventContext?: () => UniversalEventBuilderArgs;
26
+ getConsent?: () => boolean | undefined;
27
+ }
28
+ /**
29
+ * Event-triggering surface shared by the public Node and Web runtimes.
30
+ * Profile-producing calls are not serialized; await them before another
31
+ * profile-producing or Analytics call on the same bound runtime. In Node
32
+ * handoff mode an Analytics `true` means accepted into the handoff journal,
33
+ * not delivered to the Analytics transport.
34
+ */
35
+ interface RuntimeEventMethods {
36
+ readonly profile: PartialProfile | undefined;
37
+ identify(args: IdentifyBuilderArgs): Promise<OptimizationData>;
38
+ page(args?: PageViewBuilderArgs): Promise<OptimizationData>;
39
+ track(args: TrackBuilderArgs): Promise<OptimizationData>;
40
+ trackView(args: ViewBuilderArgs): Promise<boolean>;
41
+ trackClick(args: ClickBuilderArgs): Promise<boolean>;
42
+ trackHover(args: HoverBuilderArgs): Promise<boolean>;
43
+ trackFlagView(args: FlagViewBuilderArgs): Promise<boolean>;
44
+ }
45
+ /** Thrown when an Analytics event is triggered before a profile is available. */
46
+ declare class EventProfileRequiredError extends Error {
47
+ readonly method: AnalyticsEventMethod;
48
+ constructor(method: AnalyticsEventMethod);
49
+ }
50
+ declare function createRuntimeEventMethods(api: RuntimeOptimizationApiClient, eventBuilder: EventBuilder, bindings: RuntimeEventBindings, dispatch?: RuntimeEventDispatch): RuntimeEventMethods;
51
+
52
+ export { type AnalyticsEventMethod, EventProfileRequiredError, type PersonalizationEventMethod, type RuntimeEventBindings, type RuntimeEventDispatch, type RuntimeEventMethods, type RuntimeOptimizationApiClient, createRuntimeEventMethods };
@@ -0,0 +1,105 @@
1
+ class EventProfileRequiredError extends Error {
2
+ method;
3
+ constructor(method) {
4
+ super(
5
+ `${method}() requires a current event profile. Supply an initial profile or await identify(), page(), or track() first.`
6
+ );
7
+ this.name = "EventProfileRequiredError";
8
+ this.method = method;
9
+ }
10
+ }
11
+ class BoundRuntimeEventMethods {
12
+ constructor(eventBuilder, bindings, dispatch) {
13
+ this.eventBuilder = eventBuilder;
14
+ this.bindings = bindings;
15
+ this.dispatch = dispatch;
16
+ }
17
+ eventBuilder;
18
+ bindings;
19
+ dispatch;
20
+ get profile() {
21
+ return this.bindings.getProfile();
22
+ }
23
+ async identify(args) {
24
+ return this.sendPersonalizationEvent(
25
+ this.eventBuilder.buildIdentify(this.withEventContext(args))
26
+ );
27
+ }
28
+ async page(args = {}) {
29
+ return this.sendPersonalizationEvent(
30
+ this.eventBuilder.buildPageView(this.withEventContext(args))
31
+ );
32
+ }
33
+ async track(args) {
34
+ return this.sendPersonalizationEvent(this.eventBuilder.buildTrack(this.withEventContext(args)));
35
+ }
36
+ async trackView(args) {
37
+ return this.sendAnalyticsEvent(
38
+ "trackView",
39
+ this.eventBuilder.buildView(this.withEventContext(args))
40
+ );
41
+ }
42
+ async trackClick(args) {
43
+ return this.sendAnalyticsEvent(
44
+ "trackClick",
45
+ this.eventBuilder.buildClick(this.withEventContext(args))
46
+ );
47
+ }
48
+ async trackHover(args) {
49
+ return this.sendAnalyticsEvent(
50
+ "trackHover",
51
+ this.eventBuilder.buildHover(this.withEventContext(args))
52
+ );
53
+ }
54
+ async trackFlagView(args) {
55
+ return this.sendAnalyticsEvent(
56
+ "trackFlagView",
57
+ this.eventBuilder.buildFlagView(this.withEventContext(args))
58
+ );
59
+ }
60
+ withEventContext(args) {
61
+ return { ...this.bindings.getEventContext?.(), ...args };
62
+ }
63
+ withConsent(event) {
64
+ const consent = this.bindings.getConsent?.();
65
+ if (consent === void 0) return event;
66
+ return {
67
+ ...event,
68
+ context: {
69
+ ...event.context,
70
+ gdpr: { ...event.context.gdpr, isConsentGiven: consent }
71
+ }
72
+ };
73
+ }
74
+ async sendPersonalizationEvent(event) {
75
+ const eventWithConsent = this.withConsent(event);
76
+ const profileRevision = this.bindings.getProfileRevision?.();
77
+ const data = await this.dispatch.personalization(eventWithConsent, this.profile);
78
+ if (profileRevision === void 0 || this.bindings.getProfileRevision?.() === profileRevision) {
79
+ this.bindings.setProfile(data.profile);
80
+ }
81
+ return data;
82
+ }
83
+ async sendAnalyticsEvent(method, event) {
84
+ const profile = this.profile;
85
+ if (profile === void 0) throw new EventProfileRequiredError(method);
86
+ return this.dispatch.analytics(this.withConsent(event), profile);
87
+ }
88
+ }
89
+ function createDirectEventDispatch(api) {
90
+ return {
91
+ personalization: (event, profile) => api.personalization.upsertProfile(
92
+ { profileId: profile?.id, events: [event] },
93
+ { locale: event.context.locale }
94
+ ),
95
+ analytics: (event, profile) => api.analytics.sendBatchEvents([{ profile, events: [event] }])
96
+ };
97
+ }
98
+ function createRuntimeEventMethods(api, eventBuilder, bindings, dispatch = createDirectEventDispatch(api)) {
99
+ return new BoundRuntimeEventMethods(eventBuilder, bindings, dispatch);
100
+ }
101
+ export {
102
+ EventProfileRequiredError,
103
+ createRuntimeEventMethods
104
+ };
105
+ //# sourceMappingURL=runtime-event-methods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime-event-methods.ts"],"sourcesContent":["import type {\n ExperienceApiClient as PersonalizationApiClient,\n InsightsApiClient as AnalyticsApiClient,\n} from '@contentful/optimization-api-client';\nimport type {\n ExperienceEvent as PersonalizationEvent,\n InsightsEvent as AnalyticsEvent,\n OptimizationData as EventOptimizationData,\n PartialProfile as EventProfile,\n} from '@contentful/optimization-api-client/api-schemas';\n\nimport type EventBuilder from './event-builder.js';\nimport type {\n ClickBuilderArgs,\n FlagViewBuilderArgs,\n HoverBuilderArgs,\n IdentifyBuilderArgs,\n PageViewBuilderArgs,\n TrackBuilderArgs,\n UniversalEventBuilderArgs,\n ViewBuilderArgs,\n} from './event-builder.js';\nexport type { EventOptimizationData, EventProfile };\n\nexport type PersonalizationEventMethod = 'identify' | 'page' | 'track';\nexport type AnalyticsEventMethod = 'trackView' | 'trackClick' | 'trackHover' | 'trackFlagView';\n\n/** The Optimization API surface used by the shared runtime. */\nexport interface RuntimeOptimizationApiClient {\n readonly personalization: Pick<PersonalizationApiClient, 'upsertProfile'>;\n readonly analytics: Pick<AnalyticsApiClient, 'sendBatchEvents'>;\n}\n\n/** Internal strategy used by a runtime to commit or stage built events. */\nexport interface RuntimeEventDispatch {\n personalization(\n event: PersonalizationEvent,\n profile: EventProfile | undefined\n ): Promise<EventOptimizationData>;\n analytics(event: AnalyticsEvent, profile: EventProfile): Promise<boolean>;\n}\n\n/** Runtime-owned state and context used to bind otherwise stateless event methods. */\nexport interface RuntimeEventBindings {\n getProfile: () => EventProfile | undefined;\n setProfile: (profile: EventProfile) => void;\n /** Changes when an external session boundary must invalidate an in-flight profile response. */\n getProfileRevision?: () => number;\n getEventContext?: () => UniversalEventBuilderArgs;\n getConsent?: () => boolean | undefined;\n}\n\n/**\n * Event-triggering surface shared by the public Node and Web runtimes.\n * Profile-producing calls are not serialized; await them before another\n * profile-producing or Analytics call on the same bound runtime. In Node\n * handoff mode an Analytics `true` means accepted into the handoff journal,\n * not delivered to the Analytics transport.\n */\nexport interface RuntimeEventMethods {\n readonly profile: EventProfile | undefined;\n identify(args: IdentifyBuilderArgs): Promise<EventOptimizationData>;\n page(args?: PageViewBuilderArgs): Promise<EventOptimizationData>;\n track(args: TrackBuilderArgs): Promise<EventOptimizationData>;\n trackView(args: ViewBuilderArgs): Promise<boolean>;\n trackClick(args: ClickBuilderArgs): Promise<boolean>;\n trackHover(args: HoverBuilderArgs): Promise<boolean>;\n trackFlagView(args: FlagViewBuilderArgs): Promise<boolean>;\n}\n\n/** Thrown when an Analytics event is triggered before a profile is available. */\nexport class EventProfileRequiredError extends Error {\n readonly method: AnalyticsEventMethod;\n\n constructor(method: AnalyticsEventMethod) {\n super(\n `${method}() requires a current event profile. Supply an initial profile or await identify(), page(), or track() first.`\n );\n this.name = 'EventProfileRequiredError';\n this.method = method;\n }\n}\n\nclass BoundRuntimeEventMethods implements RuntimeEventMethods {\n constructor(\n private readonly eventBuilder: EventBuilder,\n private readonly bindings: RuntimeEventBindings,\n private readonly dispatch: RuntimeEventDispatch\n ) {}\n\n get profile(): EventProfile | undefined {\n return this.bindings.getProfile();\n }\n\n async identify(args: IdentifyBuilderArgs): Promise<EventOptimizationData> {\n return this.sendPersonalizationEvent(\n this.eventBuilder.buildIdentify(this.withEventContext(args))\n );\n }\n\n async page(args: PageViewBuilderArgs = {}): Promise<EventOptimizationData> {\n return this.sendPersonalizationEvent(\n this.eventBuilder.buildPageView(this.withEventContext(args))\n );\n }\n\n async track(args: TrackBuilderArgs): Promise<EventOptimizationData> {\n return this.sendPersonalizationEvent(this.eventBuilder.buildTrack(this.withEventContext(args)));\n }\n\n async trackView(args: ViewBuilderArgs): Promise<boolean> {\n return this.sendAnalyticsEvent(\n 'trackView',\n this.eventBuilder.buildView(this.withEventContext(args))\n );\n }\n\n async trackClick(args: ClickBuilderArgs): Promise<boolean> {\n return this.sendAnalyticsEvent(\n 'trackClick',\n this.eventBuilder.buildClick(this.withEventContext(args))\n );\n }\n\n async trackHover(args: HoverBuilderArgs): Promise<boolean> {\n return this.sendAnalyticsEvent(\n 'trackHover',\n this.eventBuilder.buildHover(this.withEventContext(args))\n );\n }\n\n async trackFlagView(args: FlagViewBuilderArgs): Promise<boolean> {\n return this.sendAnalyticsEvent(\n 'trackFlagView',\n this.eventBuilder.buildFlagView(this.withEventContext(args))\n );\n }\n\n private withEventContext<TArgs extends UniversalEventBuilderArgs>(args: TArgs): TArgs {\n return { ...this.bindings.getEventContext?.(), ...args } as TArgs;\n }\n\n private withConsent<TEvent extends PersonalizationEvent | AnalyticsEvent>(event: TEvent): TEvent {\n const consent = this.bindings.getConsent?.();\n if (consent === undefined) return event;\n\n return {\n ...event,\n context: {\n ...event.context,\n gdpr: { ...event.context.gdpr, isConsentGiven: consent },\n },\n } as TEvent;\n }\n\n private async sendPersonalizationEvent(\n event: PersonalizationEvent\n ): Promise<EventOptimizationData> {\n const eventWithConsent = this.withConsent(event);\n const profileRevision = this.bindings.getProfileRevision?.();\n const data = await this.dispatch.personalization(eventWithConsent, this.profile);\n if (profileRevision === undefined || this.bindings.getProfileRevision?.() === profileRevision) {\n this.bindings.setProfile(data.profile);\n }\n return data;\n }\n\n private async sendAnalyticsEvent(\n method: AnalyticsEventMethod,\n event: AnalyticsEvent\n ): Promise<boolean> {\n const profile = this.profile;\n if (profile === undefined) throw new EventProfileRequiredError(method);\n return this.dispatch.analytics(this.withConsent(event), profile);\n }\n}\n\nfunction createDirectEventDispatch(api: RuntimeOptimizationApiClient): RuntimeEventDispatch {\n return {\n personalization: (event, profile) =>\n api.personalization.upsertProfile(\n { profileId: profile?.id, events: [event] },\n { locale: event.context.locale }\n ),\n analytics: (event, profile) => api.analytics.sendBatchEvents([{ profile, events: [event] }]),\n };\n}\n\nexport function createRuntimeEventMethods(\n api: RuntimeOptimizationApiClient,\n eventBuilder: EventBuilder,\n bindings: RuntimeEventBindings,\n dispatch: RuntimeEventDispatch = createDirectEventDispatch(api)\n): RuntimeEventMethods {\n return new BoundRuntimeEventMethods(eventBuilder, bindings, dispatch);\n}\n"],"mappings":"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","names":[]}
package/dist/sdk-info.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const DEFAULT_EVENT_CONTEXT_LIBRARY = {
2
2
  name: true ? "@contentful/experiences-client" : "@contentful/experiences-client",
3
- version: true ? "0.5.2" : "0.0.0"
3
+ version: true ? "0.6.0" : "0.0.0"
4
4
  };
5
5
  export {
6
6
  DEFAULT_EVENT_CONTEXT_LIBRARY
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experiences-client",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Delivery client + fetchExperience for Contentful Experiences",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,14 +0,0 @@
1
- import { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';
2
-
3
- type CreateClientOptions = {
4
- accessToken: string;
5
- /**
6
- * Base URL for the delivery client. Defaults to `DELIVERY_HOST` when omitted.
7
- * Pass `PREVIEW_HOST` for preview mode, or any custom URL (staging, proxy,
8
- * per-region). Both constants are exported from this package.
9
- */
10
- host?: string;
11
- } & Omit<ContentfulViewDeliveryClient.Options, 'token' | 'baseUrl'>;
12
- declare function createClient(options: CreateClientOptions): ContentfulViewDeliveryClient;
13
-
14
- export { type CreateClientOptions, createClient };
@@ -1,13 +0,0 @@
1
- import { ContentfulViewDeliveryClient } from "@contentful/experience-delivery";
2
- function createClient(options) {
3
- const { accessToken, host, ...rest } = options;
4
- return new ContentfulViewDeliveryClient({
5
- ...rest,
6
- token: accessToken,
7
- baseUrl: host
8
- });
9
- }
10
- export {
11
- createClient
12
- };
13
- //# sourceMappingURL=create-client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/create-client.ts"],"sourcesContent":["import { ContentfulViewDeliveryClient } from '@contentful/experience-delivery';\n\nexport type CreateClientOptions = {\n accessToken: string;\n /**\n * Base URL for the delivery client. Defaults to `DELIVERY_HOST` when omitted.\n * Pass `PREVIEW_HOST` for preview mode, or any custom URL (staging, proxy,\n * per-region). Both constants are exported from this package.\n */\n host?: string;\n} & Omit<ContentfulViewDeliveryClient.Options, 'token' | 'baseUrl'>;\n\nexport function createClient(options: CreateClientOptions): ContentfulViewDeliveryClient {\n const { accessToken, host, ...rest } = options;\n return new ContentfulViewDeliveryClient({\n ...rest,\n token: accessToken,\n baseUrl: host,\n });\n}\n"],"mappings":"AAAA,SAAS,oCAAoC;AAYtC,SAAS,aAAa,SAA4D;AACvF,QAAM,EAAE,aAAa,MAAM,GAAG,KAAK,IAAI;AACvC,SAAO,IAAI,6BAA6B;AAAA,IACtC,GAAG;AAAA,IACH,OAAO;AAAA,IACP,SAAS;AAAA,EACX,CAAC;AACH;","names":[]}