@contentful/optimization-api-client 0.1.0-alpha
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/LICENSE +21 -0
- package/README.md +282 -0
- package/dist/ApiClient.d.ts +74 -0
- package/dist/ApiClient.d.ts.map +1 -0
- package/dist/ApiClient.js +61 -0
- package/dist/ApiClient.js.map +1 -0
- package/dist/ApiClientBase.d.ts +113 -0
- package/dist/ApiClientBase.d.ts.map +1 -0
- package/dist/ApiClientBase.js +94 -0
- package/dist/ApiClientBase.js.map +1 -0
- package/dist/builders/EventBuilder.d.ts +589 -0
- package/dist/builders/EventBuilder.d.ts.map +1 -0
- package/dist/builders/EventBuilder.js +349 -0
- package/dist/builders/EventBuilder.js.map +1 -0
- package/dist/builders/index.d.ts +3 -0
- package/dist/builders/index.d.ts.map +1 -0
- package/dist/builders/index.js +3 -0
- package/dist/builders/index.js.map +1 -0
- package/dist/experience/ExperienceApiClient.d.ts +267 -0
- package/dist/experience/ExperienceApiClient.d.ts.map +1 -0
- package/dist/experience/ExperienceApiClient.js +324 -0
- package/dist/experience/ExperienceApiClient.js.map +1 -0
- package/dist/experience/index.d.ts +4 -0
- package/dist/experience/index.d.ts.map +1 -0
- package/dist/experience/index.js +4 -0
- package/dist/experience/index.js.map +1 -0
- package/dist/fetch/Fetch.d.ts +96 -0
- package/dist/fetch/Fetch.d.ts.map +1 -0
- package/dist/fetch/Fetch.js +27 -0
- package/dist/fetch/Fetch.js.map +1 -0
- package/dist/fetch/createProtectedFetchMethod.d.ts +40 -0
- package/dist/fetch/createProtectedFetchMethod.d.ts.map +1 -0
- package/dist/fetch/createProtectedFetchMethod.js +53 -0
- package/dist/fetch/createProtectedFetchMethod.js.map +1 -0
- package/dist/fetch/createRetryFetchMethod.d.ts +60 -0
- package/dist/fetch/createRetryFetchMethod.d.ts.map +1 -0
- package/dist/fetch/createRetryFetchMethod.js +138 -0
- package/dist/fetch/createRetryFetchMethod.js.map +1 -0
- package/dist/fetch/createTimeoutFetchMethod.d.ts +51 -0
- package/dist/fetch/createTimeoutFetchMethod.d.ts.map +1 -0
- package/dist/fetch/createTimeoutFetchMethod.js +51 -0
- package/dist/fetch/createTimeoutFetchMethod.js.map +1 -0
- package/dist/fetch/index.d.ts +7 -0
- package/dist/fetch/index.d.ts.map +1 -0
- package/dist/fetch/index.js +7 -0
- package/dist/fetch/index.js.map +1 -0
- package/dist/index.cjs +708 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +583 -0
- package/dist/index.mjs.map +1 -0
- package/dist/insights/InsightsApiClient.d.ts +130 -0
- package/dist/insights/InsightsApiClient.d.ts.map +1 -0
- package/dist/insights/InsightsApiClient.js +142 -0
- package/dist/insights/InsightsApiClient.js.map +1 -0
- package/dist/insights/index.d.ts +4 -0
- package/dist/insights/index.d.ts.map +1 -0
- package/dist/insights/index.js +4 -0
- package/dist/insights/index.js.map +1 -0
- package/package.json +27 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2026 Contentful Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://www.contentful.com/developers/docs/personalization/">
|
|
3
|
+
<img alt="Contentful Logo" title="Contentful" src="../../contentful-icon.png" width="150">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">Contentful Personalization & Analytics</h1>
|
|
8
|
+
|
|
9
|
+
<h3 align="center">API Client</h3>
|
|
10
|
+
|
|
11
|
+
<div align="center">
|
|
12
|
+
|
|
13
|
+
[Readme](./README.md) · [Reference](https://contentful.github.io/optimization) ·
|
|
14
|
+
[Contributing](/CONTRIBUTING.md)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
The Contentful Optimization API Client Library provides methods for interfacing with Contentful's
|
|
19
|
+
Experience and Insights APIs, which serve its Personalization and Analytics products.
|
|
20
|
+
|
|
21
|
+
> [!NOTE]
|
|
22
|
+
>
|
|
23
|
+
> In the future, the Experience and Insights APIs may be combined behind an Optimization API
|
|
24
|
+
|
|
25
|
+
<details>
|
|
26
|
+
<summary>Table of Contents</summary>
|
|
27
|
+
<!-- mtoc-start -->
|
|
28
|
+
|
|
29
|
+
- [Getting Started](#getting-started)
|
|
30
|
+
- [Configuration](#configuration)
|
|
31
|
+
- [Top-level Configuration Options](#top-level-configuration-options)
|
|
32
|
+
- [Fetch Options](#fetch-options)
|
|
33
|
+
- [Analytics Options](#analytics-options)
|
|
34
|
+
- [Personalization Options](#personalization-options)
|
|
35
|
+
- [Working With the APIs](#working-with-the-apis)
|
|
36
|
+
- [Experience API](#experience-api)
|
|
37
|
+
- [Get Profile data](#get-profile-data)
|
|
38
|
+
- [Create a New Profile](#create-a-new-profile)
|
|
39
|
+
- [Update an Existing Profile](#update-an-existing-profile)
|
|
40
|
+
- [Upsert a Profile](#upsert-a-profile)
|
|
41
|
+
- [Upsert Many Profiles](#upsert-many-profiles)
|
|
42
|
+
- [Insights API](#insights-api)
|
|
43
|
+
- [Send Batch Events](#send-batch-events)
|
|
44
|
+
- [Event Builder](#event-builder)
|
|
45
|
+
- [Event Builder Configuration](#event-builder-configuration)
|
|
46
|
+
- [Event Builder Configured Methods](#event-builder-configured-methods)
|
|
47
|
+
|
|
48
|
+
<!-- mtoc-end -->
|
|
49
|
+
</details>
|
|
50
|
+
|
|
51
|
+
## Getting Started
|
|
52
|
+
|
|
53
|
+
Install using an NPM-compatible package manager, pnpm for example:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
pnpm install @contentful/optimization-api-client
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Import the API client; both CJS and ESM module systems are supported, ESM preferred:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { ApiClient } from '@contentful/optimization-api-client'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Configure and initialize the API Client:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const client = new ApiClient({ clientId: 'abc123' })
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
### Top-level Configuration Options
|
|
74
|
+
|
|
75
|
+
| Option | Required? | Default | Description |
|
|
76
|
+
| ----------------- | --------- | ----------------------------- | --------------------------------------------------------------------- |
|
|
77
|
+
| `analytics` | No | See "Analytics Options" | Configuration specific to the Analytics/Insights API |
|
|
78
|
+
| `clientId` | Yes | N/A | The Ninetailed API Key which can be found in the Ninetailed Admin app |
|
|
79
|
+
| `environment` | No | `'main'` | The Ninetailed environment configured in the Ninetailed Admin app |
|
|
80
|
+
| `fetchOptions` | No | See "Fetch Options" | Configuration for Fetch timeout and retry functionality |
|
|
81
|
+
| `personalization` | No | See "Personalization Options" | Configuration specific to the Personalization/Experience API |
|
|
82
|
+
|
|
83
|
+
### Fetch Options
|
|
84
|
+
|
|
85
|
+
Fetch options allow for configuration of both a Fetch API-compatible fetch method and the
|
|
86
|
+
retry/timeout logic integrated into the Optimization API Client. Specify the `fetchMethod` when the
|
|
87
|
+
host application environment does not offer a `fetch` method that is compatible with the standard
|
|
88
|
+
Fetch API in its global scope.
|
|
89
|
+
|
|
90
|
+
| Option | Required? | Default | Description |
|
|
91
|
+
| ------------------ | --------- | ----------- | --------------------------------------------------------------------- |
|
|
92
|
+
| `fetchMethod` | No | `undefined` | Signature of a fetch method used by the API clients |
|
|
93
|
+
| `intervalTimeout` | No | `0` | Delay (in milliseconds) between retry attempts |
|
|
94
|
+
| `onFailedAttempt` | No | `undefined` | Callback invoked whenever a retry attempt fails |
|
|
95
|
+
| `onRequestTimeout` | No | `undefined` | Callback invoked when a request exceeds the configured timeout |
|
|
96
|
+
| `requestTimeout` | No | `3000` | Maximum time (in milliseconds) to wait for a response before aborting |
|
|
97
|
+
| `retries` | No | `1` | Maximum number of retry attempts |
|
|
98
|
+
|
|
99
|
+
Configuration method signatures:
|
|
100
|
+
|
|
101
|
+
- `fetchMethod`: `(url: string \| URL, init: RequestInit) => Promise<Response>`
|
|
102
|
+
- `onFailedAttempt` and `onRequestTimeout`: `(options: FetchMethodCallbackOptions) => void`
|
|
103
|
+
|
|
104
|
+
### Analytics Options
|
|
105
|
+
|
|
106
|
+
| Option | Required? | Default | Description |
|
|
107
|
+
| --------------- | --------- | ------------------------------------------ | ------------------------------------------------------------------------ |
|
|
108
|
+
| `baseUrl` | No | `'https://ingest.insights.ninetailed.co/'` | Base URL for the Insights API |
|
|
109
|
+
| `beaconHandler` | No | `undefined` | Handler used to enqueue events via the Beacon API or a similar mechanism |
|
|
110
|
+
|
|
111
|
+
Configuration method signatures:
|
|
112
|
+
|
|
113
|
+
- `beaconHandler`: `(url: string | URL, data: BatchInsightsEventArray) => boolean`
|
|
114
|
+
|
|
115
|
+
### Personalization Options
|
|
116
|
+
|
|
117
|
+
| Option | Required? | Default | Description |
|
|
118
|
+
| ----------------- | --------- | ------------------------------------- | ------------------------------------------------------------------- |
|
|
119
|
+
| `baseUrl` | No | `'https://experience.ninetailed.co/'` | Base URL for the Experience API |
|
|
120
|
+
| `enabledFeatures` | No | `['ip-enrichment', 'location']` | Enabled features which the API may use for each request |
|
|
121
|
+
| `ip` | No | `undefined` | IP address to override the API behavior for IP analysis |
|
|
122
|
+
| `locale` | No | `'en-US'` (in API) | Locale used to translate `location.city` and `location.country` |
|
|
123
|
+
| `plainText` | No | `false` | Sends performance-critical endpoints in plain text |
|
|
124
|
+
| `preflight` | No | `false` | Instructs the API to aggregate a new profile state but not store it |
|
|
125
|
+
|
|
126
|
+
> [!NOTE]
|
|
127
|
+
>
|
|
128
|
+
> All options except `baseUrl` may also be provided on a per-request basis.
|
|
129
|
+
|
|
130
|
+
## Working With the APIs
|
|
131
|
+
|
|
132
|
+
### Experience API
|
|
133
|
+
|
|
134
|
+
Experience API methods are scoped to the client's `personalization` member. All singular
|
|
135
|
+
personalization methods return a `Promise` that resolves with the following data:
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"profile": {
|
|
140
|
+
/* User profile data */
|
|
141
|
+
},
|
|
142
|
+
"personalizations": [
|
|
143
|
+
{
|
|
144
|
+
/* Personalization/experience configuration for the associated profile */
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"changes": [
|
|
148
|
+
{
|
|
149
|
+
/* Similar to `personalizations` but currently used for Custom Flags */
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Get Profile data
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const client = new ApiClient({ clientId: 'abc123' })
|
|
159
|
+
const { profile } = await client.personalization.getProfile('profile-123', { locale: 'de-DE' })
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Create a New Profile
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const client = new ApiClient({ clientId: 'abc123' })
|
|
166
|
+
const { profile } = await client.personalization.createProfile({ events: [...] }, { locale: 'de-DE' })
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### Update an Existing Profile
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
const client = new ApiClient({ clientId: 'abc123' })
|
|
173
|
+
const { profile } = await client.personalization.updateProfile(
|
|
174
|
+
{
|
|
175
|
+
profileId: 'profile-123',
|
|
176
|
+
events: [...],
|
|
177
|
+
},
|
|
178
|
+
{ locale: 'de-DE' }
|
|
179
|
+
)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### Upsert a Profile
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
const client = new ApiClient({ clientId: 'abc123' })
|
|
186
|
+
const { profile } = await client.personalization.upsertProfile(
|
|
187
|
+
{
|
|
188
|
+
profileId,
|
|
189
|
+
events: [...],
|
|
190
|
+
},
|
|
191
|
+
{ locale: 'de-DE' }
|
|
192
|
+
)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### Upsert Many Profiles
|
|
196
|
+
|
|
197
|
+
The `upsertManyProfiles` method returns a `Promise` that resolves with an array of user profiles.
|
|
198
|
+
Each event should have an additional `anonymousId` property set to the associated anonymous ID or
|
|
199
|
+
profile ID.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
const client = new ApiClient({ clientId: 'abc123' })
|
|
203
|
+
const profiles = await client.personalization.upsertManyProfiles(
|
|
204
|
+
{ events: [...]},
|
|
205
|
+
{ locale: 'de-DE' },
|
|
206
|
+
)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Insights API
|
|
210
|
+
|
|
211
|
+
Insights API methods are scoped to the client's `analytics` member. All analytics methods return a
|
|
212
|
+
`Promise` that resolves to `void` (no value).
|
|
213
|
+
|
|
214
|
+
#### Send Batch Events
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
const client = new ApiClient({ clientId: 'abc123' })
|
|
218
|
+
await client.analytics.sendBatchEvents([
|
|
219
|
+
{
|
|
220
|
+
profile: { id: 'abc-123', ... },
|
|
221
|
+
events: [{ type: 'track', ... }],
|
|
222
|
+
}
|
|
223
|
+
])
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Event Builder
|
|
227
|
+
|
|
228
|
+
The Event Builder is a helper class that assists in constructing valid events for submission to the
|
|
229
|
+
Experience and Insights APIs.
|
|
230
|
+
|
|
231
|
+
### Event Builder Configuration
|
|
232
|
+
|
|
233
|
+
Event Builder configuration options assist in adding contextual data to each event created by a
|
|
234
|
+
builder instance.
|
|
235
|
+
|
|
236
|
+
| Option | Required? | Default | Description |
|
|
237
|
+
| ------------------- | --------- | ------------------------------- | ---------------------------------------------------------------------------------- |
|
|
238
|
+
| `app` | No | `undefined` | The application definition used to attribute events to a specific consumer app |
|
|
239
|
+
| `channel` | Yes | N/A | The channel that identifies where events originate from (e.g. `'web'`, `'mobile'`) |
|
|
240
|
+
| `library` | Yes | N/A | The client library metadata that is attached to all events |
|
|
241
|
+
| `getLocale` | No | `() => 'en-US'` | Function used to resolve the locale for outgoing events |
|
|
242
|
+
| `getPageProperties` | No | `() => DEFAULT_PAGE_PROPERTIES` | Function that returns the current page properties |
|
|
243
|
+
| `getUserAgent` | No | `() => undefined` | Function used to obtain the current user agent string when applicable |
|
|
244
|
+
|
|
245
|
+
The `get*` functions are most useful in stateful environments. Stateless environments should set the
|
|
246
|
+
related data directly via Event Builder method arguments.
|
|
247
|
+
|
|
248
|
+
The `channel` option may contain one of the following values:
|
|
249
|
+
|
|
250
|
+
- `web`
|
|
251
|
+
- `mobile`
|
|
252
|
+
- `server`
|
|
253
|
+
|
|
254
|
+
Configuration method signatures:
|
|
255
|
+
|
|
256
|
+
- `getLocale`: `() => string | undefined`
|
|
257
|
+
- `getPageProperties`:
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
() => {
|
|
261
|
+
path: string,
|
|
262
|
+
query: Record<string, string>,
|
|
263
|
+
referrer: string,
|
|
264
|
+
search: string,
|
|
265
|
+
title?: string,
|
|
266
|
+
url: string
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
- `getUserAgent`: `() => string | undefined`
|
|
271
|
+
|
|
272
|
+
#### Event Builder Configured Methods
|
|
273
|
+
|
|
274
|
+
- `buildComponentView`: Builds a component view event payload for a Contentful entry-based component
|
|
275
|
+
- `buildFlagView`: Builds a component view payload event for a Custom Flag component
|
|
276
|
+
- `buildIdentify`: Builds an identify event payload to associate a user ID with traits
|
|
277
|
+
- `buildPageView`: Builds a page view event payload
|
|
278
|
+
- `buildTrack`: Builds a track event payload for arbitrary user actions
|
|
279
|
+
|
|
280
|
+
See the
|
|
281
|
+
[Event Builder documentation](../classes/_contentful_optimization-api-client.EventBuilder.html) for
|
|
282
|
+
more information regarding arguments and return values.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { ApiConfig, GlobalApiConfigProperties } from './ApiClientBase';
|
|
2
|
+
import ExperienceApiClient, { type ExperienceApiClientConfig } from './experience';
|
|
3
|
+
import InsightsApiClient, { type InsightsApiClientConfig } from './insights';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for the high-level {@link ApiClient}.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export interface ApiClientConfig extends Pick<ApiConfig, GlobalApiConfigProperties> {
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for the personalization (Experience) API client.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* Any properties shared with {@link ApiConfig} are taken from the top-level
|
|
15
|
+
* config and overridden by this object when specified.
|
|
16
|
+
*/
|
|
17
|
+
personalization?: Omit<ExperienceApiClientConfig, GlobalApiConfigProperties>;
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for the analytics (Insights) API client.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* Any properties shared with {@link ApiConfig} are taken from the top-level
|
|
23
|
+
* config and overridden by this object when specified.
|
|
24
|
+
*/
|
|
25
|
+
analytics?: Omit<InsightsApiClientConfig, GlobalApiConfigProperties>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Aggregated API client providing access to Experience and Insights APIs.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* This client encapsulates shared configuration and exposes dedicated
|
|
34
|
+
* sub-clients for personalization and analytics use cases.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const client = new ApiClient({
|
|
39
|
+
* clientId: 'org-id',
|
|
40
|
+
* environment: 'main',
|
|
41
|
+
* preview: false,
|
|
42
|
+
* personalization: {
|
|
43
|
+
* // experience-specific overrides
|
|
44
|
+
* },
|
|
45
|
+
* analytics: {
|
|
46
|
+
* // insights-specific overrides
|
|
47
|
+
* },
|
|
48
|
+
* })
|
|
49
|
+
*
|
|
50
|
+
* const profile = await client.experience.getProfile('profile-id')
|
|
51
|
+
* const batch = await client.insights.upsertManyProfiles({ events: batchEvents })
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export default class ApiClient {
|
|
55
|
+
/**
|
|
56
|
+
* Shared configuration applied to both Experience and Insights clients.
|
|
57
|
+
*/
|
|
58
|
+
readonly config: ApiConfig;
|
|
59
|
+
/**
|
|
60
|
+
* Client for personalization and experience-related operations.
|
|
61
|
+
*/
|
|
62
|
+
readonly experience: ExperienceApiClient;
|
|
63
|
+
/**
|
|
64
|
+
* Client for analytics and insights-related operations.
|
|
65
|
+
*/
|
|
66
|
+
readonly insights: InsightsApiClient;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a new aggregated {@link ApiClient} instance.
|
|
69
|
+
*
|
|
70
|
+
* @param config - Global API client configuration with optional per-client overrides.
|
|
71
|
+
*/
|
|
72
|
+
constructor(config: ApiClientConfig);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=ApiClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiClient.d.ts","sourceRoot":"","sources":["../src/ApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAA;AAC3E,OAAO,mBAAmB,EAAE,EAAE,KAAK,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAClF,OAAO,iBAAiB,EAAE,EAAE,KAAK,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAE5E;;;;GAIG;AACH,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,SAAS,EAAE,yBAAyB,CAAC;IACjF;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,yBAAyB,CAAC,CAAA;IAE5E;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,IAAI,CAAC,uBAAuB,EAAE,yBAAyB,CAAC,CAAA;CACrE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAE1B;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAA;IAExC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAA;IAEpC;;;;OAIG;gBACS,MAAM,EAAE,eAAe;CAepC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import ExperienceApiClient from './experience';
|
|
2
|
+
import InsightsApiClient from './insights';
|
|
3
|
+
/**
|
|
4
|
+
* Aggregated API client providing access to Experience and Insights APIs.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* This client encapsulates shared configuration and exposes dedicated
|
|
10
|
+
* sub-clients for personalization and analytics use cases.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const client = new ApiClient({
|
|
15
|
+
* clientId: 'org-id',
|
|
16
|
+
* environment: 'main',
|
|
17
|
+
* preview: false,
|
|
18
|
+
* personalization: {
|
|
19
|
+
* // experience-specific overrides
|
|
20
|
+
* },
|
|
21
|
+
* analytics: {
|
|
22
|
+
* // insights-specific overrides
|
|
23
|
+
* },
|
|
24
|
+
* })
|
|
25
|
+
*
|
|
26
|
+
* const profile = await client.experience.getProfile('profile-id')
|
|
27
|
+
* const batch = await client.insights.upsertManyProfiles({ events: batchEvents })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export default class ApiClient {
|
|
31
|
+
/**
|
|
32
|
+
* Shared configuration applied to both Experience and Insights clients.
|
|
33
|
+
*/
|
|
34
|
+
config;
|
|
35
|
+
/**
|
|
36
|
+
* Client for personalization and experience-related operations.
|
|
37
|
+
*/
|
|
38
|
+
experience;
|
|
39
|
+
/**
|
|
40
|
+
* Client for analytics and insights-related operations.
|
|
41
|
+
*/
|
|
42
|
+
insights;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a new aggregated {@link ApiClient} instance.
|
|
45
|
+
*
|
|
46
|
+
* @param config - Global API client configuration with optional per-client overrides.
|
|
47
|
+
*/
|
|
48
|
+
constructor(config) {
|
|
49
|
+
const { personalization, analytics, ...apiConfig } = config;
|
|
50
|
+
this.config = apiConfig;
|
|
51
|
+
this.experience = new ExperienceApiClient({
|
|
52
|
+
...apiConfig,
|
|
53
|
+
...personalization,
|
|
54
|
+
});
|
|
55
|
+
this.insights = new InsightsApiClient({
|
|
56
|
+
...apiConfig,
|
|
57
|
+
...analytics,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=ApiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiClient.js","sourceRoot":"","sources":["../src/ApiClient.ts"],"names":[],"mappings":"AACA,OAAO,mBAAuD,MAAM,cAAc,CAAA;AAClF,OAAO,iBAAmD,MAAM,YAAY,CAAA;AA2B5E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B;;OAEG;IACM,MAAM,CAAW;IAE1B;;OAEG;IACM,UAAU,CAAqB;IAExC;;OAEG;IACM,QAAQ,CAAmB;IAEpC;;;;OAIG;IACH,YAAY,MAAuB;QACjC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,GAAG,MAAM,CAAA;QAE3D,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;QAEvB,IAAI,CAAC,UAAU,GAAG,IAAI,mBAAmB,CAAC;YACxC,GAAG,SAAS;YACZ,GAAG,eAAe;SACnB,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,GAAG,IAAI,iBAAiB,CAAC;YACpC,GAAG,SAAS;YACZ,GAAG,SAAS;SACb,CAAC,CAAA;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { type FetchMethod, type ProtectedFetchMethodOptions } from './fetch';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for API clients extending {@link ApiClientBase}.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface ApiConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Base URL for the API.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* When omitted, the concrete client is expected to construct full URLs
|
|
13
|
+
* internally.
|
|
14
|
+
*/
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Contentful environment identifier.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* Defaults to `main` when not provided.
|
|
21
|
+
*/
|
|
22
|
+
environment?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Options used to configure the underlying protected fetch method.
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* `apiName` is derived from the client name and must not be provided here.
|
|
28
|
+
*/
|
|
29
|
+
fetchOptions?: Omit<ProtectedFetchMethodOptions, 'apiName'>;
|
|
30
|
+
/**
|
|
31
|
+
* Client identifier used for authentication or tracking.
|
|
32
|
+
*/
|
|
33
|
+
clientId: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Properties that may be shared between global and per-client API configuration.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export type GlobalApiConfigProperties = 'environment' | 'fetchOptions' | 'clientId';
|
|
41
|
+
/**
|
|
42
|
+
* Base class for API clients that provides shared configuration and error logging.
|
|
43
|
+
*
|
|
44
|
+
* @internal
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* This abstract class is intended for internal use within the package and
|
|
48
|
+
* should not be treated as part of the public API surface.
|
|
49
|
+
*
|
|
50
|
+
* Concrete API clients should extend this class to inherit consistent logging
|
|
51
|
+
* behavior and fetch configuration.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* interface MyClientConfig extends ApiConfig {
|
|
56
|
+
* // additional config
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* class MyClient extends ApiClientBase {
|
|
60
|
+
* constructor(config: MyClientConfig) {
|
|
61
|
+
* super('MyClient', config)
|
|
62
|
+
* }
|
|
63
|
+
*
|
|
64
|
+
* async getSomething() {
|
|
65
|
+
* const response = await this.fetch('https://example.com', { method: 'GET' })
|
|
66
|
+
* return response.json()
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare abstract class ApiClientBase {
|
|
72
|
+
/**
|
|
73
|
+
* Name of the API client, used in log messages and as the `apiName` for fetch.
|
|
74
|
+
*/
|
|
75
|
+
protected readonly name: string;
|
|
76
|
+
/**
|
|
77
|
+
* Client identifier used for authentication or tracking.
|
|
78
|
+
*/
|
|
79
|
+
protected readonly clientId: string;
|
|
80
|
+
/**
|
|
81
|
+
* Contentful environment associated with this client.
|
|
82
|
+
*/
|
|
83
|
+
protected readonly environment: string;
|
|
84
|
+
/**
|
|
85
|
+
* Protected fetch method used by the client to perform HTTP requests.
|
|
86
|
+
*/
|
|
87
|
+
protected readonly fetch: FetchMethod;
|
|
88
|
+
/**
|
|
89
|
+
* Creates a new API client base instance.
|
|
90
|
+
*
|
|
91
|
+
* @param name - Human-readable name of the client (used for logging and `apiName`).
|
|
92
|
+
* @param config - Configuration options for the client.
|
|
93
|
+
*/
|
|
94
|
+
constructor(name: string, { fetchOptions, clientId, environment }: ApiConfig);
|
|
95
|
+
/**
|
|
96
|
+
* Logs errors that occur during API requests with standardized messages.
|
|
97
|
+
*
|
|
98
|
+
* @param error - The error thrown by the underlying operation.
|
|
99
|
+
* @param options - Additional metadata about the request.
|
|
100
|
+
* @param options.requestName - Human-readable name of the request operation.
|
|
101
|
+
*
|
|
102
|
+
* @protected
|
|
103
|
+
*
|
|
104
|
+
* @remarks
|
|
105
|
+
* Abort errors are logged at `warn` level and other errors at `error` level.
|
|
106
|
+
* The log message includes the client name for better debugging context.
|
|
107
|
+
*/
|
|
108
|
+
protected logRequestError(error: unknown, { requestName }: {
|
|
109
|
+
requestName: string;
|
|
110
|
+
}): void;
|
|
111
|
+
}
|
|
112
|
+
export default ApiClientBase;
|
|
113
|
+
//# sourceMappingURL=ApiClientBase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiClientBase.d.ts","sourceRoot":"","sources":["../src/ApiClientBase.ts"],"names":[],"mappings":"AACA,OAAc,EAAE,KAAK,WAAW,EAAE,KAAK,2BAA2B,EAAE,MAAM,SAAS,CAAA;AAWnF;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,IAAI,CAAC,2BAA2B,EAAE,SAAS,CAAC,CAAA;IAE3D;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG,aAAa,GAAG,cAAc,GAAG,UAAU,CAAA;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,uBAAe,aAAa;IAC1B;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAE/B;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IAEnC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAEtC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAErC;;;;;OAKG;gBACS,IAAI,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,SAAS;IAQ5E;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAW1F;AAED,eAAe,aAAa,CAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createScopedLogger } from 'logger';
|
|
2
|
+
import Fetch from './fetch';
|
|
3
|
+
const logger = createScopedLogger('ApiClient');
|
|
4
|
+
/**
|
|
5
|
+
* Default Contentful environment used when none is explicitly provided.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_ENVIRONMENT = 'main';
|
|
10
|
+
/**
|
|
11
|
+
* Base class for API clients that provides shared configuration and error logging.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This abstract class is intended for internal use within the package and
|
|
17
|
+
* should not be treated as part of the public API surface.
|
|
18
|
+
*
|
|
19
|
+
* Concrete API clients should extend this class to inherit consistent logging
|
|
20
|
+
* behavior and fetch configuration.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* interface MyClientConfig extends ApiConfig {
|
|
25
|
+
* // additional config
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* class MyClient extends ApiClientBase {
|
|
29
|
+
* constructor(config: MyClientConfig) {
|
|
30
|
+
* super('MyClient', config)
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* async getSomething() {
|
|
34
|
+
* const response = await this.fetch('https://example.com', { method: 'GET' })
|
|
35
|
+
* return response.json()
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
class ApiClientBase {
|
|
41
|
+
/**
|
|
42
|
+
* Name of the API client, used in log messages and as the `apiName` for fetch.
|
|
43
|
+
*/
|
|
44
|
+
name;
|
|
45
|
+
/**
|
|
46
|
+
* Client identifier used for authentication or tracking.
|
|
47
|
+
*/
|
|
48
|
+
clientId;
|
|
49
|
+
/**
|
|
50
|
+
* Contentful environment associated with this client.
|
|
51
|
+
*/
|
|
52
|
+
environment;
|
|
53
|
+
/**
|
|
54
|
+
* Protected fetch method used by the client to perform HTTP requests.
|
|
55
|
+
*/
|
|
56
|
+
fetch;
|
|
57
|
+
/**
|
|
58
|
+
* Creates a new API client base instance.
|
|
59
|
+
*
|
|
60
|
+
* @param name - Human-readable name of the client (used for logging and `apiName`).
|
|
61
|
+
* @param config - Configuration options for the client.
|
|
62
|
+
*/
|
|
63
|
+
constructor(name, { fetchOptions, clientId, environment }) {
|
|
64
|
+
this.clientId = clientId;
|
|
65
|
+
this.environment = environment ?? DEFAULT_ENVIRONMENT;
|
|
66
|
+
this.name = name;
|
|
67
|
+
this.fetch = Fetch.create({ ...(fetchOptions ?? {}), apiName: name });
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Logs errors that occur during API requests with standardized messages.
|
|
71
|
+
*
|
|
72
|
+
* @param error - The error thrown by the underlying operation.
|
|
73
|
+
* @param options - Additional metadata about the request.
|
|
74
|
+
* @param options.requestName - Human-readable name of the request operation.
|
|
75
|
+
*
|
|
76
|
+
* @protected
|
|
77
|
+
*
|
|
78
|
+
* @remarks
|
|
79
|
+
* Abort errors are logged at `warn` level and other errors at `error` level.
|
|
80
|
+
* The log message includes the client name for better debugging context.
|
|
81
|
+
*/
|
|
82
|
+
logRequestError(error, { requestName }) {
|
|
83
|
+
if (error instanceof Error) {
|
|
84
|
+
if (error.name === 'AbortError') {
|
|
85
|
+
logger.warn(`[${this.name}] "${requestName}" request aborted due to network issues. This request may not be retried.`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
logger.error(`[${this.name}] "${requestName}" request failed:`, error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export default ApiClientBase;
|
|
94
|
+
//# sourceMappingURL=ApiClientBase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiClientBase.js","sourceRoot":"","sources":["../src/ApiClientBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAA;AAC3C,OAAO,KAA6D,MAAM,SAAS,CAAA;AAEnF,MAAM,MAAM,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAA;AAE9C;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,MAAM,CAAA;AA8ClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAe,aAAa;IAC1B;;OAEG;IACgB,IAAI,CAAQ;IAE/B;;OAEG;IACgB,QAAQ,CAAQ;IAEnC;;OAEG;IACgB,WAAW,CAAQ;IAEtC;;OAEG;IACgB,KAAK,CAAa;IAErC;;;;;OAKG;IACH,YAAY,IAAY,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAa;QAC1E,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,WAAW,GAAG,WAAW,IAAI,mBAAmB,CAAA;QACrD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAEhB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IACvE,CAAC;IAED;;;;;;;;;;;;OAYG;IACO,eAAe,CAAC,KAAc,EAAE,EAAE,WAAW,EAA2B;QAChF,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAChC,MAAM,CAAC,IAAI,CACT,IAAI,IAAI,CAAC,IAAI,MAAM,WAAW,2EAA2E,CAC1G,CAAA;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,MAAM,WAAW,mBAAmB,EAAE,KAAK,CAAC,CAAA;YACxE,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,eAAe,aAAa,CAAA"}
|