wellcrafted 0.37.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/error/index.d.ts +2 -2
- package/dist/error/index.js +2 -2
- package/dist/{error-DLVm7dsh.js → error-Dy9wXt5_.js} +2 -45
- package/dist/error-Dy9wXt5_.js.map +1 -0
- package/dist/index-B9PnZCTt.d.ts +73 -0
- package/dist/index-B9PnZCTt.d.ts.map +1 -0
- package/dist/json.d.ts +1 -1
- package/dist/json.js +1 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.d.ts.map +1 -1
- package/dist/query/index.js.map +1 -1
- package/dist/testing.js +1 -1
- package/package.json +1 -1
- package/dist/error-DLVm7dsh.js.map +0 -1
- package/dist/index-BNWUFJ69.d.ts +0 -129
- package/dist/index-BNWUFJ69.d.ts.map +0 -1
package/dist/error/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import "../result-DKwq9BCr.js";
|
|
2
2
|
import { AnyTaggedError, DefineErrorsReturn, ErrorBody, ErrorsConfig, InferError, InferErrors, ValidatedConfig } from "../types-tXXk7K9Q.js";
|
|
3
|
-
import {
|
|
4
|
-
export { AnyTaggedError, DefineErrorsReturn,
|
|
3
|
+
import { defineErrors, extractErrorMessage } from "../index-B9PnZCTt.js";
|
|
4
|
+
export { AnyTaggedError, DefineErrorsReturn, ErrorBody, ErrorsConfig, InferError, InferErrors, ValidatedConfig, defineErrors, extractErrorMessage };
|
package/dist/error/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import "../result-C5cJ1_WU.js";
|
|
2
|
-
import { defineErrors,
|
|
2
|
+
import { defineErrors, extractErrorMessage } from "../error-Dy9wXt5_.js";
|
|
3
3
|
|
|
4
|
-
export { defineErrors,
|
|
4
|
+
export { defineErrors, extractErrorMessage };
|
|
@@ -66,49 +66,6 @@ function defineErrors(config) {
|
|
|
66
66
|
return result;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
//#endregion
|
|
70
|
-
//#region src/error/defineHttpErrors.ts
|
|
71
|
-
/**
|
|
72
|
-
* Defines a set of typed HTTP error factories, each paired with its HTTP
|
|
73
|
-
* status code.
|
|
74
|
-
*
|
|
75
|
-
* Like `defineErrors`, each factory stamps `name` onto the error and wraps it
|
|
76
|
-
* in `Err`. Unlike `defineErrors`, each factory function carries a static
|
|
77
|
-
* `.status` property with the literal HTTP status code — the status is never
|
|
78
|
-
* included in the serialized error body.
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```ts
|
|
82
|
-
* const AssetError = defineHttpErrors({
|
|
83
|
-
* MissingFile: [400, () => ({ message: 'Missing file' })],
|
|
84
|
-
* FileTooLarge: [413, ({ size }: { size: number }) => ({ message: `File too large: ${size}`, size })],
|
|
85
|
-
* StorageLimitExceeded: [402, () => ({ message: 'Storage limit exceeded' })],
|
|
86
|
-
* });
|
|
87
|
-
*
|
|
88
|
-
* type AssetError = InferHttpErrors<typeof AssetError>;
|
|
89
|
-
*
|
|
90
|
-
* // In a Hono route handler:
|
|
91
|
-
* return c.json(AssetError.MissingFile(), AssetError.MissingFile.status);
|
|
92
|
-
* // wire body: { error: { name: 'MissingFile', message: 'Missing file' }, data: null }
|
|
93
|
-
* // http status: 400
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
function defineHttpErrors(config) {
|
|
97
|
-
const result = {};
|
|
98
|
-
for (const [name, [status, factory]] of Object.entries(config)) {
|
|
99
|
-
const fn = (...args) => {
|
|
100
|
-
const body = factory(...args);
|
|
101
|
-
return Err(Object.freeze({
|
|
102
|
-
...body,
|
|
103
|
-
name
|
|
104
|
-
}));
|
|
105
|
-
};
|
|
106
|
-
fn.status = status;
|
|
107
|
-
result[name] = fn;
|
|
108
|
-
}
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
69
|
//#endregion
|
|
113
70
|
//#region src/error/extractErrorMessage.ts
|
|
114
71
|
/**
|
|
@@ -146,5 +103,5 @@ function extractErrorMessage(error) {
|
|
|
146
103
|
}
|
|
147
104
|
|
|
148
105
|
//#endregion
|
|
149
|
-
export { defineErrors,
|
|
150
|
-
//# sourceMappingURL=error-
|
|
106
|
+
export { defineErrors, extractErrorMessage };
|
|
107
|
+
//# sourceMappingURL=error-Dy9wXt5_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-Dy9wXt5_.js","names":["config: TConfig & ValidatedConfig<TConfig>","result: Record<string, unknown>","error: unknown"],"sources":["../src/error/defineErrors.ts","../src/error/extractErrorMessage.ts"],"sourcesContent":["import { Err } from \"../result/result.js\";\nimport type {\n\tDefineErrorsReturn,\n\tErrorsConfig,\n\tValidatedConfig,\n} from \"./types.js\";\n\n/**\n * Defines a set of typed error factories using Rust-style namespaced variants.\n *\n * Each key is a short variant name (the namespace provides context). Every\n * factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch\n * handlers. The variant name is stamped as `name` on the error object.\n *\n * @example\n * ```ts\n * const HttpError = defineErrors({\n * Connection: ({ cause }: { cause: unknown }) => ({\n * message: `Failed to connect: ${extractErrorMessage(cause)}`,\n * cause,\n * }),\n * Response: ({ status }: { status: number; bodyMessage?: string }) => ({\n * message: `HTTP ${status}`,\n * status,\n * }),\n * Parse: ({ cause }: { cause: unknown }) => ({\n * message: `Failed to parse response body: ${extractErrorMessage(cause)}`,\n * cause,\n * }),\n * });\n *\n * type HttpError = InferErrors<typeof HttpError>;\n *\n * const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>\n * ```\n *\n * Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The\n * mapping is nearly 1:1:\n *\n * - `enum HttpError` → `const HttpError = defineErrors(...)`\n * - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`\n * - `#[error(\"Failed: {cause}\")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``\n * - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`\n * - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`\n *\n * The equivalent Rust `thiserror` enum:\n * ```rust\n * #[derive(Error, Debug)]\n * enum HttpError {\n * #[error(\"Failed to connect: {cause}\")]\n * Connection { cause: String },\n *\n * #[error(\"HTTP {status}\")]\n * Response { status: u16, body_message: Option<String> },\n *\n * #[error(\"Failed to parse response body: {cause}\")]\n * Parse { cause: String },\n * }\n * ```\n */\nexport function defineErrors<const TConfig extends ErrorsConfig>(\n\tconfig: TConfig & ValidatedConfig<TConfig>,\n): DefineErrorsReturn<TConfig> {\n\tconst result: Record<string, unknown> = {};\n\n\tfor (const [name, ctor] of Object.entries(config)) {\n\t\tresult[name] = (...args: unknown[]) => {\n\t\t\tconst body = (ctor as (...a: unknown[]) => Record<string, unknown>)(\n\t\t\t\t...args,\n\t\t\t);\n\t\t\treturn Err(Object.freeze({ ...body, name }));\n\t\t};\n\t}\n\n\treturn result as DefineErrorsReturn<TConfig>;\n}\n","/**\n * Extracts a readable error message from an unknown error value\n *\n * @param error - The unknown error to extract a message from\n * @returns A string representation of the error\n */\nexport function extractErrorMessage(error: unknown): string {\n\t// Handle Error instances\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\t// Handle primitives\n\tif (typeof error === \"string\") return error;\n\tif (\n\t\ttypeof error === \"number\" ||\n\t\ttypeof error === \"boolean\" ||\n\t\ttypeof error === \"bigint\"\n\t)\n\t\treturn String(error);\n\tif (typeof error === \"symbol\") return error.toString();\n\tif (error === null) return \"null\";\n\tif (error === undefined) return \"undefined\";\n\n\t// Handle arrays\n\tif (Array.isArray(error)) return JSON.stringify(error);\n\n\t// Handle plain objects\n\tif (typeof error === \"object\") {\n\t\tconst errorObj = error as Record<string, unknown>;\n\n\t\t// Check common error properties\n\t\tconst messageProps = [\n\t\t\t\"message\",\n\t\t\t\"error\",\n\t\t\t\"description\",\n\t\t\t\"title\",\n\t\t\t\"reason\",\n\t\t\t\"details\",\n\t\t] as const;\n\t\tfor (const prop of messageProps) {\n\t\t\tif (prop in errorObj && typeof errorObj[prop] === \"string\") {\n\t\t\t\treturn errorObj[prop];\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to JSON stringification\n\t\ttry {\n\t\t\treturn JSON.stringify(error);\n\t\t} catch {\n\t\t\treturn String(error);\n\t\t}\n\t}\n\n\t// Final fallback\n\treturn String(error);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,SAAgB,aACfA,QAC8B;CAC9B,MAAMC,SAAkC,CAAE;AAE1C,MAAK,MAAM,CAAC,MAAM,KAAK,IAAI,OAAO,QAAQ,OAAO,CAChD,QAAO,QAAQ,CAAC,GAAG,SAAoB;EACtC,MAAM,OAAO,AAAC,KACb,GAAG,KACH;AACD,SAAO,IAAI,OAAO,OAAO;GAAE,GAAG;GAAM;EAAM,EAAC,CAAC;CAC5C;AAGF,QAAO;AACP;;;;;;;;;;ACrED,SAAgB,oBAAoBC,OAAwB;AAE3D,KAAI,iBAAiB,MACpB,QAAO,MAAM;AAId,YAAW,UAAU,SAAU,QAAO;AACtC,YACQ,UAAU,mBACV,UAAU,oBACV,UAAU,SAEjB,QAAO,OAAO,MAAM;AACrB,YAAW,UAAU,SAAU,QAAO,MAAM,UAAU;AACtD,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,iBAAqB,QAAO;AAGhC,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,UAAU,MAAM;AAGtD,YAAW,UAAU,UAAU;EAC9B,MAAM,WAAW;EAGjB,MAAM,eAAe;GACpB;GACA;GACA;GACA;GACA;GACA;EACA;AACD,OAAK,MAAM,QAAQ,aAClB,KAAI,QAAQ,mBAAmB,SAAS,UAAU,SACjD,QAAO,SAAS;AAKlB,MAAI;AACH,UAAO,KAAK,UAAU,MAAM;EAC5B,QAAO;AACP,UAAO,OAAO,MAAM;EACpB;CACD;AAGD,QAAO,OAAO,MAAM;AACpB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { DefineErrorsReturn, ErrorsConfig, ValidatedConfig } from "./types-tXXk7K9Q.js";
|
|
2
|
+
|
|
3
|
+
//#region src/error/defineErrors.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Defines a set of typed error factories using Rust-style namespaced variants.
|
|
7
|
+
*
|
|
8
|
+
* Each key is a short variant name (the namespace provides context). Every
|
|
9
|
+
* factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch
|
|
10
|
+
* handlers. The variant name is stamped as `name` on the error object.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const HttpError = defineErrors({
|
|
15
|
+
* Connection: ({ cause }: { cause: unknown }) => ({
|
|
16
|
+
* message: `Failed to connect: ${extractErrorMessage(cause)}`,
|
|
17
|
+
* cause,
|
|
18
|
+
* }),
|
|
19
|
+
* Response: ({ status }: { status: number; bodyMessage?: string }) => ({
|
|
20
|
+
* message: `HTTP ${status}`,
|
|
21
|
+
* status,
|
|
22
|
+
* }),
|
|
23
|
+
* Parse: ({ cause }: { cause: unknown }) => ({
|
|
24
|
+
* message: `Failed to parse response body: ${extractErrorMessage(cause)}`,
|
|
25
|
+
* cause,
|
|
26
|
+
* }),
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* type HttpError = InferErrors<typeof HttpError>;
|
|
30
|
+
*
|
|
31
|
+
* const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The
|
|
35
|
+
* mapping is nearly 1:1:
|
|
36
|
+
*
|
|
37
|
+
* - `enum HttpError` → `const HttpError = defineErrors(...)`
|
|
38
|
+
* - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`
|
|
39
|
+
* - `#[error("Failed: {cause}")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``
|
|
40
|
+
* - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`
|
|
41
|
+
* - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`
|
|
42
|
+
*
|
|
43
|
+
* The equivalent Rust `thiserror` enum:
|
|
44
|
+
* ```rust
|
|
45
|
+
* #[derive(Error, Debug)]
|
|
46
|
+
* enum HttpError {
|
|
47
|
+
* #[error("Failed to connect: {cause}")]
|
|
48
|
+
* Connection { cause: String },
|
|
49
|
+
*
|
|
50
|
+
* #[error("HTTP {status}")]
|
|
51
|
+
* Response { status: u16, body_message: Option<String> },
|
|
52
|
+
*
|
|
53
|
+
* #[error("Failed to parse response body: {cause}")]
|
|
54
|
+
* Parse { cause: String },
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare function defineErrors<const TConfig extends ErrorsConfig>(config: TConfig & ValidatedConfig<TConfig>): DefineErrorsReturn<TConfig>;
|
|
59
|
+
//# sourceMappingURL=defineErrors.d.ts.map
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/error/extractErrorMessage.d.ts
|
|
62
|
+
/**
|
|
63
|
+
* Extracts a readable error message from an unknown error value
|
|
64
|
+
*
|
|
65
|
+
* @param error - The unknown error to extract a message from
|
|
66
|
+
* @returns A string representation of the error
|
|
67
|
+
*/
|
|
68
|
+
declare function extractErrorMessage(error: unknown): string;
|
|
69
|
+
//# sourceMappingURL=extractErrorMessage.d.ts.map
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { defineErrors, extractErrorMessage };
|
|
73
|
+
//# sourceMappingURL=index-B9PnZCTt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B9PnZCTt.d.ts","names":[],"sources":["../src/error/defineErrors.ts","../src/error/extractErrorMessage.ts"],"sourcesContent":[],"mappings":";;;;;;AA4DA;;;;;;;;AAEqB;;;;ACxDrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBDsDgB,mCAAmC,sBAC1C,UAAU,gBAAgB,WAChC,mBAAmB;;;;;;;AAFtB;;;AACS,iBCvDO,mBAAA,CDuDP,KAAA,EAAA,OAAA,CAAA,EAAA,MAAA"}
|
package/dist/json.d.ts
CHANGED
package/dist/json.js
CHANGED
package/dist/query/index.d.ts
CHANGED
|
@@ -153,7 +153,7 @@ type DefineMutationOutput<TData, TError, TVariables = void, TContext = unknown>
|
|
|
153
153
|
* ```
|
|
154
154
|
*/
|
|
155
155
|
declare function createQueryFactories(queryClient: QueryClient): {
|
|
156
|
-
defineQuery: <TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = readonly unknown[]>(options: DefineQueryInput<TQueryFnData, TError, TData, TQueryData, TQueryKey>) => DefineQueryOutput<TQueryFnData, TError, TData, TQueryData, TQueryKey>;
|
|
156
|
+
defineQuery: <TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryData = TQueryFnData, const TQueryKey extends QueryKey = readonly unknown[]>(options: DefineQueryInput<TQueryFnData, TError, TData, TQueryData, TQueryKey>) => DefineQueryOutput<TQueryFnData, TError, TData, TQueryData, TQueryKey>;
|
|
157
157
|
defineMutation: <TData, TError, TVariables = void, TContext = unknown>(options: DefineMutationInput<TData, TError, TVariables, TContext>) => DefineMutationOutput<TData, TError, TVariables, TContext>;
|
|
158
158
|
};
|
|
159
159
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/query/utils.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AAUmE;;;;;;;;KAc9D,gBAO+B,CAAA,eAAA,OAAA,EAAA,SAL1B,YAK0B,EAAA,QAJ3B,YAI2B,EAAA,aAHtB,YAGsB,EAAA,kBAFjB,QAEiB,GAFN,QAEM,CAAA,GADhC,IACgC,CAAnC,oBAAmC,CAAd,YAAc,EAAA,MAAA,EAAQ,KAAR,EAAe,UAAf,EAA2B,SAA3B,CAAA,EAAA,SAAA,CAAA,GAAA;EAAM,QAAE,EAGjC,SAHiC;EAAK,OAAE,EAIzC,aAJyC,CAI3B,MAJ2B,CAIpB,YAJoB,EAIN,MAJM,CAAA,EAIG,SAJH,CAAA;CAAU;;;;;;;;;AAItC;AAAA;;;;;;;;;;;;;;;;;;;;;;;;KAoClB,iBAeU,CAAA,eAAA,OAAA,EAAA,SAbL,YAaK,EAAA,QAZN,YAYM,EAAA,aAXD,YAWC,EAAA,kBAVI,QAUJ,GAVe,QAUf,CAAA,GAAA,CAAA,GAAA,GATJ,OASI,CATI,MASJ,CATW,UASX,EATuB,MASvB,CAAA,CAAA,CAAA,GAAA;EAAO,OAAA,EARZ,oBAQY,CAPpB,YAOoB,EANpB,MAMoB,EALpB,KAKoB,EAJpB,UAIoB,EAHpB,SAGoB,CAAA;EAejB,KAAA,EAAA,GAAA,GAhBS,OAgBT,CAhBiB,MAgBE,CAhBK,UAgBL,EAhBiB,MAgBjB,CAAA,CAAA;EAAA,MAAA,EAAA,GAAA,GAfT,OAeS,CAfD,MAeC,CAfM,UAeN,EAfkB,MAelB,CAAA,CAAA;CAAA;;;;;;;;;;;;AAOK;AAAA,KAPxB,mBAyCA,CAAA,KAAoB,EAAA,MAAA,EAAA,aAAA,IAAA,EAAA,WAAA,OAAA,CAAA,GApCrB,IAoCqB,CApChB,eAoCgB,CApCA,KAoCA,EApCO,MAoCP,EApCe,UAoCf,EApC2B,QAoC3B,CAAA,EAAA,YAAA,CAAA,GAAA;EAAA,WAAA,EAnCX,WAmCW;EAAA,UAKR,EAvCJ,gBAuCI,CAvCa,MAuCb,CAvCoB,KAuCpB,EAvC2B,MAuC3B,CAAA,EAvCoC,UAuCpC,CAAA;CAAU;;;;;;;;;;;;;;AAEiB;AA6C5C;;;;;;;;;;;;;;;;;KApDK,oBAmI0D,CAAA,KAAA,EAAA,MAAA,EAAA,aAAA,IAAA,EAAA,WAAA,OAAA,CAAA,GAAA,CAAA,CAAA,SAAA,EA9H9C,UA8H8C,EAAA,GA9H/B,OA8H+B,CA9HvB,MA8HuB,CA9HhB,KA8HgB,EA9HT,MA8HS,CAAA,CAAA,CAAA,GAAA;EAAS,OAApE,EA7HM,eA6HN,CA7HsB,KA6HtB,EA7H6B,MA6H7B,EA7HqC,UA6HrC,EA7HiD,QA6HjD,CAAA;EAAiB,OA8LU,EAAA,CAAA,SAAA,EA1TT,UA0TS,EAAA,GA1TM,OA0TN,CA1Tc,MA0Td,CA1TqB,KA0TrB,EA1T4B,MA0T5B,CAAA,CAAA;CAAK;;;;;;;;;AACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA9QR,oBAAA,cAAkC;iDAmE1C,eACD,2BACK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/query/utils.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AAUmE;;;;;;;;KAc9D,gBAO+B,CAAA,eAAA,OAAA,EAAA,SAL1B,YAK0B,EAAA,QAJ3B,YAI2B,EAAA,aAHtB,YAGsB,EAAA,kBAFjB,QAEiB,GAFN,QAEM,CAAA,GADhC,IACgC,CAAnC,oBAAmC,CAAd,YAAc,EAAA,MAAA,EAAQ,KAAR,EAAe,UAAf,EAA2B,SAA3B,CAAA,EAAA,SAAA,CAAA,GAAA;EAAM,QAAE,EAGjC,SAHiC;EAAK,OAAE,EAIzC,aAJyC,CAI3B,MAJ2B,CAIpB,YAJoB,EAIN,MAJM,CAAA,EAIG,SAJH,CAAA;CAAU;;;;;;;;;AAItC;AAAA;;;;;;;;;;;;;;;;;;;;;;;;KAoClB,iBAeU,CAAA,eAAA,OAAA,EAAA,SAbL,YAaK,EAAA,QAZN,YAYM,EAAA,aAXD,YAWC,EAAA,kBAVI,QAUJ,GAVe,QAUf,CAAA,GAAA,CAAA,GAAA,GATJ,OASI,CATI,MASJ,CATW,UASX,EATuB,MASvB,CAAA,CAAA,CAAA,GAAA;EAAO,OAAA,EARZ,oBAQY,CAPpB,YAOoB,EANpB,MAMoB,EALpB,KAKoB,EAJpB,UAIoB,EAHpB,SAGoB,CAAA;EAejB,KAAA,EAAA,GAAA,GAhBS,OAgBT,CAhBiB,MAgBE,CAhBK,UAgBL,EAhBiB,MAgBjB,CAAA,CAAA;EAAA,MAAA,EAAA,GAAA,GAfT,OAeS,CAfD,MAeC,CAfM,UAeN,EAfkB,MAelB,CAAA,CAAA;CAAA;;;;;;;;;;;;AAOK;AAAA,KAPxB,mBAyCA,CAAA,KAAoB,EAAA,MAAA,EAAA,aAAA,IAAA,EAAA,WAAA,OAAA,CAAA,GApCrB,IAoCqB,CApChB,eAoCgB,CApCA,KAoCA,EApCO,MAoCP,EApCe,UAoCf,EApC2B,QAoC3B,CAAA,EAAA,YAAA,CAAA,GAAA;EAAA,WAAA,EAnCX,WAmCW;EAAA,UAKR,EAvCJ,gBAuCI,CAvCa,MAuCb,CAvCoB,KAuCpB,EAvC2B,MAuC3B,CAAA,EAvCoC,UAuCpC,CAAA;CAAU;;;;;;;;;;;;;;AAEiB;AA6C5C;;;;;;;;;;;;;;;;;KApDK,oBAmI0D,CAAA,KAAA,EAAA,MAAA,EAAA,aAAA,IAAA,EAAA,WAAA,OAAA,CAAA,GAAA,CAAA,CAAA,SAAA,EA9H9C,UA8H8C,EAAA,GA9H/B,OA8H+B,CA9HvB,MA8HuB,CA9HhB,KA8HgB,EA9HT,MA8HS,CAAA,CAAA,CAAA,GAAA;EAAS,OAApE,EA7HM,eA6HN,CA7HsB,KA6HtB,EA7H6B,MA6H7B,EA7HqC,UA6HrC,EA7HiD,QA6HjD,CAAA;EAAiB,OA8LU,EAAA,CAAA,SAAA,EA1TT,UA0TS,EAAA,GA1TM,OA0TN,CA1Tc,MA0Td,CA1TqB,KA0TrB,EA1T4B,MA0T5B,CAAA,CAAA;CAAK;;;;;;;;;AACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA9QR,oBAAA,cAAkC;iDAmE1C,eACD,2BACK,sCACc,wCAEf,iBACR,cACA,QACA,OACA,YACA,eAEC,kBAAkB,cAAc,QAAQ,OAAO,YAAY;kFA8LpD,oBAAoB,OAAO,QAAQ,YAAY,cACtD,qBAAqB,OAAO,QAAQ,YAAY"}
|
package/dist/query/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["queryClient: QueryClient","options: DefineQueryInput<\n\t\t\tTQueryFnData,\n\t\t\tTError,\n\t\t\tTData,\n\t\t\tTQueryData,\n\t\t\tTQueryKey\n\t\t>","options: DefineMutationInput<TData, TError, TVariables, TContext>","variables: TVariables","options: MutationOptions<TData, TError, TVariables, TContext>"],"sources":["../../src/query/utils.ts"],"sourcesContent":["import type {\n\tDefaultError,\n\tMutationFunction,\n\tMutationKey,\n\tMutationOptions,\n\tQueryClient,\n\tQueryFunction,\n\tQueryKey,\n\tQueryObserverOptions,\n} from \"@tanstack/query-core\";\nimport { Err, Ok, type Result, resolve } from \"../result/index.js\";\n\n/**\n * Input options for defining a query.\n *\n * Extends TanStack Query's QueryObserverOptions but expects queryFn to return a Result type.\n * This type represents the configuration for creating a query definition with both\n * reactive and imperative interfaces for data fetching.\n *\n * @template TQueryFnData - The type of data returned by the query function\n * @template TError - The type of error that can be thrown\n * @template TData - The type of data returned by the query (after select transform)\n * @template TQueryKey - The type of the query key\n */\ntype DefineQueryInput<\n\tTQueryFnData = unknown,\n\tTError = DefaultError,\n\tTData = TQueryFnData,\n\tTQueryData = TQueryFnData,\n\tTQueryKey extends QueryKey = QueryKey,\n> = Omit<\n\tQueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,\n\t\"queryFn\"\n> & {\n\tqueryKey: TQueryKey;\n\tqueryFn: QueryFunction<Result<TQueryFnData, TError>, TQueryKey>;\n};\n\n/**\n * Output of defineQuery function.\n *\n * The query definition is directly callable and defaults to `ensure()` behavior,\n * which is recommended for most imperative use cases like preloaders.\n *\n * Provides both reactive and imperative interfaces for data fetching:\n * - `()` (callable): Same as `ensure()` - returns cached data if available, fetches if not\n * - `options`: Returns config for use with useQuery() or createQuery()\n * - `fetch()`: Always attempts to fetch data (from cache if fresh, network if stale)\n * - `ensure()`: Guarantees data availability, preferring cached data (recommended for preloaders)\n *\n * @template TQueryFnData - The type of data returned by the query function\n * @template TError - The type of error that can be thrown\n * @template TData - The type of data returned by the query (after select transform)\n * @template TQueryKey - The type of the query key\n *\n * @example\n * ```typescript\n * const userQuery = defineQuery({...});\n *\n * // Directly callable (same as .ensure())\n * const { data, error } = await userQuery();\n *\n * // Or use explicit methods\n * const { data, error } = await userQuery.ensure();\n * const { data, error } = await userQuery.fetch();\n *\n * // For reactive usage (Svelte 5 requires accessor wrapper)\n * const query = createQuery(() => userQuery.options); // Svelte 5\n * const query = useQuery(userQuery.options); // React\n * ```\n */\ntype DefineQueryOutput<\n\tTQueryFnData = unknown,\n\tTError = DefaultError,\n\tTData = TQueryFnData,\n\tTQueryData = TQueryFnData,\n\tTQueryKey extends QueryKey = QueryKey,\n> = (() => Promise<Result<TQueryData, TError>>) & {\n\toptions: QueryObserverOptions<\n\t\tTQueryFnData,\n\t\tTError,\n\t\tTData,\n\t\tTQueryData,\n\t\tTQueryKey\n\t>;\n\tfetch: () => Promise<Result<TQueryData, TError>>;\n\tensure: () => Promise<Result<TQueryData, TError>>;\n};\n\n/**\n * Input options for defining a mutation.\n *\n * Extends TanStack Query's MutationOptions but expects mutationFn to return a Result type.\n * This type represents the configuration for creating a mutation definition with both\n * reactive and imperative interfaces for data mutations.\n *\n * @template TData - The type of data returned by the mutation\n * @template TError - The type of error that can be thrown\n * @template TVariables - The type of variables passed to the mutation\n * @template TContext - The type of context data for optimistic updates\n */\ntype DefineMutationInput<\n\tTData,\n\tTError,\n\tTVariables = void,\n\tTContext = unknown,\n> = Omit<MutationOptions<TData, TError, TVariables, TContext>, \"mutationFn\"> & {\n\tmutationKey: MutationKey;\n\tmutationFn: MutationFunction<Result<TData, TError>, TVariables>;\n};\n\n/**\n * Output of defineMutation function.\n *\n * The mutation definition is directly callable, which executes the mutation\n * and returns a Result. This is equivalent to calling `.execute()`.\n *\n * Provides both reactive and imperative interfaces for data mutations:\n * - `(variables)` (callable): Same as `execute()` - directly executes the mutation\n * - `options`: Returns config for use with useMutation() or createMutation()\n * - `execute(variables)`: Directly executes the mutation and returns a Result\n *\n * @template TData - The type of data returned by the mutation\n * @template TError - The type of error that can be thrown\n * @template TVariables - The type of variables passed to the mutation\n * @template TContext - The type of context data for optimistic updates\n *\n * @example\n * ```typescript\n * const createUser = defineMutation({...});\n *\n * // Directly callable (same as .execute())\n * const { data, error } = await createUser({ name: 'John' });\n *\n * // Or use explicit method\n * const { data, error } = await createUser.execute({ name: 'John' });\n *\n * // For reactive usage (Svelte 5 requires accessor wrapper)\n * const mutation = createMutation(() => createUser.options); // Svelte 5\n * const mutation = useMutation(createUser.options); // React\n * ```\n */\ntype DefineMutationOutput<\n\tTData,\n\tTError,\n\tTVariables = void,\n\tTContext = unknown,\n> = ((variables: TVariables) => Promise<Result<TData, TError>>) & {\n\toptions: MutationOptions<TData, TError, TVariables, TContext>;\n\texecute: (variables: TVariables) => Promise<Result<TData, TError>>;\n};\n\n/**\n * Creates factory functions for defining queries and mutations bound to a specific QueryClient.\n *\n * This factory pattern allows you to create isolated query/mutation definitions that are\n * bound to a specific QueryClient instance, enabling:\n * - Multiple query clients in the same application\n * - Testing with isolated query clients\n * - Framework-agnostic query definitions\n * - Proper separation of concerns between query logic and client instances\n *\n * The returned functions handle Result types automatically, unwrapping them for TanStack Query\n * while maintaining type safety throughout your application.\n *\n * @param queryClient - The QueryClient instance to bind the factories to\n * @returns An object containing defineQuery and defineMutation functions bound to the provided client\n *\n * @example\n * ```typescript\n * // Create your query client\n * const queryClient = new QueryClient({\n * defaultOptions: {\n * queries: { staleTime: 5 * 60 * 1000 }\n * }\n * });\n *\n * // Create the factory functions\n * const { defineQuery, defineMutation } = createQueryFactories(queryClient);\n *\n * // Now use defineQuery and defineMutation as before\n * const userQuery = defineQuery({\n * queryKey: ['user', userId],\n * queryFn: () => services.getUser(userId)\n * });\n *\n * // Use in components (Svelte 5 requires accessor wrapper)\n * const query = createQuery(() => userQuery.options); // Svelte 5\n * const query = useQuery(userQuery.options); // React\n *\n * // Or imperatively\n * const { data, error } = await userQuery.fetch();\n * ```\n */\nexport function createQueryFactories(queryClient: QueryClient) {\n\t/**\n\t * Creates a query definition that bridges the gap between pure service functions and reactive UI components.\n\t *\n\t * This factory function is the cornerstone of our data fetching architecture. It wraps service calls\n\t * with TanStack Query superpowers while maintaining type safety through Result types.\n\t *\n\t * The returned query definition is **directly callable** and defaults to `ensure()` behavior,\n\t * which is recommended for most imperative use cases like preloaders.\n\t *\n\t * ## Why use defineQuery?\n\t *\n\t * 1. **Callable**: Call directly like `userQuery()` for imperative data fetching\n\t * 2. **Dual Interface**: Also provides reactive (`.options`) and explicit imperative (`.fetch()`, `.ensure()`) APIs\n\t * 3. **Automatic Error Handling**: Service functions return `Result<T, E>` types which are automatically\n\t * unwrapped by TanStack Query, giving you proper error states in your components\n\t * 4. **Type Safety**: Full TypeScript support with proper inference for data and error types\n\t * 5. **Consistency**: Every query in the app follows the same pattern, making it easy to understand\n\t *\n\t * @template TQueryFnData - The type of data returned by the query function\n\t * @template TError - The type of error that can be thrown\n\t * @template TData - The type of data returned by the query (after select transform)\n\t * @template TQueryKey - The type of the query key\n\t *\n\t * @param options - Query configuration object\n\t * @param options.queryKey - Unique key for this query (used for caching and refetching)\n\t * @param options.queryFn - Function that fetches data and returns a Result type\n\t * @param options.* - Any other TanStack Query options (staleTime, refetchInterval, etc.)\n\t *\n\t * @returns Callable query definition with:\n\t * - `()` (callable): Same as `ensure()` - returns cached data if available, fetches if not\n\t * - `.options`: Config for use with useQuery() or createQuery()\n\t * - `.fetch()`: Always attempts to fetch (from cache if fresh, network if stale)\n\t * - `.ensure()`: Guarantees data availability, preferring cached data (recommended for preloaders)\n\t *\n\t * @example\n\t * ```typescript\n\t * // Step 1: Define your query in the query layer\n\t * const userQuery = defineQuery({\n\t * queryKey: ['users', userId],\n\t * queryFn: () => services.getUser(userId), // Returns Result<User, ApiError>\n\t * staleTime: 5 * 60 * 1000, // Consider data fresh for 5 minutes\n\t * });\n\t *\n\t * // Step 2a: Use reactively in a Svelte 5 component (accessor wrapper required)\n\t * const query = createQuery(() => userQuery.options);\n\t * // query.data is User | undefined\n\t * // query.error is ApiError | null\n\t *\n\t * // Step 2b: Call directly in preloaders (recommended)\n\t * export const load = async () => {\n\t * const { data, error } = await userQuery(); // Same as userQuery.ensure()\n\t * if (error) throw error;\n\t * return { user: data };\n\t * };\n\t *\n\t * // Step 2c: Use explicit methods when needed\n\t * async function refreshUser() {\n\t * const { data, error } = await userQuery.fetch(); // Force fresh fetch\n\t * if (error) {\n\t * console.error('Failed to fetch user:', error);\n\t * }\n\t * }\n\t * ```\n\t */\n\tconst defineQuery = <\n\t\tTQueryFnData = unknown,\n\t\tTError = DefaultError,\n\t\tTData = TQueryFnData,\n\t\tTQueryData = TQueryFnData,\n\t\tTQueryKey extends QueryKey = QueryKey,\n\t>(\n\t\toptions: DefineQueryInput<\n\t\t\tTQueryFnData,\n\t\t\tTError,\n\t\t\tTData,\n\t\t\tTQueryData,\n\t\t\tTQueryKey\n\t\t>,\n\t): DefineQueryOutput<TQueryFnData, TError, TData, TQueryData, TQueryKey> => {\n\t\tconst newOptions = {\n\t\t\t...options,\n\t\t\tqueryFn: async (context) => {\n\t\t\t\tlet result = options.queryFn(context);\n\t\t\t\tif (result instanceof Promise) result = await result;\n\t\t\t\treturn resolve(result);\n\t\t\t},\n\t\t} satisfies QueryObserverOptions<\n\t\t\tTQueryFnData,\n\t\t\tTError,\n\t\t\tTData,\n\t\t\tTQueryData,\n\t\t\tTQueryKey\n\t\t>;\n\n\t\t/**\n\t\t * Fetches data for this query using queryClient.fetchQuery().\n\t\t *\n\t\t * This method ALWAYS evaluates freshness and will refetch if data is stale.\n\t\t * It wraps TanStack Query's fetchQuery method, which returns cached data if fresh\n\t\t * or makes a network request if the data is stale or missing.\n\t\t *\n\t\t * **When to use fetch():**\n\t\t * - When you explicitly want to check data freshness\n\t\t * - For user-triggered refresh actions\n\t\t * - When you need the most up-to-date data\n\t\t *\n\t\t * **For preloaders, use ensure() instead** - it's more efficient for initial data loading.\n\t\t *\n\t\t * @returns Promise that resolves with a Result containing either the data or an error\n\t\t *\n\t\t * @example\n\t\t * // Good for user-triggered refresh\n\t\t * const { data, error } = await userQuery.fetch();\n\t\t * if (error) {\n\t\t * console.error('Failed to load user:', error);\n\t\t * }\n\t\t */\n\t\tasync function fetch(): Promise<Result<TQueryData, TError>> {\n\t\t\ttry {\n\t\t\t\treturn Ok(\n\t\t\t\t\tawait queryClient.fetchQuery<\n\t\t\t\t\t\tTQueryFnData,\n\t\t\t\t\t\tTError,\n\t\t\t\t\t\tTQueryData,\n\t\t\t\t\t\tTQueryKey\n\t\t\t\t\t>({\n\t\t\t\t\t\tqueryKey: newOptions.queryKey,\n\t\t\t\t\t\tqueryFn: newOptions.queryFn,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treturn Err(error as TError);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Ensures data is available for this query using queryClient.ensureQueryData().\n\t\t *\n\t\t * This method PRIORITIZES cached data and only calls fetchQuery internally if no cached\n\t\t * data exists. It wraps TanStack Query's ensureQueryData method, which is perfect for\n\t\t * guaranteeing data availability with minimal network requests.\n\t\t *\n\t\t * **This is the RECOMMENDED method for preloaders** because:\n\t\t * - It returns cached data immediately if available\n\t\t * - It updates the query client cache properly\n\t\t * - It minimizes network requests during navigation\n\t\t * - It ensures components have data ready when they mount\n\t\t *\n\t\t * **When to use ensure():**\n\t\t * - Route preloaders and data loading functions\n\t\t * - Initial component data requirements\n\t\t * - When cached data is acceptable for immediate display\n\t\t *\n\t\t * This is also the default behavior when calling the query directly.\n\t\t *\n\t\t * @returns Promise that resolves with a Result containing either the data or an error\n\t\t *\n\t\t * @example\n\t\t * // Perfect for preloaders\n\t\t * export const load = async () => {\n\t\t * const { data, error } = await userQuery.ensure();\n\t\t * // Or simply: await userQuery();\n\t\t * if (error) {\n\t\t * throw error;\n\t\t * }\n\t\t * return { user: data };\n\t\t * };\n\t\t */\n\t\tasync function ensure(): Promise<Result<TQueryData, TError>> {\n\t\t\ttry {\n\t\t\t\treturn Ok(\n\t\t\t\t\tawait queryClient.ensureQueryData<\n\t\t\t\t\t\tTQueryFnData,\n\t\t\t\t\t\tTError,\n\t\t\t\t\t\tTQueryData,\n\t\t\t\t\t\tTQueryKey\n\t\t\t\t\t>({\n\t\t\t\t\t\tqueryKey: newOptions.queryKey,\n\t\t\t\t\t\tqueryFn: newOptions.queryFn,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treturn Err(error as TError);\n\t\t\t}\n\t\t}\n\n\t\t// Create a callable function that defaults to ensure() behavior\n\t\t// and attach options, fetch, and ensure as properties\n\t\treturn Object.assign(ensure, {\n\t\t\toptions: newOptions,\n\t\t\tfetch,\n\t\t\tensure,\n\t\t});\n\t};\n\n\t/**\n\t * Creates a mutation definition for operations that modify data (create, update, delete).\n\t *\n\t * This factory function is the mutation counterpart to defineQuery. It provides a clean way to\n\t * wrap service functions that perform side effects, while maintaining the same dual interface\n\t * pattern for maximum flexibility.\n\t *\n\t * The returned mutation definition is **directly callable**, which executes the mutation\n\t * and returns a Result. This is equivalent to calling `.execute()`.\n\t *\n\t * ## Why use defineMutation?\n\t *\n\t * 1. **Callable**: Call directly like `createUser({ name: 'John' })` for imperative execution\n\t * 2. **Dual Interface**: Also provides reactive (`.options`) and explicit imperative (`.execute()`) APIs\n\t * 3. **Consistent Error Handling**: Service functions return `Result<T, E>` types, ensuring\n\t * errors are handled consistently throughout the app\n\t * 4. **Cache Management**: Mutations often update the cache after success (see examples)\n\t *\n\t * @template TData - The type of data returned by the mutation\n\t * @template TError - The type of error that can be thrown\n\t * @template TVariables - The type of variables passed to the mutation\n\t * @template TContext - The type of context data for optimistic updates\n\t *\n\t * @param options - Mutation configuration object\n\t * @param options.mutationKey - Unique key for this mutation (used for tracking in-flight state)\n\t * @param options.mutationFn - Function that performs the mutation and returns a Result type\n\t * @param options.* - Any other TanStack Mutation options (onSuccess, onError, etc.)\n\t *\n\t * @returns Callable mutation definition with:\n\t * - `(variables)` (callable): Same as `execute()` - directly executes the mutation\n\t * - `.options`: Config for use with useMutation() or createMutation()\n\t * - `.execute(variables)`: Directly executes the mutation and returns a Result\n\t *\n\t * @example\n\t * ```typescript\n\t * // Step 1: Define your mutation with cache updates\n\t * const createRecording = defineMutation({\n\t * mutationKey: ['recordings', 'create'],\n\t * mutationFn: async (recording: Recording) => {\n\t * // Call the service\n\t * const result = await services.db.createRecording(recording);\n\t * if (result.error) return Err(result.error);\n\t *\n\t * // Update cache on success\n\t * queryClient.setQueryData(['recordings'], (old) =>\n\t * [...(old || []), recording]\n\t * );\n\t *\n\t * return Ok(result.data);\n\t * }\n\t * });\n\t *\n\t * // Step 2a: Use reactively in a Svelte 5 component (accessor wrapper required)\n\t * const mutation = createMutation(() => createRecording.options);\n\t * // Call with: mutation.mutate(recordingData)\n\t *\n\t * // Step 2b: Call directly in an action (recommended)\n\t * async function saveRecording(data: Recording) {\n\t * const { error } = await createRecording(data); // Same as createRecording.execute(data)\n\t * if (error) {\n\t * notify.error({ title: 'Failed to save', description: error.message });\n\t * } else {\n\t * notify.success({ title: 'Recording saved!' });\n\t * }\n\t * }\n\t * ```\n\t *\n\t * @tip Calling directly is especially useful for:\n\t * - Event handlers that need to await the result\n\t * - Sequential operations that depend on each other\n\t * - Non-component code that needs to trigger mutations\n\t */\n\tconst defineMutation = <TData, TError, TVariables = void, TContext = unknown>(\n\t\toptions: DefineMutationInput<TData, TError, TVariables, TContext>,\n\t): DefineMutationOutput<TData, TError, TVariables, TContext> => {\n\t\tconst newOptions = {\n\t\t\t...options,\n\t\t\tmutationFn: async (variables: TVariables) => {\n\t\t\t\treturn resolve(await options.mutationFn(variables));\n\t\t\t},\n\t\t} satisfies MutationOptions<TData, TError, TVariables, TContext>;\n\n\t\t/**\n\t\t * Executes the mutation imperatively and returns a Result.\n\t\t *\n\t\t * This is the recommended way to trigger mutations from:\n\t\t * - Button click handlers\n\t\t * - Form submissions\n\t\t * - Keyboard shortcuts\n\t\t * - Any non-component code\n\t\t *\n\t\t * The method automatically wraps the result in a Result type, so you always\n\t\t * get back `{ data, error }` for consistent error handling.\n\t\t *\n\t\t * This is also the default behavior when calling the mutation directly.\n\t\t *\n\t\t * @param variables - The variables to pass to the mutation function\n\t\t * @returns Promise that resolves with a Result containing either the data or an error\n\t\t *\n\t\t * @example\n\t\t * // In an event handler\n\t\t * async function handleSubmit(formData: FormData) {\n\t\t * const { data, error } = await createUser.execute(formData);\n\t\t * // Or simply: await createUser(formData);\n\t\t * if (error) {\n\t\t * notify.error({ title: 'Failed to create user', description: error.message });\n\t\t * return;\n\t\t * }\n\t\t * goto(`/users/${data.id}`);\n\t\t * }\n\t\t */\n\t\tasync function execute(variables: TVariables) {\n\t\t\ttry {\n\t\t\t\treturn Ok(await runMutation(queryClient, newOptions, variables));\n\t\t\t} catch (error) {\n\t\t\t\treturn Err(error as TError);\n\t\t\t}\n\t\t}\n\n\t\t// Create a callable function that executes the mutation\n\t\t// and attach options and execute as properties\n\t\treturn Object.assign(execute, {\n\t\t\toptions: newOptions,\n\t\t\texecute,\n\t\t});\n\t};\n\n\treturn {\n\t\tdefineQuery,\n\t\tdefineMutation,\n\t};\n}\n\n/**\n * Internal helper that executes a mutation directly using the query client's mutation cache.\n *\n * This is what powers the callable behavior and `.execute()` method on mutations.\n * It bypasses the reactive mutation hooks and runs the mutation imperatively,\n * which is perfect for event handlers and other imperative code.\n *\n * @internal\n * @template TData - The type of data returned by the mutation\n * @template TError - The type of error that can be thrown\n * @template TVariables - The type of variables passed to the mutation\n * @template TContext - The type of context data\n * @param queryClient - The query client instance to use\n * @param options - The mutation options including mutationFn and mutationKey\n * @param variables - The variables to pass to the mutation function\n * @returns Promise that resolves with the mutation result\n */\nfunction runMutation<TData, TError, TVariables, TContext>(\n\tqueryClient: QueryClient,\n\toptions: MutationOptions<TData, TError, TVariables, TContext>,\n\tvariables: TVariables,\n) {\n\tconst mutation = queryClient.getMutationCache().build(queryClient, options);\n\treturn mutation.execute(variables);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkMA,SAAgB,qBAAqBA,aAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiE9D,MAAM,cAAc,CAOnBC,YAO2E;EAC3E,MAAM,aAAa;GAClB,GAAG;GACH,SAAS,OAAO,YAAY;IAC3B,IAAI,SAAS,QAAQ,QAAQ,QAAQ;AACrC,QAAI,kBAAkB,QAAS,UAAS,MAAM;AAC9C,WAAO,QAAQ,OAAO;GACtB;EACD;;;;;;;;;;;;;;;;;;;;;;;;EA+BD,eAAe,QAA6C;AAC3D,OAAI;AACH,WAAO,GACN,MAAM,YAAY,WAKhB;KACD,UAAU,WAAW;KACrB,SAAS,WAAW;IACpB,EAAC,CACF;GACD,SAAQ,OAAO;AACf,WAAO,IAAI,MAAgB;GAC3B;EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCD,eAAe,SAA8C;AAC5D,OAAI;AACH,WAAO,GACN,MAAM,YAAY,gBAKhB;KACD,UAAU,WAAW;KACrB,SAAS,WAAW;IACpB,EAAC,CACF;GACD,SAAQ,OAAO;AACf,WAAO,IAAI,MAAgB;GAC3B;EACD;AAID,SAAO,OAAO,OAAO,QAAQ;GAC5B,SAAS;GACT;GACA;EACA,EAAC;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0ED,MAAM,iBAAiB,CACtBC,YAC+D;EAC/D,MAAM,aAAa;GAClB,GAAG;GACH,YAAY,OAAOC,cAA0B;AAC5C,WAAO,QAAQ,MAAM,QAAQ,WAAW,UAAU,CAAC;GACnD;EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BD,eAAe,QAAQA,WAAuB;AAC7C,OAAI;AACH,WAAO,GAAG,MAAM,YAAY,aAAa,YAAY,UAAU,CAAC;GAChE,SAAQ,OAAO;AACf,WAAO,IAAI,MAAgB;GAC3B;EACD;AAID,SAAO,OAAO,OAAO,SAAS;GAC7B,SAAS;GACT;EACA,EAAC;CACF;AAED,QAAO;EACN;EACA;CACA;AACD;;;;;;;;;;;;;;;;;;AAmBD,SAAS,YACRH,aACAI,SACAD,WACC;CACD,MAAM,WAAW,YAAY,kBAAkB,CAAC,MAAM,aAAa,QAAQ;AAC3E,QAAO,SAAS,QAAQ,UAAU;AAClC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["queryClient: QueryClient","options: DefineQueryInput<\n\t\t\tTQueryFnData,\n\t\t\tTError,\n\t\t\tTData,\n\t\t\tTQueryData,\n\t\t\tTQueryKey\n\t\t>","options: DefineMutationInput<TData, TError, TVariables, TContext>","variables: TVariables","options: MutationOptions<TData, TError, TVariables, TContext>"],"sources":["../../src/query/utils.ts"],"sourcesContent":["import type {\n\tDefaultError,\n\tMutationFunction,\n\tMutationKey,\n\tMutationOptions,\n\tQueryClient,\n\tQueryFunction,\n\tQueryKey,\n\tQueryObserverOptions,\n} from \"@tanstack/query-core\";\nimport { Err, Ok, type Result, resolve } from \"../result/index.js\";\n\n/**\n * Input options for defining a query.\n *\n * Extends TanStack Query's QueryObserverOptions but expects queryFn to return a Result type.\n * This type represents the configuration for creating a query definition with both\n * reactive and imperative interfaces for data fetching.\n *\n * @template TQueryFnData - The type of data returned by the query function\n * @template TError - The type of error that can be thrown\n * @template TData - The type of data returned by the query (after select transform)\n * @template TQueryKey - The type of the query key\n */\ntype DefineQueryInput<\n\tTQueryFnData = unknown,\n\tTError = DefaultError,\n\tTData = TQueryFnData,\n\tTQueryData = TQueryFnData,\n\tTQueryKey extends QueryKey = QueryKey,\n> = Omit<\n\tQueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,\n\t\"queryFn\"\n> & {\n\tqueryKey: TQueryKey;\n\tqueryFn: QueryFunction<Result<TQueryFnData, TError>, TQueryKey>;\n};\n\n/**\n * Output of defineQuery function.\n *\n * The query definition is directly callable and defaults to `ensure()` behavior,\n * which is recommended for most imperative use cases like preloaders.\n *\n * Provides both reactive and imperative interfaces for data fetching:\n * - `()` (callable): Same as `ensure()` - returns cached data if available, fetches if not\n * - `options`: Returns config for use with useQuery() or createQuery()\n * - `fetch()`: Always attempts to fetch data (from cache if fresh, network if stale)\n * - `ensure()`: Guarantees data availability, preferring cached data (recommended for preloaders)\n *\n * @template TQueryFnData - The type of data returned by the query function\n * @template TError - The type of error that can be thrown\n * @template TData - The type of data returned by the query (after select transform)\n * @template TQueryKey - The type of the query key\n *\n * @example\n * ```typescript\n * const userQuery = defineQuery({...});\n *\n * // Directly callable (same as .ensure())\n * const { data, error } = await userQuery();\n *\n * // Or use explicit methods\n * const { data, error } = await userQuery.ensure();\n * const { data, error } = await userQuery.fetch();\n *\n * // For reactive usage (Svelte 5 requires accessor wrapper)\n * const query = createQuery(() => userQuery.options); // Svelte 5\n * const query = useQuery(userQuery.options); // React\n * ```\n */\ntype DefineQueryOutput<\n\tTQueryFnData = unknown,\n\tTError = DefaultError,\n\tTData = TQueryFnData,\n\tTQueryData = TQueryFnData,\n\tTQueryKey extends QueryKey = QueryKey,\n> = (() => Promise<Result<TQueryData, TError>>) & {\n\toptions: QueryObserverOptions<\n\t\tTQueryFnData,\n\t\tTError,\n\t\tTData,\n\t\tTQueryData,\n\t\tTQueryKey\n\t>;\n\tfetch: () => Promise<Result<TQueryData, TError>>;\n\tensure: () => Promise<Result<TQueryData, TError>>;\n};\n\n/**\n * Input options for defining a mutation.\n *\n * Extends TanStack Query's MutationOptions but expects mutationFn to return a Result type.\n * This type represents the configuration for creating a mutation definition with both\n * reactive and imperative interfaces for data mutations.\n *\n * @template TData - The type of data returned by the mutation\n * @template TError - The type of error that can be thrown\n * @template TVariables - The type of variables passed to the mutation\n * @template TContext - The type of context data for optimistic updates\n */\ntype DefineMutationInput<\n\tTData,\n\tTError,\n\tTVariables = void,\n\tTContext = unknown,\n> = Omit<MutationOptions<TData, TError, TVariables, TContext>, \"mutationFn\"> & {\n\tmutationKey: MutationKey;\n\tmutationFn: MutationFunction<Result<TData, TError>, TVariables>;\n};\n\n/**\n * Output of defineMutation function.\n *\n * The mutation definition is directly callable, which executes the mutation\n * and returns a Result. This is equivalent to calling `.execute()`.\n *\n * Provides both reactive and imperative interfaces for data mutations:\n * - `(variables)` (callable): Same as `execute()` - directly executes the mutation\n * - `options`: Returns config for use with useMutation() or createMutation()\n * - `execute(variables)`: Directly executes the mutation and returns a Result\n *\n * @template TData - The type of data returned by the mutation\n * @template TError - The type of error that can be thrown\n * @template TVariables - The type of variables passed to the mutation\n * @template TContext - The type of context data for optimistic updates\n *\n * @example\n * ```typescript\n * const createUser = defineMutation({...});\n *\n * // Directly callable (same as .execute())\n * const { data, error } = await createUser({ name: 'John' });\n *\n * // Or use explicit method\n * const { data, error } = await createUser.execute({ name: 'John' });\n *\n * // For reactive usage (Svelte 5 requires accessor wrapper)\n * const mutation = createMutation(() => createUser.options); // Svelte 5\n * const mutation = useMutation(createUser.options); // React\n * ```\n */\ntype DefineMutationOutput<\n\tTData,\n\tTError,\n\tTVariables = void,\n\tTContext = unknown,\n> = ((variables: TVariables) => Promise<Result<TData, TError>>) & {\n\toptions: MutationOptions<TData, TError, TVariables, TContext>;\n\texecute: (variables: TVariables) => Promise<Result<TData, TError>>;\n};\n\n/**\n * Creates factory functions for defining queries and mutations bound to a specific QueryClient.\n *\n * This factory pattern allows you to create isolated query/mutation definitions that are\n * bound to a specific QueryClient instance, enabling:\n * - Multiple query clients in the same application\n * - Testing with isolated query clients\n * - Framework-agnostic query definitions\n * - Proper separation of concerns between query logic and client instances\n *\n * The returned functions handle Result types automatically, unwrapping them for TanStack Query\n * while maintaining type safety throughout your application.\n *\n * @param queryClient - The QueryClient instance to bind the factories to\n * @returns An object containing defineQuery and defineMutation functions bound to the provided client\n *\n * @example\n * ```typescript\n * // Create your query client\n * const queryClient = new QueryClient({\n * defaultOptions: {\n * queries: { staleTime: 5 * 60 * 1000 }\n * }\n * });\n *\n * // Create the factory functions\n * const { defineQuery, defineMutation } = createQueryFactories(queryClient);\n *\n * // Now use defineQuery and defineMutation as before\n * const userQuery = defineQuery({\n * queryKey: ['user', userId],\n * queryFn: () => services.getUser(userId)\n * });\n *\n * // Use in components (Svelte 5 requires accessor wrapper)\n * const query = createQuery(() => userQuery.options); // Svelte 5\n * const query = useQuery(userQuery.options); // React\n *\n * // Or imperatively\n * const { data, error } = await userQuery.fetch();\n * ```\n */\nexport function createQueryFactories(queryClient: QueryClient) {\n\t/**\n\t * Creates a query definition that bridges the gap between pure service functions and reactive UI components.\n\t *\n\t * This factory function is the cornerstone of our data fetching architecture. It wraps service calls\n\t * with TanStack Query superpowers while maintaining type safety through Result types.\n\t *\n\t * The returned query definition is **directly callable** and defaults to `ensure()` behavior,\n\t * which is recommended for most imperative use cases like preloaders.\n\t *\n\t * ## Why use defineQuery?\n\t *\n\t * 1. **Callable**: Call directly like `userQuery()` for imperative data fetching\n\t * 2. **Dual Interface**: Also provides reactive (`.options`) and explicit imperative (`.fetch()`, `.ensure()`) APIs\n\t * 3. **Automatic Error Handling**: Service functions return `Result<T, E>` types which are automatically\n\t * unwrapped by TanStack Query, giving you proper error states in your components\n\t * 4. **Type Safety**: Full TypeScript support with proper inference for data and error types\n\t * 5. **Consistency**: Every query in the app follows the same pattern, making it easy to understand\n\t *\n\t * @template TQueryFnData - The type of data returned by the query function\n\t * @template TError - The type of error that can be thrown\n\t * @template TData - The type of data returned by the query (after select transform)\n\t * @template TQueryKey - The type of the query key\n\t *\n\t * @param options - Query configuration object\n\t * @param options.queryKey - Unique key for this query (used for caching and refetching)\n\t * @param options.queryFn - Function that fetches data and returns a Result type\n\t * @param options.* - Any other TanStack Query options (staleTime, refetchInterval, etc.)\n\t *\n\t * @returns Callable query definition with:\n\t * - `()` (callable): Same as `ensure()` - returns cached data if available, fetches if not\n\t * - `.options`: Config for use with useQuery() or createQuery()\n\t * - `.fetch()`: Always attempts to fetch (from cache if fresh, network if stale)\n\t * - `.ensure()`: Guarantees data availability, preferring cached data (recommended for preloaders)\n\t *\n\t * @example\n\t * ```typescript\n\t * // Step 1: Define your query in the query layer\n\t * const userQuery = defineQuery({\n\t * queryKey: ['users', userId],\n\t * queryFn: () => services.getUser(userId), // Returns Result<User, ApiError>\n\t * staleTime: 5 * 60 * 1000, // Consider data fresh for 5 minutes\n\t * });\n\t *\n\t * // Step 2a: Use reactively in a Svelte 5 component (accessor wrapper required)\n\t * const query = createQuery(() => userQuery.options);\n\t * // query.data is User | undefined\n\t * // query.error is ApiError | null\n\t *\n\t * // Step 2b: Call directly in preloaders (recommended)\n\t * export const load = async () => {\n\t * const { data, error } = await userQuery(); // Same as userQuery.ensure()\n\t * if (error) throw error;\n\t * return { user: data };\n\t * };\n\t *\n\t * // Step 2c: Use explicit methods when needed\n\t * async function refreshUser() {\n\t * const { data, error } = await userQuery.fetch(); // Force fresh fetch\n\t * if (error) {\n\t * console.error('Failed to fetch user:', error);\n\t * }\n\t * }\n\t * ```\n\t */\n\tconst defineQuery = <\n\t\tTQueryFnData = unknown,\n\t\tTError = DefaultError,\n\t\tTData = TQueryFnData,\n\t\tTQueryData = TQueryFnData,\n\t\tconst TQueryKey extends QueryKey = QueryKey,\n\t>(\n\t\toptions: DefineQueryInput<\n\t\t\tTQueryFnData,\n\t\t\tTError,\n\t\t\tTData,\n\t\t\tTQueryData,\n\t\t\tTQueryKey\n\t\t>,\n\t): DefineQueryOutput<TQueryFnData, TError, TData, TQueryData, TQueryKey> => {\n\t\tconst newOptions = {\n\t\t\t...options,\n\t\t\tqueryFn: async (context) => {\n\t\t\t\tlet result = options.queryFn(context);\n\t\t\t\tif (result instanceof Promise) result = await result;\n\t\t\t\treturn resolve(result);\n\t\t\t},\n\t\t} satisfies QueryObserverOptions<\n\t\t\tTQueryFnData,\n\t\t\tTError,\n\t\t\tTData,\n\t\t\tTQueryData,\n\t\t\tTQueryKey\n\t\t>;\n\n\t\t/**\n\t\t * Fetches data for this query using queryClient.fetchQuery().\n\t\t *\n\t\t * This method ALWAYS evaluates freshness and will refetch if data is stale.\n\t\t * It wraps TanStack Query's fetchQuery method, which returns cached data if fresh\n\t\t * or makes a network request if the data is stale or missing.\n\t\t *\n\t\t * **When to use fetch():**\n\t\t * - When you explicitly want to check data freshness\n\t\t * - For user-triggered refresh actions\n\t\t * - When you need the most up-to-date data\n\t\t *\n\t\t * **For preloaders, use ensure() instead** - it's more efficient for initial data loading.\n\t\t *\n\t\t * @returns Promise that resolves with a Result containing either the data or an error\n\t\t *\n\t\t * @example\n\t\t * // Good for user-triggered refresh\n\t\t * const { data, error } = await userQuery.fetch();\n\t\t * if (error) {\n\t\t * console.error('Failed to load user:', error);\n\t\t * }\n\t\t */\n\t\tasync function fetch(): Promise<Result<TQueryData, TError>> {\n\t\t\ttry {\n\t\t\t\treturn Ok(\n\t\t\t\t\tawait queryClient.fetchQuery<\n\t\t\t\t\t\tTQueryFnData,\n\t\t\t\t\t\tTError,\n\t\t\t\t\t\tTQueryData,\n\t\t\t\t\t\tTQueryKey\n\t\t\t\t\t>({\n\t\t\t\t\t\tqueryKey: newOptions.queryKey,\n\t\t\t\t\t\tqueryFn: newOptions.queryFn,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treturn Err(error as TError);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Ensures data is available for this query using queryClient.ensureQueryData().\n\t\t *\n\t\t * This method PRIORITIZES cached data and only calls fetchQuery internally if no cached\n\t\t * data exists. It wraps TanStack Query's ensureQueryData method, which is perfect for\n\t\t * guaranteeing data availability with minimal network requests.\n\t\t *\n\t\t * **This is the RECOMMENDED method for preloaders** because:\n\t\t * - It returns cached data immediately if available\n\t\t * - It updates the query client cache properly\n\t\t * - It minimizes network requests during navigation\n\t\t * - It ensures components have data ready when they mount\n\t\t *\n\t\t * **When to use ensure():**\n\t\t * - Route preloaders and data loading functions\n\t\t * - Initial component data requirements\n\t\t * - When cached data is acceptable for immediate display\n\t\t *\n\t\t * This is also the default behavior when calling the query directly.\n\t\t *\n\t\t * @returns Promise that resolves with a Result containing either the data or an error\n\t\t *\n\t\t * @example\n\t\t * // Perfect for preloaders\n\t\t * export const load = async () => {\n\t\t * const { data, error } = await userQuery.ensure();\n\t\t * // Or simply: await userQuery();\n\t\t * if (error) {\n\t\t * throw error;\n\t\t * }\n\t\t * return { user: data };\n\t\t * };\n\t\t */\n\t\tasync function ensure(): Promise<Result<TQueryData, TError>> {\n\t\t\ttry {\n\t\t\t\treturn Ok(\n\t\t\t\t\tawait queryClient.ensureQueryData<\n\t\t\t\t\t\tTQueryFnData,\n\t\t\t\t\t\tTError,\n\t\t\t\t\t\tTQueryData,\n\t\t\t\t\t\tTQueryKey\n\t\t\t\t\t>({\n\t\t\t\t\t\tqueryKey: newOptions.queryKey,\n\t\t\t\t\t\tqueryFn: newOptions.queryFn,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treturn Err(error as TError);\n\t\t\t}\n\t\t}\n\n\t\t// Create a callable function that defaults to ensure() behavior\n\t\t// and attach options, fetch, and ensure as properties\n\t\treturn Object.assign(ensure, {\n\t\t\toptions: newOptions,\n\t\t\tfetch,\n\t\t\tensure,\n\t\t});\n\t};\n\n\t/**\n\t * Creates a mutation definition for operations that modify data (create, update, delete).\n\t *\n\t * This factory function is the mutation counterpart to defineQuery. It provides a clean way to\n\t * wrap service functions that perform side effects, while maintaining the same dual interface\n\t * pattern for maximum flexibility.\n\t *\n\t * The returned mutation definition is **directly callable**, which executes the mutation\n\t * and returns a Result. This is equivalent to calling `.execute()`.\n\t *\n\t * ## Why use defineMutation?\n\t *\n\t * 1. **Callable**: Call directly like `createUser({ name: 'John' })` for imperative execution\n\t * 2. **Dual Interface**: Also provides reactive (`.options`) and explicit imperative (`.execute()`) APIs\n\t * 3. **Consistent Error Handling**: Service functions return `Result<T, E>` types, ensuring\n\t * errors are handled consistently throughout the app\n\t * 4. **Cache Management**: Mutations often update the cache after success (see examples)\n\t *\n\t * @template TData - The type of data returned by the mutation\n\t * @template TError - The type of error that can be thrown\n\t * @template TVariables - The type of variables passed to the mutation\n\t * @template TContext - The type of context data for optimistic updates\n\t *\n\t * @param options - Mutation configuration object\n\t * @param options.mutationKey - Unique key for this mutation (used for tracking in-flight state)\n\t * @param options.mutationFn - Function that performs the mutation and returns a Result type\n\t * @param options.* - Any other TanStack Mutation options (onSuccess, onError, etc.)\n\t *\n\t * @returns Callable mutation definition with:\n\t * - `(variables)` (callable): Same as `execute()` - directly executes the mutation\n\t * - `.options`: Config for use with useMutation() or createMutation()\n\t * - `.execute(variables)`: Directly executes the mutation and returns a Result\n\t *\n\t * @example\n\t * ```typescript\n\t * // Step 1: Define your mutation with cache updates\n\t * const createRecording = defineMutation({\n\t * mutationKey: ['recordings', 'create'],\n\t * mutationFn: async (recording: Recording) => {\n\t * // Call the service\n\t * const result = await services.db.createRecording(recording);\n\t * if (result.error) return Err(result.error);\n\t *\n\t * // Update cache on success\n\t * queryClient.setQueryData(['recordings'], (old) =>\n\t * [...(old || []), recording]\n\t * );\n\t *\n\t * return Ok(result.data);\n\t * }\n\t * });\n\t *\n\t * // Step 2a: Use reactively in a Svelte 5 component (accessor wrapper required)\n\t * const mutation = createMutation(() => createRecording.options);\n\t * // Call with: mutation.mutate(recordingData)\n\t *\n\t * // Step 2b: Call directly in an action (recommended)\n\t * async function saveRecording(data: Recording) {\n\t * const { error } = await createRecording(data); // Same as createRecording.execute(data)\n\t * if (error) {\n\t * notify.error({ title: 'Failed to save', description: error.message });\n\t * } else {\n\t * notify.success({ title: 'Recording saved!' });\n\t * }\n\t * }\n\t * ```\n\t *\n\t * @tip Calling directly is especially useful for:\n\t * - Event handlers that need to await the result\n\t * - Sequential operations that depend on each other\n\t * - Non-component code that needs to trigger mutations\n\t */\n\tconst defineMutation = <TData, TError, TVariables = void, TContext = unknown>(\n\t\toptions: DefineMutationInput<TData, TError, TVariables, TContext>,\n\t): DefineMutationOutput<TData, TError, TVariables, TContext> => {\n\t\tconst newOptions = {\n\t\t\t...options,\n\t\t\tmutationFn: async (variables: TVariables) => {\n\t\t\t\treturn resolve(await options.mutationFn(variables));\n\t\t\t},\n\t\t} satisfies MutationOptions<TData, TError, TVariables, TContext>;\n\n\t\t/**\n\t\t * Executes the mutation imperatively and returns a Result.\n\t\t *\n\t\t * This is the recommended way to trigger mutations from:\n\t\t * - Button click handlers\n\t\t * - Form submissions\n\t\t * - Keyboard shortcuts\n\t\t * - Any non-component code\n\t\t *\n\t\t * The method automatically wraps the result in a Result type, so you always\n\t\t * get back `{ data, error }` for consistent error handling.\n\t\t *\n\t\t * This is also the default behavior when calling the mutation directly.\n\t\t *\n\t\t * @param variables - The variables to pass to the mutation function\n\t\t * @returns Promise that resolves with a Result containing either the data or an error\n\t\t *\n\t\t * @example\n\t\t * // In an event handler\n\t\t * async function handleSubmit(formData: FormData) {\n\t\t * const { data, error } = await createUser.execute(formData);\n\t\t * // Or simply: await createUser(formData);\n\t\t * if (error) {\n\t\t * notify.error({ title: 'Failed to create user', description: error.message });\n\t\t * return;\n\t\t * }\n\t\t * goto(`/users/${data.id}`);\n\t\t * }\n\t\t */\n\t\tasync function execute(variables: TVariables) {\n\t\t\ttry {\n\t\t\t\treturn Ok(await runMutation(queryClient, newOptions, variables));\n\t\t\t} catch (error) {\n\t\t\t\treturn Err(error as TError);\n\t\t\t}\n\t\t}\n\n\t\t// Create a callable function that executes the mutation\n\t\t// and attach options and execute as properties\n\t\treturn Object.assign(execute, {\n\t\t\toptions: newOptions,\n\t\t\texecute,\n\t\t});\n\t};\n\n\treturn {\n\t\tdefineQuery,\n\t\tdefineMutation,\n\t};\n}\n\n/**\n * Internal helper that executes a mutation directly using the query client's mutation cache.\n *\n * This is what powers the callable behavior and `.execute()` method on mutations.\n * It bypasses the reactive mutation hooks and runs the mutation imperatively,\n * which is perfect for event handlers and other imperative code.\n *\n * @internal\n * @template TData - The type of data returned by the mutation\n * @template TError - The type of error that can be thrown\n * @template TVariables - The type of variables passed to the mutation\n * @template TContext - The type of context data\n * @param queryClient - The query client instance to use\n * @param options - The mutation options including mutationFn and mutationKey\n * @param variables - The variables to pass to the mutation function\n * @returns Promise that resolves with the mutation result\n */\nfunction runMutation<TData, TError, TVariables, TContext>(\n\tqueryClient: QueryClient,\n\toptions: MutationOptions<TData, TError, TVariables, TContext>,\n\tvariables: TVariables,\n) {\n\tconst mutation = queryClient.getMutationCache().build(queryClient, options);\n\treturn mutation.execute(variables);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkMA,SAAgB,qBAAqBA,aAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiE9D,MAAM,cAAc,CAOnBC,YAO2E;EAC3E,MAAM,aAAa;GAClB,GAAG;GACH,SAAS,OAAO,YAAY;IAC3B,IAAI,SAAS,QAAQ,QAAQ,QAAQ;AACrC,QAAI,kBAAkB,QAAS,UAAS,MAAM;AAC9C,WAAO,QAAQ,OAAO;GACtB;EACD;;;;;;;;;;;;;;;;;;;;;;;;EA+BD,eAAe,QAA6C;AAC3D,OAAI;AACH,WAAO,GACN,MAAM,YAAY,WAKhB;KACD,UAAU,WAAW;KACrB,SAAS,WAAW;IACpB,EAAC,CACF;GACD,SAAQ,OAAO;AACf,WAAO,IAAI,MAAgB;GAC3B;EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCD,eAAe,SAA8C;AAC5D,OAAI;AACH,WAAO,GACN,MAAM,YAAY,gBAKhB;KACD,UAAU,WAAW;KACrB,SAAS,WAAW;IACpB,EAAC,CACF;GACD,SAAQ,OAAO;AACf,WAAO,IAAI,MAAgB;GAC3B;EACD;AAID,SAAO,OAAO,OAAO,QAAQ;GAC5B,SAAS;GACT;GACA;EACA,EAAC;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0ED,MAAM,iBAAiB,CACtBC,YAC+D;EAC/D,MAAM,aAAa;GAClB,GAAG;GACH,YAAY,OAAOC,cAA0B;AAC5C,WAAO,QAAQ,MAAM,QAAQ,WAAW,UAAU,CAAC;GACnD;EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BD,eAAe,QAAQA,WAAuB;AAC7C,OAAI;AACH,WAAO,GAAG,MAAM,YAAY,aAAa,YAAY,UAAU,CAAC;GAChE,SAAQ,OAAO;AACf,WAAO,IAAI,MAAgB;GAC3B;EACD;AAID,SAAO,OAAO,OAAO,SAAS;GAC7B,SAAS;GACT;EACA,EAAC;CACF;AAED,QAAO;EACN;EACA;CACA;AACD;;;;;;;;;;;;;;;;;;AAmBD,SAAS,YACRH,aACAI,SACAD,WACC;CACD,MAAM,WAAW,YAAY,kBAAkB,CAAC,MAAM,aAAa,QAAQ;AAC3E,QAAO,SAAS,QAAQ,UAAU;AAClC"}
|
package/dist/testing.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"error-DLVm7dsh.js","names":["config: TConfig & ValidatedConfig<TConfig>","result: Record<string, unknown>","config: TConfig & ValidatedHttpConfig<TConfig>","result: Record<string, unknown>","error: unknown"],"sources":["../src/error/defineErrors.ts","../src/error/defineHttpErrors.ts","../src/error/extractErrorMessage.ts"],"sourcesContent":["import { Err } from \"../result/result.js\";\nimport type {\n\tDefineErrorsReturn,\n\tErrorsConfig,\n\tValidatedConfig,\n} from \"./types.js\";\n\n/**\n * Defines a set of typed error factories using Rust-style namespaced variants.\n *\n * Each key is a short variant name (the namespace provides context). Every\n * factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch\n * handlers. The variant name is stamped as `name` on the error object.\n *\n * @example\n * ```ts\n * const HttpError = defineErrors({\n * Connection: ({ cause }: { cause: unknown }) => ({\n * message: `Failed to connect: ${extractErrorMessage(cause)}`,\n * cause,\n * }),\n * Response: ({ status }: { status: number; bodyMessage?: string }) => ({\n * message: `HTTP ${status}`,\n * status,\n * }),\n * Parse: ({ cause }: { cause: unknown }) => ({\n * message: `Failed to parse response body: ${extractErrorMessage(cause)}`,\n * cause,\n * }),\n * });\n *\n * type HttpError = InferErrors<typeof HttpError>;\n *\n * const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>\n * ```\n *\n * Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The\n * mapping is nearly 1:1:\n *\n * - `enum HttpError` → `const HttpError = defineErrors(...)`\n * - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`\n * - `#[error(\"Failed: {cause}\")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``\n * - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`\n * - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`\n *\n * The equivalent Rust `thiserror` enum:\n * ```rust\n * #[derive(Error, Debug)]\n * enum HttpError {\n * #[error(\"Failed to connect: {cause}\")]\n * Connection { cause: String },\n *\n * #[error(\"HTTP {status}\")]\n * Response { status: u16, body_message: Option<String> },\n *\n * #[error(\"Failed to parse response body: {cause}\")]\n * Parse { cause: String },\n * }\n * ```\n */\nexport function defineErrors<const TConfig extends ErrorsConfig>(\n\tconfig: TConfig & ValidatedConfig<TConfig>,\n): DefineErrorsReturn<TConfig> {\n\tconst result: Record<string, unknown> = {};\n\n\tfor (const [name, ctor] of Object.entries(config)) {\n\t\tresult[name] = (...args: unknown[]) => {\n\t\t\tconst body = (ctor as (...a: unknown[]) => Record<string, unknown>)(\n\t\t\t\t...args,\n\t\t\t);\n\t\t\treturn Err(Object.freeze({ ...body, name }));\n\t\t};\n\t}\n\n\treturn result as DefineErrorsReturn<TConfig>;\n}\n","import { Err } from \"../result/result.js\";\nimport type { ErrorBody } from \"./types.js\";\n\n// =============================================================================\n// Config types\n// =============================================================================\n\n/** Config: each key maps to `[httpStatus, factory]`. */\n// biome-ignore lint/suspicious/noExplicitAny: required for TypeScript's function type inference\nexport type HttpErrorsConfig = Record<string, [number, (...args: any[]) => ErrorBody]>;\n\n/**\n * Per-key validation applied to the factory portion of each tuple.\n * Mirrors `ValidatedConfig` from `defineErrors`: prevents `name` in the\n * factory return body since the factory key is stamped as `name`.\n */\ntype ValidateHttpErrorBody<K extends string> = {\n\tmessage: string;\n\tname?: `The 'name' key is reserved as '${K}'. Remove it.`;\n};\n\nexport type ValidatedHttpConfig<T extends HttpErrorsConfig> = {\n\t// biome-ignore lint/suspicious/noExplicitAny: required for TypeScript's function type inference\n\t[K in keyof T & string]: T[K] extends [infer TStatus, (...args: infer A) => infer R]\n\t\t? [TStatus, (...args: A) => R & ValidateHttpErrorBody<K>]\n\t\t: T[K];\n};\n\n// =============================================================================\n// Return types\n// =============================================================================\n\n/**\n * A factory function with a static `.status` property holding the literal\n * HTTP status code. The status is never included in the serialized error body.\n */\n// biome-ignore lint/suspicious/noExplicitAny: required for TypeScript's function type inference\nexport type HttpErrorFactory<TName extends string, TStatus extends number, TFn extends (...args: any[]) => ErrorBody> =\n\t((...args: Parameters<TFn>) => Err<Readonly<{ name: TName } & ReturnType<TFn>>>) & {\n\t\treadonly status: TStatus;\n\t};\n\n/** Return type of `defineHttpErrors`. Maps each config key to its `HttpErrorFactory`. */\nexport type DefineHttpErrorsReturn<TConfig extends HttpErrorsConfig> = {\n\t// biome-ignore lint/suspicious/noExplicitAny: required for conditional type inference\n\t[K in keyof TConfig & string]: TConfig[K] extends [infer TStatus extends number, infer TFn extends (...args: any[]) => ErrorBody]\n\t\t? HttpErrorFactory<K, TStatus, TFn>\n\t\t: never;\n};\n\n// =============================================================================\n// Type utilities\n// =============================================================================\n\n/** Extract the error instance type from a single `HttpErrorFactory`. */\n// biome-ignore lint/suspicious/noExplicitAny: required for conditional type inference\nexport type InferHttpError<T> = T extends (...args: any[]) => Err<infer R> ? R : never;\n\n/** Extract the union of all error instance types from a `defineHttpErrors` return. */\nexport type InferHttpErrors<T> = {\n\t// biome-ignore lint/suspicious/noExplicitAny: required for conditional type inference\n\t[K in keyof T]: T[K] extends (...args: any[]) => Err<infer R> ? R : never;\n}[keyof T];\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\n/**\n * Defines a set of typed HTTP error factories, each paired with its HTTP\n * status code.\n *\n * Like `defineErrors`, each factory stamps `name` onto the error and wraps it\n * in `Err`. Unlike `defineErrors`, each factory function carries a static\n * `.status` property with the literal HTTP status code — the status is never\n * included in the serialized error body.\n *\n * @example\n * ```ts\n * const AssetError = defineHttpErrors({\n * MissingFile: [400, () => ({ message: 'Missing file' })],\n * FileTooLarge: [413, ({ size }: { size: number }) => ({ message: `File too large: ${size}`, size })],\n * StorageLimitExceeded: [402, () => ({ message: 'Storage limit exceeded' })],\n * });\n *\n * type AssetError = InferHttpErrors<typeof AssetError>;\n *\n * // In a Hono route handler:\n * return c.json(AssetError.MissingFile(), AssetError.MissingFile.status);\n * // wire body: { error: { name: 'MissingFile', message: 'Missing file' }, data: null }\n * // http status: 400\n * ```\n */\nexport function defineHttpErrors<const TConfig extends HttpErrorsConfig>(\n\tconfig: TConfig & ValidatedHttpConfig<TConfig>,\n): DefineHttpErrorsReturn<TConfig> {\n\tconst result: Record<string, unknown> = {};\n\n\tfor (const [name, [status, factory]] of Object.entries(config)) {\n\t\tconst fn = (...args: unknown[]) => {\n\t\t\tconst body = (factory as (...a: unknown[]) => Record<string, unknown>)(\n\t\t\t\t...args,\n\t\t\t);\n\t\t\treturn Err(Object.freeze({ ...body, name }));\n\t\t};\n\t\t(fn as unknown as { status: number }).status = status;\n\t\tresult[name] = fn;\n\t}\n\n\treturn result as unknown as DefineHttpErrorsReturn<TConfig>;\n}\n","/**\n * Extracts a readable error message from an unknown error value\n *\n * @param error - The unknown error to extract a message from\n * @returns A string representation of the error\n */\nexport function extractErrorMessage(error: unknown): string {\n\t// Handle Error instances\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\t// Handle primitives\n\tif (typeof error === \"string\") return error;\n\tif (\n\t\ttypeof error === \"number\" ||\n\t\ttypeof error === \"boolean\" ||\n\t\ttypeof error === \"bigint\"\n\t)\n\t\treturn String(error);\n\tif (typeof error === \"symbol\") return error.toString();\n\tif (error === null) return \"null\";\n\tif (error === undefined) return \"undefined\";\n\n\t// Handle arrays\n\tif (Array.isArray(error)) return JSON.stringify(error);\n\n\t// Handle plain objects\n\tif (typeof error === \"object\") {\n\t\tconst errorObj = error as Record<string, unknown>;\n\n\t\t// Check common error properties\n\t\tconst messageProps = [\n\t\t\t\"message\",\n\t\t\t\"error\",\n\t\t\t\"description\",\n\t\t\t\"title\",\n\t\t\t\"reason\",\n\t\t\t\"details\",\n\t\t] as const;\n\t\tfor (const prop of messageProps) {\n\t\t\tif (prop in errorObj && typeof errorObj[prop] === \"string\") {\n\t\t\t\treturn errorObj[prop];\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to JSON stringification\n\t\ttry {\n\t\t\treturn JSON.stringify(error);\n\t\t} catch {\n\t\t\treturn String(error);\n\t\t}\n\t}\n\n\t// Final fallback\n\treturn String(error);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,SAAgB,aACfA,QAC8B;CAC9B,MAAMC,SAAkC,CAAE;AAE1C,MAAK,MAAM,CAAC,MAAM,KAAK,IAAI,OAAO,QAAQ,OAAO,CAChD,QAAO,QAAQ,CAAC,GAAG,SAAoB;EACtC,MAAM,OAAO,AAAC,KACb,GAAG,KACH;AACD,SAAO,IAAI,OAAO,OAAO;GAAE,GAAG;GAAM;EAAM,EAAC,CAAC;CAC5C;AAGF,QAAO;AACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACkBD,SAAgB,iBACfC,QACkC;CAClC,MAAMC,SAAkC,CAAE;AAE1C,MAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,QAAQ,CAAC,IAAI,OAAO,QAAQ,OAAO,EAAE;EAC/D,MAAM,KAAK,CAAC,GAAG,SAAoB;GAClC,MAAM,OAAO,AAAC,QACb,GAAG,KACH;AACD,UAAO,IAAI,OAAO,OAAO;IAAE,GAAG;IAAM;GAAM,EAAC,CAAC;EAC5C;AACD,EAAC,GAAqC,SAAS;AAC/C,SAAO,QAAQ;CACf;AAED,QAAO;AACP;;;;;;;;;;ACxGD,SAAgB,oBAAoBC,OAAwB;AAE3D,KAAI,iBAAiB,MACpB,QAAO,MAAM;AAId,YAAW,UAAU,SAAU,QAAO;AACtC,YACQ,UAAU,mBACV,UAAU,oBACV,UAAU,SAEjB,QAAO,OAAO,MAAM;AACrB,YAAW,UAAU,SAAU,QAAO,MAAM,UAAU;AACtD,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,iBAAqB,QAAO;AAGhC,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,UAAU,MAAM;AAGtD,YAAW,UAAU,UAAU;EAC9B,MAAM,WAAW;EAGjB,MAAM,eAAe;GACpB;GACA;GACA;GACA;GACA;GACA;EACA;AACD,OAAK,MAAM,QAAQ,aAClB,KAAI,QAAQ,mBAAmB,SAAS,UAAU,SACjD,QAAO,SAAS;AAKlB,MAAI;AACH,UAAO,KAAK,UAAU,MAAM;EAC5B,QAAO;AACP,UAAO,OAAO,MAAM;EACpB;CACD;AAGD,QAAO,OAAO,MAAM;AACpB"}
|
package/dist/index-BNWUFJ69.d.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { Err } from "./result-DKwq9BCr.js";
|
|
2
|
-
import { DefineErrorsReturn, ErrorBody, ErrorsConfig, ValidatedConfig } from "./types-tXXk7K9Q.js";
|
|
3
|
-
|
|
4
|
-
//#region src/error/defineErrors.d.ts
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Defines a set of typed error factories using Rust-style namespaced variants.
|
|
8
|
-
*
|
|
9
|
-
* Each key is a short variant name (the namespace provides context). Every
|
|
10
|
-
* factory returns `Err<...>` directly — ready for `trySync`/`tryAsync` catch
|
|
11
|
-
* handlers. The variant name is stamped as `name` on the error object.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* const HttpError = defineErrors({
|
|
16
|
-
* Connection: ({ cause }: { cause: unknown }) => ({
|
|
17
|
-
* message: `Failed to connect: ${extractErrorMessage(cause)}`,
|
|
18
|
-
* cause,
|
|
19
|
-
* }),
|
|
20
|
-
* Response: ({ status }: { status: number; bodyMessage?: string }) => ({
|
|
21
|
-
* message: `HTTP ${status}`,
|
|
22
|
-
* status,
|
|
23
|
-
* }),
|
|
24
|
-
* Parse: ({ cause }: { cause: unknown }) => ({
|
|
25
|
-
* message: `Failed to parse response body: ${extractErrorMessage(cause)}`,
|
|
26
|
-
* cause,
|
|
27
|
-
* }),
|
|
28
|
-
* });
|
|
29
|
-
*
|
|
30
|
-
* type HttpError = InferErrors<typeof HttpError>;
|
|
31
|
-
*
|
|
32
|
-
* const result = HttpError.Connection({ cause: 'timeout' }); // Err<...>
|
|
33
|
-
* ```
|
|
34
|
-
*
|
|
35
|
-
* Inspired by Rust's {@link https://docs.rs/thiserror | thiserror} crate. The
|
|
36
|
-
* mapping is nearly 1:1:
|
|
37
|
-
*
|
|
38
|
-
* - `enum HttpError` → `const HttpError = defineErrors(...)`
|
|
39
|
-
* - Variant `Connection { cause: String }` → key `Connection: ({ cause }: { cause: unknown }) => (...)`
|
|
40
|
-
* - `#[error("Failed: {cause}")]` → `` message: `Failed: ${extractErrorMessage(cause)}` ``
|
|
41
|
-
* - `HttpError::Connection { ... }` → `HttpError.Connection({ ... })`
|
|
42
|
-
* - `match error { Connection { .. } => }` → `switch (error.name) { case 'Connection': }`
|
|
43
|
-
*
|
|
44
|
-
* The equivalent Rust `thiserror` enum:
|
|
45
|
-
* ```rust
|
|
46
|
-
* #[derive(Error, Debug)]
|
|
47
|
-
* enum HttpError {
|
|
48
|
-
* #[error("Failed to connect: {cause}")]
|
|
49
|
-
* Connection { cause: String },
|
|
50
|
-
*
|
|
51
|
-
* #[error("HTTP {status}")]
|
|
52
|
-
* Response { status: u16, body_message: Option<String> },
|
|
53
|
-
*
|
|
54
|
-
* #[error("Failed to parse response body: {cause}")]
|
|
55
|
-
* Parse { cause: String },
|
|
56
|
-
* }
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
declare function defineErrors<const TConfig extends ErrorsConfig>(config: TConfig & ValidatedConfig<TConfig>): DefineErrorsReturn<TConfig>;
|
|
60
|
-
//# sourceMappingURL=defineErrors.d.ts.map
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region src/error/defineHttpErrors.d.ts
|
|
63
|
-
/** Config: each key maps to `[httpStatus, factory]`. */
|
|
64
|
-
type HttpErrorsConfig = Record<string, [number, (...args: any[]) => ErrorBody]>;
|
|
65
|
-
/**
|
|
66
|
-
* Per-key validation applied to the factory portion of each tuple.
|
|
67
|
-
* Mirrors `ValidatedConfig` from `defineErrors`: prevents `name` in the
|
|
68
|
-
* factory return body since the factory key is stamped as `name`.
|
|
69
|
-
*/
|
|
70
|
-
type ValidateHttpErrorBody<K extends string> = {
|
|
71
|
-
message: string;
|
|
72
|
-
name?: `The 'name' key is reserved as '${K}'. Remove it.`;
|
|
73
|
-
};
|
|
74
|
-
type ValidatedHttpConfig<T extends HttpErrorsConfig> = { [K in keyof T & string]: T[K] extends [infer TStatus, (...args: infer A) => infer R] ? [TStatus, (...args: A) => R & ValidateHttpErrorBody<K>] : T[K] };
|
|
75
|
-
/**
|
|
76
|
-
* A factory function with a static `.status` property holding the literal
|
|
77
|
-
* HTTP status code. The status is never included in the serialized error body.
|
|
78
|
-
*/
|
|
79
|
-
type HttpErrorFactory<TName extends string, TStatus extends number, TFn extends (...args: any[]) => ErrorBody> = ((...args: Parameters<TFn>) => Err<Readonly<{
|
|
80
|
-
name: TName;
|
|
81
|
-
} & ReturnType<TFn>>>) & {
|
|
82
|
-
readonly status: TStatus;
|
|
83
|
-
};
|
|
84
|
-
/** Return type of `defineHttpErrors`. Maps each config key to its `HttpErrorFactory`. */
|
|
85
|
-
type DefineHttpErrorsReturn<TConfig extends HttpErrorsConfig> = { [K in keyof TConfig & string]: TConfig[K] extends [infer TStatus extends number, infer TFn extends (...args: any[]) => ErrorBody] ? HttpErrorFactory<K, TStatus, TFn> : never };
|
|
86
|
-
/** Extract the error instance type from a single `HttpErrorFactory`. */
|
|
87
|
-
type InferHttpError<T> = T extends ((...args: any[]) => Err<infer R>) ? R : never;
|
|
88
|
-
/** Extract the union of all error instance types from a `defineHttpErrors` return. */
|
|
89
|
-
type InferHttpErrors<T> = { [K in keyof T]: T[K] extends ((...args: any[]) => Err<infer R>) ? R : never }[keyof T];
|
|
90
|
-
/**
|
|
91
|
-
* Defines a set of typed HTTP error factories, each paired with its HTTP
|
|
92
|
-
* status code.
|
|
93
|
-
*
|
|
94
|
-
* Like `defineErrors`, each factory stamps `name` onto the error and wraps it
|
|
95
|
-
* in `Err`. Unlike `defineErrors`, each factory function carries a static
|
|
96
|
-
* `.status` property with the literal HTTP status code — the status is never
|
|
97
|
-
* included in the serialized error body.
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```ts
|
|
101
|
-
* const AssetError = defineHttpErrors({
|
|
102
|
-
* MissingFile: [400, () => ({ message: 'Missing file' })],
|
|
103
|
-
* FileTooLarge: [413, ({ size }: { size: number }) => ({ message: `File too large: ${size}`, size })],
|
|
104
|
-
* StorageLimitExceeded: [402, () => ({ message: 'Storage limit exceeded' })],
|
|
105
|
-
* });
|
|
106
|
-
*
|
|
107
|
-
* type AssetError = InferHttpErrors<typeof AssetError>;
|
|
108
|
-
*
|
|
109
|
-
* // In a Hono route handler:
|
|
110
|
-
* return c.json(AssetError.MissingFile(), AssetError.MissingFile.status);
|
|
111
|
-
* // wire body: { error: { name: 'MissingFile', message: 'Missing file' }, data: null }
|
|
112
|
-
* // http status: 400
|
|
113
|
-
* ```
|
|
114
|
-
*/
|
|
115
|
-
declare function defineHttpErrors<const TConfig extends HttpErrorsConfig>(config: TConfig & ValidatedHttpConfig<TConfig>): DefineHttpErrorsReturn<TConfig>;
|
|
116
|
-
//#endregion
|
|
117
|
-
//#region src/error/extractErrorMessage.d.ts
|
|
118
|
-
/**
|
|
119
|
-
* Extracts a readable error message from an unknown error value
|
|
120
|
-
*
|
|
121
|
-
* @param error - The unknown error to extract a message from
|
|
122
|
-
* @returns A string representation of the error
|
|
123
|
-
*/
|
|
124
|
-
declare function extractErrorMessage(error: unknown): string;
|
|
125
|
-
//# sourceMappingURL=extractErrorMessage.d.ts.map
|
|
126
|
-
|
|
127
|
-
//#endregion
|
|
128
|
-
export { DefineHttpErrorsReturn, HttpErrorFactory, HttpErrorsConfig, InferHttpError, InferHttpErrors, ValidatedHttpConfig, defineErrors, defineHttpErrors, extractErrorMessage };
|
|
129
|
-
//# sourceMappingURL=index-BNWUFJ69.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BNWUFJ69.d.ts","names":[],"sources":["../src/error/defineErrors.ts","../src/error/defineHttpErrors.ts","../src/error/extractErrorMessage.ts"],"sourcesContent":[],"mappings":";;;;;;;;AA4DA;;;;;;;;AAEqB;;;;ACrDrB;;;;AAAqC;AAAkD;AAYvF;;;;;;;;;;;;;AAIO;AAYP;;;;;;;;;;;AAE0B;AAI1B;;;;;;AAEwH,iBDexG,YCfwG,CAAA,sBDerE,YCfqE,CAAA,CAAA,MAAA,EDgB/G,OChB+G,GDgBrG,eChBqG,CDgBrF,OChBqF,CAAA,CAAA,EDiBrH,kBCjBqH,CDiBlG,OCjBkG,CAAA;;;;;KApC5G,gBAAA,GAAmB,4CAA4C;ADmD3E;;;;;KC5CK,qBD6Cc,CAAA,UAAA,MAAA,CAAA,GAAA;EAAe,OACZ,EAAA,MAAA;EAAO,IAA1B,CAAA,EAAA,kCC5CuC,CD4CvC,eAAA;AAAkB,CAAA;KCzCT,8BAA8B,kCAE7B,aAAa,EAAE,6DACvB,mBAAmB,MAAM,IAAI,sBAAsB,MACpD,EAAE;AAhBN;;;;AAAqC,KA4BzB,gBA5ByB,CAAA,cAAA,MAAA,EAAA,gBAAA,MAAA,EAAA,YAAA,CAAA,GAAA,IAAA,EAAA,GAAA,EAAA,EAAA,GA4BsE,SA5BtE,CAAA,GAAA,CAAA,CAAA,GAAA,IAAA,EA6BzB,UA7ByB,CA6Bd,GA7Bc,CAAA,EAAA,GA6BL,GA7BK,CA6BD,QA7BC,CAAA;EAOhC,IAAA,EAsBgD,KAtBhD;AAKL,CAAA,GAiB+D,UAjBnD,CAiB8D,GAjB9D,CAAA,CAAA,CAAA,CAAA,GAAA;EAAmB,SAAA,MAAA,EAkBZ,OAlBY;CAAA;;AAEL,KAoBd,sBApBc,CAAA,gBAoByB,gBApBzB,CAAA,GAAA,QAAE,MAsBf,OAtBe,GAAA,MAAA,GAsBI,OAtBJ,CAsBY,CAtBZ,CAAA,SAAA,CAAA,KAAA,iBAAA,MAAA,EAAA,KAAA,aAAA,CAAA,GAAA,IAAA,EAAA,GAAA,EAAA,EAAA,GAsB4F,SAtB5F,CAAA,GAuBxB,gBAvBwB,CAuBP,CAvBO,EAuBJ,OAvBI,EAuBK,GAvBL,CAAA,GAAA,KAAA,EAAC;;AACC,KAgClB,cAhCkB,CAAA,CAAA,CAAA,GAgCE,CAhCF,UAAA,CAAA,GAAA,IAAA,EAAA,GAAA,EAAA,EAAA,GAgCgC,GAhChC,CAAA,KAAA,EAAA,CAAA,IAgC+C,CAhC/C,GAAA,KAAA;;AAAI,KAmCtB,eAnCsB,CAAA,CAAA,CAAA,GAAA,QAC9B,MAoCS,CApCT,GAoCa,CApCb,CAoCe,CApCf,CAAA,UAAA,CAAA,GAAA,IAAA,EAAA,GAAA,EAAA,EAAA,GAoC8C,GApC9C,CAAA,KAAA,EAAA,CAAA,IAoC6D,CApC7D,GAAA,KAAA,EAAC,CAAA,MAqCG,CArCF,CAAA;AAAC;AAYP;;;;;;;;;;;AAE0B;AAI1B;;;;;;;;;;;AAGoB;AAUR,iBAqCI,gBArCU,CAAA,sBAqC6B,gBArC7B,CAAA,CAAA,MAAA,EAsCjB,OAtCiB,GAsCP,mBAtCO,CAsCa,OAtCb,CAAA,CAAA,EAuCvB,sBAvCuB,CAuCA,OAvCA,CAAA;;;;;;;ADI1B;;AAAmD,iBEtDnC,mBAAA,CFsDmC,KAAA,EAAA,OAAA,CAAA,EAAA,MAAA"}
|