better-auth 0.2.3-beta.8 → 0.2.4

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/utils.js CHANGED
@@ -1,2 +1,453 @@
1
- var R=(e,o)=>{let t={};for(let[n,r]of Object.entries(e))t[n]=s=>r({...s,context:{...o,...s.context}}),t[n].path=r.path,t[n].method=r.method,t[n].options=r.options,t[n].headers=r.headers;return t},U=(e,o)=>async t=>{for(let s of e.options.plugins||[])if(s.hooks?.before){for(let i of s.hooks.before)if(i.matcher({...t,...o})){let a=await i.handler(t);a&&"context"in a&&(t={...t,...a.context,...o})}}let n=o({...t,context:{...e,...t.context}}),r=n;for(let s of e.options.plugins||[])if(s.hooks?.after){for(let i of s.hooks.after)if(i.matcher(t)){let a=Object.assign(t,{returned:n}),p=await i.handler(a);p&&"response"in p&&(r=p.response)}}return r};var f=class extends Error{constructor(o,t,n){super(o),this.name="BetterAuthError",this.message=o,this.cause=t}};function y(e){try{return new URL(e).pathname!=="/"}catch{throw new f(`Invalid base URL: ${e}. Please provide a valid base URL.`)}}function l(e,o="/api/auth"){return y(e)?e:(o=o.startsWith("/")?o:`/${o}`,`${e}${o}`)}function P(e,o){if(e)return l(e,o);let t=process?.env||{},n=t.BETTER_AUTH_URL||t.NEXT_PUBLIC_BETTER_AUTH_URL||t.PUBLIC_BETTER_AUTH_URL||t.NUXT_PUBLIC_BETTER_AUTH_URL||t.NUXT_PUBLIC_AUTH_URL||(t.BASE_URL!=="/"?t.BASE_URL:void 0);if(n)return l(n,o);if(typeof window<"u")return l(window.location.origin,o)}var g=(e,o)=>{for(let t in e){if(!e.hasOwnProperty(t))continue;let n=e[t];typeof n=="object"&&n!==null?o[t]=g(n,n.constructor()):o[t]=n}return o},m=e=>g(e,e.constructor());import{TimeSpan as C}from"oslo";function I(e){let t=!!e.advanced?.useSecureCookies||process.env.NODE_ENV!=="development"&&process.env.NODE_ENV!=="test"?"__Secure-":"",n="better-auth",r=new C(7,"d").seconds();return{sessionToken:{name:`${t}${n}.session_token`,options:{httpOnly:!0,sameSite:"lax",path:"/",secure:!!t,maxAge:r}},csrfToken:{name:`${t?"__Host-":""}${n}.csrf_token`,options:{httpOnly:!0,sameSite:"lax",path:"/",secure:!!t,maxAge:60*60*24*7}},state:{name:`${t}${n}.state`,options:{httpOnly:!0,sameSite:"lax",path:"/",secure:!!t,maxAge:60*15}},pkCodeVerifier:{name:`${t}${n}.pk_code_verifier`,options:{httpOnly:!0,sameSite:"lax",path:"/",secure:!!t,maxAge:60*15}},dontRememberToken:{name:`${t}${n}.dont_remember`,options:{httpOnly:!0,sameSite:"lax",path:"/",secure:!!t}},nonce:{name:`${t}${n}.nonce`,options:{httpOnly:!0,sameSite:"lax",path:"/",secure:!!t,maxAge:60*15}}}}function D(e){let t=!!e.advanced?.useSecureCookies||process.env.NODE_ENV==="production"?"__Secure-":"",n="better-auth";function r(s,i){return{name:process.env.NODE_ENV==="production"?`${t}${n}.${s}`:`${n}.${s}`,options:{secure:!!t,sameSite:"lax",path:"/",maxAge:60*15,...i}}}return r}async function H(e,o,t,n){let r=e.context.authCookies.sessionToken.options;r.maxAge=t?void 0:r.maxAge,await e.setSignedCookie(e.context.authCookies.sessionToken.name,o,e.context.secret,r),t&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function V(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}function j(e){let o=new Map;return e.split(", ").forEach(n=>{let[r,...s]=n.split("; "),[i,d]=r.split("="),a={value:d};s.forEach(p=>{let[k,x]=p.split("=");a[k.toLowerCase()]=x||!0}),o.set(i,a)}),o}var M=(e,o=!1)=>{let t=new Date;return new Date(t.getTime()+(o?e*1e3:e))};function X(e){let o="127.0.0.1";if(process.env.NODE_ENV==="test")return o;let t=["x-client-ip","x-forwarded-for","cf-connecting-ip","fastly-client-ip","x-real-ip","x-cluster-client-ip","x-forwarded","forwarded-for","forwarded"];for(let n of t){let r=e.headers.get(n);if(typeof r=="string"){let s=r.split(",")[0].trim();if(s)return s}}return null}var q={isAction:!1};import{alphabet as b,generateRandomString as A}from"oslo/crypto";var K=()=>A(36,b("a-z","0-9"));import{createConsola as _}from"consola";var c=_({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),w=e=>({log:(...o)=>{!e?.disabled&&c.log("",...o)},error:(...o)=>{!e?.disabled&&c.error("",...o)},warn:(...o)=>{!e?.disabled&&c.warn("",...o)},info:(...o)=>{!e?.disabled&&c.info("",...o)},debug:(...o)=>{!e?.disabled&&c.debug("",...o)},box:(...o)=>{!e?.disabled&&c.box("",...o)},success:(...o)=>{!e?.disabled&&c.success("",...o)},break:(...o)=>{!e?.disabled&&console.log(`
2
- `)}}),Z=w();var h=(e,o)=>{for(let t in o){if(!o.hasOwnProperty(t)||t==="constructor"||t==="prototype"||t==="__proto__")continue;let n=o[t];O(n)?(n!==void 0||!(t in e))&&(e[t]=n):!e[t]||T(n)?e[t]=m(n):e[t]=h(e[t],n)}return e},T=e=>Array.isArray(e),O=e=>{if(e===null)return!0;let o=typeof e;return o!=="object"&&o!=="function"},oe=e=>{let o=m(e[0]);for(let t=1,n=e.length;t<n;t++)h(o,e[t]);return o};function re(e){return e.charAt(0).toUpperCase()+e.slice(1)}async function ie(e,o){let n=(await e.context.internalAdapter.findAccounts(o.userId))?.find(i=>i.providerId==="credential"),r=n?.password;return!n||!r?!1:await e.context.password.verify(r,o.password)}import{generateState as E}from"oslo/oauth2";import{z as u}from"zod";function ue(e,o,t){let n=E();return{state:JSON.stringify({code:n,callbackURL:e,currentURL:o,dontRememberMe:t}),code:n}}function fe(e){return u.object({code:u.string(),callbackURL:u.string().optional(),currentURL:u.string().optional(),dontRememberMe:u.boolean().optional()}).safeParse(JSON.parse(e))}export{q as HIDE_METADATA,re as capitalizeFirstLetter,m as clone,D as createCookieGetter,w as createLogger,V as deleteSessionCookie,K as generateId,ue as generateState,P as getBaseURL,I as getCookies,M as getDate,X as getIp,Z as logger,oe as merge,j as parseSetCookieHeader,fe as parseState,H as setSessionCookie,R as shimContext,U as shimEndpoint,ie as validatePassword};
1
+ // src/utils/shim.ts
2
+ var shimContext = (originalObject, newContext) => {
3
+ const shimmedObj = {};
4
+ for (const [key, value] of Object.entries(originalObject)) {
5
+ shimmedObj[key] = (ctx) => {
6
+ return value({
7
+ ...ctx,
8
+ context: {
9
+ ...newContext,
10
+ ...ctx.context
11
+ }
12
+ });
13
+ };
14
+ shimmedObj[key].path = value.path;
15
+ shimmedObj[key].method = value.method;
16
+ shimmedObj[key].options = value.options;
17
+ shimmedObj[key].headers = value.headers;
18
+ }
19
+ return shimmedObj;
20
+ };
21
+ var shimEndpoint = (ctx, value) => {
22
+ return async (context) => {
23
+ for (const plugin of ctx.options.plugins || []) {
24
+ if (plugin.hooks?.before) {
25
+ for (const hook of plugin.hooks.before) {
26
+ const match = hook.matcher({
27
+ ...context,
28
+ ...value
29
+ });
30
+ if (match) {
31
+ const hookRes = await hook.handler(context);
32
+ if (hookRes && "context" in hookRes) {
33
+ context = {
34
+ ...context,
35
+ ...hookRes.context,
36
+ ...value
37
+ };
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ const endpointRes = value({
44
+ ...context,
45
+ context: {
46
+ ...ctx,
47
+ ...context.context
48
+ }
49
+ });
50
+ let response = endpointRes;
51
+ for (const plugin of ctx.options.plugins || []) {
52
+ if (plugin.hooks?.after) {
53
+ for (const hook of plugin.hooks.after) {
54
+ const match = hook.matcher(context);
55
+ if (match) {
56
+ const obj = Object.assign(context, {
57
+ returned: endpointRes
58
+ });
59
+ const hookRes = await hook.handler(obj);
60
+ if (hookRes && "response" in hookRes) {
61
+ response = hookRes.response;
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ return response;
68
+ };
69
+ };
70
+
71
+ // src/error/better-auth-error.ts
72
+ var BetterAuthError = class extends Error {
73
+ constructor(message, cause, docsLink) {
74
+ super(message);
75
+ this.name = "BetterAuthError";
76
+ this.message = message;
77
+ this.cause = cause;
78
+ this.stack = "";
79
+ }
80
+ };
81
+
82
+ // src/utils/base-url.ts
83
+ function checkHasPath(url) {
84
+ try {
85
+ const parsedUrl = new URL(url);
86
+ return parsedUrl.pathname !== "/";
87
+ } catch (error) {
88
+ throw new BetterAuthError(
89
+ `Invalid base URL: ${url}. Please provide a valid base URL.`
90
+ );
91
+ }
92
+ }
93
+ function withPath(url, path = "/api/auth") {
94
+ const hasPath = checkHasPath(url);
95
+ if (hasPath) {
96
+ return url;
97
+ }
98
+ path = path.startsWith("/") ? path : `/${path}`;
99
+ return `${url}${path}`;
100
+ }
101
+ function getBaseURL(url, path) {
102
+ if (url) {
103
+ return withPath(url, path);
104
+ }
105
+ const env = process?.env || {};
106
+ const fromEnv = env.BETTER_AUTH_URL || env.NEXT_PUBLIC_BETTER_AUTH_URL || env.PUBLIC_BETTER_AUTH_URL || env.NUXT_PUBLIC_BETTER_AUTH_URL || env.NUXT_PUBLIC_AUTH_URL || (env.BASE_URL !== "/" ? env.BASE_URL : void 0);
107
+ if (fromEnv) {
108
+ return withPath(fromEnv, path);
109
+ }
110
+ if (typeof window !== "undefined") {
111
+ return withPath(window.location.origin, path);
112
+ }
113
+ return void 0;
114
+ }
115
+
116
+ // src/utils/clone.ts
117
+ var cloneBase = (object, base) => {
118
+ for (const key in object) {
119
+ if (!object.hasOwnProperty(key)) continue;
120
+ const value = object[key];
121
+ if (typeof value === "object" && value !== null) {
122
+ base[key] = cloneBase(value, value.constructor());
123
+ } else {
124
+ base[key] = value;
125
+ }
126
+ }
127
+ return base;
128
+ };
129
+ var clone = (object) => {
130
+ return cloneBase(object, object.constructor());
131
+ };
132
+
133
+ // src/utils/cookies.ts
134
+ import { TimeSpan } from "oslo";
135
+ function getCookies(options) {
136
+ const secure = !!options.advanced?.useSecureCookies || process.env.NODE_ENV !== "development" && process.env.NODE_ENV !== "test";
137
+ const secureCookiePrefix = secure ? "__Secure-" : "";
138
+ const cookiePrefix = "better-auth";
139
+ const sessionMaxAge = new TimeSpan(7, "d").seconds();
140
+ return {
141
+ sessionToken: {
142
+ name: `${secureCookiePrefix}${cookiePrefix}.session_token`,
143
+ options: {
144
+ httpOnly: true,
145
+ sameSite: "lax",
146
+ path: "/",
147
+ secure: !!secureCookiePrefix,
148
+ maxAge: sessionMaxAge
149
+ }
150
+ },
151
+ csrfToken: {
152
+ name: `${secureCookiePrefix ? "__Host-" : ""}${cookiePrefix}.csrf_token`,
153
+ options: {
154
+ httpOnly: true,
155
+ sameSite: "lax",
156
+ path: "/",
157
+ secure: !!secureCookiePrefix,
158
+ maxAge: 60 * 60 * 24 * 7
159
+ }
160
+ },
161
+ state: {
162
+ name: `${secureCookiePrefix}${cookiePrefix}.state`,
163
+ options: {
164
+ httpOnly: true,
165
+ sameSite: "lax",
166
+ path: "/",
167
+ secure: !!secureCookiePrefix,
168
+ maxAge: 60 * 15
169
+ // 15 minutes in seconds
170
+ }
171
+ },
172
+ pkCodeVerifier: {
173
+ name: `${secureCookiePrefix}${cookiePrefix}.pk_code_verifier`,
174
+ options: {
175
+ httpOnly: true,
176
+ sameSite: "lax",
177
+ path: "/",
178
+ secure: !!secureCookiePrefix,
179
+ maxAge: 60 * 15
180
+ // 15 minutes in seconds
181
+ }
182
+ },
183
+ dontRememberToken: {
184
+ name: `${secureCookiePrefix}${cookiePrefix}.dont_remember`,
185
+ options: {
186
+ httpOnly: true,
187
+ sameSite: "lax",
188
+ path: "/",
189
+ secure: !!secureCookiePrefix
190
+ //no max age so it expires when the browser closes
191
+ }
192
+ },
193
+ nonce: {
194
+ name: `${secureCookiePrefix}${cookiePrefix}.nonce`,
195
+ options: {
196
+ httpOnly: true,
197
+ sameSite: "lax",
198
+ path: "/",
199
+ secure: !!secureCookiePrefix,
200
+ maxAge: 60 * 15
201
+ // 15 minutes in seconds
202
+ }
203
+ }
204
+ };
205
+ }
206
+ function createCookieGetter(options) {
207
+ const secure = !!options.advanced?.useSecureCookies || process.env.NODE_ENV === "production";
208
+ const secureCookiePrefix = secure ? "__Secure-" : "";
209
+ const cookiePrefix = "better-auth";
210
+ function getCookie(cookieName, options2) {
211
+ return {
212
+ name: process.env.NODE_ENV === "production" ? `${secureCookiePrefix}${cookiePrefix}.${cookieName}` : `${cookiePrefix}.${cookieName}`,
213
+ options: {
214
+ secure: !!secureCookiePrefix,
215
+ sameSite: "lax",
216
+ path: "/",
217
+ maxAge: 60 * 15,
218
+ // 15 minutes in seconds
219
+ ...options2
220
+ }
221
+ };
222
+ }
223
+ return getCookie;
224
+ }
225
+ async function setSessionCookie(ctx, sessionToken, dontRememberMe, overrides) {
226
+ const options = ctx.context.authCookies.sessionToken.options;
227
+ options.maxAge = dontRememberMe ? void 0 : options.maxAge;
228
+ await ctx.setSignedCookie(
229
+ ctx.context.authCookies.sessionToken.name,
230
+ sessionToken,
231
+ ctx.context.secret,
232
+ options
233
+ );
234
+ if (dontRememberMe) {
235
+ await ctx.setSignedCookie(
236
+ ctx.context.authCookies.dontRememberToken.name,
237
+ "true",
238
+ ctx.context.secret,
239
+ ctx.context.authCookies.dontRememberToken.options
240
+ );
241
+ }
242
+ }
243
+ function deleteSessionCookie(ctx) {
244
+ ctx.setCookie(ctx.context.authCookies.sessionToken.name, "", {
245
+ maxAge: 0
246
+ });
247
+ ctx.setCookie(ctx.context.authCookies.dontRememberToken.name, "", {
248
+ maxAge: 0
249
+ });
250
+ }
251
+ function parseSetCookieHeader(header) {
252
+ const cookieMap = /* @__PURE__ */ new Map();
253
+ const cookies = header.split(", ");
254
+ cookies.forEach((cookie) => {
255
+ const [nameValue, ...attributes] = cookie.split("; ");
256
+ const [name, value] = nameValue.split("=");
257
+ const cookieObj = { value };
258
+ attributes.forEach((attr) => {
259
+ const [attrName, attrValue] = attr.split("=");
260
+ cookieObj[attrName.toLowerCase()] = attrValue || true;
261
+ });
262
+ cookieMap.set(name, cookieObj);
263
+ });
264
+ return cookieMap;
265
+ }
266
+
267
+ // src/utils/date.ts
268
+ var getDate = (span, isSeconds = false) => {
269
+ const date = /* @__PURE__ */ new Date();
270
+ return new Date(date.getTime() + (isSeconds ? span * 1e3 : span));
271
+ };
272
+
273
+ // src/utils/get-request-ip.ts
274
+ function getIp(req) {
275
+ const testIP = "127.0.0.1";
276
+ if (process.env.NODE_ENV === "test") {
277
+ return testIP;
278
+ }
279
+ const headers = [
280
+ "x-client-ip",
281
+ "x-forwarded-for",
282
+ "cf-connecting-ip",
283
+ "fastly-client-ip",
284
+ "x-real-ip",
285
+ "x-cluster-client-ip",
286
+ "x-forwarded",
287
+ "forwarded-for",
288
+ "forwarded"
289
+ ];
290
+ for (const header of headers) {
291
+ const value = req.headers.get(header);
292
+ if (typeof value === "string") {
293
+ const ip = value.split(",")[0].trim();
294
+ if (ip) return ip;
295
+ }
296
+ }
297
+ return null;
298
+ }
299
+
300
+ // src/utils/hide-metadata.ts
301
+ var HIDE_METADATA = {
302
+ isAction: false
303
+ };
304
+
305
+ // src/utils/id.ts
306
+ import { alphabet, generateRandomString } from "oslo/crypto";
307
+ var generateId = () => {
308
+ return generateRandomString(36, alphabet("a-z", "0-9"));
309
+ };
310
+
311
+ // src/utils/logger.ts
312
+ import { createConsola } from "consola";
313
+ var consola = createConsola({
314
+ formatOptions: {
315
+ date: false,
316
+ colors: true,
317
+ compact: true
318
+ },
319
+ defaults: {
320
+ tag: "Better Auth"
321
+ }
322
+ });
323
+ var createLogger = (options) => {
324
+ return {
325
+ log: (...args) => {
326
+ !options?.disabled && consola.log("", ...args);
327
+ },
328
+ error: (...args) => {
329
+ !options?.disabled && consola.error("", ...args);
330
+ },
331
+ warn: (...args) => {
332
+ !options?.disabled && consola.warn("", ...args);
333
+ },
334
+ info: (...args) => {
335
+ !options?.disabled && consola.info("", ...args);
336
+ },
337
+ debug: (...args) => {
338
+ !options?.disabled && consola.debug("", ...args);
339
+ },
340
+ box: (...args) => {
341
+ !options?.disabled && consola.box("", ...args);
342
+ },
343
+ success: (...args) => {
344
+ !options?.disabled && consola.success("", ...args);
345
+ },
346
+ break: (...args) => {
347
+ !options?.disabled && console.log("\n");
348
+ }
349
+ };
350
+ };
351
+ var logger = createLogger();
352
+
353
+ // src/utils/merger.ts
354
+ var mergeObjects = (target, source) => {
355
+ for (const key in source) {
356
+ if (!source.hasOwnProperty(key)) continue;
357
+ if (key === "constructor" || key === "prototype" || key === "__proto__")
358
+ continue;
359
+ const value = source[key];
360
+ if (isPrimitive(value)) {
361
+ if (value !== void 0 || !(key in target)) {
362
+ target[key] = value;
363
+ }
364
+ } else if (!target[key] || isArray(value)) {
365
+ target[key] = clone(value);
366
+ } else {
367
+ target[key] = mergeObjects(target[key], value);
368
+ }
369
+ }
370
+ return target;
371
+ };
372
+ var isArray = (value) => {
373
+ return Array.isArray(value);
374
+ };
375
+ var isPrimitive = (value) => {
376
+ if (value === null) return true;
377
+ const type = typeof value;
378
+ return type !== "object" && type !== "function";
379
+ };
380
+ var merge = (objects) => {
381
+ const target = clone(objects[0]);
382
+ for (let i = 1, l = objects.length; i < l; i++) {
383
+ mergeObjects(target, objects[i]);
384
+ }
385
+ return target;
386
+ };
387
+
388
+ // src/utils/misc.ts
389
+ function capitalizeFirstLetter(str) {
390
+ return str.charAt(0).toUpperCase() + str.slice(1);
391
+ }
392
+
393
+ // src/utils/password.ts
394
+ async function validatePassword(ctx, data) {
395
+ const accounts = await ctx.context.internalAdapter.findAccounts(data.userId);
396
+ const credentialAccount = accounts?.find(
397
+ (account) => account.providerId === "credential"
398
+ );
399
+ const currentPassword = credentialAccount?.password;
400
+ if (!credentialAccount || !currentPassword) {
401
+ return false;
402
+ }
403
+ const compare = await ctx.context.password.verify(
404
+ currentPassword,
405
+ data.password
406
+ );
407
+ return compare;
408
+ }
409
+
410
+ // src/utils/state.ts
411
+ import { generateState as generateStateOAuth } from "oslo/oauth2";
412
+ import { z } from "zod";
413
+ function generateState(callbackURL, currentURL, dontRememberMe) {
414
+ const code = generateStateOAuth();
415
+ const state = JSON.stringify({
416
+ code,
417
+ callbackURL,
418
+ currentURL,
419
+ dontRememberMe
420
+ });
421
+ return { state, code };
422
+ }
423
+ function parseState(state) {
424
+ const data = z.object({
425
+ code: z.string(),
426
+ callbackURL: z.string().optional(),
427
+ currentURL: z.string().optional(),
428
+ dontRememberMe: z.boolean().optional()
429
+ }).safeParse(JSON.parse(state));
430
+ return data;
431
+ }
432
+ export {
433
+ HIDE_METADATA,
434
+ capitalizeFirstLetter,
435
+ clone,
436
+ createCookieGetter,
437
+ createLogger,
438
+ deleteSessionCookie,
439
+ generateId,
440
+ generateState,
441
+ getBaseURL,
442
+ getCookies,
443
+ getDate,
444
+ getIp,
445
+ logger,
446
+ merge,
447
+ parseSetCookieHeader,
448
+ parseState,
449
+ setSessionCookie,
450
+ shimContext,
451
+ shimEndpoint,
452
+ validatePassword
453
+ };