better-call 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +209 -110
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/index.cjs +64 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +64 -16
- package/dist/index.js.map +1 -1
- package/dist/node.cjs.map +1 -1
- package/dist/node.js.map +1 -1
- package/dist/router.d.cts +80 -58
- package/dist/router.d.ts +80 -58
- package/package.json +13 -5
package/dist/index.js
CHANGED
|
@@ -115,6 +115,17 @@ var InternalAPIError = class extends Error {
|
|
|
115
115
|
} : void 0;
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
|
+
var ValidationError = class extends InternalAPIError {
|
|
119
|
+
constructor(message, issues) {
|
|
120
|
+
super(400, {
|
|
121
|
+
message,
|
|
122
|
+
code: "VALIDATION_ERROR"
|
|
123
|
+
});
|
|
124
|
+
this.message = message;
|
|
125
|
+
this.issues = issues;
|
|
126
|
+
this.issues = issues;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
118
129
|
var BetterCallError = class extends Error {
|
|
119
130
|
constructor(message) {
|
|
120
131
|
super(message);
|
|
@@ -179,6 +190,19 @@ function tryDecode(str) {
|
|
|
179
190
|
return str;
|
|
180
191
|
}
|
|
181
192
|
}
|
|
193
|
+
async function tryCatch(promise) {
|
|
194
|
+
try {
|
|
195
|
+
return {
|
|
196
|
+
data: await promise,
|
|
197
|
+
error: null
|
|
198
|
+
};
|
|
199
|
+
} catch (error) {
|
|
200
|
+
return {
|
|
201
|
+
data: null,
|
|
202
|
+
error
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
182
206
|
|
|
183
207
|
//#endregion
|
|
184
208
|
//#region src/to-response.ts
|
|
@@ -300,11 +324,17 @@ async function runValidation(options, context = {}) {
|
|
|
300
324
|
}
|
|
301
325
|
if (options.requireHeaders && !context.headers) return {
|
|
302
326
|
data: null,
|
|
303
|
-
error: {
|
|
327
|
+
error: {
|
|
328
|
+
message: "Headers is required",
|
|
329
|
+
issues: []
|
|
330
|
+
}
|
|
304
331
|
};
|
|
305
332
|
if (options.requireRequest && !context.request) return {
|
|
306
333
|
data: null,
|
|
307
|
-
error: {
|
|
334
|
+
error: {
|
|
335
|
+
message: "Request is required",
|
|
336
|
+
issues: []
|
|
337
|
+
}
|
|
308
338
|
};
|
|
309
339
|
return {
|
|
310
340
|
data: request,
|
|
@@ -312,12 +342,12 @@ async function runValidation(options, context = {}) {
|
|
|
312
342
|
};
|
|
313
343
|
}
|
|
314
344
|
function fromError(error, validating) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
345
|
+
return {
|
|
346
|
+
message: error.map((e) => {
|
|
347
|
+
return `[${e.path?.length ? `${validating}.` + e.path.map((x) => typeof x === "object" ? x.key : x).join(".") : validating}] ${e.message}`;
|
|
348
|
+
}).join("; "),
|
|
349
|
+
issues: error
|
|
350
|
+
};
|
|
321
351
|
}
|
|
322
352
|
|
|
323
353
|
//#endregion
|
|
@@ -437,10 +467,7 @@ const createInternalContext = async (context, { options, path }) => {
|
|
|
437
467
|
const headers = new Headers();
|
|
438
468
|
let responseStatus = void 0;
|
|
439
469
|
const { data, error } = await runValidation(options, context);
|
|
440
|
-
if (error) throw new
|
|
441
|
-
message: error.message,
|
|
442
|
-
code: "VALIDATION_ERROR"
|
|
443
|
-
});
|
|
470
|
+
if (error) throw new ValidationError(error.message, error.issues);
|
|
444
471
|
const requestHeaders = "headers" in context ? context.headers instanceof Headers ? context.headers : new Headers(context.headers) : "request" in context && context.request instanceof Request ? context.request.headers : null;
|
|
445
472
|
const requestCookies = requestHeaders?.get("cookie");
|
|
446
473
|
const parsedCookies = requestCookies ? parseCookies(requestCookies) : void 0;
|
|
@@ -536,12 +563,24 @@ function createEndpoint(pathOrOptions, handlerOrOptions, handlerOrNever) {
|
|
|
536
563
|
const options = typeof handlerOrOptions === "object" ? handlerOrOptions : pathOrOptions;
|
|
537
564
|
const handler = typeof handlerOrOptions === "function" ? handlerOrOptions : handlerOrNever;
|
|
538
565
|
if ((options.method === "GET" || options.method === "HEAD") && options.body) throw new BetterCallError("Body is not allowed with GET or HEAD methods");
|
|
566
|
+
if (path && /\/{2,}/.test(path)) throw new BetterCallError("Path cannot contain consecutive slashes");
|
|
539
567
|
const internalHandler = async (...inputCtx) => {
|
|
540
568
|
const context = inputCtx[0] || {};
|
|
541
|
-
const internalContext = await createInternalContext(context, {
|
|
569
|
+
const { data: internalContext, error: validationError } = await tryCatch(createInternalContext(context, {
|
|
542
570
|
options,
|
|
543
571
|
path
|
|
544
|
-
});
|
|
572
|
+
}));
|
|
573
|
+
if (validationError) {
|
|
574
|
+
if (!(validationError instanceof ValidationError)) throw validationError;
|
|
575
|
+
if (options.onValidationError) await options.onValidationError({
|
|
576
|
+
message: validationError.message,
|
|
577
|
+
issues: validationError.issues
|
|
578
|
+
});
|
|
579
|
+
throw new APIError(400, {
|
|
580
|
+
message: validationError.message,
|
|
581
|
+
code: "VALIDATION_ERROR"
|
|
582
|
+
});
|
|
583
|
+
}
|
|
545
584
|
const response = await handler(internalContext).catch(async (e) => {
|
|
546
585
|
if (isAPIError(e)) {
|
|
547
586
|
const onAPIError = options.onAPIError;
|
|
@@ -823,7 +862,8 @@ const createRouter = (endpoints, config) => {
|
|
|
823
862
|
if (config?.routerMiddleware?.length) for (const { path, middleware } of config.routerMiddleware) addRoute(middlewareRouter, "*", path, middleware);
|
|
824
863
|
const processRequest = async (request) => {
|
|
825
864
|
const url = new URL(request.url);
|
|
826
|
-
const
|
|
865
|
+
const pathname = url.pathname;
|
|
866
|
+
const path = config?.basePath && config.basePath !== "/" ? pathname.split(config.basePath).reduce((acc, curr, index) => {
|
|
827
867
|
if (index !== 0) if (index > 1) acc.push(`${config.basePath}${curr}`);
|
|
828
868
|
else acc.push(curr);
|
|
829
869
|
return acc;
|
|
@@ -832,7 +872,15 @@ const createRouter = (endpoints, config) => {
|
|
|
832
872
|
status: 404,
|
|
833
873
|
statusText: "Not Found"
|
|
834
874
|
});
|
|
875
|
+
if (/\/{2,}/.test(path)) return new Response(null, {
|
|
876
|
+
status: 404,
|
|
877
|
+
statusText: "Not Found"
|
|
878
|
+
});
|
|
835
879
|
const route = findRoute(router, request.method, path);
|
|
880
|
+
if (path.endsWith("/") !== route?.data?.path?.endsWith("/") && !config?.skipTrailingSlashes) return new Response(null, {
|
|
881
|
+
status: 404,
|
|
882
|
+
statusText: "Not Found"
|
|
883
|
+
});
|
|
836
884
|
if (!route?.data) return new Response(null, {
|
|
837
885
|
status: 404,
|
|
838
886
|
statusText: "Not Found"
|
|
@@ -899,5 +947,5 @@ const createRouter = (endpoints, config) => {
|
|
|
899
947
|
};
|
|
900
948
|
|
|
901
949
|
//#endregion
|
|
902
|
-
export { APIError, BetterCallError, createEndpoint, createInternalContext, createMiddleware, createRouter, generator, getCookieKey, getHTML, hideInternalStackFrames, makeErrorForHideStackFrame, parseCookies, serializeCookie, serializeSignedCookie, statusCodes, toResponse };
|
|
950
|
+
export { APIError, BetterCallError, ValidationError, createEndpoint, createInternalContext, createMiddleware, createRouter, generator, getCookieKey, getHTML, hideInternalStackFrames, makeErrorForHideStackFrame, parseCookies, serializeCookie, serializeSignedCookie, statusCodes, toResponse };
|
|
903
951
|
//# sourceMappingURL=index.js.map
|