@storyblok/api-client 1.0.0-alpha.1 → 1.0.0-alpha.3
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/README.md +3 -1
- package/dist/client.cjs +7 -4
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +302 -68
- package/dist/client.d.mts +302 -68
- package/dist/client.mjs +7 -4
- package/dist/client.mjs.map +1 -1
- package/dist/generated/capi/_internal.gen.d.cts +120 -0
- package/dist/generated/capi/_internal.gen.d.mts +120 -0
- package/dist/generated/{shared → capi}/client/client.gen.cjs +1 -1
- package/dist/generated/capi/client/client.gen.cjs.map +1 -0
- package/dist/generated/{shared → capi}/client/client.gen.mjs +1 -1
- package/dist/generated/capi/client/client.gen.mjs.map +1 -0
- package/dist/generated/{shared → capi}/client/types.gen.d.cts +1 -1
- package/dist/generated/{shared → capi}/client/types.gen.d.mts +1 -1
- package/dist/generated/{shared → capi}/client/utils.gen.cjs +1 -1
- package/dist/generated/capi/client/utils.gen.cjs.map +1 -0
- package/dist/generated/{shared → capi}/client/utils.gen.d.cts +1 -1
- package/dist/generated/{shared → capi}/client/utils.gen.d.mts +1 -1
- package/dist/generated/{shared → capi}/client/utils.gen.mjs +1 -1
- package/dist/generated/capi/client/utils.gen.mjs.map +1 -0
- package/dist/generated/capi/client.gen.cjs +10 -0
- package/dist/generated/capi/client.gen.cjs.map +1 -0
- package/dist/generated/capi/client.gen.mjs +10 -0
- package/dist/generated/capi/client.gen.mjs.map +1 -0
- package/dist/generated/{shared → capi}/core/auth.gen.cjs +1 -1
- package/dist/generated/capi/core/auth.gen.cjs.map +1 -0
- package/dist/generated/{shared → capi}/core/auth.gen.d.cts +1 -1
- package/dist/generated/{shared → capi}/core/auth.gen.d.mts +1 -1
- package/dist/generated/{shared → capi}/core/auth.gen.mjs +1 -1
- package/dist/generated/capi/core/auth.gen.mjs.map +1 -0
- package/dist/generated/{shared → capi}/core/bodySerializer.gen.cjs +1 -1
- package/dist/generated/capi/core/bodySerializer.gen.cjs.map +1 -0
- package/dist/generated/{shared → capi}/core/bodySerializer.gen.d.cts +1 -1
- package/dist/generated/{shared → capi}/core/bodySerializer.gen.d.mts +1 -1
- package/dist/generated/{shared → capi}/core/bodySerializer.gen.mjs +1 -1
- package/dist/generated/capi/core/bodySerializer.gen.mjs.map +1 -0
- package/dist/generated/{shared → capi}/core/params.gen.cjs +1 -1
- package/dist/generated/capi/core/params.gen.cjs.map +1 -0
- package/dist/generated/{shared → capi}/core/params.gen.mjs +1 -1
- package/dist/generated/capi/core/params.gen.mjs.map +1 -0
- package/dist/generated/{shared → capi}/core/pathSerializer.gen.cjs +1 -1
- package/dist/generated/capi/core/pathSerializer.gen.cjs.map +1 -0
- package/dist/generated/{shared → capi}/core/pathSerializer.gen.d.cts +1 -1
- package/dist/generated/{shared → capi}/core/pathSerializer.gen.d.mts +1 -1
- package/dist/generated/{shared → capi}/core/pathSerializer.gen.mjs +1 -1
- package/dist/generated/capi/core/pathSerializer.gen.mjs.map +1 -0
- package/dist/generated/{shared → capi}/core/serverSentEvents.gen.cjs +1 -1
- package/dist/generated/capi/core/serverSentEvents.gen.cjs.map +1 -0
- package/dist/generated/{shared → capi}/core/serverSentEvents.gen.d.cts +1 -1
- package/dist/generated/{shared → capi}/core/serverSentEvents.gen.d.mts +1 -1
- package/dist/generated/{shared → capi}/core/serverSentEvents.gen.mjs +1 -1
- package/dist/generated/capi/core/serverSentEvents.gen.mjs.map +1 -0
- package/dist/generated/{shared → capi}/core/types.gen.d.cts +1 -1
- package/dist/generated/{shared → capi}/core/types.gen.d.mts +1 -1
- package/dist/generated/{shared → capi}/core/utils.gen.cjs +1 -1
- package/dist/generated/capi/core/utils.gen.cjs.map +1 -0
- package/dist/generated/{shared → capi}/core/utils.gen.mjs +1 -1
- package/dist/generated/capi/core/utils.gen.mjs.map +1 -0
- package/dist/generated/capi/sdk.gen.cjs +141 -0
- package/dist/generated/capi/sdk.gen.cjs.map +1 -0
- package/dist/generated/capi/sdk.gen.mjs +133 -0
- package/dist/generated/capi/sdk.gen.mjs.map +1 -0
- package/dist/generated/capi/types-aliased.gen.d.cts +181 -0
- package/dist/generated/capi/types-aliased.gen.d.mts +181 -0
- package/dist/generated/capi/types.gen.d.cts +919 -0
- package/dist/generated/capi/types.gen.d.mts +919 -0
- package/dist/generated/mapi/_internal.gen.d.cts +146 -0
- package/dist/generated/mapi/_internal.gen.d.mts +146 -0
- package/dist/generated/mapi/types.gen.d.cts +293 -0
- package/dist/generated/mapi/types.gen.d.mts +293 -0
- package/dist/generated/overlay/_internal.gen.d.cts +831 -0
- package/dist/generated/overlay/_internal.gen.d.mts +831 -0
- package/dist/generated/types/_utils.d.cts +7 -0
- package/dist/generated/types/_utils.d.mts +7 -0
- package/dist/generated/types/block.d.cts +49 -0
- package/dist/generated/types/block.d.mts +49 -0
- package/dist/generated/types/field.d.cts +71 -0
- package/dist/generated/types/field.d.mts +71 -0
- package/dist/generated/types/story.d.cts +19 -0
- package/dist/generated/types/story.d.mts +19 -0
- package/dist/index.d.cts +6 -3
- package/dist/index.d.mts +6 -3
- package/dist/resources/datasource-entries.cjs +2 -2
- package/dist/resources/datasource-entries.cjs.map +1 -1
- package/dist/resources/datasource-entries.mjs +2 -2
- package/dist/resources/datasource-entries.mjs.map +1 -1
- package/dist/resources/datasources.cjs +4 -4
- package/dist/resources/datasources.cjs.map +1 -1
- package/dist/resources/datasources.mjs +4 -4
- package/dist/resources/datasources.mjs.map +1 -1
- package/dist/resources/experiments.cjs +26 -0
- package/dist/resources/experiments.cjs.map +1 -0
- package/dist/resources/experiments.mjs +26 -0
- package/dist/resources/experiments.mjs.map +1 -0
- package/dist/resources/links.cjs +2 -2
- package/dist/resources/links.cjs.map +1 -1
- package/dist/resources/links.mjs +2 -2
- package/dist/resources/links.mjs.map +1 -1
- package/dist/resources/spaces.cjs +4 -4
- package/dist/resources/spaces.cjs.map +1 -1
- package/dist/resources/spaces.mjs +4 -4
- package/dist/resources/spaces.mjs.map +1 -1
- package/dist/resources/stories.cjs +10 -8
- package/dist/resources/stories.cjs.map +1 -1
- package/dist/resources/stories.d.cts +16 -13
- package/dist/resources/stories.d.mts +16 -13
- package/dist/resources/stories.mjs +10 -8
- package/dist/resources/stories.mjs.map +1 -1
- package/dist/resources/tags.cjs +2 -2
- package/dist/resources/tags.cjs.map +1 -1
- package/dist/resources/tags.mjs +2 -2
- package/dist/resources/tags.mjs.map +1 -1
- package/dist/utils/fetch-rel-uuids.cjs +2 -2
- package/dist/utils/fetch-rel-uuids.cjs.map +1 -1
- package/dist/utils/fetch-rel-uuids.mjs +2 -2
- package/dist/utils/fetch-rel-uuids.mjs.map +1 -1
- package/dist/utils/inline-relations.cjs.map +1 -1
- package/dist/utils/inline-relations.mjs.map +1 -1
- package/package.json +13 -19
- package/dist/generated/datasource_entries/client.gen.cjs +0 -10
- package/dist/generated/datasource_entries/client.gen.cjs.map +0 -1
- package/dist/generated/datasource_entries/client.gen.mjs +0 -10
- package/dist/generated/datasource_entries/client.gen.mjs.map +0 -1
- package/dist/generated/datasource_entries/sdk.gen.cjs +0 -21
- package/dist/generated/datasource_entries/sdk.gen.cjs.map +0 -1
- package/dist/generated/datasource_entries/sdk.gen.mjs +0 -21
- package/dist/generated/datasource_entries/sdk.gen.mjs.map +0 -1
- package/dist/generated/datasource_entries/types.gen.d.cts +0 -52
- package/dist/generated/datasource_entries/types.gen.d.mts +0 -52
- package/dist/generated/datasources/client.gen.cjs +0 -10
- package/dist/generated/datasources/client.gen.cjs.map +0 -1
- package/dist/generated/datasources/client.gen.mjs +0 -10
- package/dist/generated/datasources/client.gen.mjs.map +0 -1
- package/dist/generated/datasources/sdk.gen.cjs +0 -36
- package/dist/generated/datasources/sdk.gen.cjs.map +0 -1
- package/dist/generated/datasources/sdk.gen.mjs +0 -35
- package/dist/generated/datasources/sdk.gen.mjs.map +0 -1
- package/dist/generated/datasources/types.gen.d.cts +0 -82
- package/dist/generated/datasources/types.gen.d.mts +0 -82
- package/dist/generated/links/client.gen.cjs +0 -10
- package/dist/generated/links/client.gen.cjs.map +0 -1
- package/dist/generated/links/client.gen.mjs +0 -10
- package/dist/generated/links/client.gen.mjs.map +0 -1
- package/dist/generated/links/sdk.gen.cjs +0 -21
- package/dist/generated/links/sdk.gen.cjs.map +0 -1
- package/dist/generated/links/sdk.gen.mjs +0 -21
- package/dist/generated/links/sdk.gen.mjs.map +0 -1
- package/dist/generated/links/types.gen.d.cts +0 -125
- package/dist/generated/links/types.gen.d.mts +0 -125
- package/dist/generated/shared/client/client.gen.cjs.map +0 -1
- package/dist/generated/shared/client/client.gen.mjs.map +0 -1
- package/dist/generated/shared/client/utils.gen.cjs.map +0 -1
- package/dist/generated/shared/client/utils.gen.mjs.map +0 -1
- package/dist/generated/shared/core/auth.gen.cjs.map +0 -1
- package/dist/generated/shared/core/auth.gen.mjs.map +0 -1
- package/dist/generated/shared/core/bodySerializer.gen.cjs.map +0 -1
- package/dist/generated/shared/core/bodySerializer.gen.mjs.map +0 -1
- package/dist/generated/shared/core/params.gen.cjs.map +0 -1
- package/dist/generated/shared/core/params.gen.mjs.map +0 -1
- package/dist/generated/shared/core/pathSerializer.gen.cjs.map +0 -1
- package/dist/generated/shared/core/pathSerializer.gen.mjs.map +0 -1
- package/dist/generated/shared/core/serverSentEvents.gen.cjs.map +0 -1
- package/dist/generated/shared/core/serverSentEvents.gen.mjs.map +0 -1
- package/dist/generated/shared/core/utils.gen.cjs.map +0 -1
- package/dist/generated/shared/core/utils.gen.mjs.map +0 -1
- package/dist/generated/spaces/client.gen.cjs +0 -10
- package/dist/generated/spaces/client.gen.cjs.map +0 -1
- package/dist/generated/spaces/client.gen.mjs +0 -10
- package/dist/generated/spaces/client.gen.mjs.map +0 -1
- package/dist/generated/spaces/sdk.gen.cjs +0 -21
- package/dist/generated/spaces/sdk.gen.cjs.map +0 -1
- package/dist/generated/spaces/sdk.gen.mjs +0 -21
- package/dist/generated/spaces/sdk.gen.mjs.map +0 -1
- package/dist/generated/spaces/types.gen.d.cts +0 -26
- package/dist/generated/spaces/types.gen.d.mts +0 -26
- package/dist/generated/stories/client.gen.cjs +0 -10
- package/dist/generated/stories/client.gen.cjs.map +0 -1
- package/dist/generated/stories/client.gen.mjs +0 -10
- package/dist/generated/stories/client.gen.mjs.map +0 -1
- package/dist/generated/stories/index.d.mts +0 -1
- package/dist/generated/stories/sdk.gen.cjs +0 -36
- package/dist/generated/stories/sdk.gen.cjs.map +0 -1
- package/dist/generated/stories/sdk.gen.d.mts +0 -1
- package/dist/generated/stories/sdk.gen.mjs +0 -35
- package/dist/generated/stories/sdk.gen.mjs.map +0 -1
- package/dist/generated/stories/types.gen.d.cts +0 -607
- package/dist/generated/stories/types.gen.d.mts +0 -607
- package/dist/generated/tags/client.gen.cjs +0 -10
- package/dist/generated/tags/client.gen.cjs.map +0 -1
- package/dist/generated/tags/client.gen.mjs +0 -10
- package/dist/generated/tags/client.gen.mjs.map +0 -1
- package/dist/generated/tags/sdk.gen.cjs +0 -21
- package/dist/generated/tags/sdk.gen.cjs.map +0 -1
- package/dist/generated/tags/sdk.gen.mjs +0 -21
- package/dist/generated/tags/sdk.gen.mjs.map +0 -1
- package/dist/generated/tags/types.gen.d.cts +0 -29
- package/dist/generated/tags/types.gen.d.mts +0 -29
- /package/dist/generated/{shared → capi}/client/client.gen.d.mts +0 -0
- /package/dist/generated/{shared → capi}/client/index.cjs +0 -0
- /package/dist/generated/{shared → capi}/client/index.d.mts +0 -0
- /package/dist/generated/{shared → capi}/client/index.mjs +0 -0
package/dist/client.d.mts
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { SpaceCapi } from "./generated/spaces/types.gen.mjs";
|
|
7
|
-
import { StoryCapi } from "./generated/stories/types.gen.mjs";
|
|
8
|
-
import { ListData as ListData$3, TagCapi } from "./generated/tags/types.gen.mjs";
|
|
1
|
+
import { CdnExperiment, Datasource, DatasourceEntry, GetDatasourceByIdData, GetSpaceData, Link, LinkWithFullSlug, ListCdnExperimentsV2Data, ListDatasourceEntriesData, ListDatasourcesData, ListLinksData, ListTagsData, PublicSpace, Story, Tag } from "./generated/capi/types.gen.mjs";
|
|
2
|
+
import { Middleware } from "./generated/capi/client/utils.gen.mjs";
|
|
3
|
+
import { Client, RequestOptions, ResolvedRequestOptions } from "./generated/capi/client/types.gen.mjs";
|
|
4
|
+
import { StoryAlternate } from "./generated/capi/_internal.gen.mjs";
|
|
5
|
+
import { AssetFieldValueRoot, BlockContentRoot } from "./generated/overlay/_internal.gen.mjs";
|
|
9
6
|
import { CacheProvider, CacheStrategy, CacheStrategyHandler } from "./utils/cache.mjs";
|
|
10
7
|
import { ClientError } from "./error.mjs";
|
|
11
8
|
import { RateLimitConfig, ThrottleManager } from "./utils/rate-limit.mjs";
|
|
9
|
+
import { Block } from "./generated/types/block.mjs";
|
|
12
10
|
import { StoryWithInlinedRelations, createStoriesResource } from "./resources/stories.mjs";
|
|
13
11
|
import { RetryOptions } from "ky";
|
|
14
12
|
import { Region } from "@storyblok/region-helper";
|
|
15
|
-
import { Block } from "@storyblok/schema";
|
|
16
13
|
|
|
17
14
|
//#region src/client.d.ts
|
|
18
15
|
type ApiResponse<Data = unknown, ThrowOnError extends boolean = false> = ThrowOnError extends true ? {
|
|
@@ -69,6 +66,17 @@ interface CacheConfig {
|
|
|
69
66
|
strategy?: CacheStrategy | CacheStrategyHandler;
|
|
70
67
|
/** Time-to-live in milliseconds for cached entries. @default 60_000 */
|
|
71
68
|
ttlMs?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Controls how the `cv` (content version) query parameter is managed.
|
|
71
|
+
*
|
|
72
|
+
* - `'auto'` (default): automatically attach the tracked `cv` to
|
|
73
|
+
* subsequent published requests for cache busting.
|
|
74
|
+
* - `'manual'`: do not attach `cv` to outgoing requests. The client still
|
|
75
|
+
* tracks cv internally for cache invalidation (flushing when cv changes),
|
|
76
|
+
* but the query parameter is not sent. Useful for SSR with edge caching
|
|
77
|
+
* where stable URLs are required.
|
|
78
|
+
*/
|
|
79
|
+
cv?: 'auto' | 'manual';
|
|
72
80
|
/**
|
|
73
81
|
* Controls when the cache is flushed on cv change.
|
|
74
82
|
*
|
|
@@ -156,33 +164,44 @@ type ContentApiClient<TComponents extends Block = Block, InlineRelations extends
|
|
|
156
164
|
declare const createApiClientBase: <ThrowOnError extends boolean = false, InlineRelations extends boolean = false>(config: ContentApiClientConfig<ThrowOnError, InlineRelations>) => {
|
|
157
165
|
datasourceEntries: {
|
|
158
166
|
list: <ThrowOnError_1 extends boolean = ThrowOnError>(options?: {
|
|
159
|
-
query?:
|
|
167
|
+
query?: ListDatasourceEntriesData["query"];
|
|
160
168
|
signal?: AbortSignal;
|
|
161
169
|
throwOnError?: ThrowOnError_1 | undefined;
|
|
162
170
|
fetchOptions?: FetchOptions;
|
|
163
171
|
}) => Promise<ApiResponse<{
|
|
164
|
-
datasource_entries: Array<
|
|
172
|
+
datasource_entries: Array<DatasourceEntry>;
|
|
165
173
|
cv?: number | null;
|
|
166
174
|
}, ThrowOnError_1>>;
|
|
167
175
|
};
|
|
168
176
|
datasources: {
|
|
169
|
-
get: <ThrowOnError_1 extends boolean = ThrowOnError>(id:
|
|
170
|
-
query?:
|
|
177
|
+
get: <ThrowOnError_1 extends boolean = ThrowOnError>(id: GetDatasourceByIdData["path"]["id"], options?: {
|
|
178
|
+
query?: GetDatasourceByIdData["query"];
|
|
171
179
|
signal?: AbortSignal;
|
|
172
180
|
throwOnError?: ThrowOnError_1 | undefined;
|
|
173
181
|
fetchOptions?: FetchOptions;
|
|
174
182
|
}) => Promise<ApiResponse<{
|
|
175
|
-
datasource:
|
|
176
|
-
cv
|
|
183
|
+
datasource: Datasource;
|
|
184
|
+
cv: number | null;
|
|
177
185
|
}, ThrowOnError_1>>;
|
|
178
186
|
list: <ThrowOnError_1 extends boolean = ThrowOnError>(options?: {
|
|
179
|
-
query?:
|
|
187
|
+
query?: ListDatasourcesData["query"];
|
|
180
188
|
signal?: AbortSignal;
|
|
181
189
|
throwOnError?: ThrowOnError_1 | undefined;
|
|
182
190
|
fetchOptions?: FetchOptions;
|
|
183
191
|
}) => Promise<ApiResponse<{
|
|
184
|
-
datasources: Array<
|
|
185
|
-
cv?: number;
|
|
192
|
+
datasources: Array<Datasource>;
|
|
193
|
+
cv?: number | null;
|
|
194
|
+
}, ThrowOnError_1>>;
|
|
195
|
+
};
|
|
196
|
+
experiments: {
|
|
197
|
+
list: <ThrowOnError_1 extends boolean = ThrowOnError>(options?: {
|
|
198
|
+
query?: ListCdnExperimentsV2Data["query"];
|
|
199
|
+
signal?: AbortSignal;
|
|
200
|
+
throwOnError?: ThrowOnError_1 | undefined;
|
|
201
|
+
fetchOptions?: FetchOptions;
|
|
202
|
+
}) => Promise<ApiResponse<{
|
|
203
|
+
experiments: Array<CdnExperiment>;
|
|
204
|
+
cv?: number | null;
|
|
186
205
|
}, ThrowOnError_1>>;
|
|
187
206
|
};
|
|
188
207
|
flushCache: () => Promise<void>;
|
|
@@ -195,40 +214,43 @@ declare const createApiClientBase: <ThrowOnError extends boolean = false, Inline
|
|
|
195
214
|
interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions<"fields", boolean, string>>;
|
|
196
215
|
links: {
|
|
197
216
|
list: <ThrowOnError_1 extends boolean = ThrowOnError>(options?: {
|
|
198
|
-
query?:
|
|
217
|
+
query?: ListLinksData["query"];
|
|
199
218
|
signal?: AbortSignal;
|
|
200
219
|
throwOnError?: ThrowOnError_1 | undefined;
|
|
201
220
|
fetchOptions?: FetchOptions;
|
|
202
221
|
}) => Promise<ApiResponse<{
|
|
203
222
|
links: {
|
|
204
|
-
[key: string]:
|
|
223
|
+
[key: string]: Link;
|
|
205
224
|
};
|
|
206
|
-
cv?: number;
|
|
207
225
|
}, ThrowOnError_1>>;
|
|
208
226
|
};
|
|
209
227
|
spaces: {
|
|
210
228
|
get: <ThrowOnError_1 extends boolean = ThrowOnError>(options?: {
|
|
229
|
+
query?: GetSpaceData["query"];
|
|
211
230
|
signal?: AbortSignal;
|
|
212
231
|
throwOnError?: ThrowOnError_1 | undefined;
|
|
213
232
|
fetchOptions?: FetchOptions;
|
|
214
233
|
}) => Promise<ApiResponse<{
|
|
215
|
-
space:
|
|
234
|
+
space: PublicSpace;
|
|
216
235
|
}, ThrowOnError_1>>;
|
|
217
236
|
};
|
|
218
237
|
stories: {
|
|
219
|
-
get: <ThrowOnError_1 extends boolean = ThrowOnError, const ResolveRelationsStr extends string | undefined = undefined>(identifier: string
|
|
238
|
+
get: <ThrowOnError_1 extends boolean = ThrowOnError, const ResolveRelationsStr extends string | undefined = undefined>(identifier: string, options?: {
|
|
220
239
|
query?: (Omit<{
|
|
221
|
-
find_by?:
|
|
222
|
-
version?: "
|
|
223
|
-
cv?: number;
|
|
224
|
-
from_release?: string;
|
|
240
|
+
find_by?: string;
|
|
241
|
+
version?: "draft" | "published";
|
|
225
242
|
resolve_links?: "story" | "url" | "link";
|
|
226
243
|
resolve_links_level?: 1 | 2;
|
|
227
244
|
resolve_relations?: string;
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
245
|
+
from_release?: string;
|
|
246
|
+
content_type?: string;
|
|
247
|
+
cv?: number;
|
|
248
|
+
excluding_fields?: string;
|
|
231
249
|
language?: string;
|
|
250
|
+
fallback_lang?: string;
|
|
251
|
+
resolve_assets?: number;
|
|
252
|
+
resolve_level?: 2;
|
|
253
|
+
param_with_null_char?: string;
|
|
232
254
|
}, "resolve_relations"> & {
|
|
233
255
|
resolve_relations?: ResolveRelationsStr | undefined;
|
|
234
256
|
}) | undefined;
|
|
@@ -236,52 +258,177 @@ declare const createApiClientBase: <ThrowOnError extends boolean = false, Inline
|
|
|
236
258
|
throwOnError?: ThrowOnError_1 | undefined;
|
|
237
259
|
fetchOptions?: FetchOptions;
|
|
238
260
|
}) => Promise<ApiResponse<Omit<{
|
|
239
|
-
story:
|
|
240
|
-
cv
|
|
241
|
-
rels?: Array<
|
|
242
|
-
links?: Array<
|
|
243
|
-
[key: string]: unknown;
|
|
244
|
-
}>;
|
|
261
|
+
story: Story;
|
|
262
|
+
cv: number;
|
|
263
|
+
rels?: Array<Story>;
|
|
264
|
+
links?: Array<LinkWithFullSlug | Link | Story>;
|
|
245
265
|
rel_uuids?: Array<string>;
|
|
246
266
|
link_uuids?: Array<string>;
|
|
247
267
|
}, "story"> & {
|
|
248
|
-
story: InlineRelations extends true ? StoryWithInlinedRelations :
|
|
268
|
+
story: InlineRelations extends true ? StoryWithInlinedRelations : {
|
|
269
|
+
path: string | null;
|
|
270
|
+
id: number;
|
|
271
|
+
name: string;
|
|
272
|
+
created_at: string;
|
|
273
|
+
updated_at?: string | null | undefined;
|
|
274
|
+
version?: "draft" | "published" | undefined;
|
|
275
|
+
is_startpage: boolean;
|
|
276
|
+
published_at: string | null;
|
|
277
|
+
alternates: Array<StoryAlternate>;
|
|
278
|
+
uuid: string;
|
|
279
|
+
slug: string;
|
|
280
|
+
full_slug: string;
|
|
281
|
+
default_full_slug: string | null;
|
|
282
|
+
sort_by_date: string | null;
|
|
283
|
+
position: number;
|
|
284
|
+
tag_list: Array<string>;
|
|
285
|
+
parent_id: number;
|
|
286
|
+
meta_data: {
|
|
287
|
+
[key: string]: unknown;
|
|
288
|
+
} | {
|
|
289
|
+
[key: string]: unknown;
|
|
290
|
+
} | null;
|
|
291
|
+
group_id: string;
|
|
292
|
+
first_published_at: string | null;
|
|
293
|
+
release_id?: number | null | undefined;
|
|
294
|
+
lang: string;
|
|
295
|
+
translated_slugs: {
|
|
296
|
+
path: string;
|
|
297
|
+
name: string | null;
|
|
298
|
+
lang: string;
|
|
299
|
+
published: string | null;
|
|
300
|
+
}[] | {
|
|
301
|
+
path: string;
|
|
302
|
+
name: string | null;
|
|
303
|
+
lang: string;
|
|
304
|
+
published: string | null;
|
|
305
|
+
}[] | null;
|
|
306
|
+
content: {
|
|
307
|
+
[x: string]: string | number | boolean | string[] | {
|
|
308
|
+
type: "doc";
|
|
309
|
+
content?: Array<{
|
|
310
|
+
[key: string]: unknown;
|
|
311
|
+
}> | undefined;
|
|
312
|
+
} | {
|
|
313
|
+
fieldtype: "asset";
|
|
314
|
+
id: number | null;
|
|
315
|
+
alt: string | null;
|
|
316
|
+
name?: string | undefined;
|
|
317
|
+
focus?: string | null | undefined;
|
|
318
|
+
title?: string | null | undefined;
|
|
319
|
+
source?: string | null | undefined;
|
|
320
|
+
filename: string;
|
|
321
|
+
copyright?: string | null | undefined;
|
|
322
|
+
meta_data?: {
|
|
323
|
+
[key: string]: unknown;
|
|
324
|
+
} | undefined;
|
|
325
|
+
is_external_url?: boolean | undefined;
|
|
326
|
+
} | AssetFieldValueRoot[] | {
|
|
327
|
+
fieldtype: "multilink";
|
|
328
|
+
id: string;
|
|
329
|
+
url: string;
|
|
330
|
+
linktype: "story" | "url" | "email" | "asset";
|
|
331
|
+
cached_url: string;
|
|
332
|
+
anchor?: string | null | undefined;
|
|
333
|
+
target?: "_self" | "_blank" | null | undefined;
|
|
334
|
+
} | BlockContentRoot[] | {
|
|
335
|
+
thead: Array<{
|
|
336
|
+
_uid: string;
|
|
337
|
+
component: "_table_head";
|
|
338
|
+
value?: string;
|
|
339
|
+
}>;
|
|
340
|
+
tbody: Array<{
|
|
341
|
+
_uid: string;
|
|
342
|
+
component: "_table_row";
|
|
343
|
+
body?: Array<{
|
|
344
|
+
_uid: string;
|
|
345
|
+
component: "_table_col";
|
|
346
|
+
value?: string;
|
|
347
|
+
}>;
|
|
348
|
+
}>;
|
|
349
|
+
} | {
|
|
350
|
+
[x: string]: unknown;
|
|
351
|
+
plugin: string;
|
|
352
|
+
_uid?: string | undefined;
|
|
353
|
+
} | null | undefined;
|
|
354
|
+
_uid: string;
|
|
355
|
+
component: string;
|
|
356
|
+
_editable?: string | undefined;
|
|
357
|
+
};
|
|
358
|
+
};
|
|
249
359
|
}, ThrowOnError_1>>;
|
|
250
360
|
list: <ThrowOnError_1 extends boolean = ThrowOnError, const ResolveRelationsStr_1 extends string | undefined = undefined>(options?: {
|
|
251
361
|
query?: (Omit<{
|
|
252
|
-
version?: "
|
|
362
|
+
version?: "draft" | "published";
|
|
253
363
|
cv?: number;
|
|
254
364
|
starts_with?: string;
|
|
255
|
-
from_release?: string;
|
|
256
365
|
search_term?: string;
|
|
366
|
+
sort_by?: string;
|
|
257
367
|
per_page?: number;
|
|
258
368
|
page?: number;
|
|
259
|
-
resolve_links?: "story" | "url" | "link";
|
|
260
|
-
resolve_links_level?: 1 | 2;
|
|
261
|
-
resolve_relations?: string;
|
|
262
|
-
resolve_level?: 2;
|
|
263
|
-
resolve_assets?: 0 | 1;
|
|
264
|
-
fallback_lang?: string;
|
|
265
|
-
language?: string;
|
|
266
|
-
content_type?: string;
|
|
267
369
|
by_slugs?: string;
|
|
268
370
|
excluding_slugs?: string;
|
|
269
|
-
by_uuids?: string;
|
|
270
|
-
by_uuids_ordered?: string;
|
|
271
|
-
excluding_ids?: string;
|
|
272
|
-
with_tag?: string;
|
|
273
|
-
sort_by?: string;
|
|
274
|
-
in_workflow_stages?: string;
|
|
275
|
-
filter_query?: string;
|
|
276
|
-
level?: number;
|
|
277
|
-
is_startpage?: 0 | 1;
|
|
278
|
-
first_published_at_gt?: string;
|
|
279
|
-
first_published_at_lt?: string;
|
|
280
371
|
published_at_gt?: string;
|
|
372
|
+
published_at_gte?: string;
|
|
281
373
|
published_at_lt?: string;
|
|
374
|
+
published_at_lte?: string;
|
|
375
|
+
first_published_at_gt?: string;
|
|
376
|
+
first_published_at_gte?: string;
|
|
377
|
+
first_published_at_lt?: string;
|
|
378
|
+
first_published_at_lte?: string;
|
|
282
379
|
updated_at_gt?: string;
|
|
380
|
+
updated_at_gte?: string;
|
|
283
381
|
updated_at_lt?: string;
|
|
382
|
+
updated_at_lte?: string;
|
|
383
|
+
in_workflow_stages?: string;
|
|
384
|
+
content_type?: string;
|
|
385
|
+
level?: number;
|
|
386
|
+
resolve_relations?: string;
|
|
387
|
+
excluding_ids?: string;
|
|
388
|
+
by_uuids?: string;
|
|
389
|
+
by_uuids_ordered?: string;
|
|
390
|
+
by_ids?: string;
|
|
391
|
+
with_tag?: string;
|
|
392
|
+
is_startpage?: 0 | 1;
|
|
393
|
+
resolve_links?: "story" | "url" | "link";
|
|
394
|
+
resolve_links_level?: 1 | 2;
|
|
395
|
+
from_release?: string;
|
|
396
|
+
fallback_lang?: string;
|
|
397
|
+
language?: string;
|
|
398
|
+
filter_query?: {
|
|
399
|
+
__or?: Array<{
|
|
400
|
+
[key: string]: {
|
|
401
|
+
[key: string]: string;
|
|
402
|
+
};
|
|
403
|
+
}>;
|
|
404
|
+
[key: string]: {
|
|
405
|
+
in?: string;
|
|
406
|
+
not_in?: string;
|
|
407
|
+
like?: string;
|
|
408
|
+
not_like?: string;
|
|
409
|
+
exists?: string;
|
|
410
|
+
in_array?: Array<string> | string;
|
|
411
|
+
all_in_array?: Array<string> | string;
|
|
412
|
+
gt_date?: string;
|
|
413
|
+
lt_date?: string;
|
|
414
|
+
gt_int?: number;
|
|
415
|
+
lt_int?: number;
|
|
416
|
+
gt_float?: number;
|
|
417
|
+
lt_float?: number;
|
|
418
|
+
is?: "empty" | "not_empty" | "empty_array" | "not_empty_array" | "null" | "not_null" | "true" | "false";
|
|
419
|
+
} | Array<{
|
|
420
|
+
[key: string]: {
|
|
421
|
+
[key: string]: string;
|
|
422
|
+
};
|
|
423
|
+
}> | undefined;
|
|
424
|
+
};
|
|
284
425
|
excluding_fields?: string;
|
|
426
|
+
resolve_assets?: 1;
|
|
427
|
+
resolve_level?: 2;
|
|
428
|
+
only_variants?: "true";
|
|
429
|
+
non_existing_sort_by?: string;
|
|
430
|
+
non_existing_updated_at_gt?: string;
|
|
431
|
+
param_with_null_char?: string;
|
|
285
432
|
}, "resolve_relations"> & {
|
|
286
433
|
resolve_relations?: ResolveRelationsStr_1 | undefined;
|
|
287
434
|
}) | undefined;
|
|
@@ -289,27 +436,114 @@ declare const createApiClientBase: <ThrowOnError extends boolean = false, Inline
|
|
|
289
436
|
throwOnError?: ThrowOnError_1 | undefined;
|
|
290
437
|
fetchOptions?: FetchOptions;
|
|
291
438
|
}) => Promise<ApiResponse<Omit<{
|
|
292
|
-
stories: Array<
|
|
293
|
-
cv
|
|
294
|
-
rels?: Array<
|
|
295
|
-
links?: Array<
|
|
296
|
-
[key: string]: unknown;
|
|
297
|
-
}>;
|
|
439
|
+
stories: Array<Story>;
|
|
440
|
+
cv: number;
|
|
441
|
+
rels?: Array<Story>;
|
|
442
|
+
links?: Array<LinkWithFullSlug | Link | Story>;
|
|
298
443
|
rel_uuids?: Array<string>;
|
|
299
444
|
link_uuids?: Array<string>;
|
|
300
445
|
}, "stories"> & {
|
|
301
|
-
stories: (InlineRelations extends true ? StoryWithInlinedRelations :
|
|
446
|
+
stories: (InlineRelations extends true ? StoryWithInlinedRelations : {
|
|
447
|
+
path: string | null;
|
|
448
|
+
id: number;
|
|
449
|
+
name: string;
|
|
450
|
+
created_at: string;
|
|
451
|
+
updated_at?: string | null | undefined;
|
|
452
|
+
version?: "draft" | "published" | undefined;
|
|
453
|
+
is_startpage: boolean;
|
|
454
|
+
published_at: string | null;
|
|
455
|
+
alternates: Array<StoryAlternate>;
|
|
456
|
+
uuid: string;
|
|
457
|
+
slug: string;
|
|
458
|
+
full_slug: string;
|
|
459
|
+
default_full_slug: string | null;
|
|
460
|
+
sort_by_date: string | null;
|
|
461
|
+
position: number;
|
|
462
|
+
tag_list: Array<string>;
|
|
463
|
+
parent_id: number;
|
|
464
|
+
meta_data: {
|
|
465
|
+
[key: string]: unknown;
|
|
466
|
+
} | {
|
|
467
|
+
[key: string]: unknown;
|
|
468
|
+
} | null;
|
|
469
|
+
group_id: string;
|
|
470
|
+
first_published_at: string | null;
|
|
471
|
+
release_id?: number | null | undefined;
|
|
472
|
+
lang: string;
|
|
473
|
+
translated_slugs: {
|
|
474
|
+
path: string;
|
|
475
|
+
name: string | null;
|
|
476
|
+
lang: string;
|
|
477
|
+
published: string | null;
|
|
478
|
+
}[] | {
|
|
479
|
+
path: string;
|
|
480
|
+
name: string | null;
|
|
481
|
+
lang: string;
|
|
482
|
+
published: string | null;
|
|
483
|
+
}[] | null;
|
|
484
|
+
content: {
|
|
485
|
+
[x: string]: string | number | boolean | string[] | {
|
|
486
|
+
type: "doc";
|
|
487
|
+
content?: Array<{
|
|
488
|
+
[key: string]: unknown;
|
|
489
|
+
}> | undefined;
|
|
490
|
+
} | {
|
|
491
|
+
fieldtype: "asset";
|
|
492
|
+
id: number | null;
|
|
493
|
+
alt: string | null;
|
|
494
|
+
name?: string | undefined;
|
|
495
|
+
focus?: string | null | undefined;
|
|
496
|
+
title?: string | null | undefined;
|
|
497
|
+
source?: string | null | undefined;
|
|
498
|
+
filename: string;
|
|
499
|
+
copyright?: string | null | undefined;
|
|
500
|
+
meta_data?: {
|
|
501
|
+
[key: string]: unknown;
|
|
502
|
+
} | undefined;
|
|
503
|
+
is_external_url?: boolean | undefined;
|
|
504
|
+
} | AssetFieldValueRoot[] | {
|
|
505
|
+
fieldtype: "multilink";
|
|
506
|
+
id: string;
|
|
507
|
+
url: string;
|
|
508
|
+
linktype: "story" | "url" | "email" | "asset";
|
|
509
|
+
cached_url: string;
|
|
510
|
+
anchor?: string | null | undefined;
|
|
511
|
+
target?: "_self" | "_blank" | null | undefined;
|
|
512
|
+
} | BlockContentRoot[] | {
|
|
513
|
+
thead: Array<{
|
|
514
|
+
_uid: string;
|
|
515
|
+
component: "_table_head";
|
|
516
|
+
value?: string;
|
|
517
|
+
}>;
|
|
518
|
+
tbody: Array<{
|
|
519
|
+
_uid: string;
|
|
520
|
+
component: "_table_row";
|
|
521
|
+
body?: Array<{
|
|
522
|
+
_uid: string;
|
|
523
|
+
component: "_table_col";
|
|
524
|
+
value?: string;
|
|
525
|
+
}>;
|
|
526
|
+
}>;
|
|
527
|
+
} | {
|
|
528
|
+
[x: string]: unknown;
|
|
529
|
+
plugin: string;
|
|
530
|
+
_uid?: string | undefined;
|
|
531
|
+
} | null | undefined;
|
|
532
|
+
_uid: string;
|
|
533
|
+
component: string;
|
|
534
|
+
_editable?: string | undefined;
|
|
535
|
+
};
|
|
536
|
+
})[];
|
|
302
537
|
}, ThrowOnError_1>>;
|
|
303
538
|
};
|
|
304
539
|
tags: {
|
|
305
540
|
list: <ThrowOnError_1 extends boolean = ThrowOnError>(options?: {
|
|
306
|
-
query?:
|
|
541
|
+
query?: ListTagsData["query"];
|
|
307
542
|
signal?: AbortSignal;
|
|
308
543
|
throwOnError?: ThrowOnError_1 | undefined;
|
|
309
544
|
fetchOptions?: FetchOptions;
|
|
310
545
|
}) => Promise<ApiResponse<{
|
|
311
|
-
tags: Array<
|
|
312
|
-
cv?: number;
|
|
546
|
+
tags: Array<Tag>;
|
|
313
547
|
}, ThrowOnError_1>>;
|
|
314
548
|
};
|
|
315
549
|
};
|
package/dist/client.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createConfig } from "./generated/
|
|
2
|
-
import { createClient } from "./generated/
|
|
3
|
-
import "./generated/
|
|
1
|
+
import { createConfig } from "./generated/capi/client/utils.gen.mjs";
|
|
2
|
+
import { createClient } from "./generated/capi/client/client.gen.mjs";
|
|
3
|
+
import "./generated/capi/client/index.mjs";
|
|
4
4
|
import { createMemoryCacheProvider, createStrategy } from "./utils/cache.mjs";
|
|
5
5
|
import { ClientError } from "./error.mjs";
|
|
6
6
|
import { createThrottleManager } from "./utils/rate-limit.mjs";
|
|
@@ -12,6 +12,7 @@ import { createTagsResource } from "./resources/tags.mjs";
|
|
|
12
12
|
import { createDatasourcesResource } from "./resources/datasources.mjs";
|
|
13
13
|
import { createDatasourceEntriesResource } from "./resources/datasource-entries.mjs";
|
|
14
14
|
import { createSpacesResource } from "./resources/spaces.mjs";
|
|
15
|
+
import { createExperimentsResource } from "./resources/experiments.mjs";
|
|
15
16
|
import { getRegionBaseUrl } from "@storyblok/region-helper";
|
|
16
17
|
|
|
17
18
|
//#region src/client.ts
|
|
@@ -29,6 +30,7 @@ const createApiClientBase = (config) => {
|
|
|
29
30
|
const strategy = cache.strategy ? typeof cache.strategy === "string" ? createStrategy(cache.strategy, swrOptions) : cache.strategy : createStrategy("cache-first");
|
|
30
31
|
const cacheTtlMs = cache.ttlMs ?? 6e4;
|
|
31
32
|
const cacheFlush = cache.flush ?? "auto";
|
|
33
|
+
const cvMode = cache.cv ?? "auto";
|
|
32
34
|
let currentCv;
|
|
33
35
|
const client = createClient(createConfig({
|
|
34
36
|
auth: accessToken,
|
|
@@ -84,7 +86,7 @@ const createApiClientBase = (config) => {
|
|
|
84
86
|
*/
|
|
85
87
|
const asApiResponse = (p) => p;
|
|
86
88
|
const requestWithCache = async (method, path, rawQuery, fetchFn, cacheOptions) => {
|
|
87
|
-
const query = currentCv !== void 0 ? applyCvToQuery(rawQuery, currentCv) : rawQuery;
|
|
89
|
+
const query = cvMode === "auto" && currentCv !== void 0 ? applyCvToQuery(rawQuery, currentCv) : rawQuery;
|
|
88
90
|
if (!shouldUseCache(method, path, rawQuery)) {
|
|
89
91
|
const networkResult = await fetchFn(query);
|
|
90
92
|
throttleManager.adaptToResponse(networkResult.response);
|
|
@@ -137,6 +139,7 @@ const createApiClientBase = (config) => {
|
|
|
137
139
|
return {
|
|
138
140
|
datasourceEntries: createDatasourceEntriesResource(resourceDeps),
|
|
139
141
|
datasources: createDatasourcesResource(resourceDeps),
|
|
142
|
+
experiments: createExperimentsResource(resourceDeps),
|
|
140
143
|
flushCache,
|
|
141
144
|
get: getRequest,
|
|
142
145
|
interceptors: client.interceptors,
|
package/dist/client.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import { createClient, createConfig } from './generated/shared/client';\nimport type { CacheProvider, CacheStrategy, CacheStrategyHandler } from './utils/cache';\nimport { createMemoryCacheProvider, createStrategy } from './utils/cache';\nimport { ClientError } from './error';\nimport type { RateLimitConfig, ThrottleManager } from './utils/rate-limit';\nimport { createThrottleManager } from './utils/rate-limit';\nimport { applyCvToQuery, extractCv } from './utils/cv';\nimport { createCacheKey, shouldUseCache } from './utils/request';\nimport { getRegionBaseUrl, type Region } from '@storyblok/region-helper';\nimport type { Block as Component } from '@storyblok/schema';\nimport type { RetryOptions } from 'ky';\nimport type { Client, RequestOptions } from './generated/shared/client';\nimport { createStoriesResource } from './resources/stories';\nimport { createLinksResource } from './resources/links';\nimport { createTagsResource } from './resources/tags';\nimport { createDatasourcesResource } from './resources/datasources';\nimport { createDatasourceEntriesResource } from './resources/datasource-entries';\nimport { createSpacesResource } from './resources/spaces';\n\n// ---------------------------------------------------------------------------\n// Client types (co-located with runtime)\n// ---------------------------------------------------------------------------\n\nexport type ApiResponse<Data = unknown, ThrowOnError extends boolean = false> =\n ThrowOnError extends true\n ? { data: Data; error?: never; response: Response; request: Request }\n : { data?: Data; error?: ClientError; response: Response; request: Request };\n\nexport type HttpRequestOptions = Omit<\n RequestOptions,\n 'method' | 'security' | 'url'\n>;\n\nexport type HttpRequestMethod = <TData = unknown>(\n path: string,\n options?: HttpRequestOptions,\n) => Promise<ApiResponse<TData>>;\n\n/**\n * Arbitrary options forwarded to the underlying `fetch()` call.\n *\n * Standard `RequestInit` properties (`cache`, `credentials`, `mode`, …) and\n * non-standard, vendor-specific properties (Next.js `next`, Cloudflare `cf`, …)\n * are both supported.\n *\n * @example\n * ```ts\n * client.stories.get('home', {\n * fetchOptions: {\n * cache: 'no-store',\n * next: { revalidate: 60, tags: ['home'] },\n * },\n * })\n * ```\n */\nexport type FetchOptions = Record<string, unknown>;\n\nexport interface RequestWithCacheOptions {\n /** Prefix added to the cache key to namespace entries (e.g. `'inline'`). */\n cacheKeyPrefix?: string;\n}\n\nexport interface ResourceDeps<DefaultThrowOnError extends boolean = false> {\n client: Client;\n requestWithCache: <TData, ThrowOnError extends boolean = DefaultThrowOnError>(\n method: 'GET',\n path: string,\n rawQuery: Record<string, unknown>,\n fetchFn: (query: Record<string, unknown>) => Promise<ApiResponse<TData, ThrowOnError>>,\n options?: RequestWithCacheOptions,\n ) => Promise<ApiResponse<TData, ThrowOnError>>;\n asApiResponse: <TData, ThrowOnError extends boolean = DefaultThrowOnError>(p: Promise<unknown>) => Promise<ApiResponse<TData, ThrowOnError>>;\n throttleManager: ThrottleManager;\n}\n\n// ---------------------------------------------------------------------------\n// Config types\n// ---------------------------------------------------------------------------\n\n/**\n * Cache configuration.\n *\n * **Note:** Requests with `version: 'draft'` always bypass the cache regardless\n * of the configured strategy. Only published content is cached.\n */\nexport interface CacheConfig {\n /** Custom cache provider. Defaults to an in-memory LRU cache (1 000 entries). */\n provider?: CacheProvider;\n /** Cache strategy for published requests. @default 'cache-first' */\n strategy?: CacheStrategy | CacheStrategyHandler;\n /** Time-to-live in milliseconds for cached entries. @default 60_000 */\n ttlMs?: number;\n /**\n * Controls when the cache is flushed on cv change.\n *\n * - `'auto'` (default): automatically flush the cache whenever the API returns a new cv value.\n * - `'manual'`: never auto-flush; call `client.flushCache()` explicitly (e.g. on webhook trigger).\n */\n flush?: 'auto' | 'manual';\n /**\n * Called when SWR background revalidation fails.\n * Only relevant when `strategy` is `'swr'`.\n * @default console.warn\n */\n onRevalidationError?: (error: unknown) => void;\n}\n\nexport interface ContentApiClientConfig<\n ThrowOnError extends boolean = false,\n InlineRelations extends boolean = false,\n> {\n accessToken: string;\n region?: Region;\n baseUrl?: string;\n headers?: Record<string, string>;\n throwOnError?: ThrowOnError;\n cache?: CacheConfig;\n inlineRelations?: InlineRelations;\n retry?: RetryOptions;\n /**\n * Request timeout in milliseconds.\n * @default 30_000\n */\n timeout?: number;\n /**\n * Preventive rate limiting to avoid hitting the Storyblok CDN rate limits.\n *\n * - `undefined` (default): auto-detect tier from path + `per_page` query param.\n * - `number`: fixed max concurrent requests per second (single queue).\n * - `{ maxConcurrency?: number; adaptToServerHeaders?: boolean }`: full config.\n * - `false`: disable rate limiting entirely.\n */\n rateLimit?: RateLimitConfig | number | false;\n /**\n * Custom `fetch` function to use for all requests.\n * Must be fully compatible with the Fetch API standard.\n *\n * Use cases:\n * - SSR framework fetch wrappers (e.g., Next.js `fetch` with caching)\n * - Custom instrumentation or logging around requests\n *\n * @default globalThis.fetch\n */\n fetch?: typeof globalThis.fetch;\n}\n\ntype StoryblokTypesConfig = { components: Component } | { blocks: Component };\n\ntype ResolveComponents<T extends StoryblokTypesConfig> =\n T extends { components: infer C extends Component } ? C\n : T extends { blocks: infer B extends Component } ? B\n : never;\n\n/**\n * The return type of `createApiClient`, parameterised by `TComponents` and `InlineRelations`\n * so that `.withTypes<T>()` can change the story response types without touching the\n * runtime object.\n */\nexport type ContentApiClient<\n TComponents extends Component = Component,\n InlineRelations extends boolean = false,\n ThrowOnError extends boolean = false,\n> = Omit<ReturnType<typeof createApiClientBase>, 'stories' | 'withTypes'> & {\n stories: ReturnType<typeof createStoriesResource<TComponents, InlineRelations, ThrowOnError>>;\n /**\n * Returns the same client instance cast to a version that narrows story content\n * to the provided component types. No runtime cost — the type parameter is erased.\n *\n * Accepts either `{ components: ... }` or `{ blocks: ... }` — the latter matches the\n * `Schema` type produced by `@storyblok/schema`'s `InferSchema`.\n *\n * @example\n * ```ts\n * import type { Schema } from './schema';\n *\n * const client = createApiClient({ accessToken: 'your-token' })\n * .withTypes<Schema>();\n * // story.content is now typed as a discriminated union\n * ```\n */\n withTypes: <T extends StoryblokTypesConfig>() => ContentApiClient<ResolveComponents<T>, InlineRelations, ThrowOnError>;\n};\n\n// ---------------------------------------------------------------------------\n// Client factory\n// ---------------------------------------------------------------------------\n\nexport const createApiClientBase = <\n ThrowOnError extends boolean = false,\n InlineRelations extends boolean = false,\n>(\n config: ContentApiClientConfig<ThrowOnError, InlineRelations>,\n) => {\n const {\n accessToken,\n region = 'eu',\n baseUrl,\n headers = {},\n throwOnError = false,\n cache = {},\n inlineRelations = false,\n retry,\n timeout = 30_000,\n rateLimit,\n fetch: customFetch,\n } = config;\n const retryOptions: RetryOptions = { limit: 3, backoffLimit: 20_000, jitter: true, ...retry };\n // `rateLimit` defaults to `{}` (auto-detect mode) when not supplied.\n const throttleManager = createThrottleManager(rateLimit ?? {});\n const cacheProvider = cache.provider ?? createMemoryCacheProvider();\n const swrOptions = cache.onRevalidationError ? { onRevalidationError: cache.onRevalidationError } : undefined;\n const strategy = cache.strategy\n ? typeof cache.strategy === 'string'\n ? createStrategy(cache.strategy, swrOptions)\n : cache.strategy\n : createStrategy('cache-first');\n const cacheTtlMs = cache.ttlMs ?? 60_000;\n const cacheFlush = cache.flush ?? 'auto';\n let currentCv: number | undefined;\n\n const client: Client = createClient(\n createConfig({\n auth: accessToken,\n baseUrl: baseUrl || getRegionBaseUrl(region),\n headers,\n throwOnError,\n kyOptions: {\n // Enable `throwHttpErrors` to make retry work, even if `throwOnError`\n // is `false`. The client's error handling will still work because it\n // catches `HTTPError`.\n throwHttpErrors: true,\n timeout,\n retry: retryOptions,\n ...(customFetch && { fetch: customFetch }),\n },\n }),\n );\n\n client.interceptors.error.use(\n (error: unknown, response: Response) =>\n new ClientError(response?.statusText || 'API request failed', {\n status: response?.status ?? 0,\n statusText: response?.statusText ?? '',\n data: error,\n }),\n );\n\n const security = [\n {\n in: 'query' as const,\n name: 'token',\n type: 'apiKey' as const,\n },\n ];\n\n const updateCv = async (result: ApiResponse): Promise<boolean> => {\n const nextCv = extractCv(result.data);\n if (nextCv === undefined) {\n return true;\n }\n\n // Guard against cv regression: SWR background revalidation may carry a\n // stale cv from a prior request; never move cv backward.\n if (currentCv !== undefined && nextCv < currentCv) {\n return false;\n }\n\n if (cacheFlush === 'auto' && currentCv !== undefined && currentCv !== nextCv) {\n await cacheProvider.flush();\n }\n\n currentCv = nextCv;\n return true;\n };\n\n const cacheSuccessResult = async <TResponse extends ApiResponse>(key: string, result: TResponse) => {\n const shouldCacheResult = await updateCv(result);\n if (result.error === undefined && shouldCacheResult) {\n await cacheProvider.set(key, {\n value: result,\n ttlMs: cacheTtlMs,\n });\n }\n return result;\n };\n\n const requestNetwork = async (\n method: 'GET',\n path: string,\n query: Record<string, unknown>,\n options: HttpRequestOptions,\n ): Promise<ApiResponse> => {\n return client.request<unknown, ClientError, boolean>({\n ...options,\n method,\n query,\n security,\n url: path,\n });\n };\n\n /**\n * Wraps a raw SDK call to cast the `error: unknown` type returned by\n * generated code to `ClientError` — the error interceptor ensures the\n * runtime value IS a ClientError.\n */\n const asApiResponse = <TData, ThrowOnError extends boolean = false>(\n p: Promise<unknown>,\n ): Promise<ApiResponse<TData, ThrowOnError>> => p as unknown as Promise<ApiResponse<TData, ThrowOnError>>;\n\n const requestWithCache = async <TData = unknown, ThrowOnError extends boolean = false>(\n method: 'GET',\n path: string,\n rawQuery: Record<string, unknown>,\n fetchFn: (query: Record<string, unknown>) => Promise<ApiResponse<TData, ThrowOnError>>,\n cacheOptions?: RequestWithCacheOptions,\n ): Promise<ApiResponse<TData, ThrowOnError>> => {\n const query = currentCv !== undefined ? applyCvToQuery(rawQuery, currentCv) : rawQuery;\n const cacheEnabled = shouldUseCache(method, path, rawQuery);\n\n if (!cacheEnabled) {\n const networkResult = await fetchFn(query);\n throttleManager.adaptToResponse(networkResult.response);\n await updateCv(networkResult);\n return networkResult;\n }\n\n const baseKey = createCacheKey(method, path, rawQuery);\n const key = cacheOptions?.cacheKeyPrefix ? `${cacheOptions.cacheKeyPrefix}:${baseKey}` : baseKey;\n const cachedEntry = await cacheProvider.get<ApiResponse<TData, ThrowOnError>>(key);\n const cachedResult = cachedEntry?.value;\n\n const loadNetwork = async () => {\n const result = await fetchFn(query);\n throttleManager.adaptToResponse(result.response);\n return cacheSuccessResult(key, result);\n };\n\n return strategy({\n key,\n cachedResult,\n loadNetwork,\n });\n };\n\n const request = async (\n method: 'GET',\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse> => {\n const rawQuery = options.query || {};\n\n return requestWithCache(method, path, rawQuery, (query) => {\n return throttleManager.execute(path, rawQuery, () => requestNetwork(method, path, query, options));\n });\n };\n\n const getRequest = (\n path: string,\n options: HttpRequestOptions = {},\n ) => {\n return request('GET', path, options);\n };\n\n const resourceDeps: ResourceDeps<ThrowOnError> = {\n client,\n requestWithCache,\n asApiResponse,\n throttleManager,\n };\n\n const stories = createStoriesResource<Component, InlineRelations, ThrowOnError>({\n ...resourceDeps,\n inlineRelations,\n });\n\n /**\n * Flush the in-memory cache and reset the tracked cv.\n *\n * Call this explicitly when `cache.flush` is set to `'manual'`, e.g. after\n * receiving a Storyblok webhook event that signals content has changed.\n */\n const flushCache = async (): Promise<void> => {\n await cacheProvider.flush();\n currentCv = undefined;\n };\n\n return {\n datasourceEntries: createDatasourceEntriesResource(resourceDeps),\n datasources: createDatasourcesResource(resourceDeps),\n flushCache,\n get: getRequest,\n interceptors: client.interceptors,\n links: createLinksResource(resourceDeps),\n spaces: createSpacesResource(resourceDeps),\n stories,\n tags: createTagsResource(resourceDeps),\n };\n};\n\n/**\n * Creates a Storyblok Content Delivery API client.\n *\n * Use `.withTypes<YourTypes>()` on the returned client to enable discriminated\n * union typing on `story.content` without including any schema values in your bundle.\n *\n * @example\n * ```ts\n * import type { pageBlock, heroBlock } from './blocks';\n *\n * const client = createApiClient({ accessToken: 'your-token' })\n * .withTypes<StoryblokTypes>();\n * ```\n */\nexport const createApiClient = <\n ThrowOnError extends boolean = false,\n InlineRelations extends boolean = false,\n>(\n config: ContentApiClientConfig<ThrowOnError, InlineRelations>,\n): ContentApiClient<Component, InlineRelations, ThrowOnError> => {\n const base = createApiClientBase(config);\n const self: ContentApiClient<Component, InlineRelations, ThrowOnError> = {\n ...base,\n withTypes<T extends StoryblokTypesConfig>(): ContentApiClient<ResolveComponents<T>, InlineRelations, ThrowOnError> {\n return self as unknown as ContentApiClient<ResolveComponents<T>, InlineRelations, ThrowOnError>;\n },\n };\n return self;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AA2LA,MAAa,uBAIX,WACG;CACH,MAAM,EACJ,aACA,SAAS,MACT,SACA,UAAU,EAAE,EACZ,eAAe,OACf,QAAQ,EAAE,EACV,kBAAkB,OAClB,OACA,UAAU,KACV,WACA,OAAO,gBACL;CACJ,MAAM,eAA6B;EAAE,OAAO;EAAG,cAAc;EAAQ,QAAQ;EAAM,GAAG;EAAO;CAE7F,MAAM,kBAAkB,sBAAsB,aAAa,EAAE,CAAC;CAC9D,MAAM,gBAAgB,MAAM,YAAY,2BAA2B;CACnE,MAAM,aAAa,MAAM,sBAAsB,EAAE,qBAAqB,MAAM,qBAAqB,GAAG;CACpG,MAAM,WAAW,MAAM,WACnB,OAAO,MAAM,aAAa,WACxB,eAAe,MAAM,UAAU,WAAW,GAC1C,MAAM,WACR,eAAe,cAAc;CACjC,MAAM,aAAa,MAAM,SAAS;CAClC,MAAM,aAAa,MAAM,SAAS;CAClC,IAAI;CAEJ,MAAM,SAAiB,aACrB,aAAa;EACX,MAAM;EACN,SAAS,WAAW,iBAAiB,OAAO;EAC5C;EACA;EACA,WAAW;GAIT,iBAAiB;GACjB;GACA,OAAO;GACP,GAAI,eAAe,EAAE,OAAO,aAAa;GAC1C;EACF,CAAC,CACH;AAED,QAAO,aAAa,MAAM,KACvB,OAAgB,aACf,IAAI,YAAY,UAAU,cAAc,sBAAsB;EAC5D,QAAQ,UAAU,UAAU;EAC5B,YAAY,UAAU,cAAc;EACpC,MAAM;EACP,CAAC,CACL;CAED,MAAM,WAAW,CACf;EACE,IAAI;EACJ,MAAM;EACN,MAAM;EACP,CACF;CAED,MAAM,WAAW,OAAO,WAA0C;EAChE,MAAM,SAAS,UAAU,OAAO,KAAK;AACrC,MAAI,WAAW,OACb,QAAO;AAKT,MAAI,cAAc,UAAa,SAAS,UACtC,QAAO;AAGT,MAAI,eAAe,UAAU,cAAc,UAAa,cAAc,OACpE,OAAM,cAAc,OAAO;AAG7B,cAAY;AACZ,SAAO;;CAGT,MAAM,qBAAqB,OAAsC,KAAa,WAAsB;EAClG,MAAM,oBAAoB,MAAM,SAAS,OAAO;AAChD,MAAI,OAAO,UAAU,UAAa,kBAChC,OAAM,cAAc,IAAI,KAAK;GAC3B,OAAO;GACP,OAAO;GACR,CAAC;AAEJ,SAAO;;CAGT,MAAM,iBAAiB,OACrB,QACA,MACA,OACA,YACyB;AACzB,SAAO,OAAO,QAAuC;GACnD,GAAG;GACH;GACA;GACA;GACA,KAAK;GACN,CAAC;;;;;;;CAQJ,MAAM,iBACJ,MAC8C;CAEhD,MAAM,mBAAmB,OACvB,QACA,MACA,UACA,SACA,iBAC8C;EAC9C,MAAM,QAAQ,cAAc,SAAY,eAAe,UAAU,UAAU,GAAG;AAG9E,MAAI,CAFiB,eAAe,QAAQ,MAAM,SAAS,EAExC;GACjB,MAAM,gBAAgB,MAAM,QAAQ,MAAM;AAC1C,mBAAgB,gBAAgB,cAAc,SAAS;AACvD,SAAM,SAAS,cAAc;AAC7B,UAAO;;EAGT,MAAM,UAAU,eAAe,QAAQ,MAAM,SAAS;EACtD,MAAM,MAAM,cAAc,iBAAiB,GAAG,aAAa,eAAe,GAAG,YAAY;EAEzF,MAAM,gBADc,MAAM,cAAc,IAAsC,IAAI,GAChD;EAElC,MAAM,cAAc,YAAY;GAC9B,MAAM,SAAS,MAAM,QAAQ,MAAM;AACnC,mBAAgB,gBAAgB,OAAO,SAAS;AAChD,UAAO,mBAAmB,KAAK,OAAO;;AAGxC,SAAO,SAAS;GACd;GACA;GACA;GACD,CAAC;;CAGJ,MAAM,UAAU,OACd,QACA,MACA,UAA8B,EAAE,KACP;EACzB,MAAM,WAAW,QAAQ,SAAS,EAAE;AAEpC,SAAO,iBAAiB,QAAQ,MAAM,WAAW,UAAU;AACzD,UAAO,gBAAgB,QAAQ,MAAM,gBAAgB,eAAe,QAAQ,MAAM,OAAO,QAAQ,CAAC;IAClG;;CAGJ,MAAM,cACJ,MACA,UAA8B,EAAE,KAC7B;AACH,SAAO,QAAQ,OAAO,MAAM,QAAQ;;CAGtC,MAAM,eAA2C;EAC/C;EACA;EACA;EACA;EACD;CAED,MAAM,UAAU,sBAAgE;EAC9E,GAAG;EACH;EACD,CAAC;;;;;;;CAQF,MAAM,aAAa,YAA2B;AAC5C,QAAM,cAAc,OAAO;AAC3B,cAAY;;AAGd,QAAO;EACL,mBAAmB,gCAAgC,aAAa;EAChE,aAAa,0BAA0B,aAAa;EACpD;EACA,KAAK;EACL,cAAc,OAAO;EACrB,OAAO,oBAAoB,aAAa;EACxC,QAAQ,qBAAqB,aAAa;EAC1C;EACA,MAAM,mBAAmB,aAAa;EACvC;;;;;;;;;;;;;;;;AAiBH,MAAa,mBAIX,WAC+D;CAE/D,MAAM,OAAmE;EACvE,GAFW,oBAAoB,OAAO;EAGtC,YAAmH;AACjH,UAAO;;EAEV;AACD,QAAO"}
|
|
1
|
+
{"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import { createClient, createConfig } from './generated/capi/client';\nimport type { CacheProvider, CacheStrategy, CacheStrategyHandler } from './utils/cache';\nimport { createMemoryCacheProvider, createStrategy } from './utils/cache';\nimport { ClientError } from './error';\nimport type { RateLimitConfig, ThrottleManager } from './utils/rate-limit';\nimport { createThrottleManager } from './utils/rate-limit';\nimport { applyCvToQuery, extractCv } from './utils/cv';\nimport { createCacheKey, shouldUseCache } from './utils/request';\nimport { getRegionBaseUrl, type Region } from '@storyblok/region-helper';\nimport type { Block as Component } from './generated/types/block';\nimport type { RetryOptions } from 'ky';\nimport type { Client, RequestOptions } from './generated/capi/client';\nimport { createStoriesResource } from './resources/stories';\nimport { createLinksResource } from './resources/links';\nimport { createTagsResource } from './resources/tags';\nimport { createDatasourcesResource } from './resources/datasources';\nimport { createDatasourceEntriesResource } from './resources/datasource-entries';\nimport { createSpacesResource } from './resources/spaces';\nimport { createExperimentsResource } from './resources/experiments';\n\n// ---------------------------------------------------------------------------\n// Client types (co-located with runtime)\n// ---------------------------------------------------------------------------\n\nexport type ApiResponse<Data = unknown, ThrowOnError extends boolean = false> =\n ThrowOnError extends true\n ? { data: Data; error?: never; response: Response; request: Request }\n : { data?: Data; error?: ClientError; response: Response; request: Request };\n\nexport type HttpRequestOptions = Omit<\n RequestOptions,\n 'method' | 'security' | 'url'\n>;\n\nexport type HttpRequestMethod = <TData = unknown>(\n path: string,\n options?: HttpRequestOptions,\n) => Promise<ApiResponse<TData>>;\n\n/**\n * Arbitrary options forwarded to the underlying `fetch()` call.\n *\n * Standard `RequestInit` properties (`cache`, `credentials`, `mode`, …) and\n * non-standard, vendor-specific properties (Next.js `next`, Cloudflare `cf`, …)\n * are both supported.\n *\n * @example\n * ```ts\n * client.stories.get('home', {\n * fetchOptions: {\n * cache: 'no-store',\n * next: { revalidate: 60, tags: ['home'] },\n * },\n * })\n * ```\n */\nexport type FetchOptions = Record<string, unknown>;\n\nexport interface RequestWithCacheOptions {\n /** Prefix added to the cache key to namespace entries (e.g. `'inline'`). */\n cacheKeyPrefix?: string;\n}\n\nexport interface ResourceDeps<DefaultThrowOnError extends boolean = false> {\n client: Client;\n requestWithCache: <TData, ThrowOnError extends boolean = DefaultThrowOnError>(\n method: 'GET',\n path: string,\n rawQuery: Record<string, unknown>,\n fetchFn: (query: Record<string, unknown>) => Promise<ApiResponse<TData, ThrowOnError>>,\n options?: RequestWithCacheOptions,\n ) => Promise<ApiResponse<TData, ThrowOnError>>;\n asApiResponse: <TData, ThrowOnError extends boolean = DefaultThrowOnError>(p: Promise<unknown>) => Promise<ApiResponse<TData, ThrowOnError>>;\n throttleManager: ThrottleManager;\n}\n\n// ---------------------------------------------------------------------------\n// Config types\n// ---------------------------------------------------------------------------\n\n/**\n * Cache configuration.\n *\n * **Note:** Requests with `version: 'draft'` always bypass the cache regardless\n * of the configured strategy. Only published content is cached.\n */\nexport interface CacheConfig {\n /** Custom cache provider. Defaults to an in-memory LRU cache (1 000 entries). */\n provider?: CacheProvider;\n /** Cache strategy for published requests. @default 'cache-first' */\n strategy?: CacheStrategy | CacheStrategyHandler;\n /** Time-to-live in milliseconds for cached entries. @default 60_000 */\n ttlMs?: number;\n /**\n * Controls how the `cv` (content version) query parameter is managed.\n *\n * - `'auto'` (default): automatically attach the tracked `cv` to\n * subsequent published requests for cache busting.\n * - `'manual'`: do not attach `cv` to outgoing requests. The client still\n * tracks cv internally for cache invalidation (flushing when cv changes),\n * but the query parameter is not sent. Useful for SSR with edge caching\n * where stable URLs are required.\n */\n cv?: 'auto' | 'manual';\n /**\n * Controls when the cache is flushed on cv change.\n *\n * - `'auto'` (default): automatically flush the cache whenever the API returns a new cv value.\n * - `'manual'`: never auto-flush; call `client.flushCache()` explicitly (e.g. on webhook trigger).\n */\n flush?: 'auto' | 'manual';\n /**\n * Called when SWR background revalidation fails.\n * Only relevant when `strategy` is `'swr'`.\n * @default console.warn\n */\n onRevalidationError?: (error: unknown) => void;\n}\n\nexport interface ContentApiClientConfig<\n ThrowOnError extends boolean = false,\n InlineRelations extends boolean = false,\n> {\n accessToken: string;\n region?: Region;\n baseUrl?: string;\n headers?: Record<string, string>;\n throwOnError?: ThrowOnError;\n cache?: CacheConfig;\n inlineRelations?: InlineRelations;\n retry?: RetryOptions;\n /**\n * Request timeout in milliseconds.\n * @default 30_000\n */\n timeout?: number;\n /**\n * Preventive rate limiting to avoid hitting the Storyblok CDN rate limits.\n *\n * - `undefined` (default): auto-detect tier from path + `per_page` query param.\n * - `number`: fixed max concurrent requests per second (single queue).\n * - `{ maxConcurrency?: number; adaptToServerHeaders?: boolean }`: full config.\n * - `false`: disable rate limiting entirely.\n */\n rateLimit?: RateLimitConfig | number | false;\n /**\n * Custom `fetch` function to use for all requests.\n * Must be fully compatible with the Fetch API standard.\n *\n * Use cases:\n * - SSR framework fetch wrappers (e.g., Next.js `fetch` with caching)\n * - Custom instrumentation or logging around requests\n *\n * @default globalThis.fetch\n */\n fetch?: typeof globalThis.fetch;\n}\n\ntype StoryblokTypesConfig = { components: Component } | { blocks: Component };\n\ntype ResolveComponents<T extends StoryblokTypesConfig> =\n T extends { components: infer C extends Component } ? C\n : T extends { blocks: infer B extends Component } ? B\n : never;\n\n/**\n * The return type of `createApiClient`, parameterised by `TComponents` and `InlineRelations`\n * so that `.withTypes<T>()` can change the story response types without touching the\n * runtime object.\n */\nexport type ContentApiClient<\n TComponents extends Component = Component,\n InlineRelations extends boolean = false,\n ThrowOnError extends boolean = false,\n> = Omit<ReturnType<typeof createApiClientBase>, 'stories' | 'withTypes'> & {\n stories: ReturnType<typeof createStoriesResource<TComponents, InlineRelations, ThrowOnError>>;\n /**\n * Returns the same client instance cast to a version that narrows story content\n * to the provided component types. No runtime cost — the type parameter is erased.\n *\n * Accepts either `{ components: ... }` or `{ blocks: ... }` — the latter matches the\n * `Schema` type produced by `@storyblok/schema`'s `InferSchema`.\n *\n * @example\n * ```ts\n * import type { Schema } from './schema';\n *\n * const client = createApiClient({ accessToken: 'your-token' })\n * .withTypes<Schema>();\n * // story.content is now typed as a discriminated union\n * ```\n */\n withTypes: <T extends StoryblokTypesConfig>() => ContentApiClient<ResolveComponents<T>, InlineRelations, ThrowOnError>;\n};\n\n// ---------------------------------------------------------------------------\n// Client factory\n// ---------------------------------------------------------------------------\n\nexport const createApiClientBase = <\n ThrowOnError extends boolean = false,\n InlineRelations extends boolean = false,\n>(\n config: ContentApiClientConfig<ThrowOnError, InlineRelations>,\n) => {\n const {\n accessToken,\n region = 'eu',\n baseUrl,\n headers = {},\n throwOnError = false,\n cache = {},\n inlineRelations = false,\n retry,\n timeout = 30_000,\n rateLimit,\n fetch: customFetch,\n } = config;\n const retryOptions: RetryOptions = { limit: 3, backoffLimit: 20_000, jitter: true, ...retry };\n // `rateLimit` defaults to `{}` (auto-detect mode) when not supplied.\n const throttleManager = createThrottleManager(rateLimit ?? {});\n const cacheProvider = cache.provider ?? createMemoryCacheProvider();\n const swrOptions = cache.onRevalidationError ? { onRevalidationError: cache.onRevalidationError } : undefined;\n const strategy = cache.strategy\n ? typeof cache.strategy === 'string'\n ? createStrategy(cache.strategy, swrOptions)\n : cache.strategy\n : createStrategy('cache-first');\n const cacheTtlMs = cache.ttlMs ?? 60_000;\n const cacheFlush = cache.flush ?? 'auto';\n const cvMode = cache.cv ?? 'auto';\n let currentCv: number | undefined;\n\n const client: Client = createClient(\n createConfig({\n auth: accessToken,\n baseUrl: baseUrl || getRegionBaseUrl(region),\n headers,\n throwOnError,\n kyOptions: {\n // Enable `throwHttpErrors` to make retry work, even if `throwOnError`\n // is `false`. The client's error handling will still work because it\n // catches `HTTPError`.\n throwHttpErrors: true,\n timeout,\n retry: retryOptions,\n ...(customFetch && { fetch: customFetch }),\n },\n }),\n );\n\n client.interceptors.error.use(\n (error: unknown, response: Response) =>\n new ClientError(response?.statusText || 'API request failed', {\n status: response?.status ?? 0,\n statusText: response?.statusText ?? '',\n data: error,\n }),\n );\n\n const security = [\n {\n in: 'query' as const,\n name: 'token',\n type: 'apiKey' as const,\n },\n ];\n\n const updateCv = async (result: ApiResponse): Promise<boolean> => {\n const nextCv = extractCv(result.data);\n if (nextCv === undefined) {\n return true;\n }\n\n // Guard against cv regression: SWR background revalidation may carry a\n // stale cv from a prior request; never move cv backward.\n if (currentCv !== undefined && nextCv < currentCv) {\n return false;\n }\n\n if (cacheFlush === 'auto' && currentCv !== undefined && currentCv !== nextCv) {\n await cacheProvider.flush();\n }\n\n currentCv = nextCv;\n return true;\n };\n\n const cacheSuccessResult = async <TResponse extends ApiResponse>(key: string, result: TResponse) => {\n const shouldCacheResult = await updateCv(result);\n if (result.error === undefined && shouldCacheResult) {\n await cacheProvider.set(key, {\n value: result,\n ttlMs: cacheTtlMs,\n });\n }\n return result;\n };\n\n const requestNetwork = async (\n method: 'GET',\n path: string,\n query: Record<string, unknown>,\n options: HttpRequestOptions,\n ): Promise<ApiResponse> => {\n return client.request<unknown, ClientError, boolean>({\n ...options,\n method,\n query,\n security,\n url: path,\n });\n };\n\n /**\n * Wraps a raw SDK call to cast the `error: unknown` type returned by\n * generated code to `ClientError` — the error interceptor ensures the\n * runtime value IS a ClientError.\n */\n const asApiResponse = <TData, ThrowOnError extends boolean = false>(\n p: Promise<unknown>,\n ): Promise<ApiResponse<TData, ThrowOnError>> => p as unknown as Promise<ApiResponse<TData, ThrowOnError>>;\n\n const requestWithCache = async <TData = unknown, ThrowOnError extends boolean = false>(\n method: 'GET',\n path: string,\n rawQuery: Record<string, unknown>,\n fetchFn: (query: Record<string, unknown>) => Promise<ApiResponse<TData, ThrowOnError>>,\n cacheOptions?: RequestWithCacheOptions,\n ): Promise<ApiResponse<TData, ThrowOnError>> => {\n const query = cvMode === 'auto' && currentCv !== undefined ? applyCvToQuery(rawQuery, currentCv) : rawQuery;\n const cacheEnabled = shouldUseCache(method, path, rawQuery);\n\n if (!cacheEnabled) {\n const networkResult = await fetchFn(query);\n throttleManager.adaptToResponse(networkResult.response);\n await updateCv(networkResult);\n return networkResult;\n }\n\n const baseKey = createCacheKey(method, path, rawQuery);\n const key = cacheOptions?.cacheKeyPrefix ? `${cacheOptions.cacheKeyPrefix}:${baseKey}` : baseKey;\n const cachedEntry = await cacheProvider.get<ApiResponse<TData, ThrowOnError>>(key);\n const cachedResult = cachedEntry?.value;\n\n const loadNetwork = async () => {\n const result = await fetchFn(query);\n throttleManager.adaptToResponse(result.response);\n return cacheSuccessResult(key, result);\n };\n\n return strategy({\n key,\n cachedResult,\n loadNetwork,\n });\n };\n\n const request = async (\n method: 'GET',\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse> => {\n const rawQuery = options.query || {};\n\n return requestWithCache(method, path, rawQuery, (query) => {\n return throttleManager.execute(path, rawQuery, () => requestNetwork(method, path, query, options));\n });\n };\n\n const getRequest = (\n path: string,\n options: HttpRequestOptions = {},\n ) => {\n return request('GET', path, options);\n };\n\n const resourceDeps: ResourceDeps<ThrowOnError> = {\n client,\n requestWithCache,\n asApiResponse,\n throttleManager,\n };\n\n const stories = createStoriesResource<Component, InlineRelations, ThrowOnError>({\n ...resourceDeps,\n inlineRelations,\n });\n\n /**\n * Flush the in-memory cache and reset the tracked cv.\n *\n * Call this explicitly when `cache.flush` is set to `'manual'`, e.g. after\n * receiving a Storyblok webhook event that signals content has changed.\n */\n const flushCache = async (): Promise<void> => {\n await cacheProvider.flush();\n currentCv = undefined;\n };\n\n return {\n datasourceEntries: createDatasourceEntriesResource(resourceDeps),\n datasources: createDatasourcesResource(resourceDeps),\n experiments: createExperimentsResource(resourceDeps),\n flushCache,\n get: getRequest,\n interceptors: client.interceptors,\n links: createLinksResource(resourceDeps),\n spaces: createSpacesResource(resourceDeps),\n stories,\n tags: createTagsResource(resourceDeps),\n };\n};\n\n/**\n * Creates a Storyblok Content Delivery API client.\n *\n * Use `.withTypes<YourTypes>()` on the returned client to enable discriminated\n * union typing on `story.content` without including any schema values in your bundle.\n *\n * @example\n * ```ts\n * import type { pageBlock, heroBlock } from './blocks';\n *\n * const client = createApiClient({ accessToken: 'your-token' })\n * .withTypes<StoryblokTypes>();\n * ```\n */\nexport const createApiClient = <\n ThrowOnError extends boolean = false,\n InlineRelations extends boolean = false,\n>(\n config: ContentApiClientConfig<ThrowOnError, InlineRelations>,\n): ContentApiClient<Component, InlineRelations, ThrowOnError> => {\n const base = createApiClientBase(config);\n const self: ContentApiClient<Component, InlineRelations, ThrowOnError> = {\n ...base,\n withTypes<T extends StoryblokTypesConfig>(): ContentApiClient<ResolveComponents<T>, InlineRelations, ThrowOnError> {\n return self as unknown as ContentApiClient<ResolveComponents<T>, InlineRelations, ThrowOnError>;\n },\n };\n return self;\n};\n"],"mappings":"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"}
|