@b10cks/client 0.10.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/dist/index.d.ts +122 -19
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +218 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ npm install @b10cks/client
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { ApiClient } from '@b10cks/client'
|
|
14
|
+
import { ApiClient, createB10cksDataApi } from '@b10cks/client'
|
|
15
15
|
|
|
16
16
|
const client = new ApiClient(
|
|
17
17
|
{
|
|
@@ -22,28 +22,43 @@ const client = new ApiClient(
|
|
|
22
22
|
new URL(window.location.href)
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
+
const dataApi = createB10cksDataApi(client)
|
|
26
|
+
|
|
25
27
|
// Fetch blocks
|
|
26
|
-
const blocks = await
|
|
28
|
+
const blocks = await dataApi.getBlocks()
|
|
27
29
|
|
|
28
30
|
// Fetch all contents with pagination
|
|
29
|
-
const contents = await
|
|
31
|
+
const contents = await dataApi.getContents()
|
|
30
32
|
|
|
31
33
|
// Fetch specific datasource entries
|
|
32
|
-
const entries = await
|
|
34
|
+
const entries = await dataApi.getDataEntries('my-datasource')
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
## Features
|
|
36
38
|
|
|
37
39
|
- **Simple HTTP Client**: Type-safe API client for b10cks endpoints
|
|
40
|
+
- **Framework-Agnostic Data API**: Shared `B10cksDataApi` used by all framework SDKs
|
|
38
41
|
- **Pagination Support**: Automatic handling of paginated responses
|
|
39
42
|
- **Revision Tracking**: Built-in support for revision (RV) and version (VID) parameters
|
|
40
|
-
- **Flexible Fetch**: Use
|
|
43
|
+
- **Flexible Fetch**: Use browser fetch, Node fetch, or a custom fetch implementation
|
|
41
44
|
|
|
42
45
|
## API Methods
|
|
43
46
|
|
|
44
47
|
- `get<T>(endpoint, params)` - Fetch single page of data
|
|
45
48
|
- `getAll<T>(endpoint, params)` - Fetch all data across pages
|
|
46
49
|
|
|
50
|
+
## Data API Methods
|
|
51
|
+
|
|
52
|
+
- `getContent(fullSlug, params)`
|
|
53
|
+
- `getContents(params)`
|
|
54
|
+
- `getBlocks(params)`
|
|
55
|
+
- `getDataEntries(source, params)`
|
|
56
|
+
- `getDataSources(params)`
|
|
57
|
+
- `getSpace(params)`
|
|
58
|
+
- `getRedirects(params, forceRefresh)`
|
|
59
|
+
- `getConfig(options)`
|
|
60
|
+
- `syncRevision(fallbackRv)`
|
|
61
|
+
|
|
47
62
|
## Supported Endpoints
|
|
48
63
|
|
|
49
64
|
- `blocks` - Content blocks
|
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
export declare class ApiClient {
|
|
2
2
|
private readonly baseUrl;
|
|
3
|
-
|
|
3
|
+
readonly token: string;
|
|
4
4
|
private readonly vid;
|
|
5
5
|
private readonly fetchClient;
|
|
6
6
|
private readonly getRvFn?;
|
|
7
7
|
private readonly setRvFn?;
|
|
8
|
-
constructor(options: B10cksApiClientOptions,
|
|
9
|
-
get<T>(endpoint: Endpoint, params?: Omit<IBBaseQueryParams, 'token'>): Promise<T
|
|
8
|
+
constructor(options: B10cksApiClientOptions, requestUrl?: URL | string);
|
|
9
|
+
get<T>(endpoint: Endpoint, params?: Omit<IBBaseQueryParams, 'token'>): Promise<ApiResourceResponse<T>>;
|
|
10
10
|
getAll<T>(endpoint: Endpoint, params?: Omit<IBBaseQueryParams, 'token'>): Promise<T[]>;
|
|
11
11
|
setRv(value: string | number): void;
|
|
12
12
|
getRv(): string | number;
|
|
13
|
+
private parseResponse;
|
|
14
|
+
private normalizeCollectionResponse;
|
|
13
15
|
private buildUrl;
|
|
16
|
+
private resolveRequestUrl;
|
|
17
|
+
private isFetchResponse;
|
|
18
|
+
private hasRevision;
|
|
19
|
+
private isCollectionResponseEnvelope;
|
|
14
20
|
}
|
|
15
21
|
|
|
22
|
+
declare type ApiQueryParams = Omit<IBBaseQueryParams, 'token'>;
|
|
23
|
+
|
|
24
|
+
declare type ApiResourceResponse<T> = IBResponse<T> | T;
|
|
25
|
+
|
|
16
26
|
export declare interface B10cksApiClientOptions {
|
|
17
27
|
baseUrl: string;
|
|
18
28
|
token: string;
|
|
19
29
|
rv?: string | number;
|
|
20
30
|
version?: 'draft' | 'published';
|
|
21
|
-
fetchClient
|
|
31
|
+
fetchClient?: FetchClient;
|
|
22
32
|
getRv?: () => string | number;
|
|
23
33
|
setRv?: (value: string | number) => void;
|
|
24
34
|
}
|
|
@@ -28,11 +38,75 @@ export declare interface B10cksApiClientRvOptions {
|
|
|
28
38
|
setRv?: (value: string | number) => void;
|
|
29
39
|
}
|
|
30
40
|
|
|
31
|
-
export declare
|
|
41
|
+
export declare class B10cksDataApi {
|
|
42
|
+
private readonly client;
|
|
43
|
+
private redirectsCache;
|
|
44
|
+
private readonly configCache;
|
|
45
|
+
constructor(client: DataApiClient);
|
|
46
|
+
getResource<T>(endpoint: Endpoint, params?: ApiQueryParams): Promise<T>;
|
|
47
|
+
getCollection<T>(endpoint: Endpoint, params?: ApiQueryParams): Promise<T[]>;
|
|
48
|
+
getContent<T = Record<string, unknown>>(fullSlug: string, params?: Omit<IBContentQueryParams, 'token' | 'full_slug'>): Promise<IBContent<T>>;
|
|
49
|
+
getContents<T = Record<string, unknown>>(params?: Omit<IBContentQueryParams, 'token'>): Promise<IBContent<T>[]>;
|
|
50
|
+
getBlocks(params?: ApiQueryParams): Promise<IBBlock[]>;
|
|
51
|
+
getDataEntries(source: string, params?: ApiQueryParams): Promise<IBDataEntry[]>;
|
|
52
|
+
getDataSources(params?: ApiQueryParams): Promise<IBDataSource[]>;
|
|
53
|
+
getSpace(params?: ApiQueryParams): Promise<IBSpace>;
|
|
54
|
+
getRedirects(params?: ApiQueryParams, forceRefresh?: boolean): Promise<RedirectMap>;
|
|
55
|
+
getConfig<T = Record<string, unknown>>({ slug, language_iso, language, bypassCache, ...params }?: GetConfigOptions): Promise<T>;
|
|
56
|
+
syncRevision(fallbackRv?: number): Promise<string | number>;
|
|
57
|
+
clearCache(): void;
|
|
58
|
+
private unwrapResource;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export declare type BridgeEvent = {
|
|
62
|
+
type: EventType;
|
|
63
|
+
payload: EventPayloadMap[EventType];
|
|
64
|
+
b10cksId?: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export declare type ContentUpdateEvent = {
|
|
68
|
+
content: Record<string, unknown>;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export declare function createB10cksDataApi(client: DataApiClient): B10cksDataApi;
|
|
72
|
+
|
|
73
|
+
export declare interface DataApiClient {
|
|
74
|
+
get<T>(endpoint: Endpoint, params?: ApiQueryParams): Promise<T | {
|
|
75
|
+
data: T;
|
|
76
|
+
rv?: string | number;
|
|
77
|
+
}>;
|
|
78
|
+
getAll<T>(endpoint: Endpoint, params?: ApiQueryParams): Promise<T[]>;
|
|
79
|
+
setRv(value: string | number): void;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export declare type Endpoint = 'blocks' | 'contents' | `contents/${string}` | `datasources/${string}/entries` | 'datasources' | 'redirects' | 'spaces/me';
|
|
83
|
+
|
|
84
|
+
declare type EventCallback<T> = (payload: T) => void;
|
|
85
|
+
|
|
86
|
+
export declare type EventPayloadMap = {
|
|
87
|
+
CONTENT_UPDATE: ContentUpdateEvent;
|
|
88
|
+
SELECT_UPDATE: SelectUpdateEvent;
|
|
89
|
+
HOVER_UPDATE: SelectUpdateEvent;
|
|
90
|
+
FIELD_UPDATE: FieldUpdateEvent;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export declare type EventType = 'CONTENT_UPDATE' | 'SELECT_UPDATE' | 'HOVER_UPDATE' | 'FIELD_UPDATE';
|
|
32
94
|
|
|
33
|
-
export declare type FetchClient =
|
|
95
|
+
export declare type FetchClient = (input: URL | string | RequestInfo, init?: RequestInit) => Promise<unknown>;
|
|
34
96
|
|
|
35
|
-
declare
|
|
97
|
+
export declare type FieldUpdateEvent = {
|
|
98
|
+
itemId: string;
|
|
99
|
+
field: string;
|
|
100
|
+
value: string;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export declare interface GetConfigOptions extends Omit<IBContentQueryParams, 'token' | 'full_slug'> {
|
|
104
|
+
slug?: string;
|
|
105
|
+
language?: string;
|
|
106
|
+
bypassCache?: boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export declare interface IBBaseQueryParams extends IBPaginationParams, IBSortParams {
|
|
36
110
|
vid?: string;
|
|
37
111
|
version?: string;
|
|
38
112
|
token: string;
|
|
@@ -48,7 +122,7 @@ export declare interface IBBlock {
|
|
|
48
122
|
updated_at: string;
|
|
49
123
|
}
|
|
50
124
|
|
|
51
|
-
declare interface IBCollectionResponse<T> {
|
|
125
|
+
export declare interface IBCollectionResponse<T> {
|
|
52
126
|
data: T[];
|
|
53
127
|
rv?: string | number;
|
|
54
128
|
links: {
|
|
@@ -75,13 +149,13 @@ export declare interface IBContent<Content = IBContentBlock<string> & {
|
|
|
75
149
|
updated_at: string;
|
|
76
150
|
}
|
|
77
151
|
|
|
78
|
-
declare interface IBContentBlock<T extends string> {
|
|
152
|
+
export declare interface IBContentBlock<T extends string> {
|
|
79
153
|
id?: string;
|
|
80
154
|
block?: T;
|
|
81
155
|
_editable?: string;
|
|
82
156
|
}
|
|
83
157
|
|
|
84
|
-
declare interface IBContentQueryParams extends IBBaseQueryParams {
|
|
158
|
+
export declare interface IBContentQueryParams extends IBBaseQueryParams {
|
|
85
159
|
slug?: string;
|
|
86
160
|
full_slug?: string;
|
|
87
161
|
language_iso?: string;
|
|
@@ -89,7 +163,7 @@ declare interface IBContentQueryParams extends IBBaseQueryParams {
|
|
|
89
163
|
parent_id?: string;
|
|
90
164
|
}
|
|
91
165
|
|
|
92
|
-
declare interface IBContentRelation {
|
|
166
|
+
export declare interface IBContentRelation {
|
|
93
167
|
id: string;
|
|
94
168
|
name: string;
|
|
95
169
|
slug: string;
|
|
@@ -100,14 +174,14 @@ declare interface IBContentRelation {
|
|
|
100
174
|
updated_at: string;
|
|
101
175
|
}
|
|
102
176
|
|
|
103
|
-
declare interface IBDataEntry {
|
|
177
|
+
export declare interface IBDataEntry {
|
|
104
178
|
id: string;
|
|
105
179
|
key: string;
|
|
106
180
|
value: string;
|
|
107
181
|
updated_at: string;
|
|
108
182
|
}
|
|
109
183
|
|
|
110
|
-
declare interface IBDataSource {
|
|
184
|
+
export declare interface IBDataSource {
|
|
111
185
|
id: string;
|
|
112
186
|
name: string;
|
|
113
187
|
slug: string;
|
|
@@ -116,7 +190,7 @@ declare interface IBDataSource {
|
|
|
116
190
|
updated_at: string;
|
|
117
191
|
}
|
|
118
192
|
|
|
119
|
-
declare interface IBMeta {
|
|
193
|
+
export declare interface IBMeta {
|
|
120
194
|
current_page: number;
|
|
121
195
|
from: number;
|
|
122
196
|
last_page: number;
|
|
@@ -127,18 +201,18 @@ declare interface IBMeta {
|
|
|
127
201
|
total: number;
|
|
128
202
|
}
|
|
129
203
|
|
|
130
|
-
declare interface IBMetaLink {
|
|
204
|
+
export declare interface IBMetaLink {
|
|
131
205
|
url: string | null;
|
|
132
206
|
label: string | null;
|
|
133
207
|
active: boolean;
|
|
134
208
|
}
|
|
135
209
|
|
|
136
|
-
declare interface IBPaginationParams {
|
|
210
|
+
export declare interface IBPaginationParams {
|
|
137
211
|
page?: number;
|
|
138
212
|
per_page?: number;
|
|
139
213
|
}
|
|
140
214
|
|
|
141
|
-
declare interface IBRedirect {
|
|
215
|
+
export declare interface IBRedirect {
|
|
142
216
|
source: string;
|
|
143
217
|
target: string;
|
|
144
218
|
status_code: number;
|
|
@@ -149,19 +223,48 @@ export declare interface IBResponse<T> {
|
|
|
149
223
|
rv?: string | number;
|
|
150
224
|
}
|
|
151
225
|
|
|
152
|
-
declare interface IBSortParams {
|
|
226
|
+
export declare interface IBSortParams {
|
|
153
227
|
sort?: string;
|
|
154
228
|
}
|
|
155
229
|
|
|
156
|
-
declare interface IBSpace {
|
|
230
|
+
export declare interface IBSpace {
|
|
157
231
|
id: string;
|
|
158
232
|
name: string;
|
|
159
233
|
rv: string | number;
|
|
160
234
|
updated_at: string;
|
|
161
235
|
}
|
|
162
236
|
|
|
237
|
+
export declare class PreviewBridge {
|
|
238
|
+
private static instance;
|
|
239
|
+
private readonly listeners;
|
|
240
|
+
private initialized;
|
|
241
|
+
private constructor();
|
|
242
|
+
static getInstance(): PreviewBridge;
|
|
243
|
+
init(): void;
|
|
244
|
+
destroy(): void;
|
|
245
|
+
isInPreviewMode(): boolean;
|
|
246
|
+
on<T extends EventType>(eventType: T, callback: EventCallback<EventPayloadMap[T]>): () => void;
|
|
247
|
+
selectItem(selectedItem: string): void;
|
|
248
|
+
updateField(itemId: string, field: string, value: string): void;
|
|
249
|
+
private handleMessage;
|
|
250
|
+
private notify;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export declare const previewBridge: PreviewBridge;
|
|
254
|
+
|
|
255
|
+
export declare type RedirectMap = Record<string, {
|
|
256
|
+
target: string;
|
|
257
|
+
status_code: number;
|
|
258
|
+
}>;
|
|
259
|
+
|
|
260
|
+
export declare type SelectUpdateEvent = {
|
|
261
|
+
selectedItem: string;
|
|
262
|
+
};
|
|
263
|
+
|
|
163
264
|
export declare namespace types {
|
|
164
265
|
export {
|
|
266
|
+
FetchClient,
|
|
267
|
+
Endpoint,
|
|
165
268
|
IBResponse,
|
|
166
269
|
IBCollectionResponse,
|
|
167
270
|
IBMetaLink,
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=Object.freeze(Object.defineProperty({__proto__:null},Symbol.toStringTag,{value:"Module"}));class f{constructor(t){this.client=t}redirectsCache=null;configCache=new Map;async getResource(t,e={}){const s=await this.client.get(t,e);return this.unwrapResource(s)}async getCollection(t,e={}){return this.client.getAll(t,e)}async getContent(t,e={}){return this.getResource(`contents/${t}`,e)}async getContents(t={}){return this.getCollection("contents",t)}async getBlocks(t={}){return this.getCollection("blocks",t)}async getDataEntries(t,e={}){return this.getCollection(`datasources/${t}/entries`,e)}async getDataSources(t={}){return this.getCollection("datasources",t)}async getSpace(t={}){return this.getResource("spaces/me",t)}async getRedirects(t={},e=!1){if(this.redirectsCache&&!e)return this.redirectsCache;const s=await this.getCollection("redirects",t),i=Object.fromEntries(s.map(({source:n,target:o,status_code:r})=>[n,{target:o,status_code:r}]));return this.redirectsCache=i,i}async getConfig({slug:t="_config",language_iso:e,language:s,bypassCache:i=!1,...n}={}){const o=e??s,r=JSON.stringify({slug:t,language_iso:o,...n});if(!i&&this.configCache.has(r))return this.configCache.get(r);const d=(await this.getContent(t,{...n,language_iso:o})).content??{};return i||this.configCache.set(r,d),d}async syncRevision(t=426713400){const s=(await this.getSpace()).rv||t;return this.client.setRv(s),s}clearCache(){this.redirectsCache=null,this.configCache.clear()}unwrapResource(t){return typeof t=="object"&&t!==null&&"data"in t?t.data:t}}function g(c){return new f(c)}class a{static instance;listeners={};initialized=!1;constructor(){}static getInstance(){return a.instance||(a.instance=new a),a.instance}init(){!this.isInPreviewMode()||this.initialized||(window.addEventListener("message",this.handleMessage),this.initialized=!0)}destroy(){this.initialized&&typeof window<"u"&&window.removeEventListener("message",this.handleMessage),this.initialized=!1;for(const t of Object.keys(this.listeners))this.listeners[t]?.clear()}isInPreviewMode(){return typeof window<"u"&&window.self!==window.top}on(t,e){if(!this.isInPreviewMode())return()=>{};const s=this.listeners[t]||new Set;return this.listeners[t]=s,s.add(e),()=>{s.delete(e)}}selectItem(t){this.isInPreviewMode()&&window.parent.postMessage({type:"SELECT_UPDATE",payload:{selectedItem:t}},"*")}updateField(t,e,s){this.isInPreviewMode()&&window.parent.postMessage({type:"FIELD_UPDATE",payload:{itemId:t,field:e,value:s}},"*")}handleMessage=t=>{if(!t.data||typeof t.data!="object")return;const{type:e,payload:s}=t.data;!e||!s||this.notify(e,s)};notify(t,e){const s=this.listeners[t];if(s)for(const i of s)i(e)}}const p=a.getInstance();let l=0;class v{baseUrl;token;vid;fetchClient;getRvFn;setRvFn;constructor(t,e){this.baseUrl=t.baseUrl.endsWith("/")?t.baseUrl.slice(0,-1):t.baseUrl,this.token=t.token;const s=typeof globalThis.fetch=="function"?globalThis.fetch.bind(globalThis):null;if(t.fetchClient)this.fetchClient=t.fetchClient;else if(s)this.fetchClient=s;else throw new Error("No fetch implementation available. Provide `fetchClient` in ApiClient options.");this.getRvFn=t.getRv,this.setRvFn=t.setRv;const i=this.resolveRequestUrl(e);this.vid=i?.searchParams.get("b10cks_vid")||t.version||"published",this.setRv(i?.searchParams.get("b10cks_rv")||t.rv||l)}async get(t,e={}){const s=this.buildUrl(t,{vid:this.vid,...e,rv:this.getRv(),token:this.token}),i=await this.fetchClient(s),n=await this.parseResponse(i);return this.hasRevision(n)&&this.setRv(n.rv),n}async getAll(t,e={}){const s=await this.get(t,{...e,page:1}),i=this.normalizeCollectionResponse(s);if(i.rv&&this.setRv(i.rv),!i.meta||i.meta.last_page<=1)return i.data;const n=Array.from({length:i.meta.last_page-1},(r,h)=>this.get(t,{...e,page:h+2})),o=await Promise.all(n);return i.data.concat(o.flatMap(r=>this.normalizeCollectionResponse(r).data))}setRv(t){this.setRvFn?this.setRvFn(t):l=t}getRv(){return this.getRvFn?this.getRvFn():l}async parseResponse(t){if(this.isFetchResponse(t)){if(!t.ok)throw new Error(`Request failed with status ${t.status}`);return await t.json()}return t}normalizeCollectionResponse(t){if(this.isCollectionResponseEnvelope(t)){const e=t.data;return{data:e.data,meta:e.meta,rv:t.rv||e.rv}}if(Array.isArray(t))return{data:t,meta:void 0,rv:void 0};if(typeof t=="object"&&t!==null&&"data"in t){const{data:e,meta:s,rv:i}=t;return{data:e,meta:s,rv:i}}return{data:[],meta:void 0,rv:void 0}}buildUrl(t,e){const s=new URL(`${this.baseUrl}/v1/${t}`);return Object.entries(e).forEach(([i,n])=>{n!=null&&s.searchParams.append(i,String(n))}),s.toString()}resolveRequestUrl(t){return t?t instanceof URL?t:new URL(t,"http://localhost"):null}isFetchResponse(t){return typeof t=="object"&&t!==null&&"json"in t&&typeof t.json=="function"&&"ok"in t}hasRevision(t){return typeof t=="object"&&t!==null&&"rv"in t}isCollectionResponseEnvelope(t){return typeof t=="object"&&t!==null&&"data"in t&&typeof t.data=="object"&&t.data!==null&&"data"in t.data&&Array.isArray(t.data.data)}}exports.ApiClient=v;exports.B10cksDataApi=f;exports.PreviewBridge=a;exports.createB10cksDataApi=g;exports.previewBridge=p;exports.types=u;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type {\n B10cksApiClientOptions,\n IBBaseQueryParams,\n IBCollectionResponse,\n IBMeta,\n IBResponse,\n} from './types'\n\nexport type FetchClient = typeof fetch\nexport type Endpoint =\n | 'blocks'\n | 'contents'\n | `contents/${string}`\n | `datasources/${string}/entries`\n | 'datasources'\n | 'spaces/me'\n\nexport interface B10cksApiClientRvOptions {\n getRv?: () => string | number\n setRv?: (value: string | number) => void\n}\n\nexport * as types from './types'\nexport type { B10cksApiClientOptions, IBBlock, IBContent, IBResponse } from './types'\n\nlet rv: string | number = 0\n\nexport class ApiClient {\n private readonly baseUrl: string\n private readonly token: string\n private readonly vid: string | null\n private readonly fetchClient: FetchClient\n private readonly getRvFn?: () => string | number\n private readonly setRvFn?: (value: string | number) => void\n\n constructor(options: B10cksApiClientOptions, url: URL) {\n this.baseUrl = options.baseUrl.endsWith('/') ? options.baseUrl.slice(0, -1) : options.baseUrl\n this.token = options.token\n this.fetchClient = options.fetchClient\n this.getRvFn = options.getRv\n this.setRvFn = options.setRv\n\n this.vid = url.searchParams.get('b10cks_vid') || options.version || 'published'\n this.setRv(url.searchParams.get('b10cks_rv') || options.rv || rv)\n }\n\n async get<T>(endpoint: Endpoint, params: Omit<IBBaseQueryParams, 'token'> = {}): Promise<T> {\n const url = this.buildUrl(endpoint, {\n vid: this.vid,\n ...params,\n rv: this.getRv(),\n token: this.token,\n })\n\n const response = (await this.fetchClient(url)) as unknown as IBResponse<T>\n if (response.rv) {\n this.setRv(response.rv)\n }\n\n return response as T\n }\n\n async getAll<T>(endpoint: Endpoint, params: Omit<IBBaseQueryParams, 'token'> = {}): Promise<T[]> {\n const response = await this.get<IBCollectionResponse<T> & { meta?: IBMeta }>(endpoint, {\n ...params,\n page: 1,\n })\n if (response.rv) {\n this.setRv(response.rv)\n }\n\n if (!response.meta || response.meta.last_page <= 1) {\n return 'data' in response ? response.data : (response as unknown as T[])\n }\n\n const pageRequests = Array.from({ length: response.meta.last_page }, (_, i) =>\n this.get<IBCollectionResponse<T>>(endpoint, { ...params, page: i + 1 })\n )\n\n const allResponses = await Promise.all(pageRequests)\n\n return allResponses.flatMap((r) => r.data)\n }\n\n setRv(value: string | number) {\n if (this.setRvFn) {\n this.setRvFn(value)\n } else {\n rv = value\n }\n }\n\n getRv() {\n if (this.getRvFn) {\n return this.getRvFn()\n }\n return rv\n }\n\n private buildUrl(endpoint: string, params: Record<string, unknown>): string {\n const url = new URL(`${this.baseUrl}/v1/${endpoint}`)\n\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value))\n }\n })\n\n return url.toString()\n }\n}\n"],"names":["rv","ApiClient","options","url","endpoint","params","response","pageRequests","_","i","r","value","key"],"mappings":"mLAyBA,IAAIA,EAAsB,EAEnB,MAAMC,CAAU,CACJ,QACA,MACA,IACA,YACA,QACA,QAEjB,YAAYC,EAAiCC,EAAU,CACrD,KAAK,QAAUD,EAAQ,QAAQ,SAAS,GAAG,EAAIA,EAAQ,QAAQ,MAAM,EAAG,EAAE,EAAIA,EAAQ,QACtF,KAAK,MAAQA,EAAQ,MACrB,KAAK,YAAcA,EAAQ,YAC3B,KAAK,QAAUA,EAAQ,MACvB,KAAK,QAAUA,EAAQ,MAEvB,KAAK,IAAMC,EAAI,aAAa,IAAI,YAAY,GAAKD,EAAQ,SAAW,YACpE,KAAK,MAAMC,EAAI,aAAa,IAAI,WAAW,GAAKD,EAAQ,IAAMF,CAAE,CAClE,CAEA,MAAM,IAAOI,EAAoBC,EAA2C,GAAgB,CAC1F,MAAMF,EAAM,KAAK,SAASC,EAAU,CAClC,IAAK,KAAK,IACV,GAAGC,EACH,GAAI,KAAK,MAAA,EACT,MAAO,KAAK,KAAA,CACb,EAEKC,EAAY,MAAM,KAAK,YAAYH,CAAG,EAC5C,OAAIG,EAAS,IACX,KAAK,MAAMA,EAAS,EAAE,EAGjBA,CACT,CAEA,MAAM,OAAUF,EAAoBC,EAA2C,GAAkB,CAC/F,MAAMC,EAAW,MAAM,KAAK,IAAiDF,EAAU,CACrF,GAAGC,EACH,KAAM,CAAA,CACP,EAKD,GAJIC,EAAS,IACX,KAAK,MAAMA,EAAS,EAAE,EAGpB,CAACA,EAAS,MAAQA,EAAS,KAAK,WAAa,EAC/C,MAAO,SAAUA,EAAWA,EAAS,KAAQA,EAG/C,MAAMC,EAAe,MAAM,KAAK,CAAE,OAAQD,EAAS,KAAK,SAAA,EAAa,CAACE,EAAGC,IACvE,KAAK,IAA6BL,EAAU,CAAE,GAAGC,EAAQ,KAAMI,EAAI,CAAA,CAAG,CAAA,EAKxE,OAFqB,MAAM,QAAQ,IAAIF,CAAY,GAE/B,QAASG,GAAMA,EAAE,IAAI,CAC3C,CAEA,MAAMC,EAAwB,CACxB,KAAK,QACP,KAAK,QAAQA,CAAK,EAElBX,EAAKW,CAET,CAEA,OAAQ,CACN,OAAI,KAAK,QACA,KAAK,QAAA,EAEPX,CACT,CAEQ,SAASI,EAAkBC,EAAyC,CAC1E,MAAMF,EAAM,IAAI,IAAI,GAAG,KAAK,OAAO,OAAOC,CAAQ,EAAE,EAEpD,cAAO,QAAQC,CAAM,EAAE,QAAQ,CAAC,CAACO,EAAKD,CAAK,IAAM,CACpBA,GAAU,MACnCR,EAAI,aAAa,OAAOS,EAAK,OAAOD,CAAK,CAAC,CAE9C,CAAC,EAEMR,EAAI,SAAA,CACb,CACF"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/data-api.ts","../src/preview-bridge.ts","../src/index.ts"],"sourcesContent":["import type {\n Endpoint,\n IBBaseQueryParams,\n IBBlock,\n IBContent,\n IBContentQueryParams,\n IBDataEntry,\n IBDataSource,\n IBRedirect,\n IBSpace,\n} from './types'\n\ntype ApiQueryParams = Omit<IBBaseQueryParams, 'token'>\n\nexport interface DataApiClient {\n get<T>(\n endpoint: Endpoint,\n params?: ApiQueryParams\n ): Promise<T | { data: T; rv?: string | number }>\n getAll<T>(endpoint: Endpoint, params?: ApiQueryParams): Promise<T[]>\n setRv(value: string | number): void\n}\n\nexport type RedirectMap = Record<string, { target: string; status_code: number }>\n\nexport interface GetConfigOptions extends Omit<IBContentQueryParams, 'token' | 'full_slug'> {\n slug?: string\n language?: string\n bypassCache?: boolean\n}\n\nexport class B10cksDataApi {\n private redirectsCache: RedirectMap | null = null\n private readonly configCache = new Map<string, unknown>()\n\n constructor(private readonly client: DataApiClient) {}\n\n async getResource<T>(endpoint: Endpoint, params: ApiQueryParams = {}): Promise<T> {\n const response = await this.client.get<T>(endpoint, params)\n return this.unwrapResource(response)\n }\n\n async getCollection<T>(endpoint: Endpoint, params: ApiQueryParams = {}): Promise<T[]> {\n return this.client.getAll<T>(endpoint, params)\n }\n\n async getContent<T = Record<string, unknown>>(\n fullSlug: string,\n params: Omit<IBContentQueryParams, 'token' | 'full_slug'> = {}\n ): Promise<IBContent<T>> {\n return this.getResource<IBContent<T>>(`contents/${fullSlug}`, params)\n }\n\n async getContents<T = Record<string, unknown>>(\n params: Omit<IBContentQueryParams, 'token'> = {}\n ): Promise<IBContent<T>[]> {\n return this.getCollection<IBContent<T>>('contents', params)\n }\n\n async getBlocks(params: ApiQueryParams = {}): Promise<IBBlock[]> {\n return this.getCollection<IBBlock>('blocks', params)\n }\n\n async getDataEntries(source: string, params: ApiQueryParams = {}): Promise<IBDataEntry[]> {\n return this.getCollection<IBDataEntry>(`datasources/${source}/entries`, params)\n }\n\n async getDataSources(params: ApiQueryParams = {}): Promise<IBDataSource[]> {\n return this.getCollection<IBDataSource>('datasources', params)\n }\n\n async getSpace(params: ApiQueryParams = {}): Promise<IBSpace> {\n return this.getResource<IBSpace>('spaces/me', params)\n }\n\n async getRedirects(params: ApiQueryParams = {}, forceRefresh = false): Promise<RedirectMap> {\n if (this.redirectsCache && !forceRefresh) {\n return this.redirectsCache\n }\n\n const redirects = await this.getCollection<IBRedirect>('redirects', params)\n const map = Object.fromEntries(\n redirects.map(({ source, target, status_code }) => [source, { target, status_code }])\n )\n this.redirectsCache = map\n return map\n }\n\n async getConfig<T = Record<string, unknown>>({\n slug = '_config',\n language_iso,\n language,\n bypassCache = false,\n ...params\n }: GetConfigOptions = {}): Promise<T> {\n const normalizedLanguage = language_iso ?? language\n const cacheKey = JSON.stringify({ slug, language_iso: normalizedLanguage, ...params })\n if (!bypassCache && this.configCache.has(cacheKey)) {\n return this.configCache.get(cacheKey) as T\n }\n\n const configContent = await this.getContent<Record<string, unknown>>(slug, {\n ...params,\n language_iso: normalizedLanguage,\n })\n const value = (configContent.content ?? {}) as T\n\n if (!bypassCache) {\n this.configCache.set(cacheKey, value)\n }\n\n return value\n }\n\n async syncRevision(fallbackRv = 426713400): Promise<string | number> {\n const space = await this.getSpace()\n const nextRv = space.rv || fallbackRv\n this.client.setRv(nextRv)\n return nextRv\n }\n\n clearCache() {\n this.redirectsCache = null\n this.configCache.clear()\n }\n\n private unwrapResource<T>(response: T | { data: T }): T {\n if (typeof response === 'object' && response !== null && 'data' in response) {\n return response.data\n }\n\n return response\n }\n}\n\nexport function createB10cksDataApi(client: DataApiClient): B10cksDataApi {\n return new B10cksDataApi(client)\n}\n","export type ContentUpdateEvent = {\n content: Record<string, unknown>\n}\n\nexport type SelectUpdateEvent = {\n selectedItem: string\n}\n\nexport type FieldUpdateEvent = {\n itemId: string\n field: string\n value: string\n}\n\nexport type EventType = 'CONTENT_UPDATE' | 'SELECT_UPDATE' | 'HOVER_UPDATE' | 'FIELD_UPDATE'\n\nexport type EventPayloadMap = {\n CONTENT_UPDATE: ContentUpdateEvent\n SELECT_UPDATE: SelectUpdateEvent\n HOVER_UPDATE: SelectUpdateEvent\n FIELD_UPDATE: FieldUpdateEvent\n}\n\ntype EventCallback<T> = (payload: T) => void\n\nexport type BridgeEvent = {\n type: EventType\n payload: EventPayloadMap[EventType]\n b10cksId?: string\n}\n\nexport class PreviewBridge {\n private static instance: PreviewBridge\n private readonly listeners: Partial<Record<EventType, Set<EventCallback<unknown>>>> = {}\n private initialized = false\n\n private constructor() {}\n\n static getInstance() {\n if (!PreviewBridge.instance) {\n PreviewBridge.instance = new PreviewBridge()\n }\n return PreviewBridge.instance\n }\n\n init() {\n if (!this.isInPreviewMode() || this.initialized) {\n return\n }\n\n window.addEventListener('message', this.handleMessage)\n this.initialized = true\n }\n\n destroy() {\n if (this.initialized && typeof window !== 'undefined') {\n window.removeEventListener('message', this.handleMessage)\n }\n this.initialized = false\n for (const eventType of Object.keys(this.listeners) as EventType[]) {\n this.listeners[eventType]?.clear()\n }\n }\n\n isInPreviewMode(): boolean {\n return typeof window !== 'undefined' && window.self !== window.top\n }\n\n on<T extends EventType>(eventType: T, callback: EventCallback<EventPayloadMap[T]>): () => void {\n if (!this.isInPreviewMode()) {\n return () => {}\n }\n\n const listeners = this.listeners[eventType] || new Set<EventCallback<unknown>>()\n this.listeners[eventType] = listeners\n listeners.add(callback as EventCallback<unknown>)\n\n return () => {\n listeners.delete(callback as EventCallback<unknown>)\n }\n }\n\n selectItem(selectedItem: string) {\n if (!this.isInPreviewMode()) {\n return\n }\n\n window.parent.postMessage(\n {\n type: 'SELECT_UPDATE',\n payload: { selectedItem },\n },\n '*'\n )\n }\n\n updateField(itemId: string, field: string, value: string) {\n if (!this.isInPreviewMode()) {\n return\n }\n\n window.parent.postMessage(\n {\n type: 'FIELD_UPDATE',\n payload: { itemId, field, value },\n },\n '*'\n )\n }\n\n private handleMessage = (event: MessageEvent) => {\n if (!event.data || typeof event.data !== 'object') {\n return\n }\n\n const { type, payload } = event.data as BridgeEvent\n if (!type || !payload) {\n return\n }\n\n this.notify(type, payload as never)\n }\n\n private notify<T extends EventType>(type: T, payload: EventPayloadMap[T]) {\n const callbacks = this.listeners[type]\n if (!callbacks) {\n return\n }\n\n for (const callback of callbacks) {\n ;(callback as EventCallback<EventPayloadMap[T]>)(payload)\n }\n }\n}\n\nexport const previewBridge = PreviewBridge.getInstance()\n","import type {\n B10cksApiClientOptions,\n Endpoint,\n FetchClient,\n IBBaseQueryParams,\n IBCollectionResponse,\n IBMeta,\n IBResponse,\n} from './types'\n\nexport interface B10cksApiClientRvOptions {\n getRv?: () => string | number\n setRv?: (value: string | number) => void\n}\n\nexport * as types from './types'\nexport type * from './types'\nexport * from './data-api'\nexport * from './preview-bridge'\n\nlet rv: string | number = 0\n\ntype ApiResourceResponse<T> = IBResponse<T> | T\ntype ApiCollectionResponse<T> =\n | IBCollectionResponse<T>\n | IBResponse<IBCollectionResponse<T>>\n | T[]\n | { data: T[]; meta?: IBMeta; rv?: string | number }\n\nexport class ApiClient {\n private readonly baseUrl: string\n readonly token: string\n private readonly vid: string | null\n private readonly fetchClient: FetchClient\n private readonly getRvFn?: () => string | number\n private readonly setRvFn?: (value: string | number) => void\n\n constructor(options: B10cksApiClientOptions, requestUrl?: URL | string) {\n this.baseUrl = options.baseUrl.endsWith('/') ? options.baseUrl.slice(0, -1) : options.baseUrl\n this.token = options.token\n const defaultFetch =\n typeof globalThis.fetch === 'function' ? globalThis.fetch.bind(globalThis) : null\n if (options.fetchClient) {\n this.fetchClient = options.fetchClient\n } else if (defaultFetch) {\n this.fetchClient = defaultFetch as FetchClient\n } else {\n throw new Error(\n 'No fetch implementation available. Provide `fetchClient` in ApiClient options.'\n )\n }\n\n this.getRvFn = options.getRv\n this.setRvFn = options.setRv\n\n const url = this.resolveRequestUrl(requestUrl)\n this.vid = url?.searchParams.get('b10cks_vid') || options.version || 'published'\n this.setRv(url?.searchParams.get('b10cks_rv') || options.rv || rv)\n }\n\n async get<T>(\n endpoint: Endpoint,\n params: Omit<IBBaseQueryParams, 'token'> = {}\n ): Promise<ApiResourceResponse<T>> {\n const url = this.buildUrl(endpoint, {\n vid: this.vid,\n ...params,\n rv: this.getRv(),\n token: this.token,\n })\n\n const payload = await this.fetchClient(url)\n const response = await this.parseResponse<ApiResourceResponse<T>>(payload)\n\n if (this.hasRevision(response)) {\n this.setRv(response.rv)\n }\n\n return response\n }\n\n async getAll<T>(endpoint: Endpoint, params: Omit<IBBaseQueryParams, 'token'> = {}): Promise<T[]> {\n const firstResponse = await this.get<IBCollectionResponse<T> & { meta?: IBMeta }>(endpoint, {\n ...params,\n page: 1,\n })\n const normalizedFirstResponse = this.normalizeCollectionResponse<T>(firstResponse)\n\n if (normalizedFirstResponse.rv) {\n this.setRv(normalizedFirstResponse.rv)\n }\n\n if (!normalizedFirstResponse.meta || normalizedFirstResponse.meta.last_page <= 1) {\n return normalizedFirstResponse.data\n }\n\n const pageRequests = Array.from(\n { length: normalizedFirstResponse.meta.last_page - 1 },\n (_, i) => this.get<IBCollectionResponse<T>>(endpoint, { ...params, page: i + 2 })\n )\n\n const allResponses = await Promise.all(pageRequests)\n\n return normalizedFirstResponse.data.concat(\n allResponses.flatMap((response) => this.normalizeCollectionResponse<T>(response).data)\n )\n }\n\n setRv(value: string | number) {\n if (this.setRvFn) {\n this.setRvFn(value)\n } else {\n rv = value\n }\n }\n\n getRv() {\n if (this.getRvFn) {\n return this.getRvFn()\n }\n return rv\n }\n\n private async parseResponse<T>(payload: unknown): Promise<T> {\n if (this.isFetchResponse(payload)) {\n if (!payload.ok) {\n throw new Error(`Request failed with status ${payload.status}`)\n }\n\n return (await payload.json()) as T\n }\n\n return payload as T\n }\n\n private normalizeCollectionResponse<T>(response: ApiCollectionResponse<T>) {\n if (this.isCollectionResponseEnvelope(response)) {\n const nestedResponse = response.data\n\n return {\n data: nestedResponse.data,\n meta: (nestedResponse as IBCollectionResponse<T> & { meta?: IBMeta }).meta,\n rv: response.rv || nestedResponse.rv,\n }\n }\n\n if (Array.isArray(response)) {\n return { data: response, meta: undefined, rv: undefined }\n }\n\n if (typeof response === 'object' && response !== null && 'data' in response) {\n const {\n data,\n meta,\n rv: responseRv,\n } = response as {\n data: T[]\n meta?: IBMeta\n rv?: string | number\n }\n return { data, meta, rv: responseRv }\n }\n\n return { data: [], meta: undefined, rv: undefined }\n }\n\n private buildUrl(endpoint: string, params: Record<string, unknown>): string {\n const url = new URL(`${this.baseUrl}/v1/${endpoint}`)\n\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value))\n }\n })\n\n return url.toString()\n }\n\n private resolveRequestUrl(requestUrl?: URL | string): URL | null {\n if (!requestUrl) {\n return null\n }\n\n if (requestUrl instanceof URL) {\n return requestUrl\n }\n\n return new URL(requestUrl, 'http://localhost')\n }\n\n private isFetchResponse(value: unknown): value is Response {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'json' in value &&\n typeof (value as Response).json === 'function' &&\n 'ok' in value\n )\n }\n\n private hasRevision(value: unknown): value is { rv: string | number } {\n return typeof value === 'object' && value !== null && 'rv' in value\n }\n\n private isCollectionResponseEnvelope<T>(\n value: ApiCollectionResponse<T>\n ): value is IBResponse<IBCollectionResponse<T>> {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'data' in value &&\n typeof value.data === 'object' &&\n value.data !== null &&\n 'data' in value.data &&\n Array.isArray(value.data.data)\n )\n }\n}\n"],"names":["B10cksDataApi","client","endpoint","params","response","fullSlug","source","forceRefresh","redirects","map","target","status_code","slug","language_iso","language","bypassCache","normalizedLanguage","cacheKey","value","fallbackRv","nextRv","createB10cksDataApi","PreviewBridge","eventType","callback","listeners","selectedItem","itemId","field","event","type","payload","callbacks","previewBridge","rv","ApiClient","options","requestUrl","defaultFetch","url","firstResponse","normalizedFirstResponse","pageRequests","_","i","allResponses","nestedResponse","data","meta","responseRv","key"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,54 +1,243 @@
|
|
|
1
|
-
const
|
|
1
|
+
const u = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2
2
|
__proto__: null
|
|
3
3
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
class f {
|
|
5
|
+
constructor(t) {
|
|
6
|
+
this.client = t;
|
|
7
|
+
}
|
|
8
|
+
redirectsCache = null;
|
|
9
|
+
configCache = /* @__PURE__ */ new Map();
|
|
10
|
+
async getResource(t, e = {}) {
|
|
11
|
+
const s = await this.client.get(t, e);
|
|
12
|
+
return this.unwrapResource(s);
|
|
13
|
+
}
|
|
14
|
+
async getCollection(t, e = {}) {
|
|
15
|
+
return this.client.getAll(t, e);
|
|
16
|
+
}
|
|
17
|
+
async getContent(t, e = {}) {
|
|
18
|
+
return this.getResource(`contents/${t}`, e);
|
|
19
|
+
}
|
|
20
|
+
async getContents(t = {}) {
|
|
21
|
+
return this.getCollection("contents", t);
|
|
22
|
+
}
|
|
23
|
+
async getBlocks(t = {}) {
|
|
24
|
+
return this.getCollection("blocks", t);
|
|
25
|
+
}
|
|
26
|
+
async getDataEntries(t, e = {}) {
|
|
27
|
+
return this.getCollection(`datasources/${t}/entries`, e);
|
|
28
|
+
}
|
|
29
|
+
async getDataSources(t = {}) {
|
|
30
|
+
return this.getCollection("datasources", t);
|
|
31
|
+
}
|
|
32
|
+
async getSpace(t = {}) {
|
|
33
|
+
return this.getResource("spaces/me", t);
|
|
34
|
+
}
|
|
35
|
+
async getRedirects(t = {}, e = !1) {
|
|
36
|
+
if (this.redirectsCache && !e)
|
|
37
|
+
return this.redirectsCache;
|
|
38
|
+
const s = await this.getCollection("redirects", t), n = Object.fromEntries(
|
|
39
|
+
s.map(({ source: i, target: a, status_code: r }) => [i, { target: a, status_code: r }])
|
|
40
|
+
);
|
|
41
|
+
return this.redirectsCache = n, n;
|
|
42
|
+
}
|
|
43
|
+
async getConfig({
|
|
44
|
+
slug: t = "_config",
|
|
45
|
+
language_iso: e,
|
|
46
|
+
language: s,
|
|
47
|
+
bypassCache: n = !1,
|
|
48
|
+
...i
|
|
49
|
+
} = {}) {
|
|
50
|
+
const a = e ?? s, r = JSON.stringify({ slug: t, language_iso: a, ...i });
|
|
51
|
+
if (!n && this.configCache.has(r))
|
|
52
|
+
return this.configCache.get(r);
|
|
53
|
+
const d = (await this.getContent(t, {
|
|
54
|
+
...i,
|
|
55
|
+
language_iso: a
|
|
56
|
+
})).content ?? {};
|
|
57
|
+
return n || this.configCache.set(r, d), d;
|
|
58
|
+
}
|
|
59
|
+
async syncRevision(t = 426713400) {
|
|
60
|
+
const s = (await this.getSpace()).rv || t;
|
|
61
|
+
return this.client.setRv(s), s;
|
|
62
|
+
}
|
|
63
|
+
clearCache() {
|
|
64
|
+
this.redirectsCache = null, this.configCache.clear();
|
|
65
|
+
}
|
|
66
|
+
unwrapResource(t) {
|
|
67
|
+
return typeof t == "object" && t !== null && "data" in t ? t.data : t;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function g(c) {
|
|
71
|
+
return new f(c);
|
|
72
|
+
}
|
|
73
|
+
class o {
|
|
74
|
+
static instance;
|
|
75
|
+
listeners = {};
|
|
76
|
+
initialized = !1;
|
|
77
|
+
constructor() {
|
|
78
|
+
}
|
|
79
|
+
static getInstance() {
|
|
80
|
+
return o.instance || (o.instance = new o()), o.instance;
|
|
81
|
+
}
|
|
82
|
+
init() {
|
|
83
|
+
!this.isInPreviewMode() || this.initialized || (window.addEventListener("message", this.handleMessage), this.initialized = !0);
|
|
84
|
+
}
|
|
85
|
+
destroy() {
|
|
86
|
+
this.initialized && typeof window < "u" && window.removeEventListener("message", this.handleMessage), this.initialized = !1;
|
|
87
|
+
for (const t of Object.keys(this.listeners))
|
|
88
|
+
this.listeners[t]?.clear();
|
|
89
|
+
}
|
|
90
|
+
isInPreviewMode() {
|
|
91
|
+
return typeof window < "u" && window.self !== window.top;
|
|
92
|
+
}
|
|
93
|
+
on(t, e) {
|
|
94
|
+
if (!this.isInPreviewMode())
|
|
95
|
+
return () => {
|
|
96
|
+
};
|
|
97
|
+
const s = this.listeners[t] || /* @__PURE__ */ new Set();
|
|
98
|
+
return this.listeners[t] = s, s.add(e), () => {
|
|
99
|
+
s.delete(e);
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
selectItem(t) {
|
|
103
|
+
this.isInPreviewMode() && window.parent.postMessage(
|
|
104
|
+
{
|
|
105
|
+
type: "SELECT_UPDATE",
|
|
106
|
+
payload: { selectedItem: t }
|
|
107
|
+
},
|
|
108
|
+
"*"
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
updateField(t, e, s) {
|
|
112
|
+
this.isInPreviewMode() && window.parent.postMessage(
|
|
113
|
+
{
|
|
114
|
+
type: "FIELD_UPDATE",
|
|
115
|
+
payload: { itemId: t, field: e, value: s }
|
|
116
|
+
},
|
|
117
|
+
"*"
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
handleMessage = (t) => {
|
|
121
|
+
if (!t.data || typeof t.data != "object")
|
|
122
|
+
return;
|
|
123
|
+
const { type: e, payload: s } = t.data;
|
|
124
|
+
!e || !s || this.notify(e, s);
|
|
125
|
+
};
|
|
126
|
+
notify(t, e) {
|
|
127
|
+
const s = this.listeners[t];
|
|
128
|
+
if (s)
|
|
129
|
+
for (const n of s)
|
|
130
|
+
n(e);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const R = o.getInstance();
|
|
134
|
+
let l = 0;
|
|
135
|
+
class v {
|
|
6
136
|
baseUrl;
|
|
7
137
|
token;
|
|
8
138
|
vid;
|
|
9
139
|
fetchClient;
|
|
10
140
|
getRvFn;
|
|
11
141
|
setRvFn;
|
|
12
|
-
constructor(t,
|
|
13
|
-
this.baseUrl = t.baseUrl.endsWith("/") ? t.baseUrl.slice(0, -1) : t.baseUrl, this.token = t.token
|
|
142
|
+
constructor(t, e) {
|
|
143
|
+
this.baseUrl = t.baseUrl.endsWith("/") ? t.baseUrl.slice(0, -1) : t.baseUrl, this.token = t.token;
|
|
144
|
+
const s = typeof globalThis.fetch == "function" ? globalThis.fetch.bind(globalThis) : null;
|
|
145
|
+
if (t.fetchClient)
|
|
146
|
+
this.fetchClient = t.fetchClient;
|
|
147
|
+
else if (s)
|
|
148
|
+
this.fetchClient = s;
|
|
149
|
+
else
|
|
150
|
+
throw new Error(
|
|
151
|
+
"No fetch implementation available. Provide `fetchClient` in ApiClient options."
|
|
152
|
+
);
|
|
153
|
+
this.getRvFn = t.getRv, this.setRvFn = t.setRv;
|
|
154
|
+
const n = this.resolveRequestUrl(e);
|
|
155
|
+
this.vid = n?.searchParams.get("b10cks_vid") || t.version || "published", this.setRv(n?.searchParams.get("b10cks_rv") || t.rv || l);
|
|
14
156
|
}
|
|
15
|
-
async get(t,
|
|
16
|
-
const
|
|
157
|
+
async get(t, e = {}) {
|
|
158
|
+
const s = this.buildUrl(t, {
|
|
17
159
|
vid: this.vid,
|
|
18
|
-
...
|
|
160
|
+
...e,
|
|
19
161
|
rv: this.getRv(),
|
|
20
162
|
token: this.token
|
|
21
|
-
}),
|
|
22
|
-
return
|
|
163
|
+
}), n = await this.fetchClient(s), i = await this.parseResponse(n);
|
|
164
|
+
return this.hasRevision(i) && this.setRv(i.rv), i;
|
|
23
165
|
}
|
|
24
|
-
async getAll(t,
|
|
25
|
-
const
|
|
26
|
-
...
|
|
166
|
+
async getAll(t, e = {}) {
|
|
167
|
+
const s = await this.get(t, {
|
|
168
|
+
...e,
|
|
27
169
|
page: 1
|
|
28
|
-
});
|
|
29
|
-
if (
|
|
30
|
-
return
|
|
31
|
-
const
|
|
32
|
-
{ length:
|
|
33
|
-
(
|
|
170
|
+
}), n = this.normalizeCollectionResponse(s);
|
|
171
|
+
if (n.rv && this.setRv(n.rv), !n.meta || n.meta.last_page <= 1)
|
|
172
|
+
return n.data;
|
|
173
|
+
const i = Array.from(
|
|
174
|
+
{ length: n.meta.last_page - 1 },
|
|
175
|
+
(r, h) => this.get(t, { ...e, page: h + 2 })
|
|
176
|
+
), a = await Promise.all(i);
|
|
177
|
+
return n.data.concat(
|
|
178
|
+
a.flatMap((r) => this.normalizeCollectionResponse(r).data)
|
|
34
179
|
);
|
|
35
|
-
return (await Promise.all(r)).flatMap((n) => n.data);
|
|
36
180
|
}
|
|
37
181
|
setRv(t) {
|
|
38
|
-
this.setRvFn ? this.setRvFn(t) :
|
|
182
|
+
this.setRvFn ? this.setRvFn(t) : l = t;
|
|
39
183
|
}
|
|
40
184
|
getRv() {
|
|
41
|
-
return this.getRvFn ? this.getRvFn() :
|
|
185
|
+
return this.getRvFn ? this.getRvFn() : l;
|
|
186
|
+
}
|
|
187
|
+
async parseResponse(t) {
|
|
188
|
+
if (this.isFetchResponse(t)) {
|
|
189
|
+
if (!t.ok)
|
|
190
|
+
throw new Error(`Request failed with status ${t.status}`);
|
|
191
|
+
return await t.json();
|
|
192
|
+
}
|
|
193
|
+
return t;
|
|
194
|
+
}
|
|
195
|
+
normalizeCollectionResponse(t) {
|
|
196
|
+
if (this.isCollectionResponseEnvelope(t)) {
|
|
197
|
+
const e = t.data;
|
|
198
|
+
return {
|
|
199
|
+
data: e.data,
|
|
200
|
+
meta: e.meta,
|
|
201
|
+
rv: t.rv || e.rv
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (Array.isArray(t))
|
|
205
|
+
return { data: t, meta: void 0, rv: void 0 };
|
|
206
|
+
if (typeof t == "object" && t !== null && "data" in t) {
|
|
207
|
+
const {
|
|
208
|
+
data: e,
|
|
209
|
+
meta: s,
|
|
210
|
+
rv: n
|
|
211
|
+
} = t;
|
|
212
|
+
return { data: e, meta: s, rv: n };
|
|
213
|
+
}
|
|
214
|
+
return { data: [], meta: void 0, rv: void 0 };
|
|
215
|
+
}
|
|
216
|
+
buildUrl(t, e) {
|
|
217
|
+
const s = new URL(`${this.baseUrl}/v1/${t}`);
|
|
218
|
+
return Object.entries(e).forEach(([n, i]) => {
|
|
219
|
+
i != null && s.searchParams.append(n, String(i));
|
|
220
|
+
}), s.toString();
|
|
221
|
+
}
|
|
222
|
+
resolveRequestUrl(t) {
|
|
223
|
+
return t ? t instanceof URL ? t : new URL(t, "http://localhost") : null;
|
|
224
|
+
}
|
|
225
|
+
isFetchResponse(t) {
|
|
226
|
+
return typeof t == "object" && t !== null && "json" in t && typeof t.json == "function" && "ok" in t;
|
|
227
|
+
}
|
|
228
|
+
hasRevision(t) {
|
|
229
|
+
return typeof t == "object" && t !== null && "rv" in t;
|
|
42
230
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return Object.entries(s).forEach(([r, i]) => {
|
|
46
|
-
i != null && e.searchParams.append(r, String(i));
|
|
47
|
-
}), e.toString();
|
|
231
|
+
isCollectionResponseEnvelope(t) {
|
|
232
|
+
return typeof t == "object" && t !== null && "data" in t && typeof t.data == "object" && t.data !== null && "data" in t.data && Array.isArray(t.data.data);
|
|
48
233
|
}
|
|
49
234
|
}
|
|
50
235
|
export {
|
|
51
|
-
|
|
52
|
-
|
|
236
|
+
v as ApiClient,
|
|
237
|
+
f as B10cksDataApi,
|
|
238
|
+
o as PreviewBridge,
|
|
239
|
+
g as createB10cksDataApi,
|
|
240
|
+
R as previewBridge,
|
|
241
|
+
u as types
|
|
53
242
|
};
|
|
54
243
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import type {\n B10cksApiClientOptions,\n IBBaseQueryParams,\n IBCollectionResponse,\n IBMeta,\n IBResponse,\n} from './types'\n\nexport type FetchClient = typeof fetch\nexport type Endpoint =\n | 'blocks'\n | 'contents'\n | `contents/${string}`\n | `datasources/${string}/entries`\n | 'datasources'\n | 'spaces/me'\n\nexport interface B10cksApiClientRvOptions {\n getRv?: () => string | number\n setRv?: (value: string | number) => void\n}\n\nexport * as types from './types'\nexport type { B10cksApiClientOptions, IBBlock, IBContent, IBResponse } from './types'\n\nlet rv: string | number = 0\n\nexport class ApiClient {\n private readonly baseUrl: string\n private readonly token: string\n private readonly vid: string | null\n private readonly fetchClient: FetchClient\n private readonly getRvFn?: () => string | number\n private readonly setRvFn?: (value: string | number) => void\n\n constructor(options: B10cksApiClientOptions, url: URL) {\n this.baseUrl = options.baseUrl.endsWith('/') ? options.baseUrl.slice(0, -1) : options.baseUrl\n this.token = options.token\n this.fetchClient = options.fetchClient\n this.getRvFn = options.getRv\n this.setRvFn = options.setRv\n\n this.vid = url.searchParams.get('b10cks_vid') || options.version || 'published'\n this.setRv(url.searchParams.get('b10cks_rv') || options.rv || rv)\n }\n\n async get<T>(endpoint: Endpoint, params: Omit<IBBaseQueryParams, 'token'> = {}): Promise<T> {\n const url = this.buildUrl(endpoint, {\n vid: this.vid,\n ...params,\n rv: this.getRv(),\n token: this.token,\n })\n\n const response = (await this.fetchClient(url)) as unknown as IBResponse<T>\n if (response.rv) {\n this.setRv(response.rv)\n }\n\n return response as T\n }\n\n async getAll<T>(endpoint: Endpoint, params: Omit<IBBaseQueryParams, 'token'> = {}): Promise<T[]> {\n const response = await this.get<IBCollectionResponse<T> & { meta?: IBMeta }>(endpoint, {\n ...params,\n page: 1,\n })\n if (response.rv) {\n this.setRv(response.rv)\n }\n\n if (!response.meta || response.meta.last_page <= 1) {\n return 'data' in response ? response.data : (response as unknown as T[])\n }\n\n const pageRequests = Array.from({ length: response.meta.last_page }, (_, i) =>\n this.get<IBCollectionResponse<T>>(endpoint, { ...params, page: i + 1 })\n )\n\n const allResponses = await Promise.all(pageRequests)\n\n return allResponses.flatMap((r) => r.data)\n }\n\n setRv(value: string | number) {\n if (this.setRvFn) {\n this.setRvFn(value)\n } else {\n rv = value\n }\n }\n\n getRv() {\n if (this.getRvFn) {\n return this.getRvFn()\n }\n return rv\n }\n\n private buildUrl(endpoint: string, params: Record<string, unknown>): string {\n const url = new URL(`${this.baseUrl}/v1/${endpoint}`)\n\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value))\n }\n })\n\n return url.toString()\n }\n}\n"],"names":["rv","ApiClient","options","url","endpoint","params","response","pageRequests","_","i","r","value","key"],"mappings":";;;AAyBA,IAAIA,IAAsB;AAEnB,MAAMC,EAAU;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAYC,GAAiCC,GAAU;AACrD,SAAK,UAAUD,EAAQ,QAAQ,SAAS,GAAG,IAAIA,EAAQ,QAAQ,MAAM,GAAG,EAAE,IAAIA,EAAQ,SACtF,KAAK,QAAQA,EAAQ,OACrB,KAAK,cAAcA,EAAQ,aAC3B,KAAK,UAAUA,EAAQ,OACvB,KAAK,UAAUA,EAAQ,OAEvB,KAAK,MAAMC,EAAI,aAAa,IAAI,YAAY,KAAKD,EAAQ,WAAW,aACpE,KAAK,MAAMC,EAAI,aAAa,IAAI,WAAW,KAAKD,EAAQ,MAAMF,CAAE;AAAA,EAClE;AAAA,EAEA,MAAM,IAAOI,GAAoBC,IAA2C,IAAgB;AAC1F,UAAMF,IAAM,KAAK,SAASC,GAAU;AAAA,MAClC,KAAK,KAAK;AAAA,MACV,GAAGC;AAAA,MACH,IAAI,KAAK,MAAA;AAAA,MACT,OAAO,KAAK;AAAA,IAAA,CACb,GAEKC,IAAY,MAAM,KAAK,YAAYH,CAAG;AAC5C,WAAIG,EAAS,MACX,KAAK,MAAMA,EAAS,EAAE,GAGjBA;AAAA,EACT;AAAA,EAEA,MAAM,OAAUF,GAAoBC,IAA2C,IAAkB;AAC/F,UAAMC,IAAW,MAAM,KAAK,IAAiDF,GAAU;AAAA,MACrF,GAAGC;AAAA,MACH,MAAM;AAAA,IAAA,CACP;AAKD,QAJIC,EAAS,MACX,KAAK,MAAMA,EAAS,EAAE,GAGpB,CAACA,EAAS,QAAQA,EAAS,KAAK,aAAa;AAC/C,aAAO,UAAUA,IAAWA,EAAS,OAAQA;AAG/C,UAAMC,IAAe,MAAM;AAAA,MAAK,EAAE,QAAQD,EAAS,KAAK,UAAA;AAAA,MAAa,CAACE,GAAGC,MACvE,KAAK,IAA6BL,GAAU,EAAE,GAAGC,GAAQ,MAAMI,IAAI,EAAA,CAAG;AAAA,IAAA;AAKxE,YAFqB,MAAM,QAAQ,IAAIF,CAAY,GAE/B,QAAQ,CAACG,MAAMA,EAAE,IAAI;AAAA,EAC3C;AAAA,EAEA,MAAMC,GAAwB;AAC5B,IAAI,KAAK,UACP,KAAK,QAAQA,CAAK,IAElBX,IAAKW;AAAA,EAET;AAAA,EAEA,QAAQ;AACN,WAAI,KAAK,UACA,KAAK,QAAA,IAEPX;AAAA,EACT;AAAA,EAEQ,SAASI,GAAkBC,GAAyC;AAC1E,UAAMF,IAAM,IAAI,IAAI,GAAG,KAAK,OAAO,OAAOC,CAAQ,EAAE;AAEpD,kBAAO,QAAQC,CAAM,EAAE,QAAQ,CAAC,CAACO,GAAKD,CAAK,MAAM;AAC/C,MAA2BA,KAAU,QACnCR,EAAI,aAAa,OAAOS,GAAK,OAAOD,CAAK,CAAC;AAAA,IAE9C,CAAC,GAEMR,EAAI,SAAA;AAAA,EACb;AACF;"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/data-api.ts","../src/preview-bridge.ts","../src/index.ts"],"sourcesContent":["import type {\n Endpoint,\n IBBaseQueryParams,\n IBBlock,\n IBContent,\n IBContentQueryParams,\n IBDataEntry,\n IBDataSource,\n IBRedirect,\n IBSpace,\n} from './types'\n\ntype ApiQueryParams = Omit<IBBaseQueryParams, 'token'>\n\nexport interface DataApiClient {\n get<T>(\n endpoint: Endpoint,\n params?: ApiQueryParams\n ): Promise<T | { data: T; rv?: string | number }>\n getAll<T>(endpoint: Endpoint, params?: ApiQueryParams): Promise<T[]>\n setRv(value: string | number): void\n}\n\nexport type RedirectMap = Record<string, { target: string; status_code: number }>\n\nexport interface GetConfigOptions extends Omit<IBContentQueryParams, 'token' | 'full_slug'> {\n slug?: string\n language?: string\n bypassCache?: boolean\n}\n\nexport class B10cksDataApi {\n private redirectsCache: RedirectMap | null = null\n private readonly configCache = new Map<string, unknown>()\n\n constructor(private readonly client: DataApiClient) {}\n\n async getResource<T>(endpoint: Endpoint, params: ApiQueryParams = {}): Promise<T> {\n const response = await this.client.get<T>(endpoint, params)\n return this.unwrapResource(response)\n }\n\n async getCollection<T>(endpoint: Endpoint, params: ApiQueryParams = {}): Promise<T[]> {\n return this.client.getAll<T>(endpoint, params)\n }\n\n async getContent<T = Record<string, unknown>>(\n fullSlug: string,\n params: Omit<IBContentQueryParams, 'token' | 'full_slug'> = {}\n ): Promise<IBContent<T>> {\n return this.getResource<IBContent<T>>(`contents/${fullSlug}`, params)\n }\n\n async getContents<T = Record<string, unknown>>(\n params: Omit<IBContentQueryParams, 'token'> = {}\n ): Promise<IBContent<T>[]> {\n return this.getCollection<IBContent<T>>('contents', params)\n }\n\n async getBlocks(params: ApiQueryParams = {}): Promise<IBBlock[]> {\n return this.getCollection<IBBlock>('blocks', params)\n }\n\n async getDataEntries(source: string, params: ApiQueryParams = {}): Promise<IBDataEntry[]> {\n return this.getCollection<IBDataEntry>(`datasources/${source}/entries`, params)\n }\n\n async getDataSources(params: ApiQueryParams = {}): Promise<IBDataSource[]> {\n return this.getCollection<IBDataSource>('datasources', params)\n }\n\n async getSpace(params: ApiQueryParams = {}): Promise<IBSpace> {\n return this.getResource<IBSpace>('spaces/me', params)\n }\n\n async getRedirects(params: ApiQueryParams = {}, forceRefresh = false): Promise<RedirectMap> {\n if (this.redirectsCache && !forceRefresh) {\n return this.redirectsCache\n }\n\n const redirects = await this.getCollection<IBRedirect>('redirects', params)\n const map = Object.fromEntries(\n redirects.map(({ source, target, status_code }) => [source, { target, status_code }])\n )\n this.redirectsCache = map\n return map\n }\n\n async getConfig<T = Record<string, unknown>>({\n slug = '_config',\n language_iso,\n language,\n bypassCache = false,\n ...params\n }: GetConfigOptions = {}): Promise<T> {\n const normalizedLanguage = language_iso ?? language\n const cacheKey = JSON.stringify({ slug, language_iso: normalizedLanguage, ...params })\n if (!bypassCache && this.configCache.has(cacheKey)) {\n return this.configCache.get(cacheKey) as T\n }\n\n const configContent = await this.getContent<Record<string, unknown>>(slug, {\n ...params,\n language_iso: normalizedLanguage,\n })\n const value = (configContent.content ?? {}) as T\n\n if (!bypassCache) {\n this.configCache.set(cacheKey, value)\n }\n\n return value\n }\n\n async syncRevision(fallbackRv = 426713400): Promise<string | number> {\n const space = await this.getSpace()\n const nextRv = space.rv || fallbackRv\n this.client.setRv(nextRv)\n return nextRv\n }\n\n clearCache() {\n this.redirectsCache = null\n this.configCache.clear()\n }\n\n private unwrapResource<T>(response: T | { data: T }): T {\n if (typeof response === 'object' && response !== null && 'data' in response) {\n return response.data\n }\n\n return response\n }\n}\n\nexport function createB10cksDataApi(client: DataApiClient): B10cksDataApi {\n return new B10cksDataApi(client)\n}\n","export type ContentUpdateEvent = {\n content: Record<string, unknown>\n}\n\nexport type SelectUpdateEvent = {\n selectedItem: string\n}\n\nexport type FieldUpdateEvent = {\n itemId: string\n field: string\n value: string\n}\n\nexport type EventType = 'CONTENT_UPDATE' | 'SELECT_UPDATE' | 'HOVER_UPDATE' | 'FIELD_UPDATE'\n\nexport type EventPayloadMap = {\n CONTENT_UPDATE: ContentUpdateEvent\n SELECT_UPDATE: SelectUpdateEvent\n HOVER_UPDATE: SelectUpdateEvent\n FIELD_UPDATE: FieldUpdateEvent\n}\n\ntype EventCallback<T> = (payload: T) => void\n\nexport type BridgeEvent = {\n type: EventType\n payload: EventPayloadMap[EventType]\n b10cksId?: string\n}\n\nexport class PreviewBridge {\n private static instance: PreviewBridge\n private readonly listeners: Partial<Record<EventType, Set<EventCallback<unknown>>>> = {}\n private initialized = false\n\n private constructor() {}\n\n static getInstance() {\n if (!PreviewBridge.instance) {\n PreviewBridge.instance = new PreviewBridge()\n }\n return PreviewBridge.instance\n }\n\n init() {\n if (!this.isInPreviewMode() || this.initialized) {\n return\n }\n\n window.addEventListener('message', this.handleMessage)\n this.initialized = true\n }\n\n destroy() {\n if (this.initialized && typeof window !== 'undefined') {\n window.removeEventListener('message', this.handleMessage)\n }\n this.initialized = false\n for (const eventType of Object.keys(this.listeners) as EventType[]) {\n this.listeners[eventType]?.clear()\n }\n }\n\n isInPreviewMode(): boolean {\n return typeof window !== 'undefined' && window.self !== window.top\n }\n\n on<T extends EventType>(eventType: T, callback: EventCallback<EventPayloadMap[T]>): () => void {\n if (!this.isInPreviewMode()) {\n return () => {}\n }\n\n const listeners = this.listeners[eventType] || new Set<EventCallback<unknown>>()\n this.listeners[eventType] = listeners\n listeners.add(callback as EventCallback<unknown>)\n\n return () => {\n listeners.delete(callback as EventCallback<unknown>)\n }\n }\n\n selectItem(selectedItem: string) {\n if (!this.isInPreviewMode()) {\n return\n }\n\n window.parent.postMessage(\n {\n type: 'SELECT_UPDATE',\n payload: { selectedItem },\n },\n '*'\n )\n }\n\n updateField(itemId: string, field: string, value: string) {\n if (!this.isInPreviewMode()) {\n return\n }\n\n window.parent.postMessage(\n {\n type: 'FIELD_UPDATE',\n payload: { itemId, field, value },\n },\n '*'\n )\n }\n\n private handleMessage = (event: MessageEvent) => {\n if (!event.data || typeof event.data !== 'object') {\n return\n }\n\n const { type, payload } = event.data as BridgeEvent\n if (!type || !payload) {\n return\n }\n\n this.notify(type, payload as never)\n }\n\n private notify<T extends EventType>(type: T, payload: EventPayloadMap[T]) {\n const callbacks = this.listeners[type]\n if (!callbacks) {\n return\n }\n\n for (const callback of callbacks) {\n ;(callback as EventCallback<EventPayloadMap[T]>)(payload)\n }\n }\n}\n\nexport const previewBridge = PreviewBridge.getInstance()\n","import type {\n B10cksApiClientOptions,\n Endpoint,\n FetchClient,\n IBBaseQueryParams,\n IBCollectionResponse,\n IBMeta,\n IBResponse,\n} from './types'\n\nexport interface B10cksApiClientRvOptions {\n getRv?: () => string | number\n setRv?: (value: string | number) => void\n}\n\nexport * as types from './types'\nexport type * from './types'\nexport * from './data-api'\nexport * from './preview-bridge'\n\nlet rv: string | number = 0\n\ntype ApiResourceResponse<T> = IBResponse<T> | T\ntype ApiCollectionResponse<T> =\n | IBCollectionResponse<T>\n | IBResponse<IBCollectionResponse<T>>\n | T[]\n | { data: T[]; meta?: IBMeta; rv?: string | number }\n\nexport class ApiClient {\n private readonly baseUrl: string\n readonly token: string\n private readonly vid: string | null\n private readonly fetchClient: FetchClient\n private readonly getRvFn?: () => string | number\n private readonly setRvFn?: (value: string | number) => void\n\n constructor(options: B10cksApiClientOptions, requestUrl?: URL | string) {\n this.baseUrl = options.baseUrl.endsWith('/') ? options.baseUrl.slice(0, -1) : options.baseUrl\n this.token = options.token\n const defaultFetch =\n typeof globalThis.fetch === 'function' ? globalThis.fetch.bind(globalThis) : null\n if (options.fetchClient) {\n this.fetchClient = options.fetchClient\n } else if (defaultFetch) {\n this.fetchClient = defaultFetch as FetchClient\n } else {\n throw new Error(\n 'No fetch implementation available. Provide `fetchClient` in ApiClient options.'\n )\n }\n\n this.getRvFn = options.getRv\n this.setRvFn = options.setRv\n\n const url = this.resolveRequestUrl(requestUrl)\n this.vid = url?.searchParams.get('b10cks_vid') || options.version || 'published'\n this.setRv(url?.searchParams.get('b10cks_rv') || options.rv || rv)\n }\n\n async get<T>(\n endpoint: Endpoint,\n params: Omit<IBBaseQueryParams, 'token'> = {}\n ): Promise<ApiResourceResponse<T>> {\n const url = this.buildUrl(endpoint, {\n vid: this.vid,\n ...params,\n rv: this.getRv(),\n token: this.token,\n })\n\n const payload = await this.fetchClient(url)\n const response = await this.parseResponse<ApiResourceResponse<T>>(payload)\n\n if (this.hasRevision(response)) {\n this.setRv(response.rv)\n }\n\n return response\n }\n\n async getAll<T>(endpoint: Endpoint, params: Omit<IBBaseQueryParams, 'token'> = {}): Promise<T[]> {\n const firstResponse = await this.get<IBCollectionResponse<T> & { meta?: IBMeta }>(endpoint, {\n ...params,\n page: 1,\n })\n const normalizedFirstResponse = this.normalizeCollectionResponse<T>(firstResponse)\n\n if (normalizedFirstResponse.rv) {\n this.setRv(normalizedFirstResponse.rv)\n }\n\n if (!normalizedFirstResponse.meta || normalizedFirstResponse.meta.last_page <= 1) {\n return normalizedFirstResponse.data\n }\n\n const pageRequests = Array.from(\n { length: normalizedFirstResponse.meta.last_page - 1 },\n (_, i) => this.get<IBCollectionResponse<T>>(endpoint, { ...params, page: i + 2 })\n )\n\n const allResponses = await Promise.all(pageRequests)\n\n return normalizedFirstResponse.data.concat(\n allResponses.flatMap((response) => this.normalizeCollectionResponse<T>(response).data)\n )\n }\n\n setRv(value: string | number) {\n if (this.setRvFn) {\n this.setRvFn(value)\n } else {\n rv = value\n }\n }\n\n getRv() {\n if (this.getRvFn) {\n return this.getRvFn()\n }\n return rv\n }\n\n private async parseResponse<T>(payload: unknown): Promise<T> {\n if (this.isFetchResponse(payload)) {\n if (!payload.ok) {\n throw new Error(`Request failed with status ${payload.status}`)\n }\n\n return (await payload.json()) as T\n }\n\n return payload as T\n }\n\n private normalizeCollectionResponse<T>(response: ApiCollectionResponse<T>) {\n if (this.isCollectionResponseEnvelope(response)) {\n const nestedResponse = response.data\n\n return {\n data: nestedResponse.data,\n meta: (nestedResponse as IBCollectionResponse<T> & { meta?: IBMeta }).meta,\n rv: response.rv || nestedResponse.rv,\n }\n }\n\n if (Array.isArray(response)) {\n return { data: response, meta: undefined, rv: undefined }\n }\n\n if (typeof response === 'object' && response !== null && 'data' in response) {\n const {\n data,\n meta,\n rv: responseRv,\n } = response as {\n data: T[]\n meta?: IBMeta\n rv?: string | number\n }\n return { data, meta, rv: responseRv }\n }\n\n return { data: [], meta: undefined, rv: undefined }\n }\n\n private buildUrl(endpoint: string, params: Record<string, unknown>): string {\n const url = new URL(`${this.baseUrl}/v1/${endpoint}`)\n\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value))\n }\n })\n\n return url.toString()\n }\n\n private resolveRequestUrl(requestUrl?: URL | string): URL | null {\n if (!requestUrl) {\n return null\n }\n\n if (requestUrl instanceof URL) {\n return requestUrl\n }\n\n return new URL(requestUrl, 'http://localhost')\n }\n\n private isFetchResponse(value: unknown): value is Response {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'json' in value &&\n typeof (value as Response).json === 'function' &&\n 'ok' in value\n )\n }\n\n private hasRevision(value: unknown): value is { rv: string | number } {\n return typeof value === 'object' && value !== null && 'rv' in value\n }\n\n private isCollectionResponseEnvelope<T>(\n value: ApiCollectionResponse<T>\n ): value is IBResponse<IBCollectionResponse<T>> {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'data' in value &&\n typeof value.data === 'object' &&\n value.data !== null &&\n 'data' in value.data &&\n Array.isArray(value.data.data)\n )\n }\n}\n"],"names":["B10cksDataApi","client","endpoint","params","response","fullSlug","source","forceRefresh","redirects","map","target","status_code","slug","language_iso","language","bypassCache","normalizedLanguage","cacheKey","value","fallbackRv","nextRv","createB10cksDataApi","PreviewBridge","eventType","callback","listeners","selectedItem","itemId","field","event","type","payload","callbacks","previewBridge","rv","ApiClient","options","requestUrl","defaultFetch","url","firstResponse","normalizedFirstResponse","pageRequests","_","i","allResponses","nestedResponse","data","meta","responseRv","key"],"mappings":"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"}
|