stitchkit 0.20.0 → 0.22.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/cli.js +2 -2
- package/dist/{index-ng2v2ts4.js → index-4gawbm74.js} +16 -6
- package/dist/{index-ynnh9x6h.js → index-a9n8m4ec.js} +1 -1
- package/dist/{index-f5e4efj1.js → index-g8kyab85.js} +1 -1
- package/dist/{index-xmncnw8z.js → index-x8m8e7dc.js} +1 -1
- package/dist/internal/errors.d.ts +16 -0
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/node.js +2 -2
- package/dist/server/error-hook.d.ts +5 -1
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +17 -11
- package/dist/server/multipart.d.ts +3 -2
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/tools.js +3 -3
- package/llms-full.txt +49 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
emitResult,
|
|
5
5
|
parseCliArgs,
|
|
6
6
|
pollUntilDone
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-x8m8e7dc.js";
|
|
8
8
|
import"./index-0ed3bx43.js";
|
|
9
|
-
import"./index-
|
|
9
|
+
import"./index-4gawbm74.js";
|
|
10
10
|
import"./index-c7nyw0yt.js";
|
|
11
11
|
export {
|
|
12
12
|
pollUntilDone,
|
|
@@ -84,17 +84,25 @@ function base64UrlToBytes(segment) {
|
|
|
84
84
|
}
|
|
85
85
|
// src/internal/errors.ts
|
|
86
86
|
import { z as z2 } from "zod";
|
|
87
|
+
function issuePath(path) {
|
|
88
|
+
return path.length > 0 ? path.map(String).join(".") : "(root)";
|
|
89
|
+
}
|
|
87
90
|
function formatZodError(error) {
|
|
88
91
|
const issues = error.issues.slice(0, 5);
|
|
89
|
-
const lines = issues.map((issue) => {
|
|
90
|
-
const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
|
|
91
|
-
return `${path}: ${issue.message}`;
|
|
92
|
-
});
|
|
92
|
+
const lines = issues.map((issue) => `${issuePath(issue.path)}: ${issue.message}`);
|
|
93
93
|
const suffix = error.issues.length > 5 ? `
|
|
94
94
|
...and ${error.issues.length - 5} more issues` : "";
|
|
95
95
|
return lines.join(`
|
|
96
96
|
`) + suffix;
|
|
97
97
|
}
|
|
98
|
+
function zodIssues(error) {
|
|
99
|
+
return error.issues.map((issue) => ({
|
|
100
|
+
path: issuePath(issue.path),
|
|
101
|
+
code: issue.code,
|
|
102
|
+
message: issue.message
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
var MAX_DETAIL_ISSUES = 20;
|
|
98
106
|
function errorCode(err) {
|
|
99
107
|
if (AppError.is(err))
|
|
100
108
|
return err.code;
|
|
@@ -106,7 +114,9 @@ function normalizeError(err) {
|
|
|
106
114
|
if (AppError.is(err))
|
|
107
115
|
return err;
|
|
108
116
|
if (err instanceof z2.ZodError) {
|
|
109
|
-
return new AppError("VALIDATION_ERROR", formatZodError(err), 400
|
|
117
|
+
return new AppError("VALIDATION_ERROR", formatZodError(err), 400, {
|
|
118
|
+
issues: zodIssues(err).slice(0, MAX_DETAIL_ISSUES)
|
|
119
|
+
});
|
|
110
120
|
}
|
|
111
121
|
console.error("[stitchkit] unhandled error:", err);
|
|
112
122
|
return new AppError("INTERNAL_SERVER_ERROR", "Internal server error", 500);
|
|
@@ -128,4 +138,4 @@ function isWithinDir(root, target) {
|
|
|
128
138
|
return target === root || target === base || target.startsWith(base + sep);
|
|
129
139
|
}
|
|
130
140
|
|
|
131
|
-
export { AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, bytesToBase64Url, base64UrlToBytes, formatZodError, errorCode, normalizeError, validateHandlerOutput, isWithinDir };
|
|
141
|
+
export { AppError, notFound, badRequest, unauthorized, forbidden, conflict, rateLimited, STITCH_ERROR_STATUS, isStitchErrorCode, appError, bytesToBase64Url, base64UrlToBytes, formatZodError, zodIssues, errorCode, normalizeError, validateHandlerOutput, isWithinDir };
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { type ZodType, z } from 'zod';
|
|
2
2
|
import { AppError } from '../contract';
|
|
3
3
|
export declare function formatZodError(error: z.ZodError): string;
|
|
4
|
+
/** One field-level validation issue — the structured sibling of `formatZodError`. */
|
|
5
|
+
export interface ZodIssueSummary {
|
|
6
|
+
/** Dotted path to the offending field (`(root)` for a top-level issue). */
|
|
7
|
+
path: string;
|
|
8
|
+
/** Zod issue code (e.g. `invalid_type`, `too_small`). */
|
|
9
|
+
code: string;
|
|
10
|
+
/** Human-readable message for this field. */
|
|
11
|
+
message: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Project a `ZodError` into structured, wire-safe field issues — path / code /
|
|
15
|
+
* message only, nothing server-internal. For a machine client that matches on
|
|
16
|
+
* fields rather than parsing the text `message`. Returns every issue; a caller
|
|
17
|
+
* that bounds response size slices it (see `normalizeError`).
|
|
18
|
+
*/
|
|
19
|
+
export declare function zodIssues(error: z.ZodError): ZodIssueSummary[];
|
|
4
20
|
/**
|
|
5
21
|
* The stable error code for a thrown value — `AppError.code`, `VALIDATION_ERROR`
|
|
6
22
|
* for a `ZodError`, else `undefined`. Side-effect-free (unlike `normalizeError`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOvC,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,CAMxD;AAED,qFAAqF;AACrF,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,GAAG,eAAe,EAAE,CAM9D;AAKD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI1D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAgBrD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,GACZ;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAO9D"}
|
package/dist/node.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createImplement,
|
|
4
4
|
createSocketIOServer,
|
|
5
5
|
implement
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-g8kyab85.js";
|
|
7
7
|
import"./index-tje0q6gp.js";
|
|
8
8
|
import {
|
|
9
9
|
AppError,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
notFound,
|
|
15
15
|
rateLimited,
|
|
16
16
|
unauthorized
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-4gawbm74.js";
|
|
18
18
|
import"./index-dzx781tm.js";
|
|
19
19
|
import"./index-khwedj16.js";
|
|
20
20
|
import"./index-c7nyw0yt.js";
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
* of leaking stitchkit's code to the wire. The envelope stays app-owned via
|
|
10
10
|
* `render`, so the core prescribes no domain shape (ADR 0002).
|
|
11
11
|
*
|
|
12
|
+
* The thrown value is classified through the framework's own `normalizeError`
|
|
13
|
+
* first, so a `ZodError` (invalid input) is an honest `VALIDATION_ERROR` 400 —
|
|
14
|
+
* not a 500 — exactly as the framework default would render it.
|
|
15
|
+
*
|
|
12
16
|
* ```ts
|
|
13
17
|
* const onError = createErrorHook({
|
|
14
18
|
* codeMap: {
|
|
@@ -31,7 +35,7 @@ export interface ResolvedError {
|
|
|
31
35
|
code: string;
|
|
32
36
|
/** HTTP status. */
|
|
33
37
|
status: number;
|
|
34
|
-
/** Safe message — the `AppError`
|
|
38
|
+
/** Safe message — the `AppError` / `ZodError` summary, or a generic string for a raw throw. */
|
|
35
39
|
message: string;
|
|
36
40
|
/** Structured details, when the thrown `AppError` carried them. */
|
|
37
41
|
details?: Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-hook.d.ts","sourceRoot":"","sources":["../../src/server/error-hook.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"error-hook.d.ts","sourceRoot":"","sources":["../../src/server/error-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe,CAAC,SAAS,SAAS,MAAM,GAAG,MAAM;IAChE;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAC7C,uDAAuD;IACvD,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC;IACzC,yEAAyE;IACzE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CACzD;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,SAAS,SAAS,MAAM,GAAG,MAAM,EAC/D,MAAM,EAAE,eAAe,CAAC,SAAS,CAAC,GACjC,WAAW,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAyBxC"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AppError, appError, badRequest, conflict, forbidden, isStitchErrorCode, notFound, rateLimited, STITCH_ERROR_STATUS, type StitchErrorCode, unauthorized, } from '../contract';
|
|
2
|
+
export { errorCode, formatZodError, normalizeError, type ZodIssueSummary, zodIssues, } from '../internal/errors';
|
|
2
3
|
export { cacheHeaders, createCache } from './cache';
|
|
3
4
|
export { createHandler, createServer } from './create';
|
|
4
5
|
export { createErrorHook, type ErrorHookConfig, type ResolvedError, } from './error-hook';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,EACpB,YAAY,GACb,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,EACpB,YAAY,GACb,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,SAAS,EACT,cAAc,EACd,cAAc,EACd,KAAK,eAAe,EACpB,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EACL,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,KAAK,SAAS,EACd,cAAc,EACd,KAAK,gBAAgB,EACrB,SAAS,EACT,QAAQ,GACT,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,oBAAoB,EACzB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,OAAO,EACP,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,EACL,KAAK,eAAe,EACpB,SAAS,EACT,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrE,YAAY,EACV,SAAS,EACT,eAAe,EACf,aAAa,EACb,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,EACR,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,KAAK,YAAY,EACjB,wBAAwB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,aAAa,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
socketIoLane,
|
|
11
11
|
staticRoute,
|
|
12
12
|
webSocketLane
|
|
13
|
-
} from "../index-
|
|
13
|
+
} from "../index-g8kyab85.js";
|
|
14
14
|
import {
|
|
15
15
|
createAuthHook,
|
|
16
16
|
createBearerResolver,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
signJwt,
|
|
24
24
|
verifyJwt,
|
|
25
25
|
verifyPkce
|
|
26
|
-
} from "../index-
|
|
26
|
+
} from "../index-a9n8m4ec.js";
|
|
27
27
|
import {
|
|
28
28
|
DEFAULT_CORS_ALLOW_HEADERS,
|
|
29
29
|
corsHeaders,
|
|
@@ -39,13 +39,16 @@ import {
|
|
|
39
39
|
appError,
|
|
40
40
|
badRequest,
|
|
41
41
|
conflict,
|
|
42
|
+
errorCode,
|
|
42
43
|
forbidden,
|
|
44
|
+
formatZodError,
|
|
43
45
|
isStitchErrorCode,
|
|
44
46
|
normalizeError,
|
|
45
47
|
notFound,
|
|
46
48
|
rateLimited,
|
|
47
|
-
unauthorized
|
|
48
|
-
|
|
49
|
+
unauthorized,
|
|
50
|
+
zodIssues
|
|
51
|
+
} from "../index-4gawbm74.js";
|
|
49
52
|
import {
|
|
50
53
|
extractIp,
|
|
51
54
|
generateTraceId,
|
|
@@ -118,15 +121,14 @@ function cacheHeaders(maxAge, scope = "public") {
|
|
|
118
121
|
// src/server/error-hook.ts
|
|
119
122
|
function createErrorHook(config) {
|
|
120
123
|
return (_ctx, error) => {
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
const code = config.codeMap && isStitchErrorCode(rawCode) ? config.codeMap[rawCode] : rawCode;
|
|
124
|
+
const appErr = normalizeError(error);
|
|
125
|
+
const code = config.codeMap && isStitchErrorCode(appErr.code) ? config.codeMap[appErr.code] : appErr.code;
|
|
124
126
|
const info = {
|
|
125
127
|
code,
|
|
126
|
-
status:
|
|
127
|
-
message:
|
|
128
|
-
details:
|
|
129
|
-
hint:
|
|
128
|
+
status: appErr.status,
|
|
129
|
+
message: appErr.message,
|
|
130
|
+
details: appErr.details,
|
|
131
|
+
hint: appErr.hint
|
|
130
132
|
};
|
|
131
133
|
config.onError?.(error, info);
|
|
132
134
|
return new Response(JSON.stringify(config.render(info)), {
|
|
@@ -617,6 +619,7 @@ async function* parseSSE(response, options) {
|
|
|
617
619
|
}
|
|
618
620
|
}
|
|
619
621
|
export {
|
|
622
|
+
zodIssues,
|
|
620
623
|
webSocketLane,
|
|
621
624
|
weakETag,
|
|
622
625
|
verifyPkce,
|
|
@@ -639,15 +642,18 @@ export {
|
|
|
639
642
|
parseBody,
|
|
640
643
|
openApiRoute,
|
|
641
644
|
notFound,
|
|
645
|
+
normalizeError,
|
|
642
646
|
isStitchErrorCode,
|
|
643
647
|
implement,
|
|
644
648
|
getClientInfo,
|
|
645
649
|
generateTraceId,
|
|
646
650
|
generateOpenApiDocument,
|
|
651
|
+
formatZodError,
|
|
647
652
|
forbidden,
|
|
648
653
|
extractToken,
|
|
649
654
|
extractIp,
|
|
650
655
|
errorResponse2 as errorResponse,
|
|
656
|
+
errorCode,
|
|
651
657
|
deriveCodeChallenge,
|
|
652
658
|
defineCookie,
|
|
653
659
|
createSocketIOServer,
|
|
@@ -13,8 +13,9 @@ export interface MultipartResult {
|
|
|
13
13
|
*
|
|
14
14
|
* A multipart text field is always a **string** (per the spec) and is handed to
|
|
15
15
|
* the schema as one — the schema decides its type, exactly as with query params:
|
|
16
|
-
* `z.coerce.number()` for a number, `z.
|
|
17
|
-
* `z.
|
|
16
|
+
* `z.coerce.number()` for a number, `z.stringbool()` for a boolean (NOT
|
|
17
|
+
* `z.coerce.boolean()`, which is `Boolean(str)` — `'false'` would become `true`),
|
|
18
|
+
* and `z.preprocess((v) => JSON.parse(String(v)), Schema)` to opt a field into JSON.
|
|
18
19
|
* Content is never sniffed to guess a type — the contract owns the type, not the
|
|
19
20
|
* value (so an id like `'33111715'` never turns into a number under a `z.string()`).
|
|
20
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../src/server/multipart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;CACjB;AA0CD
|
|
1
|
+
{"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../src/server/multipart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAInC,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;CACjB;AA0CD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,EAC/B,QAAQ,SAA2B,GAClC,OAAO,CAAC,eAAe,CAAC,CAyB1B"}
|
package/dist/tools.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
inputIsQuery,
|
|
3
3
|
signJwt,
|
|
4
4
|
verifyPkce
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-a9n8m4ec.js";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULT_CORS_ALLOW_HEADERS
|
|
8
8
|
} from "./index-tje0q6gp.js";
|
|
@@ -18,14 +18,14 @@ import {
|
|
|
18
18
|
pollUntil,
|
|
19
19
|
readCapped,
|
|
20
20
|
toolResultFromError
|
|
21
|
-
} from "./index-
|
|
21
|
+
} from "./index-x8m8e7dc.js";
|
|
22
22
|
import {
|
|
23
23
|
toJsonSchema
|
|
24
24
|
} from "./index-0ed3bx43.js";
|
|
25
25
|
import {
|
|
26
26
|
AppError,
|
|
27
27
|
isWithinDir
|
|
28
|
-
} from "./index-
|
|
28
|
+
} from "./index-4gawbm74.js";
|
|
29
29
|
import"./index-khwedj16.js";
|
|
30
30
|
import {
|
|
31
31
|
isRecord,
|
package/llms-full.txt
CHANGED
|
@@ -289,8 +289,9 @@ await api.search({ q: 'x', filter: { status: 'active' } })
|
|
|
289
289
|
|
|
290
290
|
Flatten the field (`status: 'active'`) or move the operation to a body verb
|
|
291
291
|
(`POST`). Remember the server parses query values from **strings** — use
|
|
292
|
-
`z.coerce.number()`
|
|
293
|
-
|
|
292
|
+
`z.coerce.number()` for numbers and `z.stringbool()` for booleans in a
|
|
293
|
+
query-input schema (not `z.coerce.boolean()`, which is `Boolean(str)`, so
|
|
294
|
+
`'false'` would become `true`).
|
|
294
295
|
|
|
295
296
|
## Transports
|
|
296
297
|
|
|
@@ -393,7 +394,7 @@ the schema owns its type, exactly as with [query input](#query-input-get--delete
|
|
|
393
394
|
input: z.object({
|
|
394
395
|
id: z.string(), // an id like '33111715' stays a string
|
|
395
396
|
count: z.coerce.number(), // '5' → 5
|
|
396
|
-
active: z.
|
|
397
|
+
active: z.stringbool(), // 'true' → true, 'false' → false
|
|
397
398
|
meta: z.preprocess((v) => JSON.parse(String(v)), MetaSchema), // opt a field into JSON
|
|
398
399
|
})
|
|
399
400
|
```
|
|
@@ -2292,7 +2293,27 @@ transport (HTTP, MCP, agent). → ADR 0032.
|
|
|
2292
2293
|
`details` and `hint` are included when present. On HTTP this is the response
|
|
2293
2294
|
body with the matching status; for an MCP or agent call the same `code` and
|
|
2294
2295
|
`details` come back as a tool error. A schema-validation failure on the request
|
|
2295
|
-
is turned into a `400 VALIDATION_ERROR` automatically
|
|
2296
|
+
is turned into a `400 VALIDATION_ERROR` automatically — and it carries the
|
|
2297
|
+
offending fields as structured `details.issues`, so a machine client matches on
|
|
2298
|
+
them instead of parsing the text `message`:
|
|
2299
|
+
|
|
2300
|
+
```json
|
|
2301
|
+
{
|
|
2302
|
+
"error": {
|
|
2303
|
+
"code": "VALIDATION_ERROR",
|
|
2304
|
+
"message": "name: Invalid input\nage: Invalid input",
|
|
2305
|
+
"details": {
|
|
2306
|
+
"issues": [
|
|
2307
|
+
{ "path": "name", "code": "invalid_type", "message": "Invalid input" },
|
|
2308
|
+
{ "path": "age", "code": "invalid_type", "message": "Invalid input" }
|
|
2309
|
+
]
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
```
|
|
2314
|
+
|
|
2315
|
+
Use the exported `zodIssues(error)` to build the same structured list from a
|
|
2316
|
+
`ZodError` in your own hook.
|
|
2296
2317
|
|
|
2297
2318
|
### On the client
|
|
2298
2319
|
|
|
@@ -2376,6 +2397,25 @@ createServer({ services, hooks: { onError } })
|
|
|
2376
2397
|
Codes you threw yourself (not stitchkit's) pass through `codeMap` unchanged; the
|
|
2377
2398
|
`satisfies Record<StitchErrorCode, …>` keeps the map exhaustive across upgrades.
|
|
2378
2399
|
|
|
2400
|
+
Invalid input (a `ZodError`) is classified as `VALIDATION_ERROR` 400 before it
|
|
2401
|
+
reaches `render` — a client fault is an honest 400, not a 500 — and the
|
|
2402
|
+
offending fields arrive as structured `info.details.issues`, so your `render`
|
|
2403
|
+
can surface them to a machine client without parsing the message.
|
|
2404
|
+
|
|
2405
|
+
If you write a **bespoke** `onError` instead of using `createErrorHook`, run the
|
|
2406
|
+
thrown value through the exported `normalizeError` to get the same classification
|
|
2407
|
+
(a raw `ZodError` reaches your hook untouched, so the framework can inspect it —
|
|
2408
|
+
call `zodIssues(err)` yourself if you want the structured fields):
|
|
2409
|
+
|
|
2410
|
+
```ts
|
|
2411
|
+
import { normalizeError } from 'stitchkit/server'
|
|
2412
|
+
|
|
2413
|
+
onError: (ctx, err) => {
|
|
2414
|
+
const e = normalizeError(err) // ZodError → VALIDATION_ERROR 400, else generic 500
|
|
2415
|
+
return jsonError(e.code, e.status, e.message)
|
|
2416
|
+
}
|
|
2417
|
+
```
|
|
2418
|
+
|
|
2379
2419
|
|
|
2380
2420
|
==============================================================================
|
|
2381
2421
|
# Guide: Observability (docs/guide/observability.md)
|
|
@@ -3150,6 +3190,11 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
3150
3190
|
| `ByteRange` | _type_ | an inclusive `{ start, end }` byte range |
|
|
3151
3191
|
| `respondJson` | function | a raw route's JSON response (`204` for null/undefined) |
|
|
3152
3192
|
| `errorResponse` | function | any thrown value → the framework error envelope + `x-request-id` |
|
|
3193
|
+
| `normalizeError` | function | any thrown value → an `AppError` (`ZodError` → `VALIDATION_ERROR` 400 with structured `details.issues`, else generic 500) — the framework's canonical classification, for a bespoke `onError` |
|
|
3194
|
+
| `errorCode` | function | the stable error code for a thrown value (side-effect-free — for log attribution) |
|
|
3195
|
+
| `formatZodError` | function | a `ZodError` → a readable, field-summarised string |
|
|
3196
|
+
| `zodIssues` | function | a `ZodError` → structured `{ path, code, message }[]` — the machine-readable sibling of `formatZodError` |
|
|
3197
|
+
| `ZodIssueSummary` | _type_ | one structured validation issue (`{ path, code, message }`) |
|
|
3153
3198
|
| `parseBody` | function | parse + Zod-validate a JSON body → `data` or `null` (no throw) |
|
|
3154
3199
|
| `HandlerConfig` | _type_ | config for `createHandler` (runtime-agnostic) |
|
|
3155
3200
|
| `BunServerConfig` | _type_ | config for `createServer` (Bun) |
|
package/package.json
CHANGED