better-call 1.1.6 → 1.1.8

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.
Files changed (102) hide show
  1. package/README.md +35 -0
  2. package/dist/_virtual/rolldown_runtime.cjs +29 -0
  3. package/dist/adapters/node/request.cjs +125 -0
  4. package/dist/adapters/node/request.cjs.map +1 -0
  5. package/dist/{node.d.ts → adapters/node/request.d.cts} +2 -6
  6. package/dist/adapters/node/request.d.mts +16 -0
  7. package/dist/{node.js → adapters/node/request.mjs} +2 -13
  8. package/dist/adapters/node/request.mjs.map +1 -0
  9. package/dist/client.cjs +3 -3
  10. package/dist/client.cjs.map +1 -1
  11. package/dist/client.d.cts +13 -15
  12. package/dist/client.d.mts +53 -0
  13. package/dist/{client.js → client.mjs} +3 -3
  14. package/dist/client.mjs.map +1 -0
  15. package/dist/context.cjs +103 -0
  16. package/dist/context.cjs.map +1 -0
  17. package/dist/context.d.cts +340 -0
  18. package/dist/context.d.mts +340 -0
  19. package/dist/context.mjs +103 -0
  20. package/dist/context.mjs.map +1 -0
  21. package/dist/cookies.cjs +87 -0
  22. package/dist/cookies.cjs.map +1 -0
  23. package/dist/cookies.d.cts +103 -0
  24. package/dist/cookies.d.mts +103 -0
  25. package/dist/cookies.mjs +84 -0
  26. package/dist/cookies.mjs.map +1 -0
  27. package/dist/crypto.cjs +39 -0
  28. package/dist/crypto.cjs.map +1 -0
  29. package/dist/crypto.mjs +36 -0
  30. package/dist/crypto.mjs.map +1 -0
  31. package/dist/endpoint.cjs +70 -0
  32. package/dist/endpoint.cjs.map +1 -0
  33. package/dist/endpoint.d.cts +428 -0
  34. package/dist/endpoint.d.mts +428 -0
  35. package/dist/endpoint.mjs +70 -0
  36. package/dist/endpoint.mjs.map +1 -0
  37. package/dist/error.cjs +140 -7
  38. package/dist/error.cjs.map +1 -0
  39. package/dist/error.d.cts +103 -2
  40. package/dist/{error2.d.ts → error.d.mts} +5 -59
  41. package/dist/{error2.js → error.mjs} +2 -2
  42. package/dist/{error2.js.map → error.mjs.map} +1 -1
  43. package/dist/helper.d.cts +12 -0
  44. package/dist/helper.d.mts +12 -0
  45. package/dist/index.cjs +19 -829
  46. package/dist/index.d.cts +11 -15
  47. package/dist/index.d.mts +11 -0
  48. package/dist/index.mjs +10 -0
  49. package/dist/middleware.cjs +39 -0
  50. package/dist/middleware.cjs.map +1 -0
  51. package/dist/middleware.d.cts +123 -0
  52. package/dist/middleware.d.mts +123 -0
  53. package/dist/middleware.mjs +39 -0
  54. package/dist/middleware.mjs.map +1 -0
  55. package/dist/node.cjs +4 -151
  56. package/dist/node.cjs.map +1 -1
  57. package/dist/node.d.cts +2 -13
  58. package/dist/node.d.mts +9 -0
  59. package/dist/node.mjs +15 -0
  60. package/dist/node.mjs.map +1 -0
  61. package/dist/openapi.cjs +191 -0
  62. package/dist/openapi.cjs.map +1 -0
  63. package/dist/openapi.d.cts +113 -0
  64. package/dist/openapi.d.mts +113 -0
  65. package/dist/openapi.mjs +189 -0
  66. package/dist/openapi.mjs.map +1 -0
  67. package/dist/router.cjs +117 -0
  68. package/dist/router.cjs.map +1 -0
  69. package/dist/router.d.cts +3 -1088
  70. package/dist/router.d.mts +97 -0
  71. package/dist/router.mjs +116 -0
  72. package/dist/router.mjs.map +1 -0
  73. package/dist/standard-schema.d.cts +59 -0
  74. package/dist/standard-schema.d.mts +59 -0
  75. package/dist/to-response.cjs +96 -0
  76. package/dist/to-response.cjs.map +1 -0
  77. package/dist/to-response.d.cts +12 -0
  78. package/dist/to-response.d.mts +12 -0
  79. package/dist/to-response.mjs +96 -0
  80. package/dist/to-response.mjs.map +1 -0
  81. package/dist/utils.cjs +86 -0
  82. package/dist/utils.cjs.map +1 -0
  83. package/dist/utils.mjs +82 -0
  84. package/dist/utils.mjs.map +1 -0
  85. package/dist/validator.cjs +58 -0
  86. package/dist/validator.cjs.map +1 -0
  87. package/dist/validator.mjs +57 -0
  88. package/dist/validator.mjs.map +1 -0
  89. package/package.json +15 -15
  90. package/dist/client.d.ts +0 -55
  91. package/dist/client.js.map +0 -1
  92. package/dist/error.d.ts +0 -2
  93. package/dist/error.js +0 -3
  94. package/dist/error2.cjs +0 -171
  95. package/dist/error2.cjs.map +0 -1
  96. package/dist/error2.d.cts +0 -157
  97. package/dist/index.cjs.map +0 -1
  98. package/dist/index.d.ts +0 -15
  99. package/dist/index.js +0 -819
  100. package/dist/index.js.map +0 -1
  101. package/dist/node.js.map +0 -1
  102. package/dist/router.d.ts +0 -1182
package/dist/index.cjs CHANGED
@@ -1,836 +1,26 @@
1
- const require_error = require('./error2.cjs');
2
- const require_node = require('./node.cjs');
3
- let __better_auth_utils = require("@better-auth/utils");
4
- let rou3 = require("rou3");
5
- let zod = require("zod");
1
+ const require_error = require('./error.cjs');
2
+ const require_to_response = require('./to-response.cjs');
3
+ const require_cookies = require('./cookies.cjs');
4
+ const require_context = require('./context.cjs');
5
+ const require_endpoint = require('./endpoint.cjs');
6
+ const require_middleware = require('./middleware.cjs');
7
+ const require_openapi = require('./openapi.cjs');
8
+ const require_router = require('./router.cjs');
6
9
 
7
- //#region src/utils.ts
8
- const jsonContentTypeRegex = /^application\/([a-z0-9.+-]*\+)?json/i;
9
- async function getBody(request, allowedMediaTypes) {
10
- const contentType = request.headers.get("content-type") || "";
11
- const normalizedContentType = contentType.toLowerCase();
12
- if (!request.body) return;
13
- if (allowedMediaTypes && allowedMediaTypes.length > 0) {
14
- if (!allowedMediaTypes.some((allowed) => {
15
- const normalizedContentTypeBase = normalizedContentType.split(";")[0].trim();
16
- const normalizedAllowed = allowed.toLowerCase().trim();
17
- return normalizedContentTypeBase === normalizedAllowed || normalizedContentTypeBase.includes(normalizedAllowed);
18
- })) {
19
- if (!normalizedContentType) throw new require_error.APIError(415, {
20
- message: `Content-Type is required. Allowed types: ${allowedMediaTypes.join(", ")}`,
21
- code: "UNSUPPORTED_MEDIA_TYPE"
22
- });
23
- throw new require_error.APIError(415, {
24
- message: `Content-Type "${contentType}" is not allowed. Allowed types: ${allowedMediaTypes.join(", ")}`,
25
- code: "UNSUPPORTED_MEDIA_TYPE"
26
- });
27
- }
28
- }
29
- if (jsonContentTypeRegex.test(normalizedContentType)) return await request.json();
30
- if (normalizedContentType.includes("application/x-www-form-urlencoded")) {
31
- const formData = await request.formData();
32
- const result = {};
33
- formData.forEach((value, key) => {
34
- result[key] = value.toString();
35
- });
36
- return result;
37
- }
38
- if (normalizedContentType.includes("multipart/form-data")) {
39
- const formData = await request.formData();
40
- const result = {};
41
- formData.forEach((value, key) => {
42
- result[key] = value;
43
- });
44
- return result;
45
- }
46
- if (normalizedContentType.includes("text/plain")) return await request.text();
47
- if (normalizedContentType.includes("application/octet-stream")) return await request.arrayBuffer();
48
- if (normalizedContentType.includes("application/pdf") || normalizedContentType.includes("image/") || normalizedContentType.includes("video/")) return await request.blob();
49
- if (normalizedContentType.includes("application/stream") || request.body instanceof ReadableStream) return request.body;
50
- return await request.text();
51
- }
52
- function isAPIError(error) {
53
- return error instanceof require_error.APIError || error?.name === "APIError";
54
- }
55
- function tryDecode(str) {
56
- try {
57
- return str.includes("%") ? decodeURIComponent(str) : str;
58
- } catch {
59
- return str;
60
- }
61
- }
62
- async function tryCatch(promise) {
63
- try {
64
- return {
65
- data: await promise,
66
- error: null
67
- };
68
- } catch (error) {
69
- return {
70
- data: null,
71
- error
72
- };
73
- }
74
- }
75
-
76
- //#endregion
77
- //#region src/to-response.ts
78
- function isJSONSerializable(value) {
79
- if (value === void 0) return false;
80
- const t = typeof value;
81
- if (t === "string" || t === "number" || t === "boolean" || t === null) return true;
82
- if (t !== "object") return false;
83
- if (Array.isArray(value)) return true;
84
- if (value.buffer) return false;
85
- return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function";
86
- }
87
- function safeStringify(obj, replacer, space) {
88
- let id = 0;
89
- const seen = /* @__PURE__ */ new WeakMap();
90
- const safeReplacer = (key, value) => {
91
- if (typeof value === "bigint") return value.toString();
92
- if (typeof value === "object" && value !== null) {
93
- if (seen.has(value)) return `[Circular ref-${seen.get(value)}]`;
94
- seen.set(value, id++);
95
- }
96
- if (replacer) return replacer(key, value);
97
- return value;
98
- };
99
- return JSON.stringify(obj, safeReplacer, space);
100
- }
101
- function isJSONResponse(value) {
102
- if (!value || typeof value !== "object") return false;
103
- return "_flag" in value && value._flag === "json";
104
- }
105
- function toResponse(data, init) {
106
- if (data instanceof Response) {
107
- if (init?.headers instanceof Headers) init.headers.forEach((value, key) => {
108
- data.headers.set(key, value);
109
- });
110
- return data;
111
- }
112
- if (isJSONResponse(data)) {
113
- const body$1 = data.body;
114
- const routerResponse = data.routerResponse;
115
- if (routerResponse instanceof Response) return routerResponse;
116
- const headers$1 = new Headers();
117
- if (routerResponse?.headers) {
118
- const headers$2 = new Headers(routerResponse.headers);
119
- for (const [key, value] of headers$2.entries()) headers$2.set(key, value);
120
- }
121
- if (data.headers) for (const [key, value] of new Headers(data.headers).entries()) headers$1.set(key, value);
122
- if (init?.headers) for (const [key, value] of new Headers(init.headers).entries()) headers$1.set(key, value);
123
- headers$1.set("Content-Type", "application/json");
124
- return new Response(JSON.stringify(body$1), {
125
- ...routerResponse,
126
- headers: headers$1,
127
- status: data.status ?? init?.status ?? routerResponse?.status,
128
- statusText: init?.statusText ?? routerResponse?.statusText
129
- });
130
- }
131
- if (isAPIError(data)) return toResponse(data.body, {
132
- status: init?.status ?? data.statusCode,
133
- statusText: data.status.toString(),
134
- headers: init?.headers || data.headers
135
- });
136
- let body = data;
137
- let headers = new Headers(init?.headers);
138
- if (!data) {
139
- if (data === null) body = JSON.stringify(null);
140
- headers.set("content-type", "application/json");
141
- } else if (typeof data === "string") {
142
- body = data;
143
- headers.set("Content-Type", "text/plain");
144
- } else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
145
- body = data;
146
- headers.set("Content-Type", "application/octet-stream");
147
- } else if (data instanceof Blob) {
148
- body = data;
149
- headers.set("Content-Type", data.type || "application/octet-stream");
150
- } else if (data instanceof FormData) body = data;
151
- else if (data instanceof URLSearchParams) {
152
- body = data;
153
- headers.set("Content-Type", "application/x-www-form-urlencoded");
154
- } else if (data instanceof ReadableStream) {
155
- body = data;
156
- headers.set("Content-Type", "application/octet-stream");
157
- } else if (isJSONSerializable(data)) {
158
- body = safeStringify(data);
159
- headers.set("Content-Type", "application/json");
160
- }
161
- return new Response(body, {
162
- ...init,
163
- headers
164
- });
165
- }
166
-
167
- //#endregion
168
- //#region src/validator.ts
169
- /**
170
- * Runs validation on body and query
171
- * @returns error and data object
172
- */
173
- async function runValidation(options, context = {}) {
174
- let request = {
175
- body: context.body,
176
- query: context.query
177
- };
178
- if (options.body) {
179
- const result = await options.body["~standard"].validate(context.body);
180
- if (result.issues) return {
181
- data: null,
182
- error: fromError(result.issues, "body")
183
- };
184
- request.body = result.value;
185
- }
186
- if (options.query) {
187
- const result = await options.query["~standard"].validate(context.query);
188
- if (result.issues) return {
189
- data: null,
190
- error: fromError(result.issues, "query")
191
- };
192
- request.query = result.value;
193
- }
194
- if (options.requireHeaders && !context.headers) return {
195
- data: null,
196
- error: {
197
- message: "Headers is required",
198
- issues: []
199
- }
200
- };
201
- if (options.requireRequest && !context.request) return {
202
- data: null,
203
- error: {
204
- message: "Request is required",
205
- issues: []
206
- }
207
- };
208
- return {
209
- data: request,
210
- error: null
211
- };
212
- }
213
- function fromError(error, validating) {
214
- return {
215
- message: error.map((e) => {
216
- return `[${e.path?.length ? `${validating}.` + e.path.map((x) => typeof x === "object" ? x.key : x).join(".") : validating}] ${e.message}`;
217
- }).join("; "),
218
- issues: error
219
- };
220
- }
221
-
222
- //#endregion
223
- //#region src/crypto.ts
224
- const algorithm = {
225
- name: "HMAC",
226
- hash: "SHA-256"
227
- };
228
- const getCryptoKey = async (secret) => {
229
- const secretBuf = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
230
- return await (0, __better_auth_utils.getWebcryptoSubtle)().importKey("raw", secretBuf, algorithm, false, ["sign", "verify"]);
231
- };
232
- const verifySignature = async (base64Signature, value, secret) => {
233
- try {
234
- const signatureBinStr = atob(base64Signature);
235
- const signature = new Uint8Array(signatureBinStr.length);
236
- for (let i = 0, len = signatureBinStr.length; i < len; i++) signature[i] = signatureBinStr.charCodeAt(i);
237
- return await (0, __better_auth_utils.getWebcryptoSubtle)().verify(algorithm, secret, signature, new TextEncoder().encode(value));
238
- } catch (e) {
239
- return false;
240
- }
241
- };
242
- const makeSignature = async (value, secret) => {
243
- const key = await getCryptoKey(secret);
244
- const signature = await (0, __better_auth_utils.getWebcryptoSubtle)().sign(algorithm.name, key, new TextEncoder().encode(value));
245
- return btoa(String.fromCharCode(...new Uint8Array(signature)));
246
- };
247
- const signCookieValue = async (value, secret) => {
248
- const signature = await makeSignature(value, secret);
249
- value = `${value}.${signature}`;
250
- value = encodeURIComponent(value);
251
- return value;
252
- };
253
-
254
- //#endregion
255
- //#region src/cookies.ts
256
- const getCookieKey = (key, prefix) => {
257
- let finalKey = key;
258
- if (prefix) if (prefix === "secure") finalKey = "__Secure-" + key;
259
- else if (prefix === "host") finalKey = "__Host-" + key;
260
- else return;
261
- return finalKey;
262
- };
263
- /**
264
- * Parse an HTTP Cookie header string and returning an object of all cookie
265
- * name-value pairs.
266
- *
267
- * Inspired by https://github.com/unjs/cookie-es/blob/main/src/cookie/parse.ts
268
- *
269
- * @param str the string representing a `Cookie` header value
270
- */
271
- function parseCookies(str) {
272
- if (typeof str !== "string") throw new TypeError("argument str must be a string");
273
- const cookies = /* @__PURE__ */ new Map();
274
- let index = 0;
275
- while (index < str.length) {
276
- const eqIdx = str.indexOf("=", index);
277
- if (eqIdx === -1) break;
278
- let endIdx = str.indexOf(";", index);
279
- if (endIdx === -1) endIdx = str.length;
280
- else if (endIdx < eqIdx) {
281
- index = str.lastIndexOf(";", eqIdx - 1) + 1;
282
- continue;
283
- }
284
- const key = str.slice(index, eqIdx).trim();
285
- if (!cookies.has(key)) {
286
- let val = str.slice(eqIdx + 1, endIdx).trim();
287
- if (val.codePointAt(0) === 34) val = val.slice(1, -1);
288
- cookies.set(key, tryDecode(val));
289
- }
290
- index = endIdx + 1;
291
- }
292
- return cookies;
293
- }
294
- const _serialize = (key, value, opt = {}) => {
295
- let cookie;
296
- if (opt?.prefix === "secure") cookie = `${`__Secure-${key}`}=${value}`;
297
- else if (opt?.prefix === "host") cookie = `${`__Host-${key}`}=${value}`;
298
- else cookie = `${key}=${value}`;
299
- if (key.startsWith("__Secure-") && !opt.secure) opt.secure = true;
300
- if (key.startsWith("__Host-")) {
301
- if (!opt.secure) opt.secure = true;
302
- if (opt.path !== "/") opt.path = "/";
303
- if (opt.domain) opt.domain = void 0;
304
- }
305
- if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) {
306
- if (opt.maxAge > 3456e4) throw new Error("Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration.");
307
- cookie += `; Max-Age=${Math.floor(opt.maxAge)}`;
308
- }
309
- if (opt.domain && opt.prefix !== "host") cookie += `; Domain=${opt.domain}`;
310
- if (opt.path) cookie += `; Path=${opt.path}`;
311
- if (opt.expires) {
312
- if (opt.expires.getTime() - Date.now() > 3456e7) throw new Error("Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.");
313
- cookie += `; Expires=${opt.expires.toUTCString()}`;
314
- }
315
- if (opt.httpOnly) cookie += "; HttpOnly";
316
- if (opt.secure) cookie += "; Secure";
317
- if (opt.sameSite) cookie += `; SameSite=${opt.sameSite.charAt(0).toUpperCase() + opt.sameSite.slice(1)}`;
318
- if (opt.partitioned) {
319
- if (!opt.secure) opt.secure = true;
320
- cookie += "; Partitioned";
321
- }
322
- return cookie;
323
- };
324
- const serializeCookie = (key, value, opt) => {
325
- value = encodeURIComponent(value);
326
- return _serialize(key, value, opt);
327
- };
328
- const serializeSignedCookie = async (key, value, secret, opt) => {
329
- value = await signCookieValue(value, secret);
330
- return _serialize(key, value, opt);
331
- };
332
-
333
- //#endregion
334
- //#region src/context.ts
335
- const createInternalContext = async (context, { options, path }) => {
336
- const headers = new Headers();
337
- let responseStatus = void 0;
338
- const { data, error } = await runValidation(options, context);
339
- if (error) throw new require_error.ValidationError(error.message, error.issues);
340
- 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;
341
- const requestCookies = requestHeaders?.get("cookie");
342
- const parsedCookies = requestCookies ? parseCookies(requestCookies) : void 0;
343
- const internalContext = {
344
- ...context,
345
- body: data.body,
346
- query: data.query,
347
- path: context.path || path || "virtual:",
348
- context: "context" in context && context.context ? context.context : {},
349
- returned: void 0,
350
- headers: context?.headers,
351
- request: context?.request,
352
- params: "params" in context ? context.params : void 0,
353
- method: context.method,
354
- setHeader: (key, value) => {
355
- headers.set(key, value);
356
- },
357
- getHeader: (key) => {
358
- if (!requestHeaders) return null;
359
- return requestHeaders.get(key);
360
- },
361
- getCookie: (key, prefix) => {
362
- const finalKey = getCookieKey(key, prefix);
363
- if (!finalKey) return null;
364
- return parsedCookies?.get(finalKey) || null;
365
- },
366
- getSignedCookie: async (key, secret, prefix) => {
367
- const finalKey = getCookieKey(key, prefix);
368
- if (!finalKey) return null;
369
- const value = parsedCookies?.get(finalKey);
370
- if (!value) return null;
371
- const signatureStartPos = value.lastIndexOf(".");
372
- if (signatureStartPos < 1) return null;
373
- const signedValue = value.substring(0, signatureStartPos);
374
- const signature = value.substring(signatureStartPos + 1);
375
- if (signature.length !== 44 || !signature.endsWith("=")) return null;
376
- return await verifySignature(signature, signedValue, await getCryptoKey(secret)) ? signedValue : false;
377
- },
378
- setCookie: (key, value, options$1) => {
379
- const cookie = serializeCookie(key, value, options$1);
380
- headers.append("set-cookie", cookie);
381
- return cookie;
382
- },
383
- setSignedCookie: async (key, value, secret, options$1) => {
384
- const cookie = await serializeSignedCookie(key, value, secret, options$1);
385
- headers.append("set-cookie", cookie);
386
- return cookie;
387
- },
388
- redirect: (url) => {
389
- headers.set("location", url);
390
- return new require_error.APIError("FOUND", void 0, headers);
391
- },
392
- error: (status, body, headers$1) => {
393
- return new require_error.APIError(status, body, headers$1);
394
- },
395
- setStatus: (status) => {
396
- responseStatus = status;
397
- },
398
- json: (json, routerResponse) => {
399
- if (!context.asResponse) return json;
400
- return {
401
- body: routerResponse?.body || json,
402
- routerResponse,
403
- _flag: "json"
404
- };
405
- },
406
- responseHeaders: headers,
407
- get responseStatus() {
408
- return responseStatus;
409
- }
410
- };
411
- for (const middleware of options.use || []) {
412
- const response = await middleware({
413
- ...internalContext,
414
- returnHeaders: true,
415
- asResponse: false
416
- });
417
- if (response.response) Object.assign(internalContext.context, response.response);
418
- /**
419
- * Apply headers from the middleware to the endpoint headers
420
- */
421
- if (response.headers) response.headers.forEach((value, key) => {
422
- internalContext.responseHeaders.set(key, value);
423
- });
424
- }
425
- return internalContext;
426
- };
427
-
428
- //#endregion
429
- //#region src/endpoint.ts
430
- function createEndpoint(pathOrOptions, handlerOrOptions, handlerOrNever) {
431
- const path = typeof pathOrOptions === "string" ? pathOrOptions : void 0;
432
- const options = typeof handlerOrOptions === "object" ? handlerOrOptions : pathOrOptions;
433
- const handler = typeof handlerOrOptions === "function" ? handlerOrOptions : handlerOrNever;
434
- if ((options.method === "GET" || options.method === "HEAD") && options.body) throw new require_error.BetterCallError("Body is not allowed with GET or HEAD methods");
435
- if (path && /\/{2,}/.test(path)) throw new require_error.BetterCallError("Path cannot contain consecutive slashes");
436
- const internalHandler = async (...inputCtx) => {
437
- const context = inputCtx[0] || {};
438
- const { data: internalContext, error: validationError } = await tryCatch(createInternalContext(context, {
439
- options,
440
- path
441
- }));
442
- if (validationError) {
443
- if (!(validationError instanceof require_error.ValidationError)) throw validationError;
444
- if (options.onValidationError) await options.onValidationError({
445
- message: validationError.message,
446
- issues: validationError.issues
447
- });
448
- throw new require_error.APIError(400, {
449
- message: validationError.message,
450
- code: "VALIDATION_ERROR"
451
- });
452
- }
453
- const response = await handler(internalContext).catch(async (e) => {
454
- if (isAPIError(e)) {
455
- const onAPIError = options.onAPIError;
456
- if (onAPIError) await onAPIError(e);
457
- if (context.asResponse) return e;
458
- }
459
- throw e;
460
- });
461
- const headers = internalContext.responseHeaders;
462
- const status = internalContext.responseStatus;
463
- return context.asResponse ? toResponse(response, {
464
- headers,
465
- status
466
- }) : context.returnHeaders ? context.returnStatus ? {
467
- headers,
468
- response,
469
- status
470
- } : {
471
- headers,
472
- response
473
- } : context.returnStatus ? {
474
- response,
475
- status
476
- } : response;
477
- };
478
- internalHandler.options = options;
479
- internalHandler.path = path;
480
- return internalHandler;
481
- }
482
- createEndpoint.create = (opts) => {
483
- return (path, options, handler) => {
484
- return createEndpoint(path, {
485
- ...options,
486
- use: [...options?.use || [], ...opts?.use || []]
487
- }, handler);
488
- };
489
- };
490
-
491
- //#endregion
492
- //#region src/middleware.ts
493
- function createMiddleware(optionsOrHandler, handler) {
494
- const internalHandler = async (inputCtx) => {
495
- const context = inputCtx;
496
- const _handler = typeof optionsOrHandler === "function" ? optionsOrHandler : handler;
497
- const internalContext = await createInternalContext(context, {
498
- options: typeof optionsOrHandler === "function" ? {} : optionsOrHandler,
499
- path: "/"
500
- });
501
- if (!_handler) throw new Error("handler must be defined");
502
- const response = await _handler(internalContext);
503
- const headers = internalContext.responseHeaders;
504
- return context.returnHeaders ? {
505
- headers,
506
- response
507
- } : response;
508
- };
509
- internalHandler.options = typeof optionsOrHandler === "function" ? {} : optionsOrHandler;
510
- return internalHandler;
511
- }
512
- createMiddleware.create = (opts) => {
513
- function fn(optionsOrHandler, handler) {
514
- if (typeof optionsOrHandler === "function") return createMiddleware({ use: opts?.use }, optionsOrHandler);
515
- if (!handler) throw new Error("Middleware handler is required");
516
- return createMiddleware({
517
- ...optionsOrHandler,
518
- method: "*",
519
- use: [...opts?.use || [], ...optionsOrHandler.use || []]
520
- }, handler);
521
- }
522
- return fn;
523
- };
524
-
525
- //#endregion
526
- //#region src/openapi.ts
527
- const paths = {};
528
- function getTypeFromZodType(zodType) {
529
- switch (zodType.constructor.name) {
530
- case "ZodString": return "string";
531
- case "ZodNumber": return "number";
532
- case "ZodBoolean": return "boolean";
533
- case "ZodObject": return "object";
534
- case "ZodArray": return "array";
535
- default: return "string";
536
- }
537
- }
538
- function getParameters(options) {
539
- const parameters = [];
540
- if (options.metadata?.openapi?.parameters) {
541
- parameters.push(...options.metadata.openapi.parameters);
542
- return parameters;
543
- }
544
- if (options.query instanceof zod.ZodObject) Object.entries(options.query.shape).forEach(([key, value]) => {
545
- if (value instanceof zod.ZodObject) parameters.push({
546
- name: key,
547
- in: "query",
548
- schema: {
549
- type: getTypeFromZodType(value),
550
- ..."minLength" in value && value.minLength ? { minLength: value.minLength } : {},
551
- description: value.description
552
- }
553
- });
554
- });
555
- return parameters;
556
- }
557
- function getRequestBody(options) {
558
- if (options.metadata?.openapi?.requestBody) return options.metadata.openapi.requestBody;
559
- if (!options.body) return void 0;
560
- if (options.body instanceof zod.ZodObject || options.body instanceof zod.ZodOptional) {
561
- const shape = options.body.shape;
562
- if (!shape) return void 0;
563
- const properties = {};
564
- const required = [];
565
- Object.entries(shape).forEach(([key, value]) => {
566
- if (value instanceof zod.ZodObject) {
567
- properties[key] = {
568
- type: getTypeFromZodType(value),
569
- description: value.description
570
- };
571
- if (!(value instanceof zod.ZodOptional)) required.push(key);
572
- }
573
- });
574
- return {
575
- required: options.body instanceof zod.ZodOptional ? false : options.body ? true : false,
576
- content: { "application/json": { schema: {
577
- type: "object",
578
- properties,
579
- required
580
- } } }
581
- };
582
- }
583
- }
584
- function getResponse(responses) {
585
- return {
586
- "400": {
587
- content: { "application/json": { schema: {
588
- type: "object",
589
- properties: { message: { type: "string" } },
590
- required: ["message"]
591
- } } },
592
- description: "Bad Request. Usually due to missing parameters, or invalid parameters."
593
- },
594
- "401": {
595
- content: { "application/json": { schema: {
596
- type: "object",
597
- properties: { message: { type: "string" } },
598
- required: ["message"]
599
- } } },
600
- description: "Unauthorized. Due to missing or invalid authentication."
601
- },
602
- "403": {
603
- content: { "application/json": { schema: {
604
- type: "object",
605
- properties: { message: { type: "string" } }
606
- } } },
607
- description: "Forbidden. You do not have permission to access this resource or to perform this action."
608
- },
609
- "404": {
610
- content: { "application/json": { schema: {
611
- type: "object",
612
- properties: { message: { type: "string" } }
613
- } } },
614
- description: "Not Found. The requested resource was not found."
615
- },
616
- "429": {
617
- content: { "application/json": { schema: {
618
- type: "object",
619
- properties: { message: { type: "string" } }
620
- } } },
621
- description: "Too Many Requests. You have exceeded the rate limit. Try again later."
622
- },
623
- "500": {
624
- content: { "application/json": { schema: {
625
- type: "object",
626
- properties: { message: { type: "string" } }
627
- } } },
628
- description: "Internal Server Error. This is a problem with the server that you cannot fix."
629
- },
630
- ...responses
631
- };
632
- }
633
- async function generator(endpoints, config) {
634
- const components = { schemas: {} };
635
- Object.entries(endpoints).forEach(([_, value]) => {
636
- const options = value.options;
637
- if (!value.path || options.metadata?.SERVER_ONLY) return;
638
- if (options.method === "GET") paths[value.path] = { get: {
639
- tags: ["Default", ...options.metadata?.openapi?.tags || []],
640
- description: options.metadata?.openapi?.description,
641
- operationId: options.metadata?.openapi?.operationId,
642
- security: [{ bearerAuth: [] }],
643
- parameters: getParameters(options),
644
- responses: getResponse(options.metadata?.openapi?.responses)
645
- } };
646
- if (options.method === "POST") {
647
- const body = getRequestBody(options);
648
- paths[value.path] = { post: {
649
- tags: ["Default", ...options.metadata?.openapi?.tags || []],
650
- description: options.metadata?.openapi?.description,
651
- operationId: options.metadata?.openapi?.operationId,
652
- security: [{ bearerAuth: [] }],
653
- parameters: getParameters(options),
654
- ...body ? { requestBody: body } : { requestBody: { content: { "application/json": { schema: {
655
- type: "object",
656
- properties: {}
657
- } } } } },
658
- responses: getResponse(options.metadata?.openapi?.responses)
659
- } };
660
- }
661
- });
662
- return {
663
- openapi: "3.1.1",
664
- info: {
665
- title: "Better Auth",
666
- description: "API Reference for your Better Auth Instance",
667
- version: "1.1.0"
668
- },
669
- components,
670
- security: [{ apiKeyCookie: [] }],
671
- servers: [{ url: config?.url }],
672
- tags: [{
673
- name: "Default",
674
- description: "Default endpoints that are included with Better Auth by default. These endpoints are not part of any plugin."
675
- }],
676
- paths
677
- };
678
- }
679
- const getHTML = (apiReference, config) => `<!doctype html>
680
- <html>
681
- <head>
682
- <title>Scalar API Reference</title>
683
- <meta charset="utf-8" />
684
- <meta
685
- name="viewport"
686
- content="width=device-width, initial-scale=1" />
687
- </head>
688
- <body>
689
- <script
690
- id="api-reference"
691
- type="application/json">
692
- ${JSON.stringify(apiReference)}
693
- <\/script>
694
- <script>
695
- var configuration = {
696
- favicon: ${config?.logo ? `data:image/svg+xml;utf8,${encodeURIComponent(config.logo)}` : void 0} ,
697
- theme: ${config?.theme || "saturn"},
698
- metaData: {
699
- title: ${config?.title || "Open API Reference"},
700
- description: ${config?.description || "Better Call Open API"},
701
- }
702
- }
703
- document.getElementById('api-reference').dataset.configuration =
704
- JSON.stringify(configuration)
705
- <\/script>
706
- <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
707
- </body>
708
- </html>`;
709
-
710
- //#endregion
711
- //#region src/router.ts
712
- const createRouter = (endpoints, config) => {
713
- if (!config?.openapi?.disabled) {
714
- const openapi = {
715
- path: "/api/reference",
716
- ...config?.openapi
717
- };
718
- endpoints["openapi"] = createEndpoint(openapi.path, { method: "GET" }, async (c) => {
719
- const schema = await generator(endpoints);
720
- return new Response(getHTML(schema, openapi.scalar), { headers: { "Content-Type": "text/html" } });
721
- });
722
- }
723
- const router = (0, rou3.createRouter)();
724
- const middlewareRouter = (0, rou3.createRouter)();
725
- for (const endpoint of Object.values(endpoints)) {
726
- if (!endpoint.options || !endpoint.path) continue;
727
- if (endpoint.options?.metadata?.SERVER_ONLY) continue;
728
- const methods = Array.isArray(endpoint.options?.method) ? endpoint.options.method : [endpoint.options?.method];
729
- for (const method of methods) (0, rou3.addRoute)(router, method, endpoint.path, endpoint);
730
- }
731
- if (config?.routerMiddleware?.length) for (const { path, middleware } of config.routerMiddleware) (0, rou3.addRoute)(middlewareRouter, "*", path, middleware);
732
- const processRequest = async (request) => {
733
- const url = new URL(request.url);
734
- const pathname = url.pathname;
735
- const path = config?.basePath && config.basePath !== "/" ? pathname.split(config.basePath).reduce((acc, curr, index) => {
736
- if (index !== 0) if (index > 1) acc.push(`${config.basePath}${curr}`);
737
- else acc.push(curr);
738
- return acc;
739
- }, []).join("") : url.pathname;
740
- if (!path?.length) return new Response(null, {
741
- status: 404,
742
- statusText: "Not Found"
743
- });
744
- if (/\/{2,}/.test(path)) return new Response(null, {
745
- status: 404,
746
- statusText: "Not Found"
747
- });
748
- const route = (0, rou3.findRoute)(router, request.method, path);
749
- if (path.endsWith("/") !== route?.data?.path?.endsWith("/") && !config?.skipTrailingSlashes) return new Response(null, {
750
- status: 404,
751
- statusText: "Not Found"
752
- });
753
- if (!route?.data) return new Response(null, {
754
- status: 404,
755
- statusText: "Not Found"
756
- });
757
- const query = {};
758
- url.searchParams.forEach((value, key) => {
759
- if (key in query) if (Array.isArray(query[key])) query[key].push(value);
760
- else query[key] = [query[key], value];
761
- else query[key] = value;
762
- });
763
- const handler = route.data;
764
- try {
765
- const allowedMediaTypes = handler.options.metadata?.allowedMediaTypes || config?.allowedMediaTypes;
766
- const context = {
767
- path,
768
- method: request.method,
769
- headers: request.headers,
770
- params: route.params ? JSON.parse(JSON.stringify(route.params)) : {},
771
- request,
772
- body: handler.options.disableBody ? void 0 : await getBody(handler.options.cloneRequest ? request.clone() : request, allowedMediaTypes),
773
- query,
774
- _flag: "router",
775
- asResponse: true,
776
- context: config?.routerContext
777
- };
778
- const middlewareRoutes = (0, rou3.findAllRoutes)(middlewareRouter, "*", path);
779
- if (middlewareRoutes?.length) for (const { data: middleware, params } of middlewareRoutes) {
780
- const res = await middleware({
781
- ...context,
782
- params,
783
- asResponse: false
784
- });
785
- if (res instanceof Response) return res;
786
- }
787
- return await handler(context);
788
- } catch (error) {
789
- if (config?.onError) try {
790
- const errorResponse = await config.onError(error);
791
- if (errorResponse instanceof Response) return toResponse(errorResponse);
792
- } catch (error$1) {
793
- if (isAPIError(error$1)) return toResponse(error$1);
794
- throw error$1;
795
- }
796
- if (config?.throwError) throw error;
797
- if (isAPIError(error)) return toResponse(error);
798
- console.error(`# SERVER_ERROR: `, error);
799
- return new Response(null, {
800
- status: 500,
801
- statusText: "Internal Server Error"
802
- });
803
- }
804
- };
805
- return {
806
- handler: async (request) => {
807
- const onReq = await config?.onRequest?.(request);
808
- if (onReq instanceof Response) return onReq;
809
- const res = await processRequest(onReq instanceof Request ? onReq : request);
810
- const onRes = await config?.onResponse?.(res);
811
- if (onRes instanceof Response) return onRes;
812
- return res;
813
- },
814
- endpoints
815
- };
816
- };
817
-
818
- //#endregion
819
10
  exports.APIError = require_error.APIError;
820
11
  exports.BetterCallError = require_error.BetterCallError;
821
12
  exports.ValidationError = require_error.ValidationError;
822
- exports.createEndpoint = createEndpoint;
823
- exports.createInternalContext = createInternalContext;
824
- exports.createMiddleware = createMiddleware;
825
- exports.createRouter = createRouter;
826
- exports.generator = generator;
827
- exports.getCookieKey = getCookieKey;
828
- exports.getHTML = getHTML;
13
+ exports.createEndpoint = require_endpoint.createEndpoint;
14
+ exports.createInternalContext = require_context.createInternalContext;
15
+ exports.createMiddleware = require_middleware.createMiddleware;
16
+ exports.createRouter = require_router.createRouter;
17
+ exports.generator = require_openapi.generator;
18
+ exports.getCookieKey = require_cookies.getCookieKey;
19
+ exports.getHTML = require_openapi.getHTML;
829
20
  exports.hideInternalStackFrames = require_error.hideInternalStackFrames;
830
21
  exports.makeErrorForHideStackFrame = require_error.makeErrorForHideStackFrame;
831
- exports.parseCookies = parseCookies;
832
- exports.serializeCookie = serializeCookie;
833
- exports.serializeSignedCookie = serializeSignedCookie;
22
+ exports.parseCookies = require_cookies.parseCookies;
23
+ exports.serializeCookie = require_cookies.serializeCookie;
24
+ exports.serializeSignedCookie = require_cookies.serializeSignedCookie;
834
25
  exports.statusCodes = require_error.statusCodes;
835
- exports.toResponse = toResponse;
836
- //# sourceMappingURL=index.cjs.map
26
+ exports.toResponse = require_to_response.toResponse;