@fragno-dev/stripe 1.0.0 → 2.0.2
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/dist/browser/client/react.d.ts +1 -1
- package/dist/browser/client/react.d.ts.map +1 -1
- package/dist/browser/client/react.js +105 -13
- package/dist/browser/client/react.js.map +1 -1
- package/dist/browser/client/solid.d.ts +1 -1
- package/dist/browser/client/solid.d.ts.map +1 -1
- package/dist/browser/client/solid.js +25 -11
- package/dist/browser/client/solid.js.map +1 -1
- package/dist/browser/client/svelte.d.ts +1 -1
- package/dist/browser/client/svelte.d.ts.map +1 -1
- package/dist/browser/client/svelte.js +11 -3
- package/dist/browser/client/svelte.js.map +1 -1
- package/dist/browser/client/vanilla.d.ts +1 -1
- package/dist/browser/client/vanilla.d.ts.map +1 -1
- package/dist/browser/client/vanilla.js +21 -1
- package/dist/browser/client/vanilla.js.map +1 -1
- package/dist/browser/client/vue.d.ts +1 -1
- package/dist/browser/client/vue.d.ts.map +1 -1
- package/dist/browser/client/vue.js +23 -1
- package/dist/browser/client/vue.js.map +1 -1
- package/dist/browser/index.d.ts +31 -66
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/{src-Cw3xL5oQ.js → src-D6VWnvEs.js} +658 -449
- package/dist/browser/src-D6VWnvEs.js.map +1 -0
- package/dist/node/index.d.ts +32 -67
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +512 -462
- package/dist/node/index.js.map +1 -1
- package/package.json +33 -54
- package/dist/browser/src-Cw3xL5oQ.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineFragment, defineRoutes } from "@fragno-dev/core";
|
|
2
|
+
import { column, idColumn, schema } from "@fragno-dev/db/schema";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
|
|
4
5
|
//#region ../fragno/dist/api/route.js
|
|
@@ -15,6 +16,80 @@ function resolveRouteFactories(context, routesOrFactories) {
|
|
|
15
16
|
return routes$1;
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region ../fragno/dist/api/internal/path.js
|
|
21
|
+
/**
|
|
22
|
+
* Extract parameter names from a path pattern at runtime.
|
|
23
|
+
* Examples:
|
|
24
|
+
* - "/users/:id" => ["id"]
|
|
25
|
+
* - "/files/**" => ["**"]
|
|
26
|
+
* - "/files/**:rest" => ["rest"]
|
|
27
|
+
*/
|
|
28
|
+
function extractPathParams(pathPattern) {
|
|
29
|
+
const segments = pathPattern.split("/").filter((s) => s.length > 0);
|
|
30
|
+
const names = [];
|
|
31
|
+
for (const segment of segments) {
|
|
32
|
+
if (segment.startsWith(":")) {
|
|
33
|
+
names.push(segment.slice(1));
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (segment === "**") {
|
|
37
|
+
names.push("**");
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (segment.startsWith("**:")) {
|
|
41
|
+
names.push(segment.slice(3));
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return names;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build a concrete path by replacing placeholders in a path pattern with values.
|
|
49
|
+
*
|
|
50
|
+
* Supports the same placeholder syntax as the matcher:
|
|
51
|
+
* - Named parameter ":name" is URL-encoded as a single segment
|
|
52
|
+
* - Anonymous wildcard "**" inserts the remainder as-is (slashes preserved)
|
|
53
|
+
* - Named wildcard "**:name" inserts the remainder from the named key
|
|
54
|
+
*
|
|
55
|
+
* Examples:
|
|
56
|
+
* - buildPath("/users/:id", { id: "123" }) => "/users/123"
|
|
57
|
+
* - buildPath("/files/**", { "**": "a/b" }) => "/files/a/b"
|
|
58
|
+
* - buildPath("/files/**:rest", { rest: "a/b" }) => "/files/a/b"
|
|
59
|
+
*/
|
|
60
|
+
function buildPath(pathPattern, params) {
|
|
61
|
+
const patternSegments = pathPattern.split("/");
|
|
62
|
+
const builtSegments = [];
|
|
63
|
+
for (const segment of patternSegments) {
|
|
64
|
+
if (segment.length === 0) {
|
|
65
|
+
builtSegments.push("");
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (segment.startsWith(":")) {
|
|
69
|
+
const name = segment.slice(1);
|
|
70
|
+
const value = params[name];
|
|
71
|
+
if (value === void 0) throw new Error(`Missing value for path parameter :${name}`);
|
|
72
|
+
builtSegments.push(encodeURIComponent(value));
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (segment === "**") {
|
|
76
|
+
const value = params["**"];
|
|
77
|
+
if (value === void 0) throw new Error("Missing value for path wildcard **");
|
|
78
|
+
builtSegments.push(value);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (segment.startsWith("**:")) {
|
|
82
|
+
const name = segment.slice(3);
|
|
83
|
+
const value = params[name];
|
|
84
|
+
if (value === void 0) throw new Error(`Missing value for path wildcard **:${name}`);
|
|
85
|
+
builtSegments.push(value);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
builtSegments.push(segment);
|
|
89
|
+
}
|
|
90
|
+
return builtSegments.join("/");
|
|
91
|
+
}
|
|
92
|
+
|
|
18
93
|
//#endregion
|
|
19
94
|
//#region ../fragno/dist/api/internal/route.js
|
|
20
95
|
function getMountRoute(opts) {
|
|
@@ -161,6 +236,72 @@ var RequestInputContext = class RequestInputContext$1 {
|
|
|
161
236
|
return this.#body;
|
|
162
237
|
}
|
|
163
238
|
/**
|
|
239
|
+
* Access the request body as FormData.
|
|
240
|
+
*
|
|
241
|
+
* Use this method when handling file uploads or multipart form submissions.
|
|
242
|
+
* The request must have been sent with Content-Type: multipart/form-data.
|
|
243
|
+
*
|
|
244
|
+
* @throws Error if the request body is not FormData
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```typescript
|
|
248
|
+
* defineRoute({
|
|
249
|
+
* method: "POST",
|
|
250
|
+
* path: "/upload",
|
|
251
|
+
* async handler(ctx, res) {
|
|
252
|
+
* const formData = ctx.formData();
|
|
253
|
+
* const file = formData.get("file") as File;
|
|
254
|
+
* const description = formData.get("description") as string;
|
|
255
|
+
* // ... process file
|
|
256
|
+
* }
|
|
257
|
+
* });
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
formData() {
|
|
261
|
+
if (!(this.#parsedBody instanceof FormData)) throw new Error("Request body is not FormData. Ensure the request was sent with Content-Type: multipart/form-data.");
|
|
262
|
+
return this.#parsedBody;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Check if the request body is FormData.
|
|
266
|
+
*
|
|
267
|
+
* Useful for routes that accept both JSON and FormData payloads.
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```typescript
|
|
271
|
+
* defineRoute({
|
|
272
|
+
* method: "POST",
|
|
273
|
+
* path: "/upload",
|
|
274
|
+
* async handler(ctx, res) {
|
|
275
|
+
* if (ctx.isFormData()) {
|
|
276
|
+
* const formData = ctx.formData();
|
|
277
|
+
* // handle file upload
|
|
278
|
+
* } else {
|
|
279
|
+
* const json = await ctx.input.valid();
|
|
280
|
+
* // handle JSON payload
|
|
281
|
+
* }
|
|
282
|
+
* }
|
|
283
|
+
* });
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
isFormData() {
|
|
287
|
+
return this.#parsedBody instanceof FormData;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Access the request body as a ReadableStream (application/octet-stream).
|
|
291
|
+
*
|
|
292
|
+
* @throws Error if the request body is not a ReadableStream
|
|
293
|
+
*/
|
|
294
|
+
bodyStream() {
|
|
295
|
+
if (!(this.#parsedBody instanceof ReadableStream)) throw new Error("Request body is not a ReadableStream. Ensure the request was sent with Content-Type: application/octet-stream.");
|
|
296
|
+
return this.#parsedBody;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Check if the request body is a ReadableStream.
|
|
300
|
+
*/
|
|
301
|
+
isBodyStream() {
|
|
302
|
+
return this.#parsedBody instanceof ReadableStream;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
164
305
|
* Input validation context (only if inputSchema is defined)
|
|
165
306
|
* @remarks `InputContext`
|
|
166
307
|
*/
|
|
@@ -177,6 +318,7 @@ var RequestInputContext = class RequestInputContext$1 {
|
|
|
177
318
|
async #validateInput() {
|
|
178
319
|
if (!this.#inputSchema) throw new Error("No input schema defined for this route");
|
|
179
320
|
if (this.#parsedBody instanceof FormData || this.#parsedBody instanceof Blob) throw new Error("Schema validation is only supported for JSON data, not FormData or Blob");
|
|
321
|
+
if (this.#parsedBody instanceof ReadableStream) throw new Error("Schema validation is only supported for JSON data, not FormData, Blob, or ReadableStream");
|
|
180
322
|
const result = await this.#inputSchema["~standard"].validate(this.#parsedBody);
|
|
181
323
|
if (result.issues) throw new FragnoApiValidationError("Validation failed", result.issues);
|
|
182
324
|
return result.value;
|
|
@@ -377,170 +519,6 @@ var RequestOutputContext = class extends OutputContext {
|
|
|
377
519
|
}
|
|
378
520
|
};
|
|
379
521
|
|
|
380
|
-
//#endregion
|
|
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;
|
|
396
|
-
}
|
|
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;
|
|
407
|
-
}
|
|
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("/");
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
//#endregion
|
|
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
|
-
}
|
|
542
|
-
};
|
|
543
|
-
|
|
544
522
|
//#endregion
|
|
545
523
|
//#region ../fragno/dist/util/content-type.js
|
|
546
524
|
/**
|
|
@@ -589,142 +567,36 @@ function parseContentType(contentType) {
|
|
|
589
567
|
}
|
|
590
568
|
|
|
591
569
|
//#endregion
|
|
592
|
-
//#region ../fragno/dist/
|
|
570
|
+
//#region ../fragno/dist/util/nanostores.js
|
|
593
571
|
/**
|
|
594
|
-
*
|
|
572
|
+
* Normalizes a value that could be a plain value, an Atom, or a Vue Ref to a plain value.
|
|
595
573
|
*/
|
|
596
|
-
function
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
reject(new FragnoClientFetchAbortError("Operation was aborted"));
|
|
600
|
-
};
|
|
601
|
-
if (abortSignal.aborted) abortHandler();
|
|
602
|
-
else abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
603
|
-
});
|
|
574
|
+
function unwrapAtom(value) {
|
|
575
|
+
if (value && typeof value === "object" && "get" in value && typeof value.get === "function") return value.get();
|
|
576
|
+
return value;
|
|
604
577
|
}
|
|
605
578
|
/**
|
|
606
|
-
*
|
|
607
|
-
*
|
|
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
|
|
579
|
+
* Normalizes an object where values can be plain values, Atoms, or Vue Refs.
|
|
580
|
+
* Returns a new object with all values normalized to plain values.
|
|
617
581
|
*/
|
|
618
|
-
|
|
619
|
-
if (!
|
|
620
|
-
|
|
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
|
-
}
|
|
655
|
-
}
|
|
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
|
-
}
|
|
582
|
+
function unwrapObject(params) {
|
|
583
|
+
if (!params) return;
|
|
584
|
+
return Object.fromEntries(Object.entries(params).map(([key, value]) => [key, unwrapAtom(value)]));
|
|
672
585
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
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;
|
|
697
|
-
}
|
|
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 });
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
}
|
|
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;
|
|
586
|
+
function isReadableAtom(value) {
|
|
587
|
+
if (!value) return false;
|
|
588
|
+
if (typeof value !== "object" || value === null) return false;
|
|
589
|
+
if (!("get" in value) || typeof value.get !== "function") return false;
|
|
590
|
+
if (!("lc" in value) || typeof value.lc !== "number") return false;
|
|
591
|
+
if (!("notify" in value) || typeof value.notify !== "function") return false;
|
|
592
|
+
if (!("off" in value) || typeof value.off !== "function") return false;
|
|
593
|
+
if (!("subscribe" in value) || typeof value.subscribe !== "function") return false;
|
|
594
|
+
if (!("value" in value)) return false;
|
|
595
|
+
return true;
|
|
724
596
|
}
|
|
725
597
|
|
|
726
598
|
//#endregion
|
|
727
|
-
//#region ../../node_modules/.pnpm/nanostores@1.
|
|
599
|
+
//#region ../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/task/index.js
|
|
728
600
|
let tasks = 0;
|
|
729
601
|
let resolves = [];
|
|
730
602
|
function startTask() {
|
|
@@ -746,11 +618,11 @@ function task(cb) {
|
|
|
746
618
|
}
|
|
747
619
|
|
|
748
620
|
//#endregion
|
|
749
|
-
//#region ../../node_modules/.pnpm/nanostores@1.
|
|
621
|
+
//#region ../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/clean-stores/index.js
|
|
750
622
|
let clean = Symbol("clean");
|
|
751
623
|
|
|
752
624
|
//#endregion
|
|
753
|
-
//#region ../../node_modules/.pnpm/nanostores@1.
|
|
625
|
+
//#region ../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/atom/index.js
|
|
754
626
|
let listenerQueue = [];
|
|
755
627
|
let lqIndex = 0;
|
|
756
628
|
const QUEUE_ITEMS_PER_LISTENER = 4;
|
|
@@ -762,6 +634,7 @@ const atom = /* @__NO_SIDE_EFFECTS__ */ (initialValue) => {
|
|
|
762
634
|
if (!$atom.lc) $atom.listen(() => {})();
|
|
763
635
|
return $atom.value;
|
|
764
636
|
},
|
|
637
|
+
init: initialValue,
|
|
765
638
|
lc: 0,
|
|
766
639
|
listen(listener) {
|
|
767
640
|
$atom.lc = listeners.push(listener);
|
|
@@ -808,7 +681,7 @@ const atom = /* @__NO_SIDE_EFFECTS__ */ (initialValue) => {
|
|
|
808
681
|
};
|
|
809
682
|
|
|
810
683
|
//#endregion
|
|
811
|
-
//#region ../../node_modules/.pnpm/nanostores@1.
|
|
684
|
+
//#region ../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/lifecycle/index.js
|
|
812
685
|
const START = 0;
|
|
813
686
|
const STOP = 1;
|
|
814
687
|
const MOUNT = 5;
|
|
@@ -903,7 +776,21 @@ let onMount = ($store, initialize) => {
|
|
|
903
776
|
};
|
|
904
777
|
|
|
905
778
|
//#endregion
|
|
906
|
-
//#region ../../node_modules/.pnpm/nanostores@1.
|
|
779
|
+
//#region ../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/warn/index.js
|
|
780
|
+
let warned = {};
|
|
781
|
+
function warn(text) {
|
|
782
|
+
if (!warned[text]) {
|
|
783
|
+
warned[text] = true;
|
|
784
|
+
if (typeof console !== "undefined" && console.warn) {
|
|
785
|
+
console.groupCollapsed("Nano Stores: " + text);
|
|
786
|
+
console.trace("Source of deprecated call");
|
|
787
|
+
console.groupEnd();
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
//#endregion
|
|
793
|
+
//#region ../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/computed/index.js
|
|
907
794
|
let computedStore = (stores$1, cb, batched$1) => {
|
|
908
795
|
if (!Array.isArray(stores$1)) stores$1 = [stores$1];
|
|
909
796
|
let previousArgs;
|
|
@@ -915,10 +802,12 @@ let computedStore = (stores$1, cb, batched$1) => {
|
|
|
915
802
|
if (!previousArgs || args.some((arg, i) => arg !== previousArgs[i])) {
|
|
916
803
|
previousArgs = args;
|
|
917
804
|
let value = cb(...args);
|
|
918
|
-
if (value && value.then && value.t)
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
805
|
+
if (value && value.then && value.t) {
|
|
806
|
+
warn("Use @nanostores/async for async computed. We will remove Promise support in computed() in Nano Stores 2.0");
|
|
807
|
+
value.then((asyncValue) => {
|
|
808
|
+
if (previousArgs === args) $computed.set(asyncValue);
|
|
809
|
+
});
|
|
810
|
+
} else {
|
|
922
811
|
$computed.set(value);
|
|
923
812
|
currentEpoch = epoch;
|
|
924
813
|
}
|
|
@@ -948,7 +837,7 @@ const computed = /* @__NO_SIDE_EFFECTS__ */ (stores$1, fn) => computedStore(stor
|
|
|
948
837
|
const batched = /* @__NO_SIDE_EFFECTS__ */ (stores$1, fn) => computedStore(stores$1, fn, true);
|
|
949
838
|
|
|
950
839
|
//#endregion
|
|
951
|
-
//#region ../../node_modules/.pnpm/nanostores@1.
|
|
840
|
+
//#region ../../node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/map/index.js
|
|
952
841
|
const map = /* @__NO_SIDE_EFFECTS__ */ (initial = {}) => {
|
|
953
842
|
let $map = atom(initial);
|
|
954
843
|
$map.setKey = function(key, value) {
|
|
@@ -985,33 +874,94 @@ function getInitialData(key) {
|
|
|
985
874
|
}
|
|
986
875
|
|
|
987
876
|
//#endregion
|
|
988
|
-
//#region ../fragno/dist/
|
|
877
|
+
//#region ../fragno/dist/client/client-error.js
|
|
989
878
|
/**
|
|
990
|
-
*
|
|
879
|
+
* Base error class for all Fragno client errors.
|
|
991
880
|
*/
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
}
|
|
881
|
+
var FragnoClientError = class extends Error {
|
|
882
|
+
#code;
|
|
883
|
+
constructor(message, code, options = {}) {
|
|
884
|
+
super(message, { cause: options.cause });
|
|
885
|
+
this.name = "FragnoClientError";
|
|
886
|
+
this.#code = code;
|
|
887
|
+
}
|
|
888
|
+
get code() {
|
|
889
|
+
return this.#code;
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
var FragnoClientFetchError = class extends FragnoClientError {
|
|
893
|
+
constructor(message, code, options = {}) {
|
|
894
|
+
super(message, code, options);
|
|
895
|
+
this.name = "FragnoClientFetchError";
|
|
896
|
+
}
|
|
897
|
+
static fromUnknownFetchError(error) {
|
|
898
|
+
if (!(error instanceof Error)) return new FragnoClientFetchNetworkError("Network request failed", { cause: error });
|
|
899
|
+
if (error.name === "AbortError") return new FragnoClientFetchAbortError("Request was aborted", { cause: error });
|
|
900
|
+
return new FragnoClientFetchNetworkError("Network request failed", { cause: error });
|
|
901
|
+
}
|
|
902
|
+
};
|
|
996
903
|
/**
|
|
997
|
-
*
|
|
998
|
-
* Returns a new object with all values normalized to plain values.
|
|
904
|
+
* Error thrown when a network request fails (e.g., no internet connection, DNS failure).
|
|
999
905
|
*/
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
}
|
|
906
|
+
var FragnoClientFetchNetworkError = class extends FragnoClientFetchError {
|
|
907
|
+
constructor(message = "Network request failed", options = {}) {
|
|
908
|
+
super(message, "NETWORK_ERROR", options);
|
|
909
|
+
this.name = "FragnoClientFetchNetworkError";
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
/**
|
|
913
|
+
* Error thrown when a request is aborted (e.g., user cancels request, timeout).
|
|
914
|
+
*/
|
|
915
|
+
var FragnoClientFetchAbortError = class extends FragnoClientFetchError {
|
|
916
|
+
constructor(message = "Request was aborted", options = {}) {
|
|
917
|
+
super(message, "ABORT_ERROR", options);
|
|
918
|
+
this.name = "FragnoClientFetchAbortError";
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
/**
|
|
922
|
+
* Error thrown when the API result is unexpected, e.g. no json is returned.
|
|
923
|
+
*/
|
|
924
|
+
var FragnoClientUnknownApiError = class extends FragnoClientError {
|
|
925
|
+
#status;
|
|
926
|
+
constructor(message = "Unknown API error", status, options = {}) {
|
|
927
|
+
super(message, "UNKNOWN_API_ERROR", options);
|
|
928
|
+
this.name = "FragnoClientUnknownApiError";
|
|
929
|
+
this.#status = status;
|
|
930
|
+
}
|
|
931
|
+
get status() {
|
|
932
|
+
return this.#status;
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
var FragnoClientApiError = class FragnoClientApiError$1 extends FragnoClientError {
|
|
936
|
+
#status;
|
|
937
|
+
constructor({ message, code }, status, options = {}) {
|
|
938
|
+
super(message, code, options);
|
|
939
|
+
this.name = "FragnoClientApiError";
|
|
940
|
+
this.#status = status;
|
|
941
|
+
}
|
|
942
|
+
get status() {
|
|
943
|
+
return this.#status;
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* The error code returned by the API.
|
|
947
|
+
*
|
|
948
|
+
* The type is `TErrorCode` (the set of known error codes for this route), but may also be a string
|
|
949
|
+
* for forward compatibility with future error codes.
|
|
950
|
+
*/
|
|
951
|
+
get code() {
|
|
952
|
+
return super.code;
|
|
953
|
+
}
|
|
954
|
+
static async fromResponse(response) {
|
|
955
|
+
const unknown = await response.json();
|
|
956
|
+
const status = response.status;
|
|
957
|
+
if (!("message" in unknown || "code" in unknown)) return new FragnoClientUnknownApiError("Unknown API error", status);
|
|
958
|
+
if (!(typeof unknown.message === "string" && typeof unknown.code === "string")) return new FragnoClientUnknownApiError("Unknown API error", status);
|
|
959
|
+
return new FragnoClientApiError$1({
|
|
960
|
+
message: unknown.message,
|
|
961
|
+
code: unknown.code
|
|
962
|
+
}, status);
|
|
963
|
+
}
|
|
964
|
+
};
|
|
1015
965
|
|
|
1016
966
|
//#endregion
|
|
1017
967
|
//#region ../fragno/dist/client/internal/fetcher-merge.js
|
|
@@ -1047,6 +997,141 @@ function mergeHeaders(author, user) {
|
|
|
1047
997
|
return merged;
|
|
1048
998
|
}
|
|
1049
999
|
|
|
1000
|
+
//#endregion
|
|
1001
|
+
//#region ../fragno/dist/client/internal/ndjson-streaming.js
|
|
1002
|
+
/**
|
|
1003
|
+
* Creates a promise that rejects when the abort signal is triggered
|
|
1004
|
+
*/
|
|
1005
|
+
function createAbortPromise(abortSignal) {
|
|
1006
|
+
return new Promise((_, reject) => {
|
|
1007
|
+
const abortHandler = () => {
|
|
1008
|
+
reject(new FragnoClientFetchAbortError("Operation was aborted"));
|
|
1009
|
+
};
|
|
1010
|
+
if (abortSignal.aborted) abortHandler();
|
|
1011
|
+
else abortSignal.addEventListener("abort", abortHandler, { once: true });
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Handles NDJSON streaming responses by returning the first item from the fetcher
|
|
1016
|
+
* and then continuing to stream updates via the store's mutate method.
|
|
1017
|
+
*
|
|
1018
|
+
* This makes it so that we can wait until the first chunk before updating the store, if we did
|
|
1019
|
+
* not do this, `loading` would briefly be false before the first item would be populated in the
|
|
1020
|
+
* result.
|
|
1021
|
+
*
|
|
1022
|
+
* @param response - The fetch Response object containing the NDJSON stream
|
|
1023
|
+
* @param store - The fetcher store to update with streaming data
|
|
1024
|
+
* @param abortSignal - Optional AbortSignal to cancel the streaming operation
|
|
1025
|
+
* @returns A promise that resolves to an object containing the first item and a streaming promise
|
|
1026
|
+
*/
|
|
1027
|
+
async function handleNdjsonStreamingFirstItem(response, store, options = {}) {
|
|
1028
|
+
if (!response.body) throw new FragnoClientFetchError("Streaming response has no body", "NO_BODY");
|
|
1029
|
+
const { abortSignal } = options;
|
|
1030
|
+
if (abortSignal?.aborted) throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
1031
|
+
const decoder = new TextDecoder();
|
|
1032
|
+
const reader = response.body.getReader();
|
|
1033
|
+
let buffer = "";
|
|
1034
|
+
let firstItem = null;
|
|
1035
|
+
const items = [];
|
|
1036
|
+
try {
|
|
1037
|
+
while (firstItem === null) {
|
|
1038
|
+
if (abortSignal?.aborted) {
|
|
1039
|
+
reader.releaseLock();
|
|
1040
|
+
throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
1041
|
+
}
|
|
1042
|
+
const { done, value } = await (abortSignal ? Promise.race([reader.read(), createAbortPromise(abortSignal)]) : reader.read());
|
|
1043
|
+
if (done) break;
|
|
1044
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1045
|
+
const lines = buffer.split("\n");
|
|
1046
|
+
buffer = lines.pop() || "";
|
|
1047
|
+
for (const line of lines) {
|
|
1048
|
+
if (!line.trim()) continue;
|
|
1049
|
+
try {
|
|
1050
|
+
const jsonObject = JSON.parse(line);
|
|
1051
|
+
items.push(jsonObject);
|
|
1052
|
+
if (firstItem === null) {
|
|
1053
|
+
firstItem = jsonObject;
|
|
1054
|
+
const streamingPromise = continueStreaming(reader, decoder, buffer, items, store, abortSignal);
|
|
1055
|
+
return {
|
|
1056
|
+
firstItem,
|
|
1057
|
+
streamingPromise
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
} catch (parseError) {
|
|
1061
|
+
throw new FragnoClientUnknownApiError("Failed to parse NDJSON line", 500, { cause: parseError });
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
if (firstItem === null) {
|
|
1066
|
+
reader.releaseLock();
|
|
1067
|
+
throw new FragnoClientUnknownApiError("NDJSON stream contained no valid items", 500);
|
|
1068
|
+
}
|
|
1069
|
+
reader.releaseLock();
|
|
1070
|
+
throw new FragnoClientFetchError("Unexpected end of stream processing", "NO_BODY");
|
|
1071
|
+
} catch (error) {
|
|
1072
|
+
if (error instanceof FragnoClientError) {
|
|
1073
|
+
store?.setError(error);
|
|
1074
|
+
throw error;
|
|
1075
|
+
} else {
|
|
1076
|
+
const clientError = new FragnoClientUnknownApiError("Unknown streaming error", 500, { cause: error });
|
|
1077
|
+
store?.setError(clientError);
|
|
1078
|
+
throw clientError;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Continues streaming the remaining items in the background
|
|
1084
|
+
*/
|
|
1085
|
+
async function continueStreaming(reader, decoder, initialBuffer, items, store, abortSignal) {
|
|
1086
|
+
let buffer = initialBuffer;
|
|
1087
|
+
try {
|
|
1088
|
+
while (true) {
|
|
1089
|
+
if (abortSignal?.aborted) throw new FragnoClientFetchAbortError("Operation was aborted");
|
|
1090
|
+
const { done, value } = await (abortSignal ? Promise.race([reader.read(), createAbortPromise(abortSignal)]) : reader.read());
|
|
1091
|
+
if (done) {
|
|
1092
|
+
if (buffer.trim()) {
|
|
1093
|
+
const lines$1 = buffer.split("\n");
|
|
1094
|
+
for (const line of lines$1) {
|
|
1095
|
+
if (!line.trim()) continue;
|
|
1096
|
+
try {
|
|
1097
|
+
const jsonObject = JSON.parse(line);
|
|
1098
|
+
items.push(jsonObject);
|
|
1099
|
+
store?.setData([...items]);
|
|
1100
|
+
} catch (parseError) {
|
|
1101
|
+
throw new FragnoClientUnknownApiError("Failed to parse NDJSON line", 400, { cause: parseError });
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
break;
|
|
1106
|
+
}
|
|
1107
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1108
|
+
const lines = buffer.split("\n");
|
|
1109
|
+
buffer = lines.pop() || "";
|
|
1110
|
+
for (const line of lines) {
|
|
1111
|
+
if (!line.trim()) continue;
|
|
1112
|
+
try {
|
|
1113
|
+
const jsonObject = JSON.parse(line);
|
|
1114
|
+
items.push(jsonObject);
|
|
1115
|
+
store?.setData([...items]);
|
|
1116
|
+
} catch (parseError) {
|
|
1117
|
+
throw new FragnoClientUnknownApiError("Failed to parse NDJSON line", 400, { cause: parseError });
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
if (error instanceof FragnoClientError) store?.setError(error);
|
|
1123
|
+
else {
|
|
1124
|
+
const clientError = new FragnoClientUnknownApiError("Unknown streaming error", 400, { cause: error });
|
|
1125
|
+
store?.setError(clientError);
|
|
1126
|
+
throw clientError;
|
|
1127
|
+
}
|
|
1128
|
+
throw error;
|
|
1129
|
+
} finally {
|
|
1130
|
+
reader.releaseLock();
|
|
1131
|
+
}
|
|
1132
|
+
return items;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1050
1135
|
//#endregion
|
|
1051
1136
|
//#region ../../node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js
|
|
1052
1137
|
let createNanoEvents = () => ({
|
|
@@ -1063,7 +1148,7 @@ let createNanoEvents = () => ({
|
|
|
1063
1148
|
});
|
|
1064
1149
|
|
|
1065
1150
|
//#endregion
|
|
1066
|
-
//#region ../../node_modules/.pnpm/@nanostores+query@0.3.4_nanostores@1.
|
|
1151
|
+
//#region ../../node_modules/.pnpm/@nanostores+query@0.3.4_nanostores@1.2.0/node_modules/@nanostores/query/dist/nanoquery.js
|
|
1067
1152
|
function defaultOnErrorRetry({ retryCount }) {
|
|
1068
1153
|
return ~~((Math.random() + .5) * (1 << (retryCount < 8 ? retryCount : 8))) * 2e3;
|
|
1069
1154
|
}
|
|
@@ -1414,11 +1499,102 @@ const nanoquery = nanoqueryFactory(browserCompat);
|
|
|
1414
1499
|
//#endregion
|
|
1415
1500
|
//#region ../fragno/dist/client/client.js
|
|
1416
1501
|
/**
|
|
1417
|
-
* Symbols used to identify hook types
|
|
1502
|
+
* Symbols used to identify hook types
|
|
1503
|
+
*/
|
|
1504
|
+
const GET_HOOK_SYMBOL = Symbol("fragno-get-hook");
|
|
1505
|
+
const MUTATOR_HOOK_SYMBOL = Symbol("fragno-mutator-hook");
|
|
1506
|
+
const STORE_SYMBOL = Symbol("fragno-store");
|
|
1507
|
+
/**
|
|
1508
|
+
* Check if a value contains files that should be sent as FormData.
|
|
1509
|
+
* @internal
|
|
1510
|
+
*/
|
|
1511
|
+
function containsFiles(value) {
|
|
1512
|
+
if (value instanceof File || value instanceof Blob) return true;
|
|
1513
|
+
if (value instanceof FormData) return true;
|
|
1514
|
+
if (typeof value === "object" && value !== null) return Object.values(value).some((v) => v instanceof File || v instanceof Blob || v instanceof FormData);
|
|
1515
|
+
return false;
|
|
1516
|
+
}
|
|
1517
|
+
/**
|
|
1518
|
+
* Convert an object containing files to FormData.
|
|
1519
|
+
* Handles nested File/Blob values by appending them directly.
|
|
1520
|
+
* Other values are JSON-stringified.
|
|
1521
|
+
* @internal
|
|
1522
|
+
*/
|
|
1523
|
+
function toFormData(value) {
|
|
1524
|
+
const formData = new FormData();
|
|
1525
|
+
for (const [key, val] of Object.entries(value)) if (val instanceof File) formData.append(key, val, val.name);
|
|
1526
|
+
else if (val instanceof Blob) formData.append(key, val);
|
|
1527
|
+
else if (val !== void 0 && val !== null) formData.append(key, typeof val === "string" ? val : JSON.stringify(val));
|
|
1528
|
+
return formData;
|
|
1529
|
+
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Prepare request body and headers for sending.
|
|
1532
|
+
* Handles FormData (file uploads) vs JSON data.
|
|
1533
|
+
* @internal
|
|
1418
1534
|
*/
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1535
|
+
function prepareRequestBody(body, contentType) {
|
|
1536
|
+
if (body === void 0) return { body: void 0 };
|
|
1537
|
+
if (contentType === "application/octet-stream") {
|
|
1538
|
+
if (body instanceof ReadableStream || body instanceof Blob || body instanceof File || body instanceof ArrayBuffer || body instanceof Uint8Array) return {
|
|
1539
|
+
body,
|
|
1540
|
+
headers: { "Content-Type": "application/octet-stream" }
|
|
1541
|
+
};
|
|
1542
|
+
throw new Error("Octet-stream routes only accept Blob, File, ArrayBuffer, Uint8Array, or ReadableStream bodies.");
|
|
1543
|
+
}
|
|
1544
|
+
if (body instanceof FormData) return { body };
|
|
1545
|
+
if (body instanceof File) {
|
|
1546
|
+
const formData = new FormData();
|
|
1547
|
+
formData.append("file", body, body.name);
|
|
1548
|
+
return { body: formData };
|
|
1549
|
+
}
|
|
1550
|
+
if (body instanceof Blob) {
|
|
1551
|
+
const formData = new FormData();
|
|
1552
|
+
formData.append("file", body);
|
|
1553
|
+
return { body: formData };
|
|
1554
|
+
}
|
|
1555
|
+
if (typeof body === "object" && body !== null && containsFiles(body)) return { body: toFormData(body) };
|
|
1556
|
+
return {
|
|
1557
|
+
body: JSON.stringify(body),
|
|
1558
|
+
headers: { "Content-Type": "application/json" }
|
|
1559
|
+
};
|
|
1560
|
+
}
|
|
1561
|
+
async function schemaAllowsUndefined(schema$1) {
|
|
1562
|
+
try {
|
|
1563
|
+
return !(await schema$1["~standard"].validate(void 0)).issues;
|
|
1564
|
+
} catch {
|
|
1565
|
+
return false;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
async function assertBodyProvided(body, inputSchema, errorMessage) {
|
|
1569
|
+
if (typeof body !== "undefined" || inputSchema === void 0) return;
|
|
1570
|
+
if (await schemaAllowsUndefined(inputSchema)) return;
|
|
1571
|
+
throw new Error(errorMessage);
|
|
1572
|
+
}
|
|
1573
|
+
/**
|
|
1574
|
+
* Merge request headers from multiple sources.
|
|
1575
|
+
* Returns undefined if there are no headers to merge.
|
|
1576
|
+
* @internal
|
|
1577
|
+
*/
|
|
1578
|
+
function mergeRequestHeaders(...headerSources) {
|
|
1579
|
+
const result = {};
|
|
1580
|
+
let hasHeaders = false;
|
|
1581
|
+
for (const source of headerSources) {
|
|
1582
|
+
if (!source) continue;
|
|
1583
|
+
if (source instanceof Headers) for (const [key, value] of source.entries()) {
|
|
1584
|
+
result[key] = value;
|
|
1585
|
+
hasHeaders = true;
|
|
1586
|
+
}
|
|
1587
|
+
else if (Array.isArray(source)) for (const [key, value] of source) {
|
|
1588
|
+
result[key] = value;
|
|
1589
|
+
hasHeaders = true;
|
|
1590
|
+
}
|
|
1591
|
+
else for (const [key, value] of Object.entries(source)) {
|
|
1592
|
+
result[key] = value;
|
|
1593
|
+
hasHeaders = true;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
return hasHeaders ? result : void 0;
|
|
1597
|
+
}
|
|
1422
1598
|
/**
|
|
1423
1599
|
* @internal
|
|
1424
1600
|
*/
|
|
@@ -1504,9 +1680,13 @@ var ClientBuilder = class {
|
|
|
1504
1680
|
get cacheEntries() {
|
|
1505
1681
|
return Object.fromEntries(this.#cache.entries());
|
|
1506
1682
|
}
|
|
1507
|
-
createStore(
|
|
1683
|
+
createStore(input) {
|
|
1684
|
+
if (typeof input === "function") return {
|
|
1685
|
+
factory: input,
|
|
1686
|
+
[STORE_SYMBOL]: true
|
|
1687
|
+
};
|
|
1508
1688
|
return {
|
|
1509
|
-
obj,
|
|
1689
|
+
obj: input,
|
|
1510
1690
|
[STORE_SYMBOL]: true
|
|
1511
1691
|
};
|
|
1512
1692
|
}
|
|
@@ -1517,7 +1697,10 @@ var ClientBuilder = class {
|
|
|
1517
1697
|
buildUrl(path, params) {
|
|
1518
1698
|
return buildUrl({
|
|
1519
1699
|
baseUrl: this.#publicConfig.baseUrl ?? "",
|
|
1520
|
-
mountRoute: getMountRoute(
|
|
1700
|
+
mountRoute: getMountRoute({
|
|
1701
|
+
name: this.#fragmentConfig.name,
|
|
1702
|
+
mountRoute: this.#publicConfig.mountRoute
|
|
1703
|
+
}),
|
|
1521
1704
|
path
|
|
1522
1705
|
}, {
|
|
1523
1706
|
pathParams: params?.path,
|
|
@@ -1536,7 +1719,7 @@ var ClientBuilder = class {
|
|
|
1536
1719
|
}
|
|
1537
1720
|
#getFetcher() {
|
|
1538
1721
|
if (this.#fetcherConfig?.type === "function") return this.#fetcherConfig.fetcher;
|
|
1539
|
-
return fetch;
|
|
1722
|
+
return globalThis.fetch.bind(globalThis);
|
|
1540
1723
|
}
|
|
1541
1724
|
#getFetcherOptions() {
|
|
1542
1725
|
if (this.#fetcherConfig?.type === "options") return this.#fetcherConfig.options;
|
|
@@ -1555,7 +1738,10 @@ var ClientBuilder = class {
|
|
|
1555
1738
|
if (route.method !== "GET") throw new Error(`Only GET routes are supported for hooks. Route '${route.path}' is a ${route.method} route.`);
|
|
1556
1739
|
if (!route.outputSchema) throw new Error(`Output schema is required for GET routes. Route '${route.path}' has no output schema.`);
|
|
1557
1740
|
const baseUrl = this.#publicConfig.baseUrl ?? "";
|
|
1558
|
-
const mountRoute = getMountRoute(
|
|
1741
|
+
const mountRoute = getMountRoute({
|
|
1742
|
+
name: this.#fragmentConfig.name,
|
|
1743
|
+
mountRoute: this.#publicConfig.mountRoute
|
|
1744
|
+
});
|
|
1559
1745
|
const fetcher = this.#getFetcher();
|
|
1560
1746
|
const fetcherOptions = this.#getFetcherOptions();
|
|
1561
1747
|
async function callServerSideHandler(params) {
|
|
@@ -1663,7 +1849,10 @@ var ClientBuilder = class {
|
|
|
1663
1849
|
#createRouteQueryMutator(route, onInvalidate = (invalidate, params) => invalidate("GET", route.path, params)) {
|
|
1664
1850
|
const method = route.method;
|
|
1665
1851
|
const baseUrl = this.#publicConfig.baseUrl ?? "";
|
|
1666
|
-
const mountRoute = getMountRoute(
|
|
1852
|
+
const mountRoute = getMountRoute({
|
|
1853
|
+
name: this.#fragmentConfig.name,
|
|
1854
|
+
mountRoute: this.#publicConfig.mountRoute
|
|
1855
|
+
});
|
|
1667
1856
|
const fetcher = this.#getFetcher();
|
|
1668
1857
|
const fetcherOptions = this.#getFetcherOptions();
|
|
1669
1858
|
async function executeMutateQuery({ body, path, query }) {
|
|
@@ -1685,11 +1874,16 @@ var ClientBuilder = class {
|
|
|
1685
1874
|
});
|
|
1686
1875
|
let response;
|
|
1687
1876
|
try {
|
|
1688
|
-
|
|
1877
|
+
const { body: preparedBody, headers: bodyHeaders } = prepareRequestBody(body, route.contentType);
|
|
1878
|
+
const mergedHeaders = mergeRequestHeaders(fetcherOptions?.headers, bodyHeaders);
|
|
1879
|
+
const requestOptions = {
|
|
1689
1880
|
...fetcherOptions,
|
|
1690
1881
|
method,
|
|
1691
|
-
body:
|
|
1692
|
-
|
|
1882
|
+
body: preparedBody,
|
|
1883
|
+
...mergedHeaders ? { headers: mergedHeaders } : {}
|
|
1884
|
+
};
|
|
1885
|
+
if (preparedBody instanceof ReadableStream) requestOptions.duplex = "half";
|
|
1886
|
+
response = await fetcher(url, requestOptions);
|
|
1693
1887
|
} catch (error) {
|
|
1694
1888
|
throw FragnoClientFetchError.fromUnknownFetchError(error);
|
|
1695
1889
|
}
|
|
@@ -1699,7 +1893,7 @@ var ClientBuilder = class {
|
|
|
1699
1893
|
const mutatorStore = this.#createMutatorStore(async ({ data }) => {
|
|
1700
1894
|
if (typeof window === "undefined") {}
|
|
1701
1895
|
const { body, path, query } = data;
|
|
1702
|
-
|
|
1896
|
+
await assertBodyProvided(body, route.inputSchema, "Body is required.");
|
|
1703
1897
|
const response = await executeMutateQuery({
|
|
1704
1898
|
body,
|
|
1705
1899
|
path,
|
|
@@ -1738,7 +1932,7 @@ var ClientBuilder = class {
|
|
|
1738
1932
|
} });
|
|
1739
1933
|
const mutateQuery = async (data) => {
|
|
1740
1934
|
const { body, path, query } = data;
|
|
1741
|
-
|
|
1935
|
+
await assertBodyProvided(body, route.inputSchema, "Body is required for mutateQuery");
|
|
1742
1936
|
const response = await executeMutateQuery({
|
|
1743
1937
|
body,
|
|
1744
1938
|
path,
|
|
@@ -1784,7 +1978,10 @@ function createClientBuilder(definition, publicConfig, routesOrFactories, author
|
|
|
1784
1978
|
name: definition.name,
|
|
1785
1979
|
routes: routes$1
|
|
1786
1980
|
};
|
|
1787
|
-
const mountRoute =
|
|
1981
|
+
const mountRoute = getMountRoute({
|
|
1982
|
+
name: definition.name,
|
|
1983
|
+
mountRoute: publicConfig.mountRoute
|
|
1984
|
+
});
|
|
1788
1985
|
const mergedFetcherConfig = mergeFetcherConfigs(authorFetcherConfig, publicConfig.fetcherConfig);
|
|
1789
1986
|
return new ClientBuilder({
|
|
1790
1987
|
...publicConfig,
|
|
@@ -1794,24 +1991,19 @@ function createClientBuilder(definition, publicConfig, routesOrFactories, author
|
|
|
1794
1991
|
}
|
|
1795
1992
|
|
|
1796
1993
|
//#endregion
|
|
1797
|
-
//#region src/
|
|
1798
|
-
|
|
1994
|
+
//#region src/database/schema.ts
|
|
1995
|
+
/**
|
|
1996
|
+
* Database schema for subscriptions that are linked to external stripe subscriptions.
|
|
1997
|
+
*/
|
|
1998
|
+
const stripeSchema = schema("stripe", (s) => {
|
|
1999
|
+
return s.addTable("subscription", (t) => {
|
|
2000
|
+
return t.addColumn("id", idColumn()).addColumn("referenceId", column("string").nullable()).addColumn("stripePriceId", column("string")).addColumn("stripeCustomerId", column("string")).addColumn("stripeSubscriptionId", column("string")).addColumn("status", column("string").defaultTo("incomplete")).addColumn("periodStart", column("timestamp").nullable()).addColumn("periodEnd", column("timestamp").nullable()).addColumn("trialStart", column("timestamp").nullable()).addColumn("trialEnd", column("timestamp").nullable()).addColumn("cancelAtPeriodEnd", column("bool").defaultTo(false)).addColumn("cancelAt", column("timestamp").nullable()).addColumn("seats", column("integer").nullable()).addColumn("createdAt", column("timestamp").defaultTo((b) => b.now())).addColumn("updatedAt", column("timestamp").defaultTo((b) => b.now())).createIndex("idx_stripe_customer_id", ["stripeCustomerId"]).createIndex("idx_stripe_subscription_id", ["stripeSubscriptionId"]).createIndex("idx_reference_id", ["referenceId"]);
|
|
2001
|
+
});
|
|
2002
|
+
});
|
|
1799
2003
|
|
|
1800
2004
|
//#endregion
|
|
1801
|
-
//#region src/
|
|
1802
|
-
const
|
|
1803
|
-
return [defineRoute({
|
|
1804
|
-
method: "POST",
|
|
1805
|
-
path: "/webhook",
|
|
1806
|
-
outputSchema: z.object({ success: z.boolean() }),
|
|
1807
|
-
errorCodes: [
|
|
1808
|
-
"MISSING_SIGNATURE",
|
|
1809
|
-
"WEBHOOK_SIGNATURE_INVALID",
|
|
1810
|
-
"WEBHOOK_ERROR"
|
|
1811
|
-
],
|
|
1812
|
-
handler: () => {}
|
|
1813
|
-
})];
|
|
1814
|
-
});
|
|
2005
|
+
//#region src/definition.ts
|
|
2006
|
+
const stripeFragmentDefinition = defineFragment("stripe").extend((x) => x).withDependencies(() => {}).providesBaseService(() => {}).build();
|
|
1815
2007
|
|
|
1816
2008
|
//#endregion
|
|
1817
2009
|
//#region src/models/customers.ts
|
|
@@ -1865,6 +2057,104 @@ const customersRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({
|
|
|
1865
2057
|
})];
|
|
1866
2058
|
});
|
|
1867
2059
|
|
|
2060
|
+
//#endregion
|
|
2061
|
+
//#region src/models/prices.ts
|
|
2062
|
+
const PriceResponseSchema = z.object({
|
|
2063
|
+
id: z.string(),
|
|
2064
|
+
object: z.literal("price"),
|
|
2065
|
+
active: z.boolean(),
|
|
2066
|
+
billing_scheme: z.string(),
|
|
2067
|
+
created: z.number(),
|
|
2068
|
+
currency: z.string(),
|
|
2069
|
+
custom_unit_amount: z.any().nullable().optional(),
|
|
2070
|
+
deleted: z.void().optional(),
|
|
2071
|
+
livemode: z.boolean(),
|
|
2072
|
+
lookup_key: z.string().nullable().optional(),
|
|
2073
|
+
metadata: z.any(),
|
|
2074
|
+
nickname: z.string().nullable().optional(),
|
|
2075
|
+
product: z.union([z.string(), z.any()]),
|
|
2076
|
+
recurring: z.object({
|
|
2077
|
+
aggregate_usage: z.string().nullable().optional(),
|
|
2078
|
+
interval: z.enum([
|
|
2079
|
+
"day",
|
|
2080
|
+
"week",
|
|
2081
|
+
"month",
|
|
2082
|
+
"year"
|
|
2083
|
+
]),
|
|
2084
|
+
interval_count: z.number(),
|
|
2085
|
+
meter: z.string().nullable().optional(),
|
|
2086
|
+
trial_period_days: z.number().nullable().optional(),
|
|
2087
|
+
usage_type: z.string()
|
|
2088
|
+
}).nullable().optional(),
|
|
2089
|
+
tax_behavior: z.string().nullable().optional(),
|
|
2090
|
+
tiers_mode: z.string().nullable().optional(),
|
|
2091
|
+
transform_quantity: z.any().nullable().optional(),
|
|
2092
|
+
type: z.enum(["one_time", "recurring"]),
|
|
2093
|
+
unit_amount: z.number().nullable().optional(),
|
|
2094
|
+
unit_amount_decimal: z.string().nullable().optional()
|
|
2095
|
+
});
|
|
2096
|
+
|
|
2097
|
+
//#endregion
|
|
2098
|
+
//#region src/routes/prices.ts
|
|
2099
|
+
const pricesRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ deps, config, defineRoute }) => {
|
|
2100
|
+
return [defineRoute({
|
|
2101
|
+
method: "GET",
|
|
2102
|
+
path: "/admin/products/:productId/prices",
|
|
2103
|
+
inputSchema: z.object({
|
|
2104
|
+
limit: z.number().int().positive().max(100).optional().default(50).describe("Number of prices to return (max 100)"),
|
|
2105
|
+
startingAfter: z.string().optional().describe("Price ID to start after for pagination")
|
|
2106
|
+
}),
|
|
2107
|
+
outputSchema: z.object({
|
|
2108
|
+
prices: z.array(PriceResponseSchema),
|
|
2109
|
+
hasMore: z.boolean().describe("Whether there are more items to fetch")
|
|
2110
|
+
}),
|
|
2111
|
+
handler: () => {}
|
|
2112
|
+
})];
|
|
2113
|
+
});
|
|
2114
|
+
|
|
2115
|
+
//#endregion
|
|
2116
|
+
//#region src/models/products.ts
|
|
2117
|
+
const ProductResponseSchema = z.object({
|
|
2118
|
+
id: z.string(),
|
|
2119
|
+
object: z.literal("product"),
|
|
2120
|
+
active: z.boolean(),
|
|
2121
|
+
created: z.number(),
|
|
2122
|
+
default_price: z.union([z.string(), z.any()]).nullable().optional(),
|
|
2123
|
+
deleted: z.void().optional(),
|
|
2124
|
+
description: z.string().nullable(),
|
|
2125
|
+
images: z.array(z.string()),
|
|
2126
|
+
livemode: z.boolean(),
|
|
2127
|
+
marketing_features: z.array(z.any()),
|
|
2128
|
+
metadata: z.any(),
|
|
2129
|
+
name: z.string(),
|
|
2130
|
+
package_dimensions: z.any().nullable(),
|
|
2131
|
+
shippable: z.boolean().nullable(),
|
|
2132
|
+
statement_descriptor: z.string().nullable().optional(),
|
|
2133
|
+
tax_code: z.union([z.string(), z.any()]).nullable(),
|
|
2134
|
+
type: z.string(),
|
|
2135
|
+
unit_label: z.string().nullable().optional(),
|
|
2136
|
+
updated: z.number(),
|
|
2137
|
+
url: z.string().nullable()
|
|
2138
|
+
});
|
|
2139
|
+
|
|
2140
|
+
//#endregion
|
|
2141
|
+
//#region src/routes/products.ts
|
|
2142
|
+
const productsRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ deps, config, defineRoute }) => {
|
|
2143
|
+
return [defineRoute({
|
|
2144
|
+
method: "GET",
|
|
2145
|
+
path: "/admin/products",
|
|
2146
|
+
inputSchema: z.object({
|
|
2147
|
+
limit: z.number().int().positive().max(100).optional().default(50).describe("Number of products to return (max 100)"),
|
|
2148
|
+
startingAfter: z.string().optional().describe("Product ID to start after for pagination")
|
|
2149
|
+
}),
|
|
2150
|
+
outputSchema: z.object({
|
|
2151
|
+
products: z.array(ProductResponseSchema),
|
|
2152
|
+
hasMore: z.boolean().describe("Whether there are more items to fetch")
|
|
2153
|
+
}),
|
|
2154
|
+
handler: () => {}
|
|
2155
|
+
})];
|
|
2156
|
+
});
|
|
2157
|
+
|
|
1868
2158
|
//#endregion
|
|
1869
2159
|
//#region src/models/subscriptions.ts
|
|
1870
2160
|
const SubscriptionReponseSchema = z.object({
|
|
@@ -1910,6 +2200,7 @@ const subscriptionsRoutesFactory = defineRoutes(stripeFragmentDefinition).create
|
|
|
1910
2200
|
defineRoute({
|
|
1911
2201
|
method: "GET",
|
|
1912
2202
|
path: "/admin/subscriptions",
|
|
2203
|
+
errorCodes: ["UNAUTHORIZED"],
|
|
1913
2204
|
outputSchema: z.object({ subscriptions: z.array(SubscriptionReponseSchema) }),
|
|
1914
2205
|
handler: () => {}
|
|
1915
2206
|
}),
|
|
@@ -1959,99 +2250,17 @@ const subscriptionsRoutesFactory = defineRoutes(stripeFragmentDefinition).create
|
|
|
1959
2250
|
});
|
|
1960
2251
|
|
|
1961
2252
|
//#endregion
|
|
1962
|
-
//#region src/
|
|
1963
|
-
const
|
|
1964
|
-
id: z.string(),
|
|
1965
|
-
object: z.literal("product"),
|
|
1966
|
-
active: z.boolean(),
|
|
1967
|
-
created: z.number(),
|
|
1968
|
-
default_price: z.union([z.string(), z.any()]).nullable().optional(),
|
|
1969
|
-
deleted: z.void().optional(),
|
|
1970
|
-
description: z.string().nullable(),
|
|
1971
|
-
images: z.array(z.string()),
|
|
1972
|
-
livemode: z.boolean(),
|
|
1973
|
-
marketing_features: z.array(z.any()),
|
|
1974
|
-
metadata: z.any(),
|
|
1975
|
-
name: z.string(),
|
|
1976
|
-
package_dimensions: z.any().nullable(),
|
|
1977
|
-
shippable: z.boolean().nullable(),
|
|
1978
|
-
statement_descriptor: z.string().nullable().optional(),
|
|
1979
|
-
tax_code: z.union([z.string(), z.any()]).nullable(),
|
|
1980
|
-
type: z.string(),
|
|
1981
|
-
unit_label: z.string().nullable().optional(),
|
|
1982
|
-
updated: z.number(),
|
|
1983
|
-
url: z.string().nullable()
|
|
1984
|
-
});
|
|
1985
|
-
|
|
1986
|
-
//#endregion
|
|
1987
|
-
//#region src/routes/products.ts
|
|
1988
|
-
const productsRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ deps, config, defineRoute }) => {
|
|
1989
|
-
return [defineRoute({
|
|
1990
|
-
method: "GET",
|
|
1991
|
-
path: "/admin/products",
|
|
1992
|
-
inputSchema: z.object({
|
|
1993
|
-
limit: z.number().int().positive().max(100).optional().default(50).describe("Number of products to return (max 100)"),
|
|
1994
|
-
startingAfter: z.string().optional().describe("Product ID to start after for pagination")
|
|
1995
|
-
}),
|
|
1996
|
-
outputSchema: z.object({
|
|
1997
|
-
products: z.array(ProductResponseSchema),
|
|
1998
|
-
hasMore: z.boolean().describe("Whether there are more items to fetch")
|
|
1999
|
-
}),
|
|
2000
|
-
handler: () => {}
|
|
2001
|
-
})];
|
|
2002
|
-
});
|
|
2003
|
-
|
|
2004
|
-
//#endregion
|
|
2005
|
-
//#region src/models/prices.ts
|
|
2006
|
-
const PriceResponseSchema = z.object({
|
|
2007
|
-
id: z.string(),
|
|
2008
|
-
object: z.literal("price"),
|
|
2009
|
-
active: z.boolean(),
|
|
2010
|
-
billing_scheme: z.string(),
|
|
2011
|
-
created: z.number(),
|
|
2012
|
-
currency: z.string(),
|
|
2013
|
-
custom_unit_amount: z.any().nullable().optional(),
|
|
2014
|
-
deleted: z.void().optional(),
|
|
2015
|
-
livemode: z.boolean(),
|
|
2016
|
-
lookup_key: z.string().nullable().optional(),
|
|
2017
|
-
metadata: z.any(),
|
|
2018
|
-
nickname: z.string().nullable().optional(),
|
|
2019
|
-
product: z.union([z.string(), z.any()]),
|
|
2020
|
-
recurring: z.object({
|
|
2021
|
-
aggregate_usage: z.string().nullable().optional(),
|
|
2022
|
-
interval: z.enum([
|
|
2023
|
-
"day",
|
|
2024
|
-
"week",
|
|
2025
|
-
"month",
|
|
2026
|
-
"year"
|
|
2027
|
-
]),
|
|
2028
|
-
interval_count: z.number(),
|
|
2029
|
-
meter: z.string().nullable().optional(),
|
|
2030
|
-
trial_period_days: z.number().nullable().optional(),
|
|
2031
|
-
usage_type: z.string()
|
|
2032
|
-
}).nullable().optional(),
|
|
2033
|
-
tax_behavior: z.string().nullable().optional(),
|
|
2034
|
-
tiers_mode: z.string().nullable().optional(),
|
|
2035
|
-
transform_quantity: z.any().nullable().optional(),
|
|
2036
|
-
type: z.enum(["one_time", "recurring"]),
|
|
2037
|
-
unit_amount: z.number().nullable().optional(),
|
|
2038
|
-
unit_amount_decimal: z.string().nullable().optional()
|
|
2039
|
-
});
|
|
2040
|
-
|
|
2041
|
-
//#endregion
|
|
2042
|
-
//#region src/routes/prices.ts
|
|
2043
|
-
const pricesRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ deps, config, defineRoute }) => {
|
|
2253
|
+
//#region src/routes/webhooks.ts
|
|
2254
|
+
const webhookRoutesFactory = defineRoutes(stripeFragmentDefinition).create(({ config, deps, services, defineRoute }) => {
|
|
2044
2255
|
return [defineRoute({
|
|
2045
|
-
method: "
|
|
2046
|
-
path: "/
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
hasMore: z.boolean().describe("Whether there are more items to fetch")
|
|
2054
|
-
}),
|
|
2256
|
+
method: "POST",
|
|
2257
|
+
path: "/webhook",
|
|
2258
|
+
outputSchema: z.object({ success: z.boolean() }),
|
|
2259
|
+
errorCodes: [
|
|
2260
|
+
"MISSING_SIGNATURE",
|
|
2261
|
+
"WEBHOOK_SIGNATURE_INVALID",
|
|
2262
|
+
"WEBHOOK_ERROR"
|
|
2263
|
+
],
|
|
2055
2264
|
handler: () => {}
|
|
2056
2265
|
})];
|
|
2057
2266
|
});
|
|
@@ -2083,4 +2292,4 @@ function createStripeFragmentClients(fragnoConfig = {}) {
|
|
|
2083
2292
|
|
|
2084
2293
|
//#endregion
|
|
2085
2294
|
export { atom, createStripeFragment, createStripeFragmentClients, isGetHook, isMutatorHook, isReadableAtom, isStore, stripeFragmentDefinition };
|
|
2086
|
-
//# sourceMappingURL=src-
|
|
2295
|
+
//# sourceMappingURL=src-D6VWnvEs.js.map
|