@fragno-dev/stripe 0.0.2 → 0.1.1
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 +7 -0
- package/dist/browser/client/react.d.ts +130 -121
- package/dist/browser/client/react.js +1 -1
- package/dist/browser/client/react.js.map +1 -1
- package/dist/browser/client/solid.d.ts +130 -121
- package/dist/browser/client/solid.js +1 -1
- package/dist/browser/client/solid.js.map +1 -1
- package/dist/browser/client/svelte.d.ts +130 -121
- package/dist/browser/client/svelte.d.ts.map +1 -1
- package/dist/browser/client/svelte.js +1 -1
- package/dist/browser/client/svelte.js.map +1 -1
- package/dist/browser/client/vanilla.d.ts +129 -120
- package/dist/browser/client/vanilla.d.ts.map +1 -1
- package/dist/browser/client/vanilla.js +5 -2
- package/dist/browser/client/vanilla.js.map +1 -1
- package/dist/browser/client/vue.d.ts +130 -121
- package/dist/browser/client/vue.d.ts.map +1 -1
- package/dist/browser/client/vue.js +1 -1
- package/dist/browser/client/vue.js.map +1 -1
- package/dist/browser/index.d.ts +326 -511
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/{src-k2PmVjgJ.js → src-D6S1gN3I.js} +837 -766
- package/dist/browser/src-D6S1gN3I.js.map +1 -0
- package/dist/node/index.d.ts +93 -278
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +247 -196
- package/dist/node/index.js.map +1 -1
- package/package.json +6 -6
- package/dist/browser/src-k2PmVjgJ.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -1,18 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineFragment, defineRoutes } from "@fragno-dev/core";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
|
-
//#region ../fragno/dist/route
|
|
4
|
+
//#region ../fragno/dist/api/route.js
|
|
5
|
+
/**
|
|
6
|
+
* Helper to resolve route factories into routes
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
5
9
|
function resolveRouteFactories(context, routesOrFactories) {
|
|
6
|
-
const routes = [];
|
|
10
|
+
const routes$1 = [];
|
|
7
11
|
for (const item of routesOrFactories) if (typeof item === "function") {
|
|
8
12
|
const factoryRoutes = item(context);
|
|
9
|
-
routes.push(...factoryRoutes);
|
|
10
|
-
} else routes.push(item);
|
|
11
|
-
return routes;
|
|
13
|
+
routes$1.push(...factoryRoutes);
|
|
14
|
+
} else routes$1.push(item);
|
|
15
|
+
return routes$1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region ../fragno/dist/api/internal/route.js
|
|
20
|
+
function getMountRoute(opts) {
|
|
21
|
+
const mountRoute = opts.mountRoute ?? `/api/${opts.name}`;
|
|
22
|
+
if (mountRoute.endsWith("/")) return mountRoute.slice(0, -1);
|
|
23
|
+
return mountRoute;
|
|
12
24
|
}
|
|
13
25
|
|
|
14
26
|
//#endregion
|
|
15
|
-
//#region ../fragno/dist/
|
|
27
|
+
//#region ../fragno/dist/api/error.js
|
|
16
28
|
var FragnoApiError = class extends Error {
|
|
17
29
|
#status;
|
|
18
30
|
#code;
|
|
@@ -56,11 +68,9 @@ var FragnoApiValidationError = class extends FragnoApiError {
|
|
|
56
68
|
}, { status: this.status });
|
|
57
69
|
}
|
|
58
70
|
};
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return mountRoute;
|
|
63
|
-
}
|
|
71
|
+
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region ../fragno/dist/api/request-input-context.js
|
|
64
74
|
var RequestInputContext = class RequestInputContext$1 {
|
|
65
75
|
#path;
|
|
66
76
|
#method;
|
|
@@ -172,6 +182,9 @@ var RequestInputContext = class RequestInputContext$1 {
|
|
|
172
182
|
return result.value;
|
|
173
183
|
}
|
|
174
184
|
};
|
|
185
|
+
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region ../fragno/dist/api/internal/response-stream.js
|
|
175
188
|
var ResponseStream = class {
|
|
176
189
|
#writer;
|
|
177
190
|
#encoder;
|
|
@@ -248,6 +261,9 @@ var ResponseStream = class {
|
|
|
248
261
|
}
|
|
249
262
|
}
|
|
250
263
|
};
|
|
264
|
+
|
|
265
|
+
//#endregion
|
|
266
|
+
//#region ../fragno/dist/api/request-output-context.js
|
|
251
267
|
/**
|
|
252
268
|
* Utility function to merge headers from multiple sources.
|
|
253
269
|
* Later headers override earlier ones.
|
|
@@ -362,188 +378,534 @@ var RequestOutputContext = class extends OutputContext {
|
|
|
362
378
|
};
|
|
363
379
|
|
|
364
380
|
//#endregion
|
|
365
|
-
//#region
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
381
|
+
//#region ../fragno/dist/api/internal/path.js
|
|
382
|
+
/**
|
|
383
|
+
* Extract parameter names from a path pattern at runtime.
|
|
384
|
+
* Examples:
|
|
385
|
+
* - "/users/:id" => ["id"]
|
|
386
|
+
* - "/files/**" => ["**"]
|
|
387
|
+
* - "/files/**:rest" => ["rest"]
|
|
388
|
+
*/
|
|
389
|
+
function extractPathParams(pathPattern) {
|
|
390
|
+
const segments = pathPattern.split("/").filter((s) => s.length > 0);
|
|
391
|
+
const names = [];
|
|
392
|
+
for (const segment of segments) {
|
|
393
|
+
if (segment.startsWith(":")) {
|
|
394
|
+
names.push(segment.slice(1));
|
|
395
|
+
continue;
|
|
376
396
|
}
|
|
377
|
-
|
|
397
|
+
if (segment === "**") {
|
|
398
|
+
names.push("**");
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
if (segment.startsWith("**:")) {
|
|
402
|
+
names.push(segment.slice(3));
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return names;
|
|
378
407
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
408
|
+
/**
|
|
409
|
+
* Build a concrete path by replacing placeholders in a path pattern with values.
|
|
410
|
+
*
|
|
411
|
+
* Supports the same placeholder syntax as the matcher:
|
|
412
|
+
* - Named parameter ":name" is URL-encoded as a single segment
|
|
413
|
+
* - Anonymous wildcard "**" inserts the remainder as-is (slashes preserved)
|
|
414
|
+
* - Named wildcard "**:name" inserts the remainder from the named key
|
|
415
|
+
*
|
|
416
|
+
* Examples:
|
|
417
|
+
* - buildPath("/users/:id", { id: "123" }) => "/users/123"
|
|
418
|
+
* - buildPath("/files/**", { "**": "a/b" }) => "/files/a/b"
|
|
419
|
+
* - buildPath("/files/**:rest", { rest: "a/b" }) => "/files/a/b"
|
|
420
|
+
*/
|
|
421
|
+
function buildPath(pathPattern, params) {
|
|
422
|
+
const patternSegments = pathPattern.split("/");
|
|
423
|
+
const builtSegments = [];
|
|
424
|
+
for (const segment of patternSegments) {
|
|
425
|
+
if (segment.length === 0) {
|
|
426
|
+
builtSegments.push("");
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
if (segment.startsWith(":")) {
|
|
430
|
+
const name = segment.slice(1);
|
|
431
|
+
const value = params[name];
|
|
432
|
+
if (value === void 0) throw new Error(`Missing value for path parameter :${name}`);
|
|
433
|
+
builtSegments.push(encodeURIComponent(value));
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
if (segment === "**") {
|
|
437
|
+
const value = params["**"];
|
|
438
|
+
if (value === void 0) throw new Error("Missing value for path wildcard **");
|
|
439
|
+
builtSegments.push(value);
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
if (segment.startsWith("**:")) {
|
|
443
|
+
const name = segment.slice(3);
|
|
444
|
+
const value = params[name];
|
|
445
|
+
if (value === void 0) throw new Error(`Missing value for path wildcard **:${name}`);
|
|
446
|
+
builtSegments.push(value);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
builtSegments.push(segment);
|
|
450
|
+
}
|
|
451
|
+
return builtSegments.join("/");
|
|
384
452
|
}
|
|
385
453
|
|
|
386
454
|
//#endregion
|
|
387
|
-
//#region
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
455
|
+
//#region ../fragno/dist/client/client-error.js
|
|
456
|
+
/**
|
|
457
|
+
* Base error class for all Fragno client errors.
|
|
458
|
+
*/
|
|
459
|
+
var FragnoClientError = class extends Error {
|
|
460
|
+
#code;
|
|
461
|
+
constructor(message, code, options = {}) {
|
|
462
|
+
super(message, { cause: options.cause });
|
|
463
|
+
this.name = "FragnoClientError";
|
|
464
|
+
this.#code = code;
|
|
465
|
+
}
|
|
466
|
+
get code() {
|
|
467
|
+
return this.#code;
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
var FragnoClientFetchError = class extends FragnoClientError {
|
|
471
|
+
constructor(message, code, options = {}) {
|
|
472
|
+
super(message, code, options);
|
|
473
|
+
this.name = "FragnoClientFetchError";
|
|
474
|
+
}
|
|
475
|
+
static fromUnknownFetchError(error) {
|
|
476
|
+
if (!(error instanceof Error)) return new FragnoClientFetchNetworkError("Network request failed", { cause: error });
|
|
477
|
+
if (error.name === "AbortError") return new FragnoClientFetchAbortError("Request was aborted", { cause: error });
|
|
478
|
+
return new FragnoClientFetchNetworkError("Network request failed", { cause: error });
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
/**
|
|
482
|
+
* Error thrown when a network request fails (e.g., no internet connection, DNS failure).
|
|
483
|
+
*/
|
|
484
|
+
var FragnoClientFetchNetworkError = class extends FragnoClientFetchError {
|
|
485
|
+
constructor(message = "Network request failed", options = {}) {
|
|
486
|
+
super(message, "NETWORK_ERROR", options);
|
|
487
|
+
this.name = "FragnoClientFetchNetworkError";
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
/**
|
|
491
|
+
* Error thrown when a request is aborted (e.g., user cancels request, timeout).
|
|
492
|
+
*/
|
|
493
|
+
var FragnoClientFetchAbortError = class extends FragnoClientFetchError {
|
|
494
|
+
constructor(message = "Request was aborted", options = {}) {
|
|
495
|
+
super(message, "ABORT_ERROR", options);
|
|
496
|
+
this.name = "FragnoClientFetchAbortError";
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
/**
|
|
500
|
+
* Error thrown when the API result is unexpected, e.g. no json is returned.
|
|
501
|
+
*/
|
|
502
|
+
var FragnoClientUnknownApiError = class extends FragnoClientError {
|
|
503
|
+
#status;
|
|
504
|
+
constructor(message = "Unknown API error", status, options = {}) {
|
|
505
|
+
super(message, "UNKNOWN_API_ERROR", options);
|
|
506
|
+
this.name = "FragnoClientUnknownApiError";
|
|
507
|
+
this.#status = status;
|
|
508
|
+
}
|
|
509
|
+
get status() {
|
|
510
|
+
return this.#status;
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
var FragnoClientApiError = class FragnoClientApiError$1 extends FragnoClientError {
|
|
514
|
+
#status;
|
|
515
|
+
constructor({ message, code }, status, options = {}) {
|
|
516
|
+
super(message, code, options);
|
|
517
|
+
this.name = "FragnoClientApiError";
|
|
518
|
+
this.#status = status;
|
|
519
|
+
}
|
|
520
|
+
get status() {
|
|
521
|
+
return this.#status;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* The error code returned by the API.
|
|
525
|
+
*
|
|
526
|
+
* The type is `TErrorCode` (the set of known error codes for this route), but may also be a string
|
|
527
|
+
* for forward compatibility with future error codes.
|
|
528
|
+
*/
|
|
529
|
+
get code() {
|
|
530
|
+
return super.code;
|
|
531
|
+
}
|
|
532
|
+
static async fromResponse(response) {
|
|
533
|
+
const unknown = await response.json();
|
|
534
|
+
const status = response.status;
|
|
535
|
+
if (!("message" in unknown || "code" in unknown)) return new FragnoClientUnknownApiError("Unknown API error", status);
|
|
536
|
+
if (!(typeof unknown.message === "string" && typeof unknown.code === "string")) return new FragnoClientUnknownApiError("Unknown API error", status);
|
|
537
|
+
return new FragnoClientApiError$1({
|
|
538
|
+
message: unknown.message,
|
|
539
|
+
code: unknown.code
|
|
540
|
+
}, status);
|
|
541
|
+
}
|
|
446
542
|
};
|
|
447
543
|
|
|
448
544
|
//#endregion
|
|
449
|
-
//#region
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
545
|
+
//#region ../fragno/dist/util/content-type.js
|
|
546
|
+
/**
|
|
547
|
+
* Parses a content-type header string into its components
|
|
548
|
+
*
|
|
549
|
+
* @param contentType - The content-type header value to parse
|
|
550
|
+
* @returns A ParsedContentType object or null if the input is invalid
|
|
551
|
+
*
|
|
552
|
+
* @example
|
|
553
|
+
* ```ts
|
|
554
|
+
* const { type, subtype, mediaType, parameters }
|
|
555
|
+
* = parseContentType("application/json; charset=utf-8");
|
|
556
|
+
* console.assert(type === "application");
|
|
557
|
+
* console.assert(subtype === "json");
|
|
558
|
+
* console.assert(mediaType === "application/json");
|
|
559
|
+
* console.assert(parameters["charset"] === "utf-8");
|
|
560
|
+
*/
|
|
561
|
+
function parseContentType(contentType) {
|
|
562
|
+
if (!contentType || typeof contentType !== "string") return null;
|
|
563
|
+
const trimmed = contentType.trim();
|
|
564
|
+
if (!trimmed) return null;
|
|
565
|
+
const parts = trimmed.split(";").map((part) => part.trim());
|
|
566
|
+
const mediaType = parts[0];
|
|
567
|
+
if (!mediaType) return null;
|
|
568
|
+
const typeParts = mediaType.split("/");
|
|
569
|
+
if (typeParts.length !== 2) return null;
|
|
570
|
+
const [type, subtype] = typeParts.map((part) => part.trim().toLowerCase());
|
|
571
|
+
if (!type || !subtype) return null;
|
|
572
|
+
const parameters = {};
|
|
573
|
+
for (let i = 1; i < parts.length; i++) {
|
|
574
|
+
const param = parts[i];
|
|
575
|
+
const equalIndex = param.indexOf("=");
|
|
576
|
+
if (equalIndex > 0) {
|
|
577
|
+
const key = param.slice(0, equalIndex).trim().toLowerCase();
|
|
578
|
+
let value = param.slice(equalIndex + 1).trim();
|
|
579
|
+
if (value.startsWith("\"") && value.endsWith("\"")) value = value.slice(1, -1);
|
|
580
|
+
if (key) parameters[key] = value;
|
|
473
581
|
}
|
|
582
|
+
}
|
|
583
|
+
return {
|
|
584
|
+
type,
|
|
585
|
+
subtype,
|
|
586
|
+
mediaType: `${type}/${subtype}`,
|
|
587
|
+
parameters
|
|
474
588
|
};
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
//#endregion
|
|
592
|
+
//#region ../fragno/dist/client/internal/ndjson-streaming.js
|
|
593
|
+
/**
|
|
594
|
+
* Creates a promise that rejects when the abort signal is triggered
|
|
595
|
+
*/
|
|
596
|
+
function createAbortPromise(abortSignal) {
|
|
597
|
+
return new Promise((_, reject) => {
|
|
598
|
+
const abortHandler = () => {
|
|
599
|
+
reject(new FragnoClientFetchAbortError("Operation was aborted"));
|
|
600
|
+
};
|
|
601
|
+
if (abortSignal.aborted) abortHandler();
|
|
602
|
+
else abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Handles NDJSON streaming responses by returning the first item from the fetcher
|
|
607
|
+
* and then continuing to stream updates via the store's mutate method.
|
|
608
|
+
*
|
|
609
|
+
* This makes it so that we can wait until the first chunk before updating the store, if we did
|
|
610
|
+
* not do this, `loading` would briefly be false before the first item would be populated in the
|
|
611
|
+
* result.
|
|
612
|
+
*
|
|
613
|
+
* @param response - The fetch Response object containing the NDJSON stream
|
|
614
|
+
* @param store - The fetcher store to update with streaming data
|
|
615
|
+
* @param abortSignal - Optional AbortSignal to cancel the streaming operation
|
|
616
|
+
* @returns A promise that resolves to an object containing the first item and a streaming promise
|
|
617
|
+
*/
|
|
618
|
+
async function handleNdjsonStreamingFirstItem(response, store, options = {}) {
|
|
619
|
+
if (!response.body) throw new FragnoClientFetchError("Streaming response has no body", "NO_BODY");
|
|
620
|
+
const { abortSignal } = options;
|
|
621
|
+
if (abortSignal?.aborted) throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
622
|
+
const decoder = new TextDecoder();
|
|
623
|
+
const reader = response.body.getReader();
|
|
624
|
+
let buffer = "";
|
|
625
|
+
let firstItem = null;
|
|
626
|
+
const items = [];
|
|
627
|
+
try {
|
|
628
|
+
while (firstItem === null) {
|
|
629
|
+
if (abortSignal?.aborted) {
|
|
630
|
+
reader.releaseLock();
|
|
631
|
+
throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
632
|
+
}
|
|
633
|
+
const { done, value } = await (abortSignal ? Promise.race([reader.read(), createAbortPromise(abortSignal)]) : reader.read());
|
|
634
|
+
if (done) break;
|
|
635
|
+
buffer += decoder.decode(value, { stream: true });
|
|
636
|
+
const lines = buffer.split("\n");
|
|
637
|
+
buffer = lines.pop() || "";
|
|
638
|
+
for (const line of lines) {
|
|
639
|
+
if (!line.trim()) continue;
|
|
640
|
+
try {
|
|
641
|
+
const jsonObject = JSON.parse(line);
|
|
642
|
+
items.push(jsonObject);
|
|
643
|
+
if (firstItem === null) {
|
|
644
|
+
firstItem = jsonObject;
|
|
645
|
+
const streamingPromise = continueStreaming(reader, decoder, buffer, items, store, abortSignal);
|
|
646
|
+
return {
|
|
647
|
+
firstItem,
|
|
648
|
+
streamingPromise
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
} catch (parseError) {
|
|
652
|
+
throw new FragnoClientUnknownApiError("Failed to parse NDJSON line", 500, { cause: parseError });
|
|
653
|
+
}
|
|
654
|
+
}
|
|
483
655
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
656
|
+
if (firstItem === null) {
|
|
657
|
+
reader.releaseLock();
|
|
658
|
+
throw new FragnoClientUnknownApiError("NDJSON stream contained no valid items", 500);
|
|
659
|
+
}
|
|
660
|
+
reader.releaseLock();
|
|
661
|
+
throw new FragnoClientFetchError("Unexpected end of stream processing", "NO_BODY");
|
|
662
|
+
} catch (error) {
|
|
663
|
+
if (error instanceof FragnoClientError) {
|
|
664
|
+
store?.setError(error);
|
|
665
|
+
throw error;
|
|
666
|
+
} else {
|
|
667
|
+
const clientError = new FragnoClientUnknownApiError("Unknown streaming error", 500, { cause: error });
|
|
668
|
+
store?.setError(clientError);
|
|
669
|
+
throw clientError;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Continues streaming the remaining items in the background
|
|
675
|
+
*/
|
|
676
|
+
async function continueStreaming(reader, decoder, initialBuffer, items, store, abortSignal) {
|
|
677
|
+
let buffer = initialBuffer;
|
|
678
|
+
try {
|
|
679
|
+
while (true) {
|
|
680
|
+
if (abortSignal?.aborted) throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
681
|
+
const { done, value } = await (abortSignal ? Promise.race([reader.read(), createAbortPromise(abortSignal)]) : reader.read());
|
|
682
|
+
if (done) {
|
|
683
|
+
if (buffer.trim()) {
|
|
684
|
+
const lines$1 = buffer.split("\n");
|
|
685
|
+
for (const line of lines$1) {
|
|
686
|
+
if (!line.trim()) continue;
|
|
687
|
+
try {
|
|
688
|
+
const jsonObject = JSON.parse(line);
|
|
689
|
+
items.push(jsonObject);
|
|
690
|
+
store?.setData([...items]);
|
|
691
|
+
} catch (parseError) {
|
|
692
|
+
throw new FragnoClientUnknownApiError("Failed to parse NDJSON line", 400, { cause: parseError });
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
break;
|
|
512
697
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
698
|
+
buffer += decoder.decode(value, { stream: true });
|
|
699
|
+
const lines = buffer.split("\n");
|
|
700
|
+
buffer = lines.pop() || "";
|
|
701
|
+
for (const line of lines) {
|
|
702
|
+
if (!line.trim()) continue;
|
|
703
|
+
try {
|
|
704
|
+
const jsonObject = JSON.parse(line);
|
|
705
|
+
items.push(jsonObject);
|
|
706
|
+
store?.setData([...items]);
|
|
707
|
+
} catch (parseError) {
|
|
708
|
+
throw new FragnoClientUnknownApiError("Failed to parse NDJSON line", 400, { cause: parseError });
|
|
524
709
|
}
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
{
|
|
528
|
-
let originClean = $store[clean];
|
|
529
|
-
$store[clean] = () => {
|
|
530
|
-
for (let destroy of $store.events[UNMOUNT]) destroy();
|
|
531
|
-
$store.events[UNMOUNT] = [];
|
|
532
|
-
$store.active = false;
|
|
533
|
-
originClean();
|
|
534
|
-
};
|
|
710
|
+
}
|
|
535
711
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
712
|
+
} catch (error) {
|
|
713
|
+
if (error instanceof FragnoClientError) store?.setError(error);
|
|
714
|
+
else {
|
|
715
|
+
const clientError = new FragnoClientUnknownApiError("Unknown streaming error", 400, { cause: error });
|
|
716
|
+
store?.setError(clientError);
|
|
717
|
+
throw clientError;
|
|
718
|
+
}
|
|
719
|
+
throw error;
|
|
720
|
+
} finally {
|
|
721
|
+
reader.releaseLock();
|
|
722
|
+
}
|
|
723
|
+
return items;
|
|
724
|
+
}
|
|
542
725
|
|
|
543
726
|
//#endregion
|
|
544
|
-
//#region ../../node_modules/.pnpm/nanostores@1.0.1/node_modules/nanostores/
|
|
545
|
-
let
|
|
546
|
-
|
|
727
|
+
//#region ../../node_modules/.pnpm/nanostores@1.0.1/node_modules/nanostores/task/index.js
|
|
728
|
+
let tasks = 0;
|
|
729
|
+
let resolves = [];
|
|
730
|
+
function startTask() {
|
|
731
|
+
tasks += 1;
|
|
732
|
+
return () => {
|
|
733
|
+
tasks -= 1;
|
|
734
|
+
if (tasks === 0) {
|
|
735
|
+
let prevResolves = resolves;
|
|
736
|
+
resolves = [];
|
|
737
|
+
for (let i of prevResolves) i();
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
function task(cb) {
|
|
742
|
+
let endTask = startTask();
|
|
743
|
+
let promise = cb().finally(endTask);
|
|
744
|
+
promise.t = true;
|
|
745
|
+
return promise;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
//#endregion
|
|
749
|
+
//#region ../../node_modules/.pnpm/nanostores@1.0.1/node_modules/nanostores/clean-stores/index.js
|
|
750
|
+
let clean = Symbol("clean");
|
|
751
|
+
|
|
752
|
+
//#endregion
|
|
753
|
+
//#region ../../node_modules/.pnpm/nanostores@1.0.1/node_modules/nanostores/atom/index.js
|
|
754
|
+
let listenerQueue = [];
|
|
755
|
+
let lqIndex = 0;
|
|
756
|
+
const QUEUE_ITEMS_PER_LISTENER = 4;
|
|
757
|
+
let epoch = 0;
|
|
758
|
+
let atom = (initialValue) => {
|
|
759
|
+
let listeners = [];
|
|
760
|
+
let $atom = {
|
|
761
|
+
get() {
|
|
762
|
+
if (!$atom.lc) $atom.listen(() => {})();
|
|
763
|
+
return $atom.value;
|
|
764
|
+
},
|
|
765
|
+
lc: 0,
|
|
766
|
+
listen(listener) {
|
|
767
|
+
$atom.lc = listeners.push(listener);
|
|
768
|
+
return () => {
|
|
769
|
+
for (let i = lqIndex + QUEUE_ITEMS_PER_LISTENER; i < listenerQueue.length;) if (listenerQueue[i] === listener) listenerQueue.splice(i, QUEUE_ITEMS_PER_LISTENER);
|
|
770
|
+
else i += QUEUE_ITEMS_PER_LISTENER;
|
|
771
|
+
let index = listeners.indexOf(listener);
|
|
772
|
+
if (~index) {
|
|
773
|
+
listeners.splice(index, 1);
|
|
774
|
+
if (!--$atom.lc) $atom.off();
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
},
|
|
778
|
+
notify(oldValue, changedKey) {
|
|
779
|
+
epoch++;
|
|
780
|
+
let runListenerQueue = !listenerQueue.length;
|
|
781
|
+
for (let listener of listeners) listenerQueue.push(listener, $atom.value, oldValue, changedKey);
|
|
782
|
+
if (runListenerQueue) {
|
|
783
|
+
for (lqIndex = 0; lqIndex < listenerQueue.length; lqIndex += QUEUE_ITEMS_PER_LISTENER) listenerQueue[lqIndex](listenerQueue[lqIndex + 1], listenerQueue[lqIndex + 2], listenerQueue[lqIndex + 3]);
|
|
784
|
+
listenerQueue.length = 0;
|
|
785
|
+
}
|
|
786
|
+
},
|
|
787
|
+
off() {},
|
|
788
|
+
set(newValue) {
|
|
789
|
+
let oldValue = $atom.value;
|
|
790
|
+
if (oldValue !== newValue) {
|
|
791
|
+
$atom.value = newValue;
|
|
792
|
+
$atom.notify(oldValue);
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
subscribe(listener) {
|
|
796
|
+
let unbind = $atom.listen(listener);
|
|
797
|
+
listener($atom.value);
|
|
798
|
+
return unbind;
|
|
799
|
+
},
|
|
800
|
+
value: initialValue
|
|
801
|
+
};
|
|
802
|
+
$atom[clean] = () => {
|
|
803
|
+
listeners = [];
|
|
804
|
+
$atom.lc = 0;
|
|
805
|
+
$atom.off();
|
|
806
|
+
};
|
|
807
|
+
return $atom;
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
//#endregion
|
|
811
|
+
//#region ../../node_modules/.pnpm/nanostores@1.0.1/node_modules/nanostores/lifecycle/index.js
|
|
812
|
+
const START = 0;
|
|
813
|
+
const STOP = 1;
|
|
814
|
+
const MOUNT = 5;
|
|
815
|
+
const UNMOUNT = 6;
|
|
816
|
+
const REVERT_MUTATION = 10;
|
|
817
|
+
let on = (object, listener, eventKey, mutateStore) => {
|
|
818
|
+
object.events = object.events || {};
|
|
819
|
+
if (!object.events[eventKey + REVERT_MUTATION]) object.events[eventKey + REVERT_MUTATION] = mutateStore((eventProps) => {
|
|
820
|
+
object.events[eventKey].reduceRight((event, l) => (l(event), event), {
|
|
821
|
+
shared: {},
|
|
822
|
+
...eventProps
|
|
823
|
+
});
|
|
824
|
+
});
|
|
825
|
+
object.events[eventKey] = object.events[eventKey] || [];
|
|
826
|
+
object.events[eventKey].push(listener);
|
|
827
|
+
return () => {
|
|
828
|
+
let currentListeners = object.events[eventKey];
|
|
829
|
+
let index = currentListeners.indexOf(listener);
|
|
830
|
+
currentListeners.splice(index, 1);
|
|
831
|
+
if (!currentListeners.length) {
|
|
832
|
+
delete object.events[eventKey];
|
|
833
|
+
object.events[eventKey + REVERT_MUTATION]();
|
|
834
|
+
delete object.events[eventKey + REVERT_MUTATION];
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
};
|
|
838
|
+
let onStart = ($store, listener) => on($store, listener, START, (runListeners) => {
|
|
839
|
+
let originListen = $store.listen;
|
|
840
|
+
$store.listen = (arg) => {
|
|
841
|
+
if (!$store.lc && !$store.starting) {
|
|
842
|
+
$store.starting = true;
|
|
843
|
+
runListeners();
|
|
844
|
+
delete $store.starting;
|
|
845
|
+
}
|
|
846
|
+
return originListen(arg);
|
|
847
|
+
};
|
|
848
|
+
return () => {
|
|
849
|
+
$store.listen = originListen;
|
|
850
|
+
};
|
|
851
|
+
});
|
|
852
|
+
let onStop = ($store, listener) => on($store, listener, STOP, (runListeners) => {
|
|
853
|
+
let originOff = $store.off;
|
|
854
|
+
$store.off = () => {
|
|
855
|
+
runListeners();
|
|
856
|
+
originOff();
|
|
857
|
+
};
|
|
858
|
+
return () => {
|
|
859
|
+
$store.off = originOff;
|
|
860
|
+
};
|
|
861
|
+
});
|
|
862
|
+
let STORE_UNMOUNT_DELAY = 1e3;
|
|
863
|
+
let onMount = ($store, initialize) => {
|
|
864
|
+
let listener = (payload) => {
|
|
865
|
+
let destroy = initialize(payload);
|
|
866
|
+
if (destroy) $store.events[UNMOUNT].push(destroy);
|
|
867
|
+
};
|
|
868
|
+
return on($store, listener, MOUNT, (runListeners) => {
|
|
869
|
+
let originListen = $store.listen;
|
|
870
|
+
$store.listen = (...args) => {
|
|
871
|
+
if (!$store.lc && !$store.active) {
|
|
872
|
+
$store.active = true;
|
|
873
|
+
runListeners();
|
|
874
|
+
}
|
|
875
|
+
return originListen(...args);
|
|
876
|
+
};
|
|
877
|
+
let originOff = $store.off;
|
|
878
|
+
$store.events[UNMOUNT] = [];
|
|
879
|
+
$store.off = () => {
|
|
880
|
+
originOff();
|
|
881
|
+
setTimeout(() => {
|
|
882
|
+
if ($store.active && !$store.lc) {
|
|
883
|
+
$store.active = false;
|
|
884
|
+
for (let destroy of $store.events[UNMOUNT]) destroy();
|
|
885
|
+
$store.events[UNMOUNT] = [];
|
|
886
|
+
}
|
|
887
|
+
}, STORE_UNMOUNT_DELAY);
|
|
888
|
+
};
|
|
889
|
+
{
|
|
890
|
+
let originClean = $store[clean];
|
|
891
|
+
$store[clean] = () => {
|
|
892
|
+
for (let destroy of $store.events[UNMOUNT]) destroy();
|
|
893
|
+
$store.events[UNMOUNT] = [];
|
|
894
|
+
$store.active = false;
|
|
895
|
+
originClean();
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
return () => {
|
|
899
|
+
$store.listen = originListen;
|
|
900
|
+
$store.off = originOff;
|
|
901
|
+
};
|
|
902
|
+
});
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
//#endregion
|
|
906
|
+
//#region ../../node_modules/.pnpm/nanostores@1.0.1/node_modules/nanostores/computed/index.js
|
|
907
|
+
let computedStore = (stores$1, cb, batched$1) => {
|
|
908
|
+
if (!Array.isArray(stores$1)) stores$1 = [stores$1];
|
|
547
909
|
let previousArgs;
|
|
548
910
|
let currentEpoch;
|
|
549
911
|
let set = () => {
|
|
@@ -607,7 +969,7 @@ let map = (initial = {}) => {
|
|
|
607
969
|
};
|
|
608
970
|
|
|
609
971
|
//#endregion
|
|
610
|
-
//#region ../fragno/dist/ssr
|
|
972
|
+
//#region ../fragno/dist/util/ssr.js
|
|
611
973
|
let stores = [];
|
|
612
974
|
const SSR_ENABLED = false;
|
|
613
975
|
function addStore(store) {
|
|
@@ -622,6 +984,69 @@ function getInitialData(key) {
|
|
|
622
984
|
}
|
|
623
985
|
}
|
|
624
986
|
|
|
987
|
+
//#endregion
|
|
988
|
+
//#region ../fragno/dist/util/nanostores.js
|
|
989
|
+
/**
|
|
990
|
+
* Normalizes a value that could be a plain value, an Atom, or a Vue Ref to a plain value.
|
|
991
|
+
*/
|
|
992
|
+
function unwrapAtom(value) {
|
|
993
|
+
if (value && typeof value === "object" && "get" in value && typeof value.get === "function") return value.get();
|
|
994
|
+
return value;
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Normalizes an object where values can be plain values, Atoms, or Vue Refs.
|
|
998
|
+
* Returns a new object with all values normalized to plain values.
|
|
999
|
+
*/
|
|
1000
|
+
function unwrapObject(params) {
|
|
1001
|
+
if (!params) return;
|
|
1002
|
+
return Object.fromEntries(Object.entries(params).map(([key, value]) => [key, unwrapAtom(value)]));
|
|
1003
|
+
}
|
|
1004
|
+
function isReadableAtom(value) {
|
|
1005
|
+
if (!value) return false;
|
|
1006
|
+
if (typeof value !== "object" || value === null) return false;
|
|
1007
|
+
if (!("get" in value) || typeof value.get !== "function") return false;
|
|
1008
|
+
if (!("lc" in value) || typeof value.lc !== "number") return false;
|
|
1009
|
+
if (!("notify" in value) || typeof value.notify !== "function") return false;
|
|
1010
|
+
if (!("off" in value) || typeof value.off !== "function") return false;
|
|
1011
|
+
if (!("subscribe" in value) || typeof value.subscribe !== "function") return false;
|
|
1012
|
+
if (!("value" in value)) return false;
|
|
1013
|
+
return true;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
//#endregion
|
|
1017
|
+
//#region ../fragno/dist/client/internal/fetcher-merge.js
|
|
1018
|
+
/**
|
|
1019
|
+
* Merge two fetcher configurations, with user config taking precedence.
|
|
1020
|
+
* If user provides a custom function, it takes full precedence.
|
|
1021
|
+
* Otherwise, deep merge RequestInit options.
|
|
1022
|
+
*/
|
|
1023
|
+
function mergeFetcherConfigs(authorConfig, userConfig) {
|
|
1024
|
+
if (userConfig?.type === "function") return userConfig;
|
|
1025
|
+
if (!userConfig && authorConfig?.type === "function") return authorConfig;
|
|
1026
|
+
const authorOpts = authorConfig?.type === "options" ? authorConfig.options : {};
|
|
1027
|
+
const userOpts = userConfig?.type === "options" ? userConfig.options : {};
|
|
1028
|
+
if (Object.keys(authorOpts).length === 0 && Object.keys(userOpts).length === 0) return;
|
|
1029
|
+
return {
|
|
1030
|
+
type: "options",
|
|
1031
|
+
options: {
|
|
1032
|
+
...authorOpts,
|
|
1033
|
+
...userOpts,
|
|
1034
|
+
headers: mergeHeaders(authorOpts.headers, userOpts.headers)
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
/**
|
|
1039
|
+
* Merge headers from author and user configs.
|
|
1040
|
+
* User headers override author headers.
|
|
1041
|
+
*/
|
|
1042
|
+
function mergeHeaders(author, user) {
|
|
1043
|
+
if (!author && !user) return;
|
|
1044
|
+
const merged = new Headers(author);
|
|
1045
|
+
new Headers(user).forEach((value, key) => merged.set(key, value));
|
|
1046
|
+
if (merged.keys().next().done) return;
|
|
1047
|
+
return merged;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
625
1050
|
//#endregion
|
|
626
1051
|
//#region ../../node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js
|
|
627
1052
|
let createNanoEvents = () => ({
|
|
@@ -816,575 +1241,187 @@ const nanoqueryFactory = ([isAppVisible, visibilityChangeSubscribe, reconnectCha
|
|
|
816
1241
|
if (prevKey && prevKeyParts) runFetcher([prevKey, prevKeyParts], fetcherStore, settings);
|
|
817
1242
|
};
|
|
818
1243
|
const originListen = fetcherStore.listen;
|
|
819
|
-
fetcherStore.listen = (listener) => {
|
|
820
|
-
const unsub = originListen(listener);
|
|
821
|
-
listener(fetcherStore.value);
|
|
822
|
-
handleNewListener();
|
|
823
|
-
return unsub;
|
|
824
|
-
};
|
|
825
|
-
onStop(fetcherStore, () => {
|
|
826
|
-
fetcherStore.value = { ...notLoading };
|
|
827
|
-
keysInternalUnsub?.();
|
|
828
|
-
evtUnsubs.forEach((fn) => fn());
|
|
829
|
-
evtUnsubs = [];
|
|
830
|
-
keyUnsub?.();
|
|
831
|
-
clearInterval(_revalidateOnInterval.get(keyInput));
|
|
832
|
-
});
|
|
833
|
-
return fetcherStore;
|
|
834
|
-
};
|
|
835
|
-
const iterOverCache = (keySelector, cb) => {
|
|
836
|
-
for (const key of cache.keys()) if (testKeyAgainstSelector(key, keySelector)) cb(key);
|
|
837
|
-
};
|
|
838
|
-
const invalidateKeys = (keySelector) => {
|
|
839
|
-
iterOverCache(keySelector, (key) => {
|
|
840
|
-
cache.delete(key);
|
|
841
|
-
});
|
|
842
|
-
events.emit(INVALIDATE_KEYS, keySelector);
|
|
843
|
-
};
|
|
844
|
-
const revalidateKeys = (keySelector) => {
|
|
845
|
-
iterOverCache(keySelector, (key) => {
|
|
846
|
-
const cached = cache.get(key);
|
|
847
|
-
if (cached) cache.set(key, {
|
|
848
|
-
...cached,
|
|
849
|
-
created: -Infinity
|
|
850
|
-
});
|
|
851
|
-
});
|
|
852
|
-
events.emit(REVALIDATE_KEYS, keySelector);
|
|
853
|
-
};
|
|
854
|
-
const mutateCache = (keySelector, data) => {
|
|
855
|
-
iterOverCache(keySelector, (key) => {
|
|
856
|
-
if (data === void 0) cache.delete(key);
|
|
857
|
-
else cache.set(key, {
|
|
858
|
-
data,
|
|
859
|
-
created: getNow(),
|
|
860
|
-
expires: getNow() + (globalSettings.cacheLifetime ?? 8e3)
|
|
861
|
-
});
|
|
862
|
-
});
|
|
863
|
-
events.emit(SET_CACHE, keySelector, data);
|
|
864
|
-
};
|
|
865
|
-
function createMutatorStore(mutator, opts) {
|
|
866
|
-
const { throttleCalls, onError } = opts ?? {
|
|
867
|
-
throttleCalls: true,
|
|
868
|
-
onError: globalSettings?.onError
|
|
869
|
-
};
|
|
870
|
-
const mutate = async (data) => {
|
|
871
|
-
if (throttleCalls && store.value?.loading) return;
|
|
872
|
-
const newMutator = rewrittenSettings.fetcher ?? mutator;
|
|
873
|
-
const keysToInvalidate = [], keysToRevalidate = [];
|
|
874
|
-
const safeKeySet = (k, v) => {
|
|
875
|
-
if (store.lc) store.setKey(k, v);
|
|
876
|
-
};
|
|
877
|
-
try {
|
|
878
|
-
store.set({
|
|
879
|
-
error: void 0,
|
|
880
|
-
data: void 0,
|
|
881
|
-
mutate,
|
|
882
|
-
...loading
|
|
883
|
-
});
|
|
884
|
-
const result = await newMutator({
|
|
885
|
-
data,
|
|
886
|
-
invalidate: (key) => {
|
|
887
|
-
keysToInvalidate.push(key);
|
|
888
|
-
},
|
|
889
|
-
revalidate: (key) => {
|
|
890
|
-
keysToRevalidate.push(key);
|
|
891
|
-
},
|
|
892
|
-
getCacheUpdater: (key, shouldRevalidate = true) => [(newVal) => {
|
|
893
|
-
mutateCache(key, newVal);
|
|
894
|
-
if (shouldRevalidate) keysToRevalidate.push(key);
|
|
895
|
-
}, cache.get(key)?.data]
|
|
896
|
-
});
|
|
897
|
-
safeKeySet("data", result);
|
|
898
|
-
return result;
|
|
899
|
-
} catch (error) {
|
|
900
|
-
onError?.(error);
|
|
901
|
-
safeKeySet("error", error);
|
|
902
|
-
store.setKey("error", error);
|
|
903
|
-
} finally {
|
|
904
|
-
safeKeySet("loading", false);
|
|
905
|
-
keysToInvalidate.forEach(invalidateKeys);
|
|
906
|
-
keysToRevalidate.forEach(revalidateKeys);
|
|
907
|
-
}
|
|
908
|
-
};
|
|
909
|
-
const store = map({
|
|
910
|
-
mutate,
|
|
911
|
-
...notLoading
|
|
912
|
-
});
|
|
913
|
-
onStop(store, () => store.set({
|
|
914
|
-
mutate,
|
|
915
|
-
...notLoading
|
|
916
|
-
}));
|
|
917
|
-
store.mutate = mutate;
|
|
918
|
-
return store;
|
|
919
|
-
}
|
|
920
|
-
const __unsafeOverruleSettings = (data) => {
|
|
921
|
-
console.warn(`You should only use __unsafeOverruleSettings in test environment`);
|
|
922
|
-
rewrittenSettings = data;
|
|
923
|
-
};
|
|
924
|
-
return [
|
|
925
|
-
createFetcherStore,
|
|
926
|
-
createMutatorStore,
|
|
927
|
-
{
|
|
928
|
-
__unsafeOverruleSettings,
|
|
929
|
-
invalidateKeys,
|
|
930
|
-
revalidateKeys,
|
|
931
|
-
mutateCache
|
|
932
|
-
}
|
|
933
|
-
];
|
|
934
|
-
};
|
|
935
|
-
function isSomeKey(key) {
|
|
936
|
-
return typeof key === "string" || typeof key === "number" || key === true;
|
|
937
|
-
}
|
|
938
|
-
const getKeyStore = (keys) => {
|
|
939
|
-
if (isSomeKey(keys)) return [atom(["" + keys, [keys]]), () => {}];
|
|
940
|
-
const keyParts = [];
|
|
941
|
-
const $key = atom(null);
|
|
942
|
-
const keysAsStoresToIndexes = /* @__PURE__ */ new Map();
|
|
943
|
-
const setKeyStoreValue = () => {
|
|
944
|
-
if (keyParts.some((v) => v === null || v === void 0 || v === false)) $key.set(null);
|
|
945
|
-
else $key.set([keyParts.join(""), keyParts]);
|
|
946
|
-
};
|
|
947
|
-
for (let i = 0; i < keys.length; i++) {
|
|
948
|
-
const keyOrStore = keys[i];
|
|
949
|
-
if (isSomeKey(keyOrStore)) keyParts.push(keyOrStore);
|
|
950
|
-
else {
|
|
951
|
-
keyParts.push(null);
|
|
952
|
-
keysAsStoresToIndexes.set(keyOrStore, i);
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
const storesAsArray = [...keysAsStoresToIndexes.keys()];
|
|
956
|
-
const $storeKeys = batched(storesAsArray, (...storeValues) => {
|
|
957
|
-
for (let i = 0; i < storeValues.length; i++) {
|
|
958
|
-
const store = storesAsArray[i], partIndex = keysAsStoresToIndexes.get(store);
|
|
959
|
-
keyParts[partIndex] = store._ === fetcherSymbol ? store.value && "data" in store.value ? store.key : null : storeValues[i];
|
|
960
|
-
}
|
|
961
|
-
setKeyStoreValue();
|
|
962
|
-
});
|
|
963
|
-
setKeyStoreValue();
|
|
964
|
-
return [$key, $storeKeys.subscribe(noop)];
|
|
965
|
-
};
|
|
966
|
-
function noop() {}
|
|
967
|
-
const FOCUS = 1, RECONNECT = 2, INVALIDATE_KEYS = 3, REVALIDATE_KEYS = 4, SET_CACHE = 5;
|
|
968
|
-
const testKeyAgainstSelector = (key, selector) => {
|
|
969
|
-
if (Array.isArray(selector)) return selector.includes(key);
|
|
970
|
-
else if (typeof selector === "function") return selector(key);
|
|
971
|
-
else return key === selector;
|
|
972
|
-
};
|
|
973
|
-
const getNow = () => (/* @__PURE__ */ new Date()).getTime();
|
|
974
|
-
const fetcherSymbol = Symbol();
|
|
975
|
-
const loading = { loading: true }, notLoading = { loading: false };
|
|
976
|
-
return nanoquery$1;
|
|
977
|
-
};
|
|
978
|
-
const subscribe = (name, fn) => {
|
|
979
|
-
const isServer = typeof window === "undefined";
|
|
980
|
-
if (!isServer) addEventListener(name, fn);
|
|
981
|
-
};
|
|
982
|
-
const browserCompat = [
|
|
983
|
-
() => !document.hidden,
|
|
984
|
-
(cb) => subscribe("visibilitychange", cb),
|
|
985
|
-
(cb) => subscribe("online", cb)
|
|
986
|
-
];
|
|
987
|
-
const nanoquery = nanoqueryFactory(browserCompat);
|
|
988
|
-
|
|
989
|
-
//#endregion
|
|
990
|
-
//#region ../fragno/dist/client-DAFHcKqA.js
|
|
991
|
-
/**
|
|
992
|
-
* Extract parameter names from a path pattern at runtime.
|
|
993
|
-
* Examples:
|
|
994
|
-
* - "/users/:id" => ["id"]
|
|
995
|
-
* - "/files/**" => ["**"]
|
|
996
|
-
* - "/files/**:rest" => ["rest"]
|
|
997
|
-
*/
|
|
998
|
-
function extractPathParams(pathPattern) {
|
|
999
|
-
const segments = pathPattern.split("/").filter((s) => s.length > 0);
|
|
1000
|
-
const names = [];
|
|
1001
|
-
for (const segment of segments) {
|
|
1002
|
-
if (segment.startsWith(":")) {
|
|
1003
|
-
names.push(segment.slice(1));
|
|
1004
|
-
continue;
|
|
1005
|
-
}
|
|
1006
|
-
if (segment === "**") {
|
|
1007
|
-
names.push("**");
|
|
1008
|
-
continue;
|
|
1009
|
-
}
|
|
1010
|
-
if (segment.startsWith("**:")) {
|
|
1011
|
-
names.push(segment.slice(3));
|
|
1012
|
-
continue;
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
return names;
|
|
1016
|
-
}
|
|
1017
|
-
/**
|
|
1018
|
-
* Build a concrete path by replacing placeholders in a path pattern with values.
|
|
1019
|
-
*
|
|
1020
|
-
* Supports the same placeholder syntax as the matcher:
|
|
1021
|
-
* - Named parameter ":name" is URL-encoded as a single segment
|
|
1022
|
-
* - Anonymous wildcard "**" inserts the remainder as-is (slashes preserved)
|
|
1023
|
-
* - Named wildcard "**:name" inserts the remainder from the named key
|
|
1024
|
-
*
|
|
1025
|
-
* Examples:
|
|
1026
|
-
* - buildPath("/users/:id", { id: "123" }) => "/users/123"
|
|
1027
|
-
* - buildPath("/files/**", { "**": "a/b" }) => "/files/a/b"
|
|
1028
|
-
* - buildPath("/files/**:rest", { rest: "a/b" }) => "/files/a/b"
|
|
1029
|
-
*/
|
|
1030
|
-
function buildPath(pathPattern, params) {
|
|
1031
|
-
const patternSegments = pathPattern.split("/");
|
|
1032
|
-
const builtSegments = [];
|
|
1033
|
-
for (const segment of patternSegments) {
|
|
1034
|
-
if (segment.length === 0) {
|
|
1035
|
-
builtSegments.push("");
|
|
1036
|
-
continue;
|
|
1037
|
-
}
|
|
1038
|
-
if (segment.startsWith(":")) {
|
|
1039
|
-
const name = segment.slice(1);
|
|
1040
|
-
const value = params[name];
|
|
1041
|
-
if (value === void 0) throw new Error(`Missing value for path parameter :${name}`);
|
|
1042
|
-
builtSegments.push(encodeURIComponent(value));
|
|
1043
|
-
continue;
|
|
1044
|
-
}
|
|
1045
|
-
if (segment === "**") {
|
|
1046
|
-
const value = params["**"];
|
|
1047
|
-
if (value === void 0) throw new Error("Missing value for path wildcard **");
|
|
1048
|
-
builtSegments.push(value);
|
|
1049
|
-
continue;
|
|
1050
|
-
}
|
|
1051
|
-
if (segment.startsWith("**:")) {
|
|
1052
|
-
const name = segment.slice(3);
|
|
1053
|
-
const value = params[name];
|
|
1054
|
-
if (value === void 0) throw new Error(`Missing value for path wildcard **:${name}`);
|
|
1055
|
-
builtSegments.push(value);
|
|
1056
|
-
continue;
|
|
1057
|
-
}
|
|
1058
|
-
builtSegments.push(segment);
|
|
1059
|
-
}
|
|
1060
|
-
return builtSegments.join("/");
|
|
1061
|
-
}
|
|
1062
|
-
/**
|
|
1063
|
-
* Base error class for all Fragno client errors.
|
|
1064
|
-
*/
|
|
1065
|
-
var FragnoClientError = class extends Error {
|
|
1066
|
-
#code;
|
|
1067
|
-
constructor(message, code, options = {}) {
|
|
1068
|
-
super(message, { cause: options.cause });
|
|
1069
|
-
this.name = "FragnoClientError";
|
|
1070
|
-
this.#code = code;
|
|
1071
|
-
}
|
|
1072
|
-
get code() {
|
|
1073
|
-
return this.#code;
|
|
1074
|
-
}
|
|
1075
|
-
};
|
|
1076
|
-
var FragnoClientFetchError = class extends FragnoClientError {
|
|
1077
|
-
constructor(message, code, options = {}) {
|
|
1078
|
-
super(message, code, options);
|
|
1079
|
-
this.name = "FragnoClientFetchError";
|
|
1080
|
-
}
|
|
1081
|
-
static fromUnknownFetchError(error) {
|
|
1082
|
-
if (!(error instanceof Error)) return new FragnoClientFetchNetworkError("Network request failed", { cause: error });
|
|
1083
|
-
if (error.name === "AbortError") return new FragnoClientFetchAbortError("Request was aborted", { cause: error });
|
|
1084
|
-
return new FragnoClientFetchNetworkError("Network request failed", { cause: error });
|
|
1085
|
-
}
|
|
1086
|
-
};
|
|
1087
|
-
/**
|
|
1088
|
-
* Error thrown when a network request fails (e.g., no internet connection, DNS failure).
|
|
1089
|
-
*/
|
|
1090
|
-
var FragnoClientFetchNetworkError = class extends FragnoClientFetchError {
|
|
1091
|
-
constructor(message = "Network request failed", options = {}) {
|
|
1092
|
-
super(message, "NETWORK_ERROR", options);
|
|
1093
|
-
this.name = "FragnoClientFetchNetworkError";
|
|
1094
|
-
}
|
|
1095
|
-
};
|
|
1096
|
-
/**
|
|
1097
|
-
* Error thrown when a request is aborted (e.g., user cancels request, timeout).
|
|
1098
|
-
*/
|
|
1099
|
-
var FragnoClientFetchAbortError = class extends FragnoClientFetchError {
|
|
1100
|
-
constructor(message = "Request was aborted", options = {}) {
|
|
1101
|
-
super(message, "ABORT_ERROR", options);
|
|
1102
|
-
this.name = "FragnoClientFetchAbortError";
|
|
1103
|
-
}
|
|
1104
|
-
};
|
|
1105
|
-
/**
|
|
1106
|
-
* Error thrown when the API result is unexpected, e.g. no json is returned.
|
|
1107
|
-
*/
|
|
1108
|
-
var FragnoClientUnknownApiError = class extends FragnoClientError {
|
|
1109
|
-
#status;
|
|
1110
|
-
constructor(message = "Unknown API error", status, options = {}) {
|
|
1111
|
-
super(message, "UNKNOWN_API_ERROR", options);
|
|
1112
|
-
this.name = "FragnoClientUnknownApiError";
|
|
1113
|
-
this.#status = status;
|
|
1114
|
-
}
|
|
1115
|
-
get status() {
|
|
1116
|
-
return this.#status;
|
|
1117
|
-
}
|
|
1118
|
-
};
|
|
1119
|
-
var FragnoClientApiError = class FragnoClientApiError$1 extends FragnoClientError {
|
|
1120
|
-
#status;
|
|
1121
|
-
constructor({ message, code }, status, options = {}) {
|
|
1122
|
-
super(message, code, options);
|
|
1123
|
-
this.name = "FragnoClientApiError";
|
|
1124
|
-
this.#status = status;
|
|
1125
|
-
}
|
|
1126
|
-
get status() {
|
|
1127
|
-
return this.#status;
|
|
1128
|
-
}
|
|
1129
|
-
/**
|
|
1130
|
-
* The error code returned by the API.
|
|
1131
|
-
*
|
|
1132
|
-
* The type is `TErrorCode` (the set of known error codes for this route), but may also be a string
|
|
1133
|
-
* for forward compatibility with future error codes.
|
|
1134
|
-
*/
|
|
1135
|
-
get code() {
|
|
1136
|
-
return super.code;
|
|
1137
|
-
}
|
|
1138
|
-
static async fromResponse(response) {
|
|
1139
|
-
const unknown = await response.json();
|
|
1140
|
-
const status = response.status;
|
|
1141
|
-
if (!("message" in unknown || "code" in unknown)) return new FragnoClientUnknownApiError("Unknown API error", status);
|
|
1142
|
-
if (!(typeof unknown.message === "string" && typeof unknown.code === "string")) return new FragnoClientUnknownApiError("Unknown API error", status);
|
|
1143
|
-
return new FragnoClientApiError$1({
|
|
1144
|
-
message: unknown.message,
|
|
1145
|
-
code: unknown.code
|
|
1146
|
-
}, status);
|
|
1147
|
-
}
|
|
1148
|
-
};
|
|
1149
|
-
/**
|
|
1150
|
-
* Parses a content-type header string into its components
|
|
1151
|
-
*
|
|
1152
|
-
* @param contentType - The content-type header value to parse
|
|
1153
|
-
* @returns A ParsedContentType object or null if the input is invalid
|
|
1154
|
-
*
|
|
1155
|
-
* @example
|
|
1156
|
-
* ```ts
|
|
1157
|
-
* const { type, subtype, mediaType, parameters }
|
|
1158
|
-
* = parseContentType("application/json; charset=utf-8");
|
|
1159
|
-
* console.assert(type === "application");
|
|
1160
|
-
* console.assert(subtype === "json");
|
|
1161
|
-
* console.assert(mediaType === "application/json");
|
|
1162
|
-
* console.assert(parameters["charset"] === "utf-8");
|
|
1163
|
-
*/
|
|
1164
|
-
function parseContentType(contentType) {
|
|
1165
|
-
if (!contentType || typeof contentType !== "string") return null;
|
|
1166
|
-
const trimmed = contentType.trim();
|
|
1167
|
-
if (!trimmed) return null;
|
|
1168
|
-
const parts = trimmed.split(";").map((part) => part.trim());
|
|
1169
|
-
const mediaType = parts[0];
|
|
1170
|
-
if (!mediaType) return null;
|
|
1171
|
-
const typeParts = mediaType.split("/");
|
|
1172
|
-
if (typeParts.length !== 2) return null;
|
|
1173
|
-
const [type, subtype] = typeParts.map((part) => part.trim().toLowerCase());
|
|
1174
|
-
if (!type || !subtype) return null;
|
|
1175
|
-
const parameters = {};
|
|
1176
|
-
for (let i = 1; i < parts.length; i++) {
|
|
1177
|
-
const param = parts[i];
|
|
1178
|
-
const equalIndex = param.indexOf("=");
|
|
1179
|
-
if (equalIndex > 0) {
|
|
1180
|
-
const key = param.slice(0, equalIndex).trim().toLowerCase();
|
|
1181
|
-
let value = param.slice(equalIndex + 1).trim();
|
|
1182
|
-
if (value.startsWith("\"") && value.endsWith("\"")) value = value.slice(1, -1);
|
|
1183
|
-
if (key) parameters[key] = value;
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
return {
|
|
1187
|
-
type,
|
|
1188
|
-
subtype,
|
|
1189
|
-
mediaType: `${type}/${subtype}`,
|
|
1190
|
-
parameters
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
/**
|
|
1194
|
-
* Creates a promise that rejects when the abort signal is triggered
|
|
1195
|
-
*/
|
|
1196
|
-
function createAbortPromise(abortSignal) {
|
|
1197
|
-
return new Promise((_, reject) => {
|
|
1198
|
-
const abortHandler = () => {
|
|
1199
|
-
reject(new FragnoClientFetchAbortError("Operation was aborted"));
|
|
1200
|
-
};
|
|
1201
|
-
if (abortSignal.aborted) abortHandler();
|
|
1202
|
-
else abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
1203
|
-
});
|
|
1204
|
-
}
|
|
1205
|
-
/**
|
|
1206
|
-
* Handles NDJSON streaming responses by returning the first item from the fetcher
|
|
1207
|
-
* and then continuing to stream updates via the store's mutate method.
|
|
1208
|
-
*
|
|
1209
|
-
* This makes it so that we can wait until the first chunk before updating the store, if we did
|
|
1210
|
-
* not do this, `loading` would briefly be false before the first item would be populated in the
|
|
1211
|
-
* result.
|
|
1212
|
-
*
|
|
1213
|
-
* @param response - The fetch Response object containing the NDJSON stream
|
|
1214
|
-
* @param store - The fetcher store to update with streaming data
|
|
1215
|
-
* @param abortSignal - Optional AbortSignal to cancel the streaming operation
|
|
1216
|
-
* @returns A promise that resolves to an object containing the first item and a streaming promise
|
|
1217
|
-
*/
|
|
1218
|
-
async function handleNdjsonStreamingFirstItem(response, store, options = {}) {
|
|
1219
|
-
if (!response.body) throw new FragnoClientFetchError("Streaming response has no body", "NO_BODY");
|
|
1220
|
-
const { abortSignal } = options;
|
|
1221
|
-
if (abortSignal?.aborted) throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
1222
|
-
const decoder = new TextDecoder();
|
|
1223
|
-
const reader = response.body.getReader();
|
|
1224
|
-
let buffer = "";
|
|
1225
|
-
let firstItem = null;
|
|
1226
|
-
const items = [];
|
|
1227
|
-
try {
|
|
1228
|
-
while (firstItem === null) {
|
|
1229
|
-
if (abortSignal?.aborted) {
|
|
1230
|
-
reader.releaseLock();
|
|
1231
|
-
throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
1232
|
-
}
|
|
1233
|
-
const { done, value } = await (abortSignal ? Promise.race([reader.read(), createAbortPromise(abortSignal)]) : reader.read());
|
|
1234
|
-
if (done) break;
|
|
1235
|
-
buffer += decoder.decode(value, { stream: true });
|
|
1236
|
-
const lines = buffer.split("\n");
|
|
1237
|
-
buffer = lines.pop() || "";
|
|
1238
|
-
for (const line of lines) {
|
|
1239
|
-
if (!line.trim()) continue;
|
|
1240
|
-
try {
|
|
1241
|
-
const jsonObject = JSON.parse(line);
|
|
1242
|
-
items.push(jsonObject);
|
|
1243
|
-
if (firstItem === null) {
|
|
1244
|
-
firstItem = jsonObject;
|
|
1245
|
-
const streamingPromise = continueStreaming(reader, decoder, buffer, items, store, abortSignal);
|
|
1246
|
-
return {
|
|
1247
|
-
firstItem,
|
|
1248
|
-
streamingPromise
|
|
1249
|
-
};
|
|
1250
|
-
}
|
|
1251
|
-
} catch (parseError) {
|
|
1252
|
-
throw new FragnoClientUnknownApiError("Failed to parse NDJSON line", 500, { cause: parseError });
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
if (firstItem === null) {
|
|
1257
|
-
reader.releaseLock();
|
|
1258
|
-
throw new FragnoClientUnknownApiError("NDJSON stream contained no valid items", 500);
|
|
1259
|
-
}
|
|
1260
|
-
reader.releaseLock();
|
|
1261
|
-
throw new FragnoClientFetchError("Unexpected end of stream processing", "NO_BODY");
|
|
1262
|
-
} catch (error) {
|
|
1263
|
-
if (error instanceof FragnoClientError) {
|
|
1264
|
-
store?.setError(error);
|
|
1265
|
-
throw error;
|
|
1266
|
-
} else {
|
|
1267
|
-
const clientError = new FragnoClientUnknownApiError("Unknown streaming error", 500, { cause: error });
|
|
1268
|
-
store?.setError(clientError);
|
|
1269
|
-
throw clientError;
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
/**
|
|
1274
|
-
* Continues streaming the remaining items in the background
|
|
1275
|
-
*/
|
|
1276
|
-
async function continueStreaming(reader, decoder, initialBuffer, items, store, abortSignal) {
|
|
1277
|
-
let buffer = initialBuffer;
|
|
1278
|
-
try {
|
|
1279
|
-
while (true) {
|
|
1280
|
-
if (abortSignal?.aborted) throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
1281
|
-
const { done, value } = await (abortSignal ? Promise.race([reader.read(), createAbortPromise(abortSignal)]) : reader.read());
|
|
1282
|
-
if (done) {
|
|
1283
|
-
if (buffer.trim()) {
|
|
1284
|
-
const lines$1 = buffer.split("\n");
|
|
1285
|
-
for (const line of lines$1) {
|
|
1286
|
-
if (!line.trim()) continue;
|
|
1287
|
-
try {
|
|
1288
|
-
const jsonObject = JSON.parse(line);
|
|
1289
|
-
items.push(jsonObject);
|
|
1290
|
-
store?.setData([...items]);
|
|
1291
|
-
} catch (parseError) {
|
|
1292
|
-
throw new FragnoClientUnknownApiError("Failed to parse NDJSON line", 400, { cause: parseError });
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
break;
|
|
1297
|
-
}
|
|
1298
|
-
buffer += decoder.decode(value, { stream: true });
|
|
1299
|
-
const lines = buffer.split("\n");
|
|
1300
|
-
buffer = lines.pop() || "";
|
|
1301
|
-
for (const line of lines) {
|
|
1302
|
-
if (!line.trim()) continue;
|
|
1244
|
+
fetcherStore.listen = (listener) => {
|
|
1245
|
+
const unsub = originListen(listener);
|
|
1246
|
+
listener(fetcherStore.value);
|
|
1247
|
+
handleNewListener();
|
|
1248
|
+
return unsub;
|
|
1249
|
+
};
|
|
1250
|
+
onStop(fetcherStore, () => {
|
|
1251
|
+
fetcherStore.value = { ...notLoading };
|
|
1252
|
+
keysInternalUnsub?.();
|
|
1253
|
+
evtUnsubs.forEach((fn) => fn());
|
|
1254
|
+
evtUnsubs = [];
|
|
1255
|
+
keyUnsub?.();
|
|
1256
|
+
clearInterval(_revalidateOnInterval.get(keyInput));
|
|
1257
|
+
});
|
|
1258
|
+
return fetcherStore;
|
|
1259
|
+
};
|
|
1260
|
+
const iterOverCache = (keySelector, cb) => {
|
|
1261
|
+
for (const key of cache.keys()) if (testKeyAgainstSelector(key, keySelector)) cb(key);
|
|
1262
|
+
};
|
|
1263
|
+
const invalidateKeys = (keySelector) => {
|
|
1264
|
+
iterOverCache(keySelector, (key) => {
|
|
1265
|
+
cache.delete(key);
|
|
1266
|
+
});
|
|
1267
|
+
events.emit(INVALIDATE_KEYS, keySelector);
|
|
1268
|
+
};
|
|
1269
|
+
const revalidateKeys = (keySelector) => {
|
|
1270
|
+
iterOverCache(keySelector, (key) => {
|
|
1271
|
+
const cached = cache.get(key);
|
|
1272
|
+
if (cached) cache.set(key, {
|
|
1273
|
+
...cached,
|
|
1274
|
+
created: -Infinity
|
|
1275
|
+
});
|
|
1276
|
+
});
|
|
1277
|
+
events.emit(REVALIDATE_KEYS, keySelector);
|
|
1278
|
+
};
|
|
1279
|
+
const mutateCache = (keySelector, data) => {
|
|
1280
|
+
iterOverCache(keySelector, (key) => {
|
|
1281
|
+
if (data === void 0) cache.delete(key);
|
|
1282
|
+
else cache.set(key, {
|
|
1283
|
+
data,
|
|
1284
|
+
created: getNow(),
|
|
1285
|
+
expires: getNow() + (globalSettings.cacheLifetime ?? 8e3)
|
|
1286
|
+
});
|
|
1287
|
+
});
|
|
1288
|
+
events.emit(SET_CACHE, keySelector, data);
|
|
1289
|
+
};
|
|
1290
|
+
function createMutatorStore(mutator, opts) {
|
|
1291
|
+
const { throttleCalls, onError } = opts ?? {
|
|
1292
|
+
throttleCalls: true,
|
|
1293
|
+
onError: globalSettings?.onError
|
|
1294
|
+
};
|
|
1295
|
+
const mutate = async (data) => {
|
|
1296
|
+
if (throttleCalls && store.value?.loading) return;
|
|
1297
|
+
const newMutator = rewrittenSettings.fetcher ?? mutator;
|
|
1298
|
+
const keysToInvalidate = [], keysToRevalidate = [];
|
|
1299
|
+
const safeKeySet = (k, v) => {
|
|
1300
|
+
if (store.lc) store.setKey(k, v);
|
|
1301
|
+
};
|
|
1303
1302
|
try {
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1303
|
+
store.set({
|
|
1304
|
+
error: void 0,
|
|
1305
|
+
data: void 0,
|
|
1306
|
+
mutate,
|
|
1307
|
+
...loading
|
|
1308
|
+
});
|
|
1309
|
+
const result = await newMutator({
|
|
1310
|
+
data,
|
|
1311
|
+
invalidate: (key) => {
|
|
1312
|
+
keysToInvalidate.push(key);
|
|
1313
|
+
},
|
|
1314
|
+
revalidate: (key) => {
|
|
1315
|
+
keysToRevalidate.push(key);
|
|
1316
|
+
},
|
|
1317
|
+
getCacheUpdater: (key, shouldRevalidate = true) => [(newVal) => {
|
|
1318
|
+
mutateCache(key, newVal);
|
|
1319
|
+
if (shouldRevalidate) keysToRevalidate.push(key);
|
|
1320
|
+
}, cache.get(key)?.data]
|
|
1321
|
+
});
|
|
1322
|
+
safeKeySet("data", result);
|
|
1323
|
+
return result;
|
|
1324
|
+
} catch (error) {
|
|
1325
|
+
onError?.(error);
|
|
1326
|
+
safeKeySet("error", error);
|
|
1327
|
+
store.setKey("error", error);
|
|
1328
|
+
} finally {
|
|
1329
|
+
safeKeySet("loading", false);
|
|
1330
|
+
keysToInvalidate.forEach(invalidateKeys);
|
|
1331
|
+
keysToRevalidate.forEach(revalidateKeys);
|
|
1309
1332
|
}
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1333
|
+
};
|
|
1334
|
+
const store = map({
|
|
1335
|
+
mutate,
|
|
1336
|
+
...notLoading
|
|
1337
|
+
});
|
|
1338
|
+
onStop(store, () => store.set({
|
|
1339
|
+
mutate,
|
|
1340
|
+
...notLoading
|
|
1341
|
+
}));
|
|
1342
|
+
store.mutate = mutate;
|
|
1343
|
+
return store;
|
|
1318
1344
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1345
|
+
const __unsafeOverruleSettings = (data) => {
|
|
1346
|
+
console.warn(`You should only use __unsafeOverruleSettings in test environment`);
|
|
1347
|
+
rewrittenSettings = data;
|
|
1348
|
+
};
|
|
1349
|
+
return [
|
|
1350
|
+
createFetcherStore,
|
|
1351
|
+
createMutatorStore,
|
|
1352
|
+
{
|
|
1353
|
+
__unsafeOverruleSettings,
|
|
1354
|
+
invalidateKeys,
|
|
1355
|
+
revalidateKeys,
|
|
1356
|
+
mutateCache
|
|
1357
|
+
}
|
|
1358
|
+
];
|
|
1359
|
+
};
|
|
1360
|
+
function isSomeKey(key) {
|
|
1361
|
+
return typeof key === "string" || typeof key === "number" || key === true;
|
|
1322
1362
|
}
|
|
1323
|
-
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
*/
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
}
|
|
1340
|
-
function isReadableAtom(value) {
|
|
1341
|
-
if (!value) return false;
|
|
1342
|
-
if (typeof value !== "object" || value === null) return false;
|
|
1343
|
-
if (!("get" in value) || typeof value.get !== "function") return false;
|
|
1344
|
-
if (!("lc" in value) || typeof value.lc !== "number") return false;
|
|
1345
|
-
if (!("notify" in value) || typeof value.notify !== "function") return false;
|
|
1346
|
-
if (!("off" in value) || typeof value.off !== "function") return false;
|
|
1347
|
-
if (!("subscribe" in value) || typeof value.subscribe !== "function") return false;
|
|
1348
|
-
if (!("value" in value)) return false;
|
|
1349
|
-
return true;
|
|
1350
|
-
}
|
|
1351
|
-
/**
|
|
1352
|
-
* Merge two fetcher configurations, with user config taking precedence.
|
|
1353
|
-
* If user provides a custom function, it takes full precedence.
|
|
1354
|
-
* Otherwise, deep merge RequestInit options.
|
|
1355
|
-
*/
|
|
1356
|
-
function mergeFetcherConfigs(authorConfig, userConfig) {
|
|
1357
|
-
if (userConfig?.type === "function") return userConfig;
|
|
1358
|
-
if (!userConfig && authorConfig?.type === "function") return authorConfig;
|
|
1359
|
-
const authorOpts = authorConfig?.type === "options" ? authorConfig.options : {};
|
|
1360
|
-
const userOpts = userConfig?.type === "options" ? userConfig.options : {};
|
|
1361
|
-
if (Object.keys(authorOpts).length === 0 && Object.keys(userOpts).length === 0) return;
|
|
1362
|
-
return {
|
|
1363
|
-
type: "options",
|
|
1364
|
-
options: {
|
|
1365
|
-
...authorOpts,
|
|
1366
|
-
...userOpts,
|
|
1367
|
-
headers: mergeHeaders(authorOpts.headers, userOpts.headers)
|
|
1363
|
+
const getKeyStore = (keys) => {
|
|
1364
|
+
if (isSomeKey(keys)) return [atom(["" + keys, [keys]]), () => {}];
|
|
1365
|
+
const keyParts = [];
|
|
1366
|
+
const $key = atom(null);
|
|
1367
|
+
const keysAsStoresToIndexes = /* @__PURE__ */ new Map();
|
|
1368
|
+
const setKeyStoreValue = () => {
|
|
1369
|
+
if (keyParts.some((v) => v === null || v === void 0 || v === false)) $key.set(null);
|
|
1370
|
+
else $key.set([keyParts.join(""), keyParts]);
|
|
1371
|
+
};
|
|
1372
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1373
|
+
const keyOrStore = keys[i];
|
|
1374
|
+
if (isSomeKey(keyOrStore)) keyParts.push(keyOrStore);
|
|
1375
|
+
else {
|
|
1376
|
+
keyParts.push(null);
|
|
1377
|
+
keysAsStoresToIndexes.set(keyOrStore, i);
|
|
1378
|
+
}
|
|
1368
1379
|
}
|
|
1380
|
+
const storesAsArray = [...keysAsStoresToIndexes.keys()];
|
|
1381
|
+
const $storeKeys = batched(storesAsArray, (...storeValues) => {
|
|
1382
|
+
for (let i = 0; i < storeValues.length; i++) {
|
|
1383
|
+
const store = storesAsArray[i], partIndex = keysAsStoresToIndexes.get(store);
|
|
1384
|
+
keyParts[partIndex] = store._ === fetcherSymbol ? store.value && "data" in store.value ? store.key : null : storeValues[i];
|
|
1385
|
+
}
|
|
1386
|
+
setKeyStoreValue();
|
|
1387
|
+
});
|
|
1388
|
+
setKeyStoreValue();
|
|
1389
|
+
return [$key, $storeKeys.subscribe(noop)];
|
|
1369
1390
|
};
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
return
|
|
1381
|
-
}
|
|
1391
|
+
function noop() {}
|
|
1392
|
+
const FOCUS = 1, RECONNECT = 2, INVALIDATE_KEYS = 3, REVALIDATE_KEYS = 4, SET_CACHE = 5;
|
|
1393
|
+
const testKeyAgainstSelector = (key, selector) => {
|
|
1394
|
+
if (Array.isArray(selector)) return selector.includes(key);
|
|
1395
|
+
else if (typeof selector === "function") return selector(key);
|
|
1396
|
+
else return key === selector;
|
|
1397
|
+
};
|
|
1398
|
+
const getNow = () => (/* @__PURE__ */ new Date()).getTime();
|
|
1399
|
+
const fetcherSymbol = Symbol();
|
|
1400
|
+
const loading = { loading: true }, notLoading = { loading: false };
|
|
1401
|
+
return nanoquery$1;
|
|
1402
|
+
};
|
|
1403
|
+
const subscribe = (name, fn) => {
|
|
1404
|
+
const isServer = typeof window === "undefined";
|
|
1405
|
+
if (!isServer) addEventListener(name, fn);
|
|
1406
|
+
};
|
|
1407
|
+
const browserCompat = [
|
|
1408
|
+
() => !document.hidden,
|
|
1409
|
+
(cb) => subscribe("visibilitychange", cb),
|
|
1410
|
+
(cb) => subscribe("online", cb)
|
|
1411
|
+
];
|
|
1412
|
+
const nanoquery = nanoqueryFactory(browserCompat);
|
|
1413
|
+
|
|
1414
|
+
//#endregion
|
|
1415
|
+
//#region ../fragno/dist/client/client.js
|
|
1382
1416
|
/**
|
|
1383
1417
|
* Symbols used to identify hook types
|
|
1384
1418
|
*/
|
|
1385
1419
|
const GET_HOOK_SYMBOL = Symbol("fragno-get-hook");
|
|
1386
1420
|
const MUTATOR_HOOK_SYMBOL = Symbol("fragno-mutator-hook");
|
|
1387
1421
|
const STORE_SYMBOL = Symbol("fragno-store");
|
|
1422
|
+
/**
|
|
1423
|
+
* @internal
|
|
1424
|
+
*/
|
|
1388
1425
|
function buildUrl(config, params) {
|
|
1389
1426
|
const { baseUrl = "", mountRoute, path } = config;
|
|
1390
1427
|
const { pathParams, queryParams } = params ?? {};
|
|
@@ -1403,6 +1440,7 @@ function buildUrl(config, params) {
|
|
|
1403
1440
|
* @param path
|
|
1404
1441
|
* @param params
|
|
1405
1442
|
* @returns
|
|
1443
|
+
* @internal
|
|
1406
1444
|
*/
|
|
1407
1445
|
function getCacheKey(method, path, params) {
|
|
1408
1446
|
if (!params) return [method, path];
|
|
@@ -1428,12 +1466,21 @@ function isStreamingResponse(response) {
|
|
|
1428
1466
|
if (contentType.subtype === "x-ndjson") return "ndjson";
|
|
1429
1467
|
return false;
|
|
1430
1468
|
}
|
|
1469
|
+
/**
|
|
1470
|
+
* @internal
|
|
1471
|
+
*/
|
|
1431
1472
|
function isGetHook(hook) {
|
|
1432
1473
|
return typeof hook === "object" && hook !== null && GET_HOOK_SYMBOL in hook && hook[GET_HOOK_SYMBOL] === true;
|
|
1433
1474
|
}
|
|
1475
|
+
/**
|
|
1476
|
+
* @internal
|
|
1477
|
+
*/
|
|
1434
1478
|
function isMutatorHook(hook) {
|
|
1435
1479
|
return typeof hook === "object" && hook !== null && MUTATOR_HOOK_SYMBOL in hook && hook[MUTATOR_HOOK_SYMBOL] === true;
|
|
1436
1480
|
}
|
|
1481
|
+
/**
|
|
1482
|
+
* @internal
|
|
1483
|
+
*/
|
|
1437
1484
|
function isStore(obj) {
|
|
1438
1485
|
return typeof obj === "object" && obj !== null && STORE_SYMBOL in obj && obj[STORE_SYMBOL] === true;
|
|
1439
1486
|
}
|
|
@@ -1722,16 +1769,20 @@ var ClientBuilder = class {
|
|
|
1722
1769
|
this.#invalidateKeys((key) => key.startsWith(prefix));
|
|
1723
1770
|
}
|
|
1724
1771
|
};
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1772
|
+
/**
|
|
1773
|
+
* Create a client builder for fragments using the new fragment definition API.
|
|
1774
|
+
* This is the same as createClientBuilder but works with FragmentDefinition.
|
|
1775
|
+
*/
|
|
1776
|
+
function createClientBuilder(definition, publicConfig, routesOrFactories, authorFetcherConfig) {
|
|
1777
|
+
const routes$1 = resolveRouteFactories({
|
|
1728
1778
|
config: {},
|
|
1729
1779
|
deps: {},
|
|
1730
|
-
services: {}
|
|
1780
|
+
services: {},
|
|
1781
|
+
serviceDeps: {}
|
|
1731
1782
|
}, routesOrFactories);
|
|
1732
1783
|
const fragmentConfig = {
|
|
1733
1784
|
name: definition.name,
|
|
1734
|
-
routes
|
|
1785
|
+
routes: routes$1
|
|
1735
1786
|
};
|
|
1736
1787
|
const mountRoute = publicConfig.mountRoute ?? `/${definition.name}`;
|
|
1737
1788
|
const mergedFetcherConfig = mergeFetcherConfigs(authorFetcherConfig, publicConfig.fetcherConfig);
|
|
@@ -1742,9 +1793,13 @@ function createClientBuilder(fragmentBuilder, publicConfig, routesOrFactories, a
|
|
|
1742
1793
|
}, fragmentConfig);
|
|
1743
1794
|
}
|
|
1744
1795
|
|
|
1796
|
+
//#endregion
|
|
1797
|
+
//#region src/definition.ts
|
|
1798
|
+
const stripeFragmentDefinition = defineFragment("stripe").extend(() => {}).withDependencies(() => {}).providesBaseService(() => {}).build();
|
|
1799
|
+
|
|
1745
1800
|
//#endregion
|
|
1746
1801
|
//#region src/routes/webhooks.ts
|
|
1747
|
-
const webhookRoutesFactory = defineRoutes().create(({ config, deps, services }) => {
|
|
1802
|
+
const webhookRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ config, deps, services, defineRoute }) => {
|
|
1748
1803
|
return [defineRoute({
|
|
1749
1804
|
method: "POST",
|
|
1750
1805
|
path: "/webhook",
|
|
@@ -1784,7 +1839,7 @@ const CustomerResponseSchema = z.object({
|
|
|
1784
1839
|
|
|
1785
1840
|
//#endregion
|
|
1786
1841
|
//#region src/routes/customers.ts
|
|
1787
|
-
const customersRoutesFactory = defineRoutes().create(({ deps, config }) => {
|
|
1842
|
+
const customersRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ deps, config, defineRoute }) => {
|
|
1788
1843
|
return [defineRoute({
|
|
1789
1844
|
method: "GET",
|
|
1790
1845
|
path: "/admin/customers",
|
|
@@ -1797,6 +1852,16 @@ const customersRoutesFactory = defineRoutes().create(({ deps, config }) => {
|
|
|
1797
1852
|
hasMore: z.boolean().describe("Whether there are more customers to fetch")
|
|
1798
1853
|
}),
|
|
1799
1854
|
handler: () => {}
|
|
1855
|
+
}), defineRoute({
|
|
1856
|
+
method: "POST",
|
|
1857
|
+
path: "/portal",
|
|
1858
|
+
inputSchema: z.object({ returnUrl: z.url().describe("URL to redirect to after completing billing portal") }),
|
|
1859
|
+
outputSchema: z.object({
|
|
1860
|
+
url: z.url().describe("URL to redirect to after cancellation"),
|
|
1861
|
+
redirect: z.boolean().describe("Whether to redirect to the URL")
|
|
1862
|
+
}),
|
|
1863
|
+
errorCodes: ["NO_STRIPE_CUSTOMER_FOR_ENTITY"],
|
|
1864
|
+
handler: () => {}
|
|
1800
1865
|
})];
|
|
1801
1866
|
});
|
|
1802
1867
|
|
|
@@ -1833,12 +1898,14 @@ const SubscriptionUpgradeRequestSchema = z.object({
|
|
|
1833
1898
|
quantity: z.number().positive().describe("Number of seats"),
|
|
1834
1899
|
successUrl: z.url().describe("Redirect URL after successful checkout"),
|
|
1835
1900
|
cancelUrl: z.url().describe("Redirect URL if checkout is cancelled"),
|
|
1836
|
-
returnUrl: z.string().optional().describe("Return URL for billing portal")
|
|
1901
|
+
returnUrl: z.string().optional().describe("Return URL for billing portal"),
|
|
1902
|
+
promotionCode: z.string().optional().describe("Promotion code to apply"),
|
|
1903
|
+
subscriptionId: z.string().optional().describe("Subscription ID to upgrade, if none provided assume the active subscription of the user.")
|
|
1837
1904
|
});
|
|
1838
1905
|
|
|
1839
1906
|
//#endregion
|
|
1840
1907
|
//#region src/routes/subscriptions.ts
|
|
1841
|
-
const subscriptionsRoutesFactory = defineRoutes().create(({ deps, services, config }) => {
|
|
1908
|
+
const subscriptionsRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ deps, services, config, defineRoute }) => {
|
|
1842
1909
|
return [
|
|
1843
1910
|
defineRoute({
|
|
1844
1911
|
method: "GET",
|
|
@@ -1860,14 +1927,21 @@ const subscriptionsRoutesFactory = defineRoutes().create(({ deps, services, conf
|
|
|
1860
1927
|
"SUBSCRIPTION_NOT_FOUND",
|
|
1861
1928
|
"CUSTOMER_SUBSCRIPTION_MISMATCH",
|
|
1862
1929
|
"UPGRADE_HAS_NO_EFFECT",
|
|
1863
|
-
"SUBSCRIPTION_UPDATE_NOT_ALLOWED"
|
|
1930
|
+
"SUBSCRIPTION_UPDATE_NOT_ALLOWED",
|
|
1931
|
+
"SUBSCRIPTION_UPDATE_PROMO_CODE_NOT_ALLOWED",
|
|
1932
|
+
"PROMOTION_CODE_CUSTOMER_NOT_FIRST_TIME",
|
|
1933
|
+
"MULTIPLE_ACTIVE_SUBSCRIPTIONS",
|
|
1934
|
+
"NO_ACTIVE_SUBSCRIPTIONS"
|
|
1864
1935
|
],
|
|
1865
1936
|
handler: () => {}
|
|
1866
1937
|
}),
|
|
1867
1938
|
defineRoute({
|
|
1868
1939
|
method: "POST",
|
|
1869
1940
|
path: "/subscription/cancel",
|
|
1870
|
-
inputSchema: z.object({
|
|
1941
|
+
inputSchema: z.object({
|
|
1942
|
+
returnUrl: z.url().describe("URL to redirect to after cancellation is complete"),
|
|
1943
|
+
subscriptionId: z.string().optional().describe("Which subscription to cancel, if there are multiple active subscriptions")
|
|
1944
|
+
}),
|
|
1871
1945
|
outputSchema: z.object({
|
|
1872
1946
|
url: z.url().describe("URL to redirect to after cancellation"),
|
|
1873
1947
|
redirect: z.boolean().describe("Whether to redirect to the URL")
|
|
@@ -1875,7 +1949,9 @@ const subscriptionsRoutesFactory = defineRoutes().create(({ deps, services, conf
|
|
|
1875
1949
|
errorCodes: [
|
|
1876
1950
|
"SUBSCRIPTION_NOT_FOUND",
|
|
1877
1951
|
"NO_SUBSCRIPTION_TO_CANCEL",
|
|
1878
|
-
"SUBSCRIPTION_ALREADY_CANCELED"
|
|
1952
|
+
"SUBSCRIPTION_ALREADY_CANCELED",
|
|
1953
|
+
"NO_STRIPE_CUSTOMER_LINKED",
|
|
1954
|
+
"MULTIPLE_SUBSCRIPTIONS_FOUND"
|
|
1879
1955
|
],
|
|
1880
1956
|
handler: () => {}
|
|
1881
1957
|
})
|
|
@@ -1909,7 +1985,7 @@ const ProductResponseSchema = z.object({
|
|
|
1909
1985
|
|
|
1910
1986
|
//#endregion
|
|
1911
1987
|
//#region src/routes/products.ts
|
|
1912
|
-
const productsRoutesFactory = defineRoutes().create(({ deps, config }) => {
|
|
1988
|
+
const productsRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ deps, config, defineRoute }) => {
|
|
1913
1989
|
return [defineRoute({
|
|
1914
1990
|
method: "GET",
|
|
1915
1991
|
path: "/admin/products",
|
|
@@ -1964,7 +2040,7 @@ const PriceResponseSchema = z.object({
|
|
|
1964
2040
|
|
|
1965
2041
|
//#endregion
|
|
1966
2042
|
//#region src/routes/prices.ts
|
|
1967
|
-
const pricesRoutesFactory = defineRoutes().create(({ deps, config }) => {
|
|
2043
|
+
const pricesRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ deps, config, defineRoute }) => {
|
|
1968
2044
|
return [defineRoute({
|
|
1969
2045
|
method: "GET",
|
|
1970
2046
|
path: "/admin/products/:productId/prices",
|
|
@@ -1982,29 +2058,24 @@ const pricesRoutesFactory = defineRoutes().create(({ deps, config }) => {
|
|
|
1982
2058
|
|
|
1983
2059
|
//#endregion
|
|
1984
2060
|
//#region src/index.ts
|
|
1985
|
-
const
|
|
2061
|
+
const routes = [
|
|
2062
|
+
webhookRoutesFactory,
|
|
2063
|
+
customersRoutesFactory,
|
|
2064
|
+
subscriptionsRoutesFactory,
|
|
2065
|
+
productsRoutesFactory,
|
|
2066
|
+
pricesRoutesFactory
|
|
2067
|
+
];
|
|
1986
2068
|
function createStripeFragment(config, fragnoConfig) {
|
|
1987
|
-
return
|
|
1988
|
-
webhookRoutesFactory,
|
|
1989
|
-
customersRoutesFactory,
|
|
1990
|
-
subscriptionsRoutesFactory,
|
|
1991
|
-
productsRoutesFactory,
|
|
1992
|
-
pricesRoutesFactory
|
|
1993
|
-
], fragnoConfig);
|
|
2069
|
+
return {};
|
|
1994
2070
|
}
|
|
1995
2071
|
function createStripeFragmentClients(fragnoConfig = {}) {
|
|
1996
|
-
const builder = createClientBuilder(stripeFragmentDefinition, fragnoConfig,
|
|
1997
|
-
webhookRoutesFactory,
|
|
1998
|
-
customersRoutesFactory,
|
|
1999
|
-
subscriptionsRoutesFactory,
|
|
2000
|
-
productsRoutesFactory,
|
|
2001
|
-
pricesRoutesFactory
|
|
2002
|
-
]);
|
|
2072
|
+
const builder = createClientBuilder(stripeFragmentDefinition, fragnoConfig, routes);
|
|
2003
2073
|
return {
|
|
2004
2074
|
useCustomers: builder.createHook("/admin/customers"),
|
|
2005
2075
|
useProducts: builder.createHook("/admin/products"),
|
|
2006
2076
|
usePrices: builder.createHook("/admin/products/:productId/prices"),
|
|
2007
2077
|
useSubscription: builder.createHook("/admin/subscriptions"),
|
|
2078
|
+
useBillingPortal: builder.createMutator("POST", "/portal"),
|
|
2008
2079
|
upgradeSubscription: builder.createMutator("POST", "/subscription/upgrade"),
|
|
2009
2080
|
cancelSubscription: builder.createMutator("POST", "/subscription/cancel")
|
|
2010
2081
|
};
|
|
@@ -2012,4 +2083,4 @@ function createStripeFragmentClients(fragnoConfig = {}) {
|
|
|
2012
2083
|
|
|
2013
2084
|
//#endregion
|
|
2014
2085
|
export { atom, createStripeFragment, createStripeFragmentClients, isGetHook, isMutatorHook, isReadableAtom, isStore, stripeFragmentDefinition };
|
|
2015
|
-
//# sourceMappingURL=src-
|
|
2086
|
+
//# sourceMappingURL=src-D6S1gN3I.js.map
|