better-auth 0.0.2-beta.7 → 0.0.2

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 (96) hide show
  1. package/dist/access.d.ts +4 -0
  2. package/dist/access.js +126 -0
  3. package/dist/access.js.map +1 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +553 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/client/plugins.d.ts +2436 -0
  8. package/dist/client/plugins.js +411 -0
  9. package/dist/client/plugins.js.map +1 -0
  10. package/dist/client-A2Mt04KQ.d.ts +3503 -0
  11. package/dist/client.d.ts +1433 -0
  12. package/dist/client.js +693 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/helper-B5_2Vzba.d.ts +14 -0
  15. package/dist/index-Dg4eEXZW.d.ts +24 -0
  16. package/dist/index-W5nXvJ-p.d.ts +1498 -0
  17. package/dist/index.d.ts +6 -4
  18. package/dist/index.js +2195 -1191
  19. package/dist/index.js.map +1 -1
  20. package/dist/next-js.d.ts +14 -0
  21. package/dist/next-js.js +14 -0
  22. package/dist/next-js.js.map +1 -0
  23. package/dist/plugins.d.ts +892 -49
  24. package/dist/plugins.js +3951 -253
  25. package/dist/plugins.js.map +1 -1
  26. package/dist/preact.d.ts +8 -0
  27. package/dist/preact.js +294 -0
  28. package/dist/preact.js.map +1 -0
  29. package/dist/react.d.ts +14 -0
  30. package/dist/react.js +314 -0
  31. package/dist/react.js.map +1 -0
  32. package/dist/schema-BOszzrbQ.d.ts +792 -0
  33. package/dist/social.d.ts +4 -0
  34. package/dist/social.js +509 -0
  35. package/dist/social.js.map +1 -0
  36. package/dist/solid-start.d.ts +18 -0
  37. package/dist/solid-start.js +14 -0
  38. package/dist/solid-start.js.map +1 -0
  39. package/dist/solid.d.ts +2790 -0
  40. package/dist/solid.js +306 -0
  41. package/dist/solid.js.map +1 -0
  42. package/dist/statement-COylZd3J.d.ts +81 -0
  43. package/dist/svelte-kit.d.ts +10 -7
  44. package/dist/svelte-kit.js +12 -17
  45. package/dist/svelte-kit.js.map +1 -1
  46. package/dist/svelte.d.ts +2791 -0
  47. package/dist/svelte.js +304 -0
  48. package/dist/svelte.js.map +1 -0
  49. package/dist/type-DbMyI3b5.d.ts +5724 -0
  50. package/dist/types.d.ts +7 -0
  51. package/dist/types.js +1 -0
  52. package/dist/types.js.map +1 -0
  53. package/dist/vue.d.ts +14 -0
  54. package/dist/vue.js +311 -0
  55. package/dist/vue.js.map +1 -0
  56. package/package.json +80 -54
  57. package/LICENSE +0 -21
  58. package/dist/actions.d.ts +0 -33
  59. package/dist/actions.js +0 -1373
  60. package/dist/actions.js.map +0 -1
  61. package/dist/adapters/drizzle-adapter.d.ts +0 -10
  62. package/dist/adapters/drizzle-adapter.js +0 -1095
  63. package/dist/adapters/drizzle-adapter.js.map +0 -1
  64. package/dist/adapters/memory.d.ts +0 -8
  65. package/dist/adapters/memory.js +0 -136
  66. package/dist/adapters/memory.js.map +0 -1
  67. package/dist/adapters/mongodb-adapter.d.ts +0 -9
  68. package/dist/adapters/mongodb-adapter.js +0 -97
  69. package/dist/adapters/mongodb-adapter.js.map +0 -1
  70. package/dist/adapters/prisma-adapter.d.ts +0 -7
  71. package/dist/adapters/prisma-adapter.js +0 -144
  72. package/dist/adapters/prisma-adapter.js.map +0 -1
  73. package/dist/adapters/redis-adapter.d.ts +0 -7
  74. package/dist/adapters/redis-adapter.js +0 -65
  75. package/dist/adapters/redis-adapter.js.map +0 -1
  76. package/dist/adapters.d.ts +0 -3
  77. package/dist/adapters.js +0 -206
  78. package/dist/adapters.js.map +0 -1
  79. package/dist/h3.d.ts +0 -10
  80. package/dist/h3.js +0 -326
  81. package/dist/h3.js.map +0 -1
  82. package/dist/hono.d.ts +0 -10
  83. package/dist/hono.js +0 -25
  84. package/dist/hono.js.map +0 -1
  85. package/dist/index-UcTu1vUg.d.ts +0 -107
  86. package/dist/next.d.ts +0 -17
  87. package/dist/next.js +0 -26
  88. package/dist/next.js.map +0 -1
  89. package/dist/options-CH15FEBw.d.ts +0 -1562
  90. package/dist/providers.d.ts +0 -3
  91. package/dist/providers.js +0 -653
  92. package/dist/providers.js.map +0 -1
  93. package/dist/routes/session.d.ts +0 -39
  94. package/dist/routes/session.js +0 -128
  95. package/dist/routes/session.js.map +0 -1
  96. package/dist/types-DAxaMWCy.d.ts +0 -136
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/jwt/index.ts","../src/providers/google.ts","../src/providers/github.ts","../../shared/src/error.ts","../src/providers/credential.ts","../src/crypto/password.ts","../src/crypto/random.ts","../src/cookies/index.ts","../src/utils/session.ts","../src/providers/facebook.ts","../src/providers/apple.ts","../src/providers/gitlab.ts","../src/providers/spotify.ts","../src/providers/twitch.ts","../src/providers/discord.ts","../src/providers/magic-link.ts"],"sourcesContent":["import { type JWTPayload, SignJWT, decodeJwt, jwtVerify } from \"jose\";\n\nexport function parseJWT<T>(jwt: string) {\n\tconst decoded = decodeJwt(jwt) as T & JWTPayload;\n\treturn decoded;\n}\n\nexport function validateJWT(jwt: string, secret: string) {\n\treturn jwtVerify(jwt, new TextEncoder().encode(secret));\n}\n\nexport function createJWT({\n\tpayload,\n\tsecret,\n\texpiresIn,\n\talgorithm,\n}: {\n\tpayload: Record<string, any>;\n\tsecret: string;\n\texpiresIn: number;\n\talgorithm?: string;\n}) {\n\treturn new SignJWT(payload)\n\t\t.setProtectedHeader({\n\t\t\talg: algorithm || \"HS256\",\n\t\t})\n\t\t.setExpirationTime(Math.floor(Date.now() / 1000) + expiresIn)\n\t\t.sign(new TextEncoder().encode(secret));\n}\n","import { parseJWT } from \"../jwt\";\nimport type { Provider, ProviderOptions } from \"./types\";\n\nexport interface GoogleProfile {\n\taud: string;\n\tazp: string;\n\temail: string;\n\temail_verified: boolean;\n\texp: number;\n\t/**\n\t * The family name of the user, or last name in most\n\t * Western languages.\n\t */\n\tfamily_name: string;\n\t/**\n\t * The given name of the user, or first name in most\n\t * Western languages.\n\t */\n\tgiven_name: string;\n\thd?: string;\n\tiat: number;\n\tiss: string;\n\tjti?: string;\n\tlocale?: string;\n\tname: string;\n\tnbf?: number;\n\tpicture: string;\n\tsub: string;\n}\n\ninterface GoogleOptions extends ProviderOptions<GoogleProfile> {}\n\nexport const google = (options: GoogleOptions) => {\n\treturn {\n\t\tid: \"google\" as const,\n\t\tname: \"Google\",\n\t\ttype: \"oidc\",\n\t\tnonce: true,\n\t\tparams: {\n\t\t\tclientId: options.clientId,\n\t\t\tclientSecret: options.clientSecret,\n\t\t\tlinkAccounts: options.linkAccounts,\n\t\t\tredirectURL: options.redirectURL,\n\t\t\ttokenEndpoint: \"https://oauth2.googleapis.com/token\",\n\t\t\tauthorizationEndpoint: \"https://accounts.google.com/o/oauth2/v2/auth\",\n\t\t},\n\t\tissuer: \"https://accounts.google.com\",\n\t\tscopes: options.scopes || [\"openid\", \"email\", \"profile\"],\n\t\tpkCodeVerifier: true,\n\t\tasync getUserInfo(tokens) {\n\t\t\tconst idToken = tokens?.id_token;\n\t\t\tconst user = parseJWT(idToken as string) as GoogleProfile;\n\t\t\tconst profile = {\n\t\t\t\t...user,\n\t\t\t\tid: user.sub,\n\t\t\t};\n\t\t\treturn profile;\n\t\t},\n\t} satisfies Provider<GoogleProfile>;\n};\n","import type { User } from \"../adapters/types\";\nimport type { OAuthProvider, Provider, ProviderOptions } from \"./types\";\n\ninterface GithubProfile {\n\tlogin: string;\n\tid: string;\n\tnode_id: string;\n\tavatar_url: string;\n\tgravatar_id: string;\n\turl: string;\n\thtml_url: string;\n\tfollowers_url: string;\n\tfollowing_url: string;\n\tgists_url: string;\n\tstarred_url: string;\n\tsubscriptions_url: string;\n\torganizations_url: string;\n\trepos_url: string;\n\tevents_url: string;\n\treceived_events_url: string;\n\ttype: string;\n\tsite_admin: boolean;\n\tname: string;\n\tcompany: string;\n\tblog: string;\n\tlocation: string;\n\temail: string;\n\thireable: boolean;\n\tbio: string;\n\ttwitter_username: string;\n\tpublic_repos: string;\n\tpublic_gists: string;\n\tfollowers: string;\n\tfollowing: string;\n\tcreated_at: string;\n\tupdated_at: string;\n\tprivate_gists: string;\n\ttotal_private_repos: string;\n\towned_private_repos: string;\n\tdisk_usage: string;\n\tcollaborators: string;\n\ttwo_factor_authentication: boolean;\n\tplan: {\n\t\tname: string;\n\t\tspace: string;\n\t\tprivate_repos: string;\n\t\tcollaborators: string;\n\t};\n\tfirst_name: string;\n\tlast_name: string;\n}\n\nexport interface GitHubOptions extends ProviderOptions<GithubProfile> {\n\t/**\n\t * Whether or not unauthenticated users will be offered\n\t * an option to sign up for GitHub during the OAuth flow\n\t * The default is true. Use false when a policy prohibits\n\t * signup.\n\t */\n\tallowSignup?: boolean;\n}\n\n/**\n * Github OAuth provider. This provider allows users to sign\n * in with their Github account.\n */\nexport const github = (options: GitHubOptions) => {\n\treturn {\n\t\tid: \"github\" as const,\n\t\tname: \"Github\",\n\t\ttype: \"oauth\",\n\t\tparams: {\n\t\t\tclientId: options.clientId,\n\t\t\tclientSecret: options.clientSecret,\n\t\t\tredirectURL: options.redirectURL,\n\t\t\tlinkAccounts: options.linkAccounts,\n\t\t\ttokenEndpoint: \"https://github.com/login/oauth/access_token\",\n\t\t\tauthorizationEndpoint: \"https://github.com/login/oauth/authorize\",\n\t\t\textra: {\n\t\t\t\tallow_signup:\n\t\t\t\t\toptions.allowSignup === undefined\n\t\t\t\t\t\t? \"true\"\n\t\t\t\t\t\t: options.allowSignup\n\t\t\t\t\t\t\t? \"true\"\n\t\t\t\t\t\t\t: \"false\",\n\t\t\t},\n\t\t},\n\t\tscopes: options.scopes || [\"read:user user:email\"],\n\t\tasync getUserInfo(tokens) {\n\t\t\tconst response = await fetch(\"https://api.github.com/user\", {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${tokens.access_token}`,\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst profile = (await response.json()) as GithubProfile;\n\t\t\tif (!profile.email) {\n\t\t\t\tconst res = await fetch(\"https://api.github.com/user/emails\", {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${tokens.access_token}`,\n\t\t\t\t\t\t\"User-Agent\": \"better-auth\",\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tif (res.ok) {\n\t\t\t\t\tconst emails: {\n\t\t\t\t\t\temail: string;\n\t\t\t\t\t\tprimary: boolean;\n\t\t\t\t\t\tverified: boolean;\n\t\t\t\t\t\tvisibility: \"public\" | \"private\";\n\t\t\t\t\t}[] = await res.json();\n\t\t\t\t\tprofile.email = (emails.find((e) => e.primary) ?? emails[0])\n\t\t\t\t\t\t?.email as string;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...profile,\n\t\t\t\tid: profile.id,\n\t\t\t\tfirst_name: profile.name.split(\" \")[0] || \"\",\n\t\t\t\tlast_name: profile.name.split(\" \")[1] || \"\",\n\t\t\t};\n\t\t},\n\t} satisfies Provider<GithubProfile>;\n};\n","export type BetterAuthErrorResponse = {\n\tmessage: string;\n\tdetails: string;\n\tcode: number;\n};\n\nexport class BetterAuthError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(`${message}`);\n\t\tthis.name = this.constructor.name;\n\t\tObject.setPrototypeOf(this, new.target.prototype);\n\t\tError.captureStackTrace(this, this.constructor);\n\t}\n}\n\nexport class MissingSecret extends BetterAuthError {\n\tconstructor() {\n\t\tsuper(\"Missing Secret: A secret is required in a production environment.\");\n\t}\n}\n\nexport class InvalidURL extends BetterAuthError {\n\tconstructor(message?: string) {\n\t\tsuper(\n\t\t\tmessage ||\n\t\t\t\t\"Please make sure your config includes valid base URL and base PATH.\",\n\t\t);\n\t}\n}\n\nexport class InvalidRequest extends BetterAuthError {\n\tconstructor() {\n\t\tsuper(\"Post requests must include a valid JSON parsable body.\");\n\t}\n}\n\nexport class ProviderMissing extends BetterAuthError {\n\tconstructor(id: string) {\n\t\tsuper(`Provider ${id} is missing on your configuration.`);\n\t}\n}\n\nexport class ProviderError extends BetterAuthError {}\n\nexport class CallbackError extends BetterAuthError {}\n\nexport class BaseURLMissing extends BetterAuthError {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"base url is required. Please provide a base url in your config or pass it as an environment variable.\",\n\t\t);\n\t}\n}\n","import { BetterAuthError } from \"@better-auth/shared/error\";\nimport { z } from \"zod\";\nimport type { User } from \"../adapters/types\";\nimport { setSessionCookie } from \"../cookies\";\nimport { hashPassword, validatePassword } from \"../crypto/password\";\nimport { createSession } from \"../utils/session\";\nimport type { Provider } from \"./types\";\n\ntype CredentialOption = {};\n\n/**\n * Credential provider for better auth.\n * Note: Credential provider only works on node environment.\n * It uses argon2 for hashing the password.\n */\nexport const credential = <O extends CredentialOption>(options?: O) => {\n\tconst input = z.object({\n\t\temail: z.string(),\n\t\tpassword: z.string(),\n\t});\n\treturn {\n\t\tid: \"credential\" as const,\n\t\tname: \"Credential\",\n\t\ttype: \"custom\",\n\t\tasync signIn(context) {\n\t\t\tconst {\n\t\t\t\tdata: { email, password },\n\t\t\t\tcurrentURL,\n\t\t\t\tcallbackURL,\n\t\t\t} = z\n\t\t\t\t.object({\n\t\t\t\t\tdata: z.object({\n\t\t\t\t\t\temail: z.string(),\n\t\t\t\t\t\tpassword: z.string(),\n\t\t\t\t\t}),\n\t\t\t\t\tcurrentURL: z.string(),\n\t\t\t\t\tcallbackURL: z.string(),\n\t\t\t\t})\n\t\t\t\t.parse(context.request.body);\n\n\t\t\tconst user = await context._db.findOne<\n\t\t\t\tUser & { [key in string]: string }\n\t\t\t>({\n\t\t\t\tmodel: context.user.modelName || \"user\",\n\t\t\t\twhere: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield: \"email\",\n\t\t\t\t\t\tvalue: email,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t});\n\t\t\tif (!user) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 401,\n\t\t\t\t\tbody: {\n\t\t\t\t\t\terror: \"user_not_found\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst passwordHash = user[\"password\"];\n\t\t\tif (!passwordHash) {\n\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\"Password field is missing in the user table.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst isValid = await validatePassword(\n\t\t\t\t\tpassword,\n\t\t\t\t\tpasswordHash,\n\t\t\t\t\tcontext.secret,\n\t\t\t\t);\n\t\t\t\tif (!isValid) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\terror: \"invalid_password\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 401,\n\t\t\t\t\tbody: {\n\t\t\t\t\t\terror: \"invalid_password\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tawait createSession(user.id, context);\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: {\n\t\t\t\t\tredirect: true,\n\t\t\t\t\turl: callbackURL,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tasync signUp(context) {\n\t\t\tconst { data, autoCreateSession, currentURL, callbackURL } =\n\t\t\t\tcontext.request.body;\n\t\t\tif (!data) {\n\t\t\t\tthrow new BetterAuthError(\"Data is required for sign up.\");\n\t\t\t}\n\n\t\t\tconst userExist = await context.adapter.findUserByEmail(\n\t\t\t\tdata[\"email\"],\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tif (userExist) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t\tbody: {\n\t\t\t\t\t\terror: \"user_already_exist\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst user = await context.adapter.createUser(\n\t\t\t\t{\n\t\t\t\t\tuser: {\n\t\t\t\t\t\t...data,\n\t\t\t\t\t\t[\"password\"]: await hashPassword(data[\"password\"], context.secret),\n\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t},\n\t\t\t\t\taccount: {\n\t\t\t\t\t\tproviderId: \"credential\",\n\t\t\t\t\t\taccountId: data[\"email\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcontext,\n\t\t\t);\n\n\t\t\tif (autoCreateSession) {\n\t\t\t\tawait createSession(user.user.id, context);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: {\n\t\t\t\t\tredirect: true,\n\t\t\t\t\turl: callbackURL,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tinput,\n\t} satisfies Provider;\n};\n","import * as argon2 from \"argon2\";\nimport { generateRandomString } from \"./random\";\n\nexport const hashPassword = async (password: string, secret: string) => {\n\tconst salt = generateRandomString(12);\n\tconst hash = await argon2.hash(password, {\n\t\ttype: argon2.argon2id,\n\t\tsalt: Buffer.from(salt),\n\t\tsecret: Buffer.from(secret),\n\t});\n\treturn hash;\n};\n\nexport const validatePassword = async (\n\tpassword: string,\n\thash: string,\n\tsecret: string,\n) => {\n\tconst res = await argon2.verify(hash, password, {\n\t\tsecret: Buffer.from(secret),\n\t});\n\treturn res;\n};\n","export function generateRandomString(size: number) {\n\tconst i2hex = (i: number) => `0${i.toString(16)}`.slice(-2);\n\tconst r = (a: string, i: number): string => a + i2hex(i);\n\tconst bytes = crypto.getRandomValues(new Uint8Array(size));\n\treturn Array.from(bytes).reduce(r, \"\");\n}\n","import type { Context } from \"../routes/types\";\nimport type { CookieSerializeOptions } from \"./types\";\n\nexport function serialize(\n\tname: string,\n\tvalue: string,\n\tattributes: CookieSerializeOptions,\n) {\n\tconst keyValueEntries: Array<[string, string] | [string]> = [];\n\tkeyValueEntries.push([encodeURIComponent(name), encodeURIComponent(value)]);\n\tif (attributes?.domain !== undefined) {\n\t\tkeyValueEntries.push([\"Domain\", attributes.domain]);\n\t}\n\tif (attributes?.expires !== undefined) {\n\t\tkeyValueEntries.push([\"Expires\", attributes.expires.toUTCString()]);\n\t}\n\tif (attributes?.httpOnly) {\n\t\tkeyValueEntries.push([\"HttpOnly\"]);\n\t}\n\tif (attributes?.maxAge !== undefined) {\n\t\tkeyValueEntries.push([\"Max-Age\", attributes.maxAge.toString()]);\n\t}\n\tif (attributes?.path !== undefined) {\n\t\tkeyValueEntries.push([\"Path\", attributes.path]);\n\t}\n\tif (attributes?.sameSite === \"lax\") {\n\t\tkeyValueEntries.push([\"SameSite\", \"Lax\"]);\n\t}\n\tif (attributes?.sameSite === \"none\") {\n\t\tkeyValueEntries.push([\"SameSite\", \"None\"]);\n\t}\n\tif (attributes?.sameSite === \"strict\") {\n\t\tkeyValueEntries.push([\"SameSite\", \"Strict\"]);\n\t}\n\tif (attributes?.secure) {\n\t\tkeyValueEntries.push([\"Secure\"]);\n\t}\n\treturn keyValueEntries.map((pair) => pair.join(\"=\")).join(\"; \");\n}\n\nexport function parse(header: string): Map<string, string> {\n\tconst cookies = new Map<string, string>();\n\tconst items = header.split(\"; \");\n\tfor (const item of items) {\n\t\tconst pair = item.split(\"=\");\n\t\tconst rawKey = pair[0];\n\t\tconst rawValue = pair[1] ?? \"\";\n\t\tif (!rawKey) continue;\n\t\tcookies.set(decodeURIComponent(rawKey), decodeURIComponent(rawValue));\n\t}\n\treturn cookies;\n}\n\nexport const cookieManager = (header: Headers): CookieManager => {\n\treturn {\n\t\tset(name: string, value: string, options = {}) {\n\t\t\tconst cookieStr = serialize(name, value, options);\n\t\t\theader.append(\"set-cookie\", cookieStr);\n\t\t},\n\t\tget(name: string) {\n\t\t\tconst cookie = header.get(\"cookie\");\n\t\t\tif (!cookie) return null;\n\t\t\tconst cookies = parse(cookie);\n\t\t\tconst value = cookies.get(name);\n\t\t\treturn value;\n\t\t},\n\t};\n};\n\nexport type CookieManager = {\n\tset: (name: string, value: string, options?: CookieSerializeOptions) => void;\n\tget: (name: string) => string | null | undefined;\n};\n\nexport function setSessionCookie(context: Context, sessionId: string) {\n\tcontext.request.cookies.set(\n\t\tcontext.cookies.sessionToken.name,\n\t\tsessionId,\n\t\tcontext.cookies.sessionToken.options,\n\t);\n}\n\nexport function deleteSessionCooke(context: Context) {\n\tcontext.request.cookies.set(context.cookies.sessionToken.name, \"\", {\n\t\t...context.cookies.sessionToken.options,\n\t\tmaxAge: 0,\n\t});\n}\n","import { setSessionCookie } from \"../cookies\";\nimport type { Context } from \"../routes/types\";\n\nexport const createSession = async (userId: string, context: Context) => {\n\tconst session = await context.adapter.createSession(userId, context);\n\tsetSessionCookie(context, session.id);\n\treturn session;\n};\n","import type { User } from \"../adapters/types\";\nimport type { OAuthProvider, Provider, ProviderOptions } from \"./types\";\n\nexport interface FacebookProfile {\n\tid: string;\n\tname: string;\n\temail: string;\n\temail_verified: boolean;\n\tpicture: {\n\t\tdata: {\n\t\t\theight: number;\n\t\t\tis_silhouette: boolean;\n\t\t\turl: string;\n\t\t\twidth: number;\n\t\t};\n\t};\n}\n\nexport interface FacebookOptions extends ProviderOptions<FacebookProfile> {}\n\nexport const facebook = (options: FacebookOptions) => {\n\treturn {\n\t\tid: \"facebook\" as const,\n\t\tname: \"Facebook\",\n\t\ttype: \"oauth\",\n\t\tscopes: [\"email\", \"public_profile\"],\n\t\tparams: {\n\t\t\tclientId: options.clientId,\n\t\t\tclientSecret: options.clientSecret,\n\t\t\tredirectURL: options.redirectURL,\n\t\t\tauthorizationEndpoint: \"https://www.facebook.com/v16.0/dialog/oauth\",\n\t\t\ttokenEndpoint: \"https://graph.facebook.com/v16.0/oauth/access_token\",\n\t\t},\n\t\tasync getUserInfo(tokens) {\n\t\t\tconst result = await fetch(\n\t\t\t\t\"https://graph.facebook.com/v16.0/me?fields=id,name,email,picture\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${tokens.access_token}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t)\n\t\t\t\t.then((res) => res.json())\n\t\t\t\t.then((res) => res as FacebookProfile);\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tid: result.id,\n\t\t\t\tname: result.name,\n\t\t\t\temail: result.email,\n\t\t\t\temailVerified: true,\n\t\t\t};\n\t\t},\n\t} satisfies Provider<FacebookProfile>;\n};\n","import { parseJWT } from \"../jwt\";\nimport type { Provider, ProviderOptions } from \"./types\";\n\ninterface AppleProfile {\n\t/**\n\t * The subject registered claim identifies the principal that’s the subject\n\t * of the identity token. Because this token is for your app, the value is\n\t * the unique identifier for the user.\n\t */\n\tsub: string;\n\t/**\n\t * A String value representing the user's email address.\n\t * The email address is either the user's real email address or the proxy\n\t * address, depending on their status private email relay service.\n\t */\n\temail: string;\n\t/**\n\t * A string or Boolean value that indicates whether the service verifies\n\t * the email. The value can either be a string (\"true\" or \"false\") or a\n\t * Boolean (true or false). The system may not verify email addresses for\n\t * Sign in with Apple at Work & School users, and this claim is \"false\" or\n\t * false for those users.\n\t */\n\temail_verified: true | \"true\";\n\t/**\n\t * A string or Boolean value that indicates whether the email that the user\n\t * shares is the proxy address. The value can either be a string (\"true\" or\n\t * \"false\") or a Boolean (true or false).\n\t */\n\tis_private_email: boolean;\n\t/**\n\t * An Integer value that indicates whether the user appears to be a real\n\t * person. Use the value of this claim to mitigate fraud. The possible\n\t * values are: 0 (or Unsupported), 1 (or Unknown), 2 (or LikelyReal). For\n\t * more information, see ASUserDetectionStatus. This claim is present only\n\t * in iOS 14 and later, macOS 11 and later, watchOS 7 and later, tvOS 14\n\t * and later. The claim isn’t present or supported for web-based apps.\n\t */\n\treal_user_status: number;\n\t/**\n\t * The user’s full name in the format provided during the authorization\n\t * process.\n\t */\n\tname: string;\n}\n\ninterface AppleOption extends ProviderOptions<AppleProfile> {}\n\nexport const apple = (options: AppleOption) => {\n\tconst authorizationEndpoint = \"https://appleid.apple.com/auth/authorize\";\n\tconst tokenEndpoint = \"https://appleid.apple.com/auth/token\";\n\treturn {\n\t\tid: \"apple\" as const,\n\t\tname: \"Apple\",\n\t\ttype: \"oidc\",\n\t\tparams: {\n\t\t\tauthorizationEndpoint,\n\t\t\ttokenEndpoint,\n\t\t\tlinkAccounts: options.linkAccounts,\n\t\t\tredirectURL: options.redirectURL,\n\t\t\tclientId: options.clientId,\n\t\t\tclientSecret: options.clientSecret,\n\t\t},\n\t\tissuer: \"https://appleid.apple.com\",\n\t\tscopes: options.scopes || [\"email\", \"name\"],\n\t\tasync getUserInfo(tokens) {\n\t\t\tconst idToken = tokens?.id_token;\n\t\t\tconst user = parseJWT(idToken as string)?.payload as AppleProfile;\n\t\t\tconst profile = {\n\t\t\t\t...user,\n\t\t\t\tid: user.sub,\n\t\t\t\temail: user.email,\n\t\t\t\temailVerified: true,\n\t\t\t};\n\t\t\treturn profile;\n\t\t},\n\t} satisfies Provider<AppleProfile>;\n};\n","import type { Provider, ProviderOptions } from \"./types\";\n\nexport interface GitLabProfile {\n\t/**\n\t * the user's id (i.e. the numerical snowflake) as a string\n\t */\n\tid: string;\n\tusername: string;\n\temail: string;\n\tname: string;\n\tstate: string;\n\tavatar_url: string;\n\tweb_url: string;\n\tcreated_at: string;\n\tbio: string;\n\tlocation?: string;\n\tpublic_email: string;\n\tskype: string;\n\tlinkedin: string;\n\ttwitter: string;\n\twebsite_url: string;\n\torganization: string;\n\tjob_title: string;\n\tpronouns: string;\n\tbot: boolean;\n\twork_information?: string;\n\tfollowers: number;\n\tfollowing: number;\n\tlocal_time: string;\n\tlast_sign_in_at: string;\n\tconfirmed_at: string;\n\ttheme_id: number;\n\tlast_activity_on: string;\n\tcolor_scheme_id: number;\n\tprojects_limit: number;\n\tcurrent_sign_in_at: string;\n\tidentities: Array<{\n\t\tprovider: string;\n\t\textern_uid: string;\n\t}>;\n\tcan_create_group: boolean;\n\tcan_create_project: boolean;\n\ttwo_factor_enabled: boolean;\n\texternal: boolean;\n\tprivate_profile: boolean;\n\tcommit_email: string;\n\tshared_runners_minutes_limit: number;\n\textra_shared_runners_minutes_limit: number;\n}\n\ninterface GitlabOptions extends ProviderOptions<GitLabProfile> {\n\tdomain?: string;\n}\n\nexport const gitlab = (options: GitlabOptions) => {\n\tconst domain = options?.domain ?? \"https://gitlab.com\";\n\tconst authorizationEndpoint = `${domain}/oauth/authorize`;\n\tconst tokenEndpoint = `${domain}/oauth/token`;\n\treturn {\n\t\tid: \"gitlab\" as const,\n\t\tname: \"Gitlab\",\n\t\ttype: \"oauth\",\n\t\tscopes: [\"read_user\"],\n\t\tparams: {\n\t\t\tclientId: options.clientId,\n\t\t\tclientSecret: options.clientSecret,\n\t\t\tredirectURL: options.redirectURL,\n\t\t\tauthorizationEndpoint,\n\t\t\ttokenEndpoint,\n\t\t},\n\t\tasync getUserInfo(tokens) {\n\t\t\tconst headers = {\n\t\t\t\tAuthorization: `Bearer ${tokens.access_token}`,\n\t\t\t};\n\t\t\tconst result = await fetch(\"https://gitlab.com/api/v4/user\", {\n\t\t\t\theaders,\n\t\t\t})\n\t\t\t\t.then((res) => res.json())\n\t\t\t\t.then((res) => res as GitLabProfile);\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tid: result.id.toString(),\n\t\t\t\temail: result.public_email,\n\t\t\t\temailVerified: true,\n\t\t\t\timage: result.avatar_url,\n\t\t\t};\n\t\t},\n\t} satisfies Provider<GitLabProfile>;\n};\n","import type { Provider, ProviderOptions } from \"./types\";\n\ninterface SpotifyOptions extends ProviderOptions<SpotifyProfile> {}\n\ninterface SpotifyProfile {\n\tid: string;\n\tdisplay_name: string;\n\temail: string;\n\timages: {\n\t\turl: string;\n\t}[];\n}\n\nexport const spotify = (options: SpotifyOptions) => {\n\treturn {\n\t\tid: \"spotify\" as const,\n\t\tname: \"Spotify\",\n\t\ttype: \"oauth\",\n\t\tscopes: [\"user-read-email\"],\n\t\tparams: {\n\t\t\tclientId: options.clientId,\n\t\t\tclientSecret: options.clientSecret,\n\t\t\tredirectURL: options.redirectURL,\n\t\t\tauthorizationEndpoint: \"https://accounts.spotify.com/authorize\",\n\t\t\ttokenEndpoint: \"https://accounts.spotify.com/api/token\",\n\t\t},\n\t\tasync getUserInfo(tokens) {\n\t\t\tconst profile = await fetch(\"https://api.spotify.com/v1/me\", {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${tokens.access_token}`,\n\t\t\t\t},\n\t\t\t})\n\t\t\t\t.then((res) => res.json())\n\t\t\t\t.then((res) => res as SpotifyProfile);\n\t\t\treturn {\n\t\t\t\t...profile,\n\t\t\t\tid: profile.id,\n\t\t\t\temail: profile.email,\n\t\t\t\temailVerified: true,\n\t\t\t\tname: profile.display_name,\n\t\t\t\timage: profile.images[0]?.url,\n\t\t\t};\n\t\t},\n\t} satisfies Provider<SpotifyProfile>;\n};\n","import type { Provider, ProviderOptions } from \"./types\";\n\nexport interface TwitchProfile {\n\t/**\n\t * The sub of the user\n\t */\n\tsub: string;\n\t/**\n\t * The preferred username of the user\n\t */\n\tpreferred_username: string;\n\t/**\n\t * The email of the user\n\t */\n\temail: string;\n\t/**\n\t * The picture of the user\n\t */\n\tpicture: string;\n}\n\nexport interface TwitchOptions extends ProviderOptions<TwitchProfile> {}\n\nexport const Twitch = (options: TwitchOptions) => {\n\tconst authorizeEndpoint = \"https://id.twitch.tv/oauth2/authorize\";\n\tconst tokenEndpoint = \"https://id.twitch.tv/oauth2/token\";\n\treturn {\n\t\tid: \"twitch\" as const,\n\t\tname: \"Twitch\",\n\t\ttype: \"oauth\",\n\t\tscopes: options.scopes ?? [\"openid user:read:email\"],\n\t\tparams: {\n\t\t\tclientId: options.clientId,\n\t\t\tlinkAccounts: options.linkAccounts,\n\t\t\tclientSecret: options.clientSecret,\n\t\t\tredirectURL: options.redirectURL,\n\t\t\tauthorizationEndpoint: authorizeEndpoint,\n\t\t\ttokenEndpoint: tokenEndpoint,\n\t\t},\n\t\tasync getUserInfo(tokens) {\n\t\t\tconst headers = {\n\t\t\t\tAuthorization: `Bearer ${tokens.access_token}`,\n\t\t\t};\n\t\t\tconst result = await fetch(\"https://api.twitch.tv/helix/users\", {\n\t\t\t\theaders,\n\t\t\t})\n\t\t\t\t.then((res) => res.json())\n\t\t\t\t.then((res) => res.data[0] as TwitchProfile);\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tid: result.sub,\n\t\t\t\temail: result.email,\n\t\t\t\temailVerified: true,\n\t\t\t\tname: result.preferred_username,\n\t\t\t\timage: result.picture,\n\t\t\t};\n\t\t},\n\t} satisfies Provider<TwitchProfile>;\n};\n","import type { OAuthProvider, Provider, ProviderOptions } from \"./types\";\n\nexport interface DiscordProfile extends Record<string, any> {\n\t/** the user's id (i.e. the numerical snowflake) */\n\tid: string;\n\t/** the user's username, not unique across the platform */\n\tusername: string;\n\t/** the user's Discord-tag */\n\tdiscriminator: string;\n\t/** the user's display name, if it is set */\n\tglobal_name: string | null;\n\t/**\n\t * the user's avatar hash:\n\t * https://discord.com/developers/docs/reference#image-formatting\n\t */\n\tavatar: string | null;\n\t/** whether the user belongs to an OAuth2 application */\n\tbot?: boolean;\n\t/**\n\t * whether the user is an Official Discord System user (part of the urgent\n\t * message system)\n\t */\n\tsystem?: boolean;\n\t/** whether the user has two factor enabled on their account */\n\tmfa_enabled: boolean;\n\t/**\n\t * the user's banner hash:\n\t * https://discord.com/developers/docs/reference#image-formatting\n\t */\n\tbanner: string | null;\n\n\t/** the user's banner color encoded as an integer representation of hexadecimal color code */\n\taccent_color: number | null;\n\n\t/**\n\t * the user's chosen language option:\n\t * https://discord.com/developers/docs/reference#locales\n\t */\n\tlocale: string;\n\t/** whether the email on this account has been verified */\n\tverified: boolean;\n\t/** the user's email */\n\temail: string;\n\t/**\n\t * the flags on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-user-flags\n\t */\n\tflags: number;\n\t/**\n\t * the type of Nitro subscription on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-premium-types\n\t */\n\tpremium_type: number;\n\t/**\n\t * the public flags on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-user-flags\n\t */\n\tpublic_flags: number;\n\t/** undocumented field; corresponds to the user's custom nickname */\n\tdisplay_name: string | null;\n\t/**\n\t * undocumented field; corresponds to the Discord feature where you can e.g.\n\t * put your avatar inside of an ice cube\n\t */\n\tavatar_decoration: string | null;\n\t/**\n\t * undocumented field; corresponds to the premium feature where you can\n\t * select a custom banner color\n\t */\n\tbanner_color: string | null;\n\t/** undocumented field; the CDN URL of their profile picture */\n\timage_url: string;\n}\n\ninterface DiscordOptions extends ProviderOptions<DiscordProfile> {}\n\nexport const discord = (options: DiscordOptions) => {\n\tconst authorizeEndpoint = \"https://discord.com/oauth2/authorize\";\n\tconst tokenEndpoint = \"https://discord.com/api/oauth2/token\";\n\treturn {\n\t\tid: \"discord\" as const,\n\t\tname: \"Discord\",\n\t\ttype: \"oauth\",\n\t\tparams: {\n\t\t\tclientId: options.clientId,\n\t\t\tclientSecret: options.clientSecret,\n\t\t\tlinkAccounts: options.linkAccounts,\n\t\t\tauthorizationEndpoint: authorizeEndpoint,\n\t\t\ttokenEndpoint: tokenEndpoint,\n\t\t\tredirectURL: options.redirectURL,\n\t\t},\n\t\tscopes: options.scopes || [\"identify\", \"email\"],\n\t\tasync getUserInfo(tokens) {\n\t\t\tconst profile = await fetch(\"https://discord.com/api/users/@me\", {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${tokens.access_token}`,\n\t\t\t\t},\n\t\t\t})\n\t\t\t\t.then((res) => res.json())\n\t\t\t\t.then((res) => res as DiscordProfile);\n\n\t\t\tif (profile.avatar === null) {\n\t\t\t\tconst defaultAvatarNumber =\n\t\t\t\t\tprofile.discriminator === \"0\"\n\t\t\t\t\t\t? Number(BigInt(profile.id) >> BigInt(22)) % 6\n\t\t\t\t\t\t: Number.parseInt(profile.discriminator) % 5;\n\t\t\t\tprofile.image_url = `https://cdn.discordapp.com/embed/avatars/${defaultAvatarNumber}.png`;\n\t\t\t} else {\n\t\t\t\tconst format = profile.avatar.startsWith(\"a_\") ? \"gif\" : \"png\";\n\t\t\t\tprofile.image_url = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...profile,\n\t\t\t\tid: profile.id,\n\t\t\t\temail: profile.email,\n\t\t\t\tname: profile.global_name || profile.username,\n\t\t\t\temailVerified: profile.verified || false,\n\t\t\t\timage: profile.image_url,\n\t\t\t};\n\t\t},\n\t} satisfies Provider<DiscordProfile>;\n};\n","import { BetterAuthError } from \"@better-auth/shared/error\";\nimport { base64url } from \"jose\";\nimport { z } from \"zod\";\nimport { createJWT, parseJWT, validateJWT } from \"../jwt\";\nimport type { Context } from \"../routes/types\";\nimport { createSession } from \"../utils/session\";\nimport type { Provider } from \"./types\";\n\ninterface MagicLinkOptions {\n\tsendEmail: (email: string, url: string) => Promise<void>;\n\t/**\n\t * Redirect URL\n\t * You can pass this when you call on the client.\n\t */\n\tredirect?: {\n\t\terror: string;\n\t\tsuccess: string;\n\t};\n}\n\nexport const magicLink = (options?: MagicLinkOptions) => {\n\tconst schema = z.object({\n\t\tcallbackURL: z.string(),\n\t\tcurrentURL: z.string(),\n\t\tallowSignUp: z.boolean().default(false),\n\t\tdata: z\n\t\t\t.object({\n\t\t\t\temail: z.string(),\n\t\t\t})\n\t\t\t.and(z.record(z.string(), z.any())),\n\t});\n\tasync function signIn(context: Context) {\n\t\tconst data = schema.safeParse(context.request.body);\n\t\tif (data.error) {\n\t\t\treturn {\n\t\t\t\tstatus: 400,\n\t\t\t\tstatusText: \"Invalid Data\",\n\t\t\t};\n\t\t}\n\t\tconst {\n\t\t\tdata: { email },\n\t\t\tcurrentURL,\n\t\t\tcallbackURL,\n\t\t} = data.data;\n\t\tlet user = await context.adapter.findUserByEmail(email, context);\n\t\t/**\n\t\t * Redirect URL\n\t\t */\n\t\tconst redirect = callbackURL\n\t\t\t? {\n\t\t\t\t\terror: options?.redirect?.error || currentURL,\n\t\t\t\t\tsuccess: formatURL(callbackURL, currentURL),\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\terror: options?.redirect?.error || currentURL,\n\t\t\t\t\tsuccess: options?.redirect?.success || new URL(currentURL).origin,\n\t\t\t\t};\n\t\tif (!user) {\n\t\t\tif (data.data.allowSignUp) {\n\t\t\t\tif (!data.data.data) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tstatusText: \"Invalid User Registration Data\",\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst response = await context.adapter.createUser(\n\t\t\t\t\t{\n\t\t\t\t\t\tuser: data.data.data,\n\t\t\t\t\t\taccount: {\n\t\t\t\t\t\t\tproviderId: \"magic_link\",\n\t\t\t\t\t\t\taccountId: email,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t\tuser = response.user;\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 302,\n\t\t\t\t\tLocation: `${redirect.error}?error=user_doesn't_exist`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tconst token = await createJWT({\n\t\t\tpayload: {\n\t\t\t\temail,\n\t\t\t\tredirect: {\n\t\t\t\t\terror: formatURL(redirect.error, currentURL),\n\t\t\t\t\tredirect: formatURL(redirect.error, currentURL),\n\t\t\t\t},\n\t\t\t},\n\t\t\tsecret: context.secret,\n\t\t\texpiresIn: 60 * 60 * 2,\n\t\t});\n\t\tconst encoded = base64url.encode(token);\n\t\tconst url = `${context.request.url.toString()}/magic-link/verify?token=${encoded}`;\n\t\tawait options?.sendEmail(email, url);\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\tbody: {\n\t\t\t\tsuccess: true,\n\t\t\t},\n\t\t};\n\t}\n\treturn {\n\t\tid: \"magic-link\" as const,\n\t\tname: \"magic-link\",\n\t\ttype: \"custom\",\n\t\tsignIn,\n\t\tasync signUp(context) {\n\t\t\tconst data = schema.parse(context.request.body);\n\t\t\tconst user = await context.adapter.findUserByEmail(\n\t\t\t\tdata.data.email,\n\t\t\t\tcontext,\n\t\t\t);\n\n\t\t\tif (user) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 302,\n\t\t\t\t\tLocation: `${data.currentURL}?error=user_already_exists`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn await signIn({\n\t\t\t\t...context,\n\t\t\t\trequest: {\n\t\t\t\t\t...context.request,\n\t\t\t\t\tbody: data,\n\t\t\t\t},\n\t\t\t} as Context);\n\t\t},\n\t\thandler: {\n\t\t\tmatcher: (context) => context.request.action.startsWith(\"magic-link\"),\n\t\t\thandler: async (context) => {\n\t\t\t\tconst token = context.request.url.searchParams.get(\"token\");\n\t\t\t\tif (!token) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 403,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst decoded = new TextDecoder().decode(base64url.decode(token));\n\t\t\t\tconst isValid = await validateJWT(decoded, context.secret);\n\t\t\t\tif (!isValid) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 403,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst payload = parseJWT<{\n\t\t\t\t\temail: string;\n\t\t\t\t\tredirect: {\n\t\t\t\t\t\tsuccess: string;\n\t\t\t\t\t\terror: string;\n\t\t\t\t\t};\n\t\t\t\t}>(decoded);\n\t\t\t\tconst user = await context.adapter.findUserByEmail(\n\t\t\t\t\tpayload.email,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t\tif (!user) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 302,\n\t\t\t\t\t\tLocation: `${payload.redirect.error}?error=user_not_found`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tawait createSession(user.id, context);\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t\tinput: z.object({\n\t\t\temail: z.string(),\n\t\t}),\n\t} satisfies Provider;\n};\n\nfunction formatURL(pathOrURL: string, currentURL: string) {\n\tif (pathOrURL.startsWith(\"/\")) {\n\t\treturn `${new URL(currentURL).origin}/${pathOrURL}`;\n\t}\n\tif (pathOrURL.startsWith(\"http\")) {\n\t\treturn pathOrURL;\n\t}\n\tthrow new BetterAuthError(\"Redirect url passed in magic links are invalid.\");\n}\n"],"mappings":"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","names":["hash","z","z"]}
@@ -1,39 +0,0 @@
1
- import { C as Context, I as InternalResponse } from '../options-CH15FEBw.js';
2
- import { U as User } from '../types-DAxaMWCy.js';
3
- import 'zod';
4
-
5
- type SessionContext = Context;
6
- type SessionResponse = Omit<Awaited<ReturnType<typeof session>> extends infer B ? B extends {
7
- status: 200;
8
- body: infer Body;
9
- } ? Body : never : never, "error">;
10
- declare const session: (context: SessionContext) => Promise<{
11
- status: number;
12
- statusText: string;
13
- body?: undefined;
14
- } | {
15
- status: 200;
16
- body: {
17
- user: User;
18
- expiresAt: Date;
19
- };
20
- statusText?: undefined;
21
- }>;
22
- declare const getServerSession: (context: Context) => Promise<{
23
- user: User;
24
- expiresAt: Date;
25
- } | null>;
26
- declare const sessionHandler: (ctx: SessionContext) => Promise<InternalResponse | Promise<{
27
- status: number;
28
- statusText: string;
29
- body?: undefined;
30
- } | {
31
- status: 200;
32
- body: {
33
- user: User;
34
- expiresAt: Date;
35
- };
36
- statusText?: undefined;
37
- }>>;
38
-
39
- export { type SessionContext, type SessionResponse, getServerSession, session, sessionHandler };
@@ -1,128 +0,0 @@
1
- // src/cookies/index.ts
2
- function deleteSessionCooke(context) {
3
- context.request.cookies.set(context.cookies.sessionToken.name, "", {
4
- ...context.cookies.sessionToken.options,
5
- maxAge: 0
6
- });
7
- }
8
-
9
- // src/plugins/utils.ts
10
- var usePlugins = (context, ignorePlugins) => {
11
- const plugins = context.plugins.filter(
12
- (pl) => pl.hooks && !ignorePlugins?.includes(pl.id)
13
- );
14
- const hooks = plugins.map((plugin) => {
15
- return plugin.hooks;
16
- });
17
- const before = [];
18
- const after = [];
19
- for (const hook of hooks) {
20
- if (hook.matcher(context)) {
21
- hook.before && before.push(hook.before);
22
- hook.after && after.push(hook.after);
23
- }
24
- }
25
- return {
26
- before: async (context2) => {
27
- let ctx = context2;
28
- let response;
29
- for (const hook of before) {
30
- const res = await hook(ctx);
31
- if (res?.context) {
32
- ctx = res.context;
33
- }
34
- if (res?.response) {
35
- response = res.response;
36
- break;
37
- }
38
- }
39
- return {
40
- context: ctx,
41
- response
42
- };
43
- },
44
- after: async (context2, fnResponse) => {
45
- let ctx = context2;
46
- let response;
47
- for (const hook of after) {
48
- const res = await hook(ctx, fnResponse);
49
- if (res?.context) {
50
- ctx = res.context;
51
- }
52
- if (res?.response) {
53
- response = res.response;
54
- break;
55
- }
56
- }
57
- return {
58
- context: ctx,
59
- response
60
- };
61
- }
62
- };
63
- };
64
- var withPlugins = (fn, ignorePlugins) => {
65
- return async (ctx) => {
66
- const { before, after } = usePlugins(ctx, ignorePlugins);
67
- const { context, response } = await before(ctx);
68
- if (response) {
69
- return response;
70
- }
71
- const res = await fn(context);
72
- const { response: afterResponse } = await after(context, res);
73
- if (afterResponse) {
74
- return afterResponse;
75
- }
76
- return res;
77
- };
78
- };
79
-
80
- // src/routes/session.ts
81
- var session = async (context) => {
82
- const session2 = await getServerSession(context);
83
- if (!session2) {
84
- return {
85
- status: 401,
86
- statusText: "Unauthorize"
87
- };
88
- }
89
- return {
90
- status: 200,
91
- body: session2
92
- };
93
- };
94
- var getServerSession = async (context) => {
95
- const sessionFromCookie = context.request.cookies.get(
96
- context.cookies.sessionToken.name
97
- );
98
- if (!sessionFromCookie) {
99
- return null;
100
- }
101
- const session2 = await context.adapter.findSession(sessionFromCookie, context);
102
- if (!session2 || session2.expiresAt < /* @__PURE__ */ new Date()) {
103
- session2 && await context.adapter.deleteSession(session2.id, context);
104
- deleteSessionCooke(context);
105
- return null;
106
- }
107
- const user = await context.adapter.findUserById(session2.userId, context);
108
- if (!user) {
109
- return null;
110
- }
111
- const updatedSession = await context.adapter.updateSession(session2, context);
112
- context.request.cookies.set(context.cookies.sessionToken.name, session2.id, {
113
- ...context.cookies.sessionToken.options,
114
- maxAge: updatedSession.expiresAt.valueOf() - Date.now()
115
- });
116
- sessionFromCookie;
117
- return {
118
- user,
119
- expiresAt: session2.expiresAt
120
- };
121
- };
122
- var sessionHandler = withPlugins(session);
123
- export {
124
- getServerSession,
125
- session,
126
- sessionHandler
127
- };
128
- //# sourceMappingURL=session.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/cookies/index.ts","../../src/plugins/utils.ts","../../src/routes/session.ts"],"sourcesContent":["import type { Context } from \"../routes/types\";\nimport type { CookieSerializeOptions } from \"./types\";\n\nexport function serialize(\n\tname: string,\n\tvalue: string,\n\tattributes: CookieSerializeOptions,\n) {\n\tconst keyValueEntries: Array<[string, string] | [string]> = [];\n\tkeyValueEntries.push([encodeURIComponent(name), encodeURIComponent(value)]);\n\tif (attributes?.domain !== undefined) {\n\t\tkeyValueEntries.push([\"Domain\", attributes.domain]);\n\t}\n\tif (attributes?.expires !== undefined) {\n\t\tkeyValueEntries.push([\"Expires\", attributes.expires.toUTCString()]);\n\t}\n\tif (attributes?.httpOnly) {\n\t\tkeyValueEntries.push([\"HttpOnly\"]);\n\t}\n\tif (attributes?.maxAge !== undefined) {\n\t\tkeyValueEntries.push([\"Max-Age\", attributes.maxAge.toString()]);\n\t}\n\tif (attributes?.path !== undefined) {\n\t\tkeyValueEntries.push([\"Path\", attributes.path]);\n\t}\n\tif (attributes?.sameSite === \"lax\") {\n\t\tkeyValueEntries.push([\"SameSite\", \"Lax\"]);\n\t}\n\tif (attributes?.sameSite === \"none\") {\n\t\tkeyValueEntries.push([\"SameSite\", \"None\"]);\n\t}\n\tif (attributes?.sameSite === \"strict\") {\n\t\tkeyValueEntries.push([\"SameSite\", \"Strict\"]);\n\t}\n\tif (attributes?.secure) {\n\t\tkeyValueEntries.push([\"Secure\"]);\n\t}\n\treturn keyValueEntries.map((pair) => pair.join(\"=\")).join(\"; \");\n}\n\nexport function parse(header: string): Map<string, string> {\n\tconst cookies = new Map<string, string>();\n\tconst items = header.split(\"; \");\n\tfor (const item of items) {\n\t\tconst pair = item.split(\"=\");\n\t\tconst rawKey = pair[0];\n\t\tconst rawValue = pair[1] ?? \"\";\n\t\tif (!rawKey) continue;\n\t\tcookies.set(decodeURIComponent(rawKey), decodeURIComponent(rawValue));\n\t}\n\treturn cookies;\n}\n\nexport const cookieManager = (header: Headers): CookieManager => {\n\treturn {\n\t\tset(name: string, value: string, options = {}) {\n\t\t\tconst cookieStr = serialize(name, value, options);\n\t\t\theader.append(\"set-cookie\", cookieStr);\n\t\t},\n\t\tget(name: string) {\n\t\t\tconst cookie = header.get(\"cookie\");\n\t\t\tif (!cookie) return null;\n\t\t\tconst cookies = parse(cookie);\n\t\t\tconst value = cookies.get(name);\n\t\t\treturn value;\n\t\t},\n\t};\n};\n\nexport type CookieManager = {\n\tset: (name: string, value: string, options?: CookieSerializeOptions) => void;\n\tget: (name: string) => string | null | undefined;\n};\n\nexport function setSessionCookie(context: Context, sessionId: string) {\n\tcontext.request.cookies.set(\n\t\tcontext.cookies.sessionToken.name,\n\t\tsessionId,\n\t\tcontext.cookies.sessionToken.options,\n\t);\n}\n\nexport function deleteSessionCooke(context: Context) {\n\tcontext.request.cookies.set(context.cookies.sessionToken.name, \"\", {\n\t\t...context.cookies.sessionToken.options,\n\t\tmaxAge: 0,\n\t});\n}\n","import type { BetterAuthOptions } from \"../options\";\nimport type {\n\tContext,\n\tGenericHandler,\n\tHandlerHooks,\n\tInternalResponse,\n} from \"../routes/types\";\nimport { CSRFCheckPlugin } from \"./csrf-check\";\nimport type {\n\tAfterHookHandler,\n\tBeforeHookHandler,\n\tBetterAuthPlugin,\n} from \"./types\";\n\nexport const getPlugins = (options: BetterAuthOptions) => {\n\tconst plugins: {\n\t\tpost: BetterAuthPlugin[];\n\t\tpre: BetterAuthPlugin[];\n\t\tunordered: BetterAuthPlugin[];\n\t} = {\n\t\tpost: [],\n\t\tpre: [],\n\t\tunordered: [],\n\t};\n\tfor (const plugin of options.plugins || []) {\n\t\tplugins[plugin.order || \"unordered\"].push(plugin);\n\t}\n\tconst internalPlugins = [CSRFCheckPlugin()];\n\treturn [\n\t\t...plugins.pre,\n\t\t...plugins.unordered,\n\t\t...internalPlugins,\n\t\t...plugins.post,\n\t];\n};\n\nexport const usePlugins = (context: Context, ignorePlugins?: string[]) => {\n\tconst plugins = context.plugins.filter(\n\t\t(pl) => pl.hooks && !ignorePlugins?.includes(pl.id),\n\t);\n\tconst hooks = plugins.map((plugin) => {\n\t\treturn plugin.hooks as HandlerHooks;\n\t});\n\tconst before: BeforeHookHandler[] = [];\n\tconst after: AfterHookHandler[] = [];\n\tfor (const hook of hooks) {\n\t\tif (hook.matcher(context)) {\n\t\t\thook.before && before.push(hook.before);\n\t\t\thook.after && after.push(hook.after);\n\t\t}\n\t}\n\treturn {\n\t\tbefore: async (context: Context) => {\n\t\t\tlet ctx: Context | undefined = context;\n\t\t\tlet response: InternalResponse | undefined;\n\t\t\tfor (const hook of before) {\n\t\t\t\tconst res = await hook(ctx);\n\t\t\t\tif (res?.context) {\n\t\t\t\t\tctx = res.context;\n\t\t\t\t}\n\t\t\t\tif (res?.response) {\n\t\t\t\t\tresponse = res.response;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontext: ctx,\n\t\t\t\tresponse,\n\t\t\t};\n\t\t},\n\t\tafter: async (context: Context, fnResponse: InternalResponse) => {\n\t\t\tlet ctx: Context | undefined = context;\n\t\t\tlet response: InternalResponse | undefined;\n\t\t\tfor (const hook of after) {\n\t\t\t\tconst res = await hook(ctx, fnResponse);\n\t\t\t\tif (res?.context) {\n\t\t\t\t\tctx = res.context;\n\t\t\t\t}\n\t\t\t\tif (res?.response) {\n\t\t\t\t\tresponse = res.response;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontext: ctx,\n\t\t\t\tresponse,\n\t\t\t};\n\t\t},\n\t};\n};\n\nexport const withPlugins = <T extends GenericHandler<any, any, any>>(\n\tfn: T,\n\t/**\n\t * A list of plugins id to ignore.\n\t */\n\tignorePlugins?: string[],\n) => {\n\treturn async (ctx: Parameters<T>[\"0\"]) => {\n\t\tconst { before, after } = usePlugins(ctx, ignorePlugins);\n\t\tconst { context, response } = await before(ctx);\n\t\tif (response) {\n\t\t\treturn response;\n\t\t}\n\t\tconst res = await fn(context);\n\t\tconst { response: afterResponse } = await after(context, res);\n\t\tif (afterResponse) {\n\t\t\treturn afterResponse;\n\t\t}\n\t\treturn res as ReturnType<T>;\n\t};\n};\n","import { deleteSessionCooke } from \"../cookies\";\nimport { withPlugins } from \"../plugins/utils\";\nimport type { Context, InternalResponse } from \"./types\";\n\nexport type SessionContext = Context;\n\nexport type SessionResponse = Omit<\n\tAwaited<ReturnType<typeof session>> extends infer B\n\t\t? B extends { status: 200; body: infer Body }\n\t\t\t? Body\n\t\t\t: never\n\t\t: never,\n\t\"error\"\n>;\n\nexport const session = async (context: SessionContext) => {\n\tconst session = await getServerSession(context);\n\tif (!session) {\n\t\treturn {\n\t\t\tstatus: 401,\n\t\t\tstatusText: \"Unauthorize\",\n\t\t} satisfies InternalResponse;\n\t}\n\treturn {\n\t\tstatus: 200 as const,\n\t\tbody: session,\n\t} satisfies InternalResponse;\n};\n\nexport const getServerSession = async (context: Context) => {\n\tconst sessionFromCookie = context.request.cookies.get(\n\t\tcontext.cookies.sessionToken.name,\n\t);\n\tif (!sessionFromCookie) {\n\t\treturn null;\n\t}\n\tconst session = await context.adapter.findSession(sessionFromCookie, context);\n\tif (!session || session.expiresAt < new Date()) {\n\t\tsession && (await context.adapter.deleteSession(session.id, context));\n\t\tdeleteSessionCooke(context);\n\t\treturn null;\n\t}\n\tconst user = await context.adapter.findUserById(session.userId, context);\n\tif (!user) {\n\t\treturn null;\n\t}\n\tconst updatedSession = await context.adapter.updateSession(session, context);\n\tcontext.request.cookies.set(context.cookies.sessionToken.name, session.id, {\n\t\t...context.cookies.sessionToken.options,\n\t\tmaxAge: updatedSession.expiresAt.valueOf() - Date.now(),\n\t});\n\tsessionFromCookie;\n\treturn {\n\t\tuser,\n\t\texpiresAt: session.expiresAt,\n\t};\n};\n\nexport const sessionHandler = withPlugins(session);\n"],"mappings":"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","names":["context","session"]}
@@ -1,136 +0,0 @@
1
- import { ZodSchema } from 'zod';
2
-
3
- type InternalFieldAttributes = {
4
- /**
5
- * if the field should be required when there is a request to create a new
6
- * record
7
- * @default false
8
- */
9
- required?: boolean;
10
- /**
11
- * If the value should be returned on a response body.
12
- * @default true
13
- */
14
- returned?: boolean;
15
- /**
16
- * If the value should be hashed when it's stored.
17
- * @default false
18
- */
19
- hashValue?: boolean;
20
- /**
21
- * a zod schema for validating the inputs
22
- */
23
- validator: ZodSchema;
24
- };
25
- type FieldType = "string" | "number" | "boolean" | "date";
26
- type FieldAttributes = {
27
- /**
28
- * the type of the field
29
- */
30
- type: FieldType;
31
- /**
32
- * if the field should be required on a new record.
33
- * @default false
34
- */
35
- required?: boolean;
36
- /**
37
- * If the value should be returned on a response body.
38
- * @default true
39
- */
40
- returned?: boolean;
41
- /**
42
- * If the value should be hashed when it's stored.
43
- * @default false
44
- */
45
- hashValue?: boolean;
46
- /**
47
- * transform the value before storing it.
48
- */
49
- transform?: (value: any) => any;
50
- };
51
- type BaseModel = {
52
- id: string;
53
- };
54
- interface User extends BaseModel {
55
- [key: string]: any;
56
- }
57
- type UserInput = Omit<User, "id">;
58
- interface Session extends BaseModel {
59
- userId: string;
60
- expiresAt: Date;
61
- }
62
- interface Account extends BaseModel {
63
- userId: string;
64
- providerId: string;
65
- accountId: string;
66
- }
67
- interface AccountInput extends Omit<Account, "id"> {
68
- }
69
- /**
70
- * Adapter where clause
71
- */
72
- type Where = {
73
- operator?: "eq" | "ne" | "lt" | "lte" | "gt" | "gte";
74
- value: string;
75
- field: string;
76
- connector?: "AND" | "OR";
77
- };
78
- /**
79
- * Adapter Interface
80
- */
81
- interface Adapter {
82
- create: <T extends Record<string, any>, R extends Record<string, any> = T>(data: {
83
- model: string;
84
- data: Record<string, any>;
85
- select?: string[];
86
- }) => Promise<R>;
87
- findOne: <T>(data: {
88
- model: string;
89
- where: Where[];
90
- select?: string[];
91
- }) => Promise<T | null>;
92
- findMany: <T>(data: {
93
- model: string;
94
- where?: Where[];
95
- }) => Promise<T[] | null>;
96
- update: <T>(data: {
97
- model: string;
98
- where: Where[];
99
- update: Record<string, any>;
100
- }) => Promise<T>;
101
- delete: <T>(data: {
102
- model: string;
103
- where: Where[];
104
- }) => Promise<T>;
105
- /**
106
- * adapter specific configuration
107
- */
108
- config?: {
109
- /**
110
- * the format of the date fields
111
- */
112
- dateFormat?: "number" | "date";
113
- /**
114
- * if the adapter will throw an error when a
115
- * record already exists. If this is set to
116
- * false, there will be a check if the record
117
- * exists or not before creating a new one.
118
- */
119
- failsOnRecordExist?: boolean;
120
- };
121
- }
122
- interface SessionAdapter {
123
- create: (data: {
124
- userId: string;
125
- expiresAt: Date;
126
- }) => Promise<Session>;
127
- findOne: (data: {
128
- userId: string;
129
- }) => Promise<Session | null>;
130
- update: (data: Session) => Promise<Session>;
131
- delete: (data: {
132
- sessionId: string;
133
- }) => Promise<void>;
134
- }
135
-
136
- export type { Adapter as A, BaseModel as B, FieldAttributes as F, InternalFieldAttributes as I, SessionAdapter as S, User as U, Where as W, UserInput as a, FieldType as b, Session as c, Account as d, AccountInput as e };