@tailorkit/client-core 0.1.0-beta.23 → 0.1.0-beta.24

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.
Files changed (35) hide show
  1. package/dist/{chunk-RNTQ3LLF.js → chunk-BLDTSDUG.js} +195 -123
  2. package/dist/{chunk-K3QITWU4.js → chunk-CWDPTXSZ.js} +22 -113
  3. package/dist/chunk-FUBKKH3Q.js +96 -0
  4. package/dist/chunk-LNGQREZV.js +79 -0
  5. package/dist/chunk-N4X53WS2.js +669 -0
  6. package/dist/chunk-QWOVC765.js +222 -0
  7. package/dist/client/config.d.ts +66 -0
  8. package/dist/client/index.d.ts +7 -0
  9. package/dist/client/primitive-css.d.ts +10 -0
  10. package/dist/client/slot-types.d.ts +61 -0
  11. package/dist/client/value-memo.d.ts +2 -0
  12. package/dist/client/views.d.ts +8 -0
  13. package/dist/client.js +24 -6
  14. package/dist/index.js +48 -16
  15. package/dist/store/fetch/apps.d.ts +1 -0
  16. package/dist/store/fetch/cache.d.ts +3 -1
  17. package/dist/store/fetch/meta.d.ts +1 -0
  18. package/dist/store/fetch/preview-manager.d.ts +1 -0
  19. package/dist/store/fetch/slot.d.ts +1 -0
  20. package/dist/store/index.d.ts +2 -0
  21. package/dist/store/local/index.d.ts +7 -2
  22. package/dist/store/local/node-store.d.ts +2 -0
  23. package/dist/store/local/remote-view.d.ts +31 -0
  24. package/dist/store/local/slot-runtime.d.ts +36 -0
  25. package/dist/store/local/view-context-diagnostics.d.ts +10 -0
  26. package/dist/store/local/view-context-types.d.ts +21 -0
  27. package/dist/store/local/{view-registry.d.ts → view-context.d.ts} +5 -2
  28. package/dist/store/query.d.ts +39 -0
  29. package/dist/store/snapshot-store.d.ts +5 -0
  30. package/dist/store/store.d.ts +4 -1
  31. package/dist/store-fetch.js +5 -4
  32. package/dist/store-local.js +11 -3
  33. package/package.json +6 -5
  34. package/dist/chunk-DPR3U4U2.js +0 -57
  35. package/dist/chunk-ED3BWTXG.js +0 -128
@@ -1,5 +1,52 @@
1
1
  // src/store/fetch/cache.ts
2
- import { atom } from "nanostores";
2
+ import { computedAsync } from "@nanostores/async";
3
+
4
+ // src/store/snapshot-store.ts
5
+ import { atom, onStart, onStop, readonlyType } from "nanostores";
6
+ function createSnapshotStore(getSnapshot, subscribe) {
7
+ const state = atom(getSnapshot());
8
+ let stop;
9
+ const sync = () => state.set(getSnapshot());
10
+ state.get = () => {
11
+ sync();
12
+ return state.value;
13
+ };
14
+ onStart(state, () => {
15
+ stop = subscribe(sync);
16
+ sync();
17
+ });
18
+ onStop(state, () => {
19
+ stop?.();
20
+ stop = void 0;
21
+ });
22
+ return readonlyType(state);
23
+ }
24
+ function switchStore(selection) {
25
+ return createSnapshotStore(
26
+ () => selection.get().get(),
27
+ (listener) => {
28
+ let current = selection.get();
29
+ let stopCurrent = current.listen(listener);
30
+ const stopSelection = selection.listen(() => {
31
+ const next = selection.get();
32
+ if (next !== current) {
33
+ const previousStop = stopCurrent;
34
+ current = next;
35
+ stopCurrent = next.listen(listener);
36
+ previousStop();
37
+ }
38
+ listener();
39
+ });
40
+ return () => {
41
+ stopSelection();
42
+ stopCurrent();
43
+ };
44
+ }
45
+ );
46
+ }
47
+
48
+ // src/store/fetch/cache.ts
49
+ import { atom as atom2 } from "nanostores";
3
50
  var idle = () => ({
4
51
  data: void 0,
5
52
  error: null,
@@ -63,7 +110,7 @@ function createFetchCache(defaults = {}) {
63
110
  let entry = entries.get(key);
64
111
  if (!entry) {
65
112
  entry = {
66
- state: atom(idle()),
113
+ state: atom2(idle()),
67
114
  controller: null,
68
115
  pending: null,
69
116
  observers: 0,
@@ -123,38 +170,42 @@ function createFetchCache(defaults = {}) {
123
170
  const controller = new AbortController();
124
171
  entry.controller = controller;
125
172
  const generation = ++entry.generation;
126
- const run = async () => {
127
- try {
128
- const data = await fetcher(controller.signal);
129
- if (entry.generation !== generation) return;
130
- entry.invalidated = false;
131
- entry.state.set({
132
- data,
133
- error: null,
134
- status: "ready",
135
- isFetching: false,
136
- updatedAt: Date.now()
137
- });
138
- } catch (error) {
139
- if (entry.generation !== generation) return;
140
- entry.state.set({
141
- ...entry.state.get(),
142
- error: error instanceof Error ? error : new Error(String(error)),
143
- status: "error",
144
- isFetching: false
145
- });
146
- } finally {
147
- if (entry.generation === generation) {
148
- entry.controller = null;
149
- entry.pending = null;
150
- scheduleGc(key, entry);
151
- }
152
- }
153
- };
154
173
  let start;
155
174
  const pending = new Promise((resolve) => {
156
175
  start = () => {
157
- void run().then(resolve);
176
+ const request = computedAsync(atom2(controller.signal), (signal) => {
177
+ signal.throwIfAborted();
178
+ return fetcher(signal);
179
+ });
180
+ const stop = request.listen((result) => {
181
+ if (result.state === "loading") return;
182
+ stop();
183
+ if (entry.generation === generation) {
184
+ if (result.state === "ready") {
185
+ entry.invalidated = false;
186
+ entry.state.set({
187
+ data: result.value,
188
+ error: null,
189
+ status: "ready",
190
+ isFetching: false,
191
+ updatedAt: Date.now()
192
+ });
193
+ } else {
194
+ entry.state.set({
195
+ ...entry.state.get(),
196
+ error: result.error instanceof Error ? result.error : new Error(String(result.error)),
197
+ status: "error",
198
+ isFetching: false
199
+ });
200
+ }
201
+ if (entry.generation === generation) {
202
+ entry.controller = null;
203
+ entry.pending = null;
204
+ scheduleGc(key, entry);
205
+ }
206
+ }
207
+ resolve();
208
+ });
158
209
  };
159
210
  });
160
211
  entry.pending = pending;
@@ -190,7 +241,7 @@ function createFetchCache(defaults = {}) {
190
241
  return entry.observers ? store.fetch({ force: true }) : Promise.resolve();
191
242
  }
192
243
  };
193
- return store;
244
+ return { ...store, state: createSnapshotStore(store.getSnapshot, store.subscribe) };
194
245
  },
195
246
  clear() {
196
247
  for (const [key, entry] of entries) {
@@ -208,95 +259,6 @@ function toBaseUrl(value) {
208
259
  return url;
209
260
  }
210
261
 
211
- // src/client/endpoints.ts
212
- import { createClient, createSessionProvider, reference } from "@tailorkit/app/client";
213
- import { previewMetadataSchema } from "@tailorkit/client-platform/preview";
214
- var resolveInstances = reference(
215
- "_tailorkit.instances.resolve",
216
- "action"
217
- );
218
- function createEndpointClient(options) {
219
- const baseUrl = toBaseUrl(options.baseUrl);
220
- const request = (input, init) => (options.fetch ?? globalThis.fetch)(input, init);
221
- const sessions = /* @__PURE__ */ new Map();
222
- const createSessionEntry = (appId, key) => ({
223
- key,
224
- session: createSessionProvider({ baseUrl, appId, fetch: request }),
225
- // Mounted consumers keep this wrapper, so resolve the current provider on every call.
226
- provider: async (input) => {
227
- let current = sessions.get(appId);
228
- if (!current) {
229
- current = createSessionEntry(appId);
230
- sessions.set(appId, current);
231
- }
232
- const session = current.session;
233
- const value = await session(input);
234
- if (current.session !== session) {
235
- throw new DOMException("The app session was invalidated", "AbortError");
236
- }
237
- return value;
238
- }
239
- });
240
- const getSessionProvider = (app) => {
241
- const key = JSON.stringify([app.currentDeployment?.id, app.preview?.sessionId]);
242
- let entry = sessions.get(app.id);
243
- if (entry && entry.key === void 0) entry.key = key;
244
- if (!entry || entry.key !== key) {
245
- if (entry) entry.session = void 0;
246
- entry = createSessionEntry(app.id, key);
247
- sessions.set(app.id, entry);
248
- }
249
- return entry.provider;
250
- };
251
- return {
252
- baseUrl,
253
- async apps(signal) {
254
- const response = await request(new URL("apps", baseUrl), {
255
- signal,
256
- credentials: "same-origin"
257
- });
258
- if (!response.ok)
259
- throw new Error(`Unable to fetch TailorKit apps from ${baseUrl.toString()}.`);
260
- return await response.json();
261
- },
262
- async meta(signal) {
263
- const response = await request(new URL("meta", baseUrl), {
264
- signal,
265
- credentials: "same-origin"
266
- });
267
- if (!response.ok)
268
- throw new Error(`Unable to fetch TailorKit metadata from ${baseUrl.toString()}.`);
269
- const value = await response.json();
270
- return { ...value, assetsBaseUrl: value.assetsBaseUrl ?? null };
271
- },
272
- async slotInstances(app, input, signal) {
273
- signal.throwIfAborted();
274
- const backend = createClient({ getSession: getSessionProvider(app), fetch: request });
275
- const abort = () => backend.close();
276
- signal.addEventListener("abort", abort, { once: true });
277
- try {
278
- return await backend.action(resolveInstances, input);
279
- } finally {
280
- signal.removeEventListener("abort", abort);
281
- backend.close();
282
- }
283
- },
284
- async previewMetadata(sessionId) {
285
- const url = new URL("preview/metadata", baseUrl);
286
- url.searchParams.set("sessionId", sessionId);
287
- const response = await request(url, { credentials: "same-origin" });
288
- if (response.status === 404) return null;
289
- if (!response.ok) throw new Error("Unable to refresh TailorKit preview metadata.");
290
- return previewMetadataSchema.parse(await response.json());
291
- },
292
- getSessionProvider,
293
- clearSessions: () => {
294
- for (const entry of sessions.values()) entry.session = void 0;
295
- sessions.clear();
296
- }
297
- };
298
- }
299
-
300
262
  // src/client/slot-view.ts
301
263
  import { composeViewContext, getViewHierarchy } from "@tailorkit/core/views";
302
264
  function selectSlotView(views, slot, activePath, schema) {
@@ -318,11 +280,121 @@ function resolveSlotView(views, slot, activeView, schema) {
318
280
  };
319
281
  }
320
282
 
283
+ // src/store/fetch/slot.ts
284
+ function createSlotStore(client, options) {
285
+ const {
286
+ apps,
287
+ slot,
288
+ activeView,
289
+ staleTime,
290
+ gcTime,
291
+ appsStatus = "ready",
292
+ appsError = null
293
+ } = options;
294
+ const enabled = appsStatus === "ready";
295
+ const settings = {
296
+ ...staleTime === void 0 ? {} : { staleTime },
297
+ ...gcTime === void 0 ? {} : { gcTime }
298
+ };
299
+ const waiting = {
300
+ data: void 0,
301
+ error: appsStatus === "error" ? appsError : null,
302
+ status: appsStatus,
303
+ isFetching: false
304
+ };
305
+ const query = client.cache.getStore(
306
+ ["tailorkit", client.baseUrl.toString(), "slot", apps, slot, activeView],
307
+ async (signal) => {
308
+ const candidates = apps.filter(
309
+ (app) => app.views?.some((view) => view.slot === slot && !view.disabled)
310
+ );
311
+ if (!candidates.length) return { status: "ready", data: [] };
312
+ const meta = client.meta();
313
+ await meta.fetch();
314
+ signal.throwIfAborted();
315
+ const snapshot2 = meta.getSnapshot();
316
+ if (snapshot2.error) throw snapshot2.error;
317
+ if (!snapshot2.data) throw new Error("TailorKit metadata is unavailable.");
318
+ const schema = snapshot2.data.schema;
319
+ const definition = schema.slots[slot];
320
+ if (!definition) return { status: "ready", data: [] };
321
+ if (definition.multiple !== true) {
322
+ return {
323
+ status: "ready",
324
+ data: candidates.filter(
325
+ (app) => app.views?.some(
326
+ (view) => view.slot === slot && !view.disabled && !view.instances && definition.views.includes(view.path)
327
+ )
328
+ ).map((app) => ({ app }))
329
+ };
330
+ }
331
+ if (activeView === null) return { status: "idle" };
332
+ const matches = candidates.flatMap((app) => {
333
+ const resolved = resolveSlotView(app.views ?? [], slot, activeView, schema);
334
+ return resolved?.instances ? [{ app, resolved }] : [];
335
+ });
336
+ for (const { resolved } of matches) {
337
+ if (resolved.status === "error")
338
+ throw new Error(`Context for view "${resolved.view}" is unavailable.`);
339
+ }
340
+ if (matches.some(({ resolved }) => resolved.status !== "ready")) return { status: "loading" };
341
+ const controller = new AbortController();
342
+ const abort = () => controller.abort();
343
+ signal.addEventListener("abort", abort, { once: true });
344
+ try {
345
+ const results = await Promise.all(
346
+ matches.map(async ({ app, resolved }) => {
347
+ if (resolved.status !== "ready") return [];
348
+ const data = await client.endpoints.slotInstances(
349
+ app,
350
+ { slot, path: resolved.view, context: resolved.context },
351
+ controller.signal
352
+ );
353
+ return data.map((instance) => ({ ...instance, app }));
354
+ })
355
+ );
356
+ return { status: "ready", data: results.flat() };
357
+ } catch (error) {
358
+ controller.abort();
359
+ throw error;
360
+ } finally {
361
+ signal.removeEventListener("abort", abort);
362
+ }
363
+ },
364
+ { ...client.cacheOptions?.slot, ...settings, abortOnUnsubscribe: true }
365
+ );
366
+ let last;
367
+ let snapshot;
368
+ const store = {
369
+ getSnapshot() {
370
+ if (!enabled) return waiting;
371
+ const current = query.getSnapshot();
372
+ if (current !== last) {
373
+ snapshot = {
374
+ data: current.data?.data,
375
+ error: current.error,
376
+ status: current.status === "ready" ? current.data.status : current.status,
377
+ isFetching: current.isFetching
378
+ };
379
+ last = current;
380
+ }
381
+ return snapshot;
382
+ },
383
+ subscribe: (listener) => enabled ? query.subscribe(listener) : () => {
384
+ },
385
+ fetch: (fetchOptions = {}) => enabled ? query.fetch(fetchOptions) : Promise.resolve(),
386
+ invalidate: () => enabled ? query.invalidate() : Promise.resolve()
387
+ };
388
+ return { ...store, state: createSnapshotStore(store.getSnapshot, store.subscribe) };
389
+ }
390
+
321
391
  export {
392
+ createSnapshotStore,
393
+ switchStore,
322
394
  serializeCacheKey,
323
395
  createFetchCache,
324
396
  toBaseUrl,
325
- createEndpointClient,
326
397
  selectSlotView,
327
- resolveSlotView
398
+ resolveSlotView,
399
+ createSlotStore
328
400
  };
@@ -1,7 +1,9 @@
1
1
  import {
2
- createEndpointClient,
3
- resolveSlotView
4
- } from "./chunk-RNTQ3LLF.js";
2
+ createEndpointClient
3
+ } from "./chunk-FUBKKH3Q.js";
4
+ import {
5
+ createSnapshotStore
6
+ } from "./chunk-BLDTSDUG.js";
5
7
 
6
8
  // src/store/fetch/apps.ts
7
9
  import { atom } from "nanostores";
@@ -77,7 +79,7 @@ function createAppsStore(client, initialApps) {
77
79
  },
78
80
  invalidate: () => supplied ? Promise.resolve() : query.invalidate()
79
81
  };
80
- return store;
82
+ return { ...store, state: createSnapshotStore(store.getSnapshot, store.subscribe) };
81
83
  }
82
84
 
83
85
  // src/store/fetch/meta.ts
@@ -85,7 +87,7 @@ function createMetadataStore(client) {
85
87
  const query = client.meta();
86
88
  let last;
87
89
  let snapshot;
88
- return {
90
+ const store = {
89
91
  getSnapshot() {
90
92
  const current = query.getSnapshot();
91
93
  if (current !== last) {
@@ -104,6 +106,7 @@ function createMetadataStore(client) {
104
106
  fetch: query.fetch,
105
107
  invalidate: query.invalidate
106
108
  };
109
+ return { ...store, state: createSnapshotStore(store.getSnapshot, store.subscribe) };
107
110
  }
108
111
 
109
112
  // src/store/fetch/preview-manager.ts
@@ -275,7 +278,7 @@ function createPreviewManager(baseUrl, onEnded, onViews, refreshMetadata = creat
275
278
  }
276
279
  });
277
280
  };
278
- return {
281
+ const manager = {
279
282
  getSnapshot: (sessionId) => entries.get(sessionId)?.state.get() ?? empty,
280
283
  updateApp: (app) => {
281
284
  const sessionId = app.preview?.sessionId;
@@ -330,118 +333,24 @@ function createPreviewManager(baseUrl, onEnded, onViews, refreshMetadata = creat
330
333
  entries.clear();
331
334
  }
332
335
  };
333
- }
334
-
335
- // src/store/fetch/slot.ts
336
- function createSlotStore(client, options) {
337
- const {
338
- apps,
339
- slot,
340
- activeView,
341
- staleTime,
342
- gcTime,
343
- appsStatus = "ready",
344
- appsError = null
345
- } = options;
346
- const enabled = appsStatus === "ready";
347
- const settings = {
348
- ...staleTime === void 0 ? {} : { staleTime },
349
- ...gcTime === void 0 ? {} : { gcTime }
350
- };
351
- const waiting = {
352
- data: void 0,
353
- error: appsStatus === "error" ? appsError : null,
354
- status: appsStatus,
355
- isFetching: false
356
- };
357
- const query = client.cache.getStore(
358
- ["tailorkit", client.baseUrl.toString(), "slot", apps, slot, activeView],
359
- async (signal) => {
360
- const candidates = apps.filter(
361
- (app) => app.views?.some((view) => view.slot === slot && !view.disabled)
362
- );
363
- if (!candidates.length) return { status: "ready", data: [] };
364
- const meta = client.meta();
365
- await meta.fetch();
366
- signal.throwIfAborted();
367
- const snapshot2 = meta.getSnapshot();
368
- if (snapshot2.error) throw snapshot2.error;
369
- if (!snapshot2.data) throw new Error("TailorKit metadata is unavailable.");
370
- const schema = snapshot2.data.schema;
371
- const definition = schema.slots[slot];
372
- if (!definition) return { status: "ready", data: [] };
373
- if (definition.multiple !== true) {
374
- return {
375
- status: "ready",
376
- data: candidates.filter(
377
- (app) => app.views?.some(
378
- (view) => view.slot === slot && !view.disabled && !view.instances && definition.views.includes(view.path)
379
- )
380
- ).map((app) => ({ app }))
381
- };
382
- }
383
- if (activeView === null) return { status: "idle" };
384
- const matches = candidates.flatMap((app) => {
385
- const resolved = resolveSlotView(app.views ?? [], slot, activeView, schema);
386
- return resolved?.instances ? [{ app, resolved }] : [];
387
- });
388
- for (const { resolved } of matches) {
389
- if (resolved.status === "error")
390
- throw new Error(`Context for view "${resolved.view}" is unavailable.`);
391
- }
392
- if (matches.some(({ resolved }) => resolved.status !== "ready")) return { status: "loading" };
393
- const controller = new AbortController();
394
- const abort = () => controller.abort();
395
- signal.addEventListener("abort", abort, { once: true });
396
- try {
397
- const results = await Promise.all(
398
- matches.map(async ({ app, resolved }) => {
399
- if (resolved.status !== "ready") return [];
400
- const data = await client.endpoints.slotInstances(
401
- app,
402
- { slot, path: resolved.view, context: resolved.context },
403
- controller.signal
404
- );
405
- return data.map((instance) => ({ ...instance, app }));
406
- })
407
- );
408
- return { status: "ready", data: results.flat() };
409
- } catch (error) {
410
- controller.abort();
411
- throw error;
412
- } finally {
413
- signal.removeEventListener("abort", abort);
414
- }
415
- },
416
- { ...client.cacheOptions?.slot, ...settings, abortOnUnsubscribe: true }
417
- );
418
- let last;
419
- let snapshot;
420
336
  return {
421
- getSnapshot() {
422
- if (!enabled) return waiting;
423
- const current = query.getSnapshot();
424
- if (current !== last) {
425
- snapshot = {
426
- data: current.data?.data,
427
- error: current.error,
428
- status: current.status === "ready" ? current.data.status : current.status,
429
- isFetching: current.isFetching
430
- };
431
- last = current;
432
- }
433
- return snapshot;
434
- },
435
- subscribe: (listener) => enabled ? query.subscribe(listener) : () => {
436
- },
437
- fetch: (fetchOptions = {}) => enabled ? query.fetch(fetchOptions) : Promise.resolve(),
438
- invalidate: () => enabled ? query.invalidate() : Promise.resolve()
337
+ ...manager,
338
+ getStore(getApp) {
339
+ const sessionId = getApp().preview?.sessionId ?? "";
340
+ return createSnapshotStore(
341
+ () => manager.getSnapshot(sessionId),
342
+ (listener) => {
343
+ const app = getApp();
344
+ return app.preview?.sessionId === sessionId ? manager.subscribe(app, listener) : () => {
345
+ };
346
+ }
347
+ );
348
+ }
439
349
  };
440
350
  }
441
351
 
442
352
  export {
443
353
  createAppsStore,
444
354
  createMetadataStore,
445
- createPreviewManager,
446
- createSlotStore
355
+ createPreviewManager
447
356
  };
@@ -0,0 +1,96 @@
1
+ import {
2
+ toBaseUrl
3
+ } from "./chunk-BLDTSDUG.js";
4
+
5
+ // src/client/endpoints.ts
6
+ import { createClient, createSessionProvider, reference } from "@tailorkit/app/client/connection";
7
+ import { previewMetadataSchema } from "@tailorkit/client-platform/preview";
8
+ var resolveInstances = reference(
9
+ "_tailorkit.instances.resolve",
10
+ "action"
11
+ );
12
+ function createEndpointClient(options) {
13
+ const baseUrl = toBaseUrl(options.baseUrl);
14
+ const request = (input, init) => (options.fetch ?? globalThis.fetch)(input, init);
15
+ const sessions = /* @__PURE__ */ new Map();
16
+ const createSessionEntry = (appId, key) => ({
17
+ key,
18
+ session: createSessionProvider({ baseUrl, appId, fetch: request }),
19
+ // Mounted consumers keep this wrapper, so resolve the current provider on every call.
20
+ provider: async (input) => {
21
+ let current = sessions.get(appId);
22
+ if (!current) {
23
+ current = createSessionEntry(appId);
24
+ sessions.set(appId, current);
25
+ }
26
+ const session = current.session;
27
+ const value = await session(input);
28
+ if (current.session !== session) {
29
+ throw new DOMException("The app session was invalidated", "AbortError");
30
+ }
31
+ return value;
32
+ }
33
+ });
34
+ const getSessionProvider = (app) => {
35
+ const key = JSON.stringify([app.currentDeployment?.id, app.preview?.sessionId]);
36
+ let entry = sessions.get(app.id);
37
+ if (entry && entry.key === void 0) entry.key = key;
38
+ if (!entry || entry.key !== key) {
39
+ if (entry) entry.session = void 0;
40
+ entry = createSessionEntry(app.id, key);
41
+ sessions.set(app.id, entry);
42
+ }
43
+ return entry.provider;
44
+ };
45
+ return {
46
+ baseUrl,
47
+ async apps(signal) {
48
+ const response = await request(new URL("apps", baseUrl), {
49
+ signal,
50
+ credentials: "same-origin"
51
+ });
52
+ if (!response.ok)
53
+ throw new Error(`Unable to fetch TailorKit apps from ${baseUrl.toString()}.`);
54
+ return await response.json();
55
+ },
56
+ async meta(signal) {
57
+ const response = await request(new URL("meta", baseUrl), {
58
+ signal,
59
+ credentials: "same-origin"
60
+ });
61
+ if (!response.ok)
62
+ throw new Error(`Unable to fetch TailorKit metadata from ${baseUrl.toString()}.`);
63
+ const value = await response.json();
64
+ return { ...value, assetsBaseUrl: value.assetsBaseUrl ?? null };
65
+ },
66
+ async slotInstances(app, input, signal) {
67
+ signal.throwIfAborted();
68
+ const backend = createClient({ getSession: getSessionProvider(app), fetch: request });
69
+ const abort = () => backend.close();
70
+ signal.addEventListener("abort", abort, { once: true });
71
+ try {
72
+ return await backend.action(resolveInstances, input);
73
+ } finally {
74
+ signal.removeEventListener("abort", abort);
75
+ backend.close();
76
+ }
77
+ },
78
+ async previewMetadata(sessionId) {
79
+ const url = new URL("preview/metadata", baseUrl);
80
+ url.searchParams.set("sessionId", sessionId);
81
+ const response = await request(url, { credentials: "same-origin" });
82
+ if (response.status === 404) return null;
83
+ if (!response.ok) throw new Error("Unable to refresh TailorKit preview metadata.");
84
+ return previewMetadataSchema.parse(await response.json());
85
+ },
86
+ getSessionProvider,
87
+ clearSessions: () => {
88
+ for (const entry of sessions.values()) entry.session = void 0;
89
+ sessions.clear();
90
+ }
91
+ };
92
+ }
93
+
94
+ export {
95
+ createEndpointClient
96
+ };