better-auth 1.4.8-beta.1 → 1.4.8-beta.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 (95) hide show
  1. package/dist/api/index.d.mts +393 -393
  2. package/dist/api/middlewares/origin-check.d.mts +3 -3
  3. package/dist/api/routes/account.d.mts +11 -11
  4. package/dist/api/routes/callback.d.mts +2 -2
  5. package/dist/api/routes/email-verification.d.mts +4 -4
  6. package/dist/api/routes/error.d.mts +2 -2
  7. package/dist/api/routes/ok.d.mts +2 -2
  8. package/dist/api/routes/reset-password.d.mts +5 -5
  9. package/dist/api/routes/session.d.mts +14 -14
  10. package/dist/api/routes/sign-in.d.mts +3 -3
  11. package/dist/api/routes/sign-out.d.mts +2 -2
  12. package/dist/api/routes/sign-up.d.mts +2 -2
  13. package/dist/api/routes/update-user.d.mts +13 -13
  14. package/dist/client/lynx/index.d.mts +15 -15
  15. package/dist/client/react/index.d.mts +13 -13
  16. package/dist/client/solid/index.d.mts +13 -13
  17. package/dist/client/svelte/index.d.mts +13 -13
  18. package/dist/client/vue/index.d.mts +15 -15
  19. package/dist/db/field.d.mts +6 -6
  20. package/dist/integrations/next-js.d.mts +4 -4
  21. package/dist/integrations/svelte-kit.d.mts +2 -2
  22. package/dist/integrations/tanstack-start.d.mts +4 -4
  23. package/dist/plugins/anonymous/index.d.mts +6 -5
  24. package/dist/plugins/anonymous/index.mjs +1 -0
  25. package/dist/plugins/anonymous/index.mjs.map +1 -1
  26. package/dist/plugins/api-key/index.d.mts +18 -18
  27. package/dist/plugins/bearer/index.d.mts +8 -7
  28. package/dist/plugins/bearer/index.mjs +2 -1
  29. package/dist/plugins/bearer/index.mjs.map +1 -1
  30. package/dist/plugins/captcha/index.d.mts +3 -2
  31. package/dist/plugins/captcha/index.mjs +2 -1
  32. package/dist/plugins/captcha/index.mjs.map +1 -1
  33. package/dist/plugins/custom-session/index.d.mts +6 -5
  34. package/dist/plugins/custom-session/index.mjs +2 -1
  35. package/dist/plugins/custom-session/index.mjs.map +1 -1
  36. package/dist/plugins/device-authorization/index.d.mts +35 -8
  37. package/dist/plugins/device-authorization/index.mjs +2 -1
  38. package/dist/plugins/device-authorization/index.mjs.map +1 -1
  39. package/dist/plugins/email-otp/index.d.mts +49 -48
  40. package/dist/plugins/email-otp/index.mjs +2 -1
  41. package/dist/plugins/email-otp/index.mjs.map +1 -1
  42. package/dist/plugins/generic-oauth/index.d.mts +1 -0
  43. package/dist/plugins/generic-oauth/index.mjs +1 -0
  44. package/dist/plugins/generic-oauth/index.mjs.map +1 -1
  45. package/dist/plugins/haveibeenpwned/index.d.mts +4 -3
  46. package/dist/plugins/haveibeenpwned/index.mjs +1 -0
  47. package/dist/plugins/haveibeenpwned/index.mjs.map +1 -1
  48. package/dist/plugins/index.d.mts +4 -3
  49. package/dist/plugins/jwt/index.d.mts +9 -9
  50. package/dist/plugins/last-login-method/index.d.mts +3 -2
  51. package/dist/plugins/last-login-method/index.mjs +2 -1
  52. package/dist/plugins/last-login-method/index.mjs.map +1 -1
  53. package/dist/plugins/magic-link/index.d.mts +5 -4
  54. package/dist/plugins/magic-link/index.mjs +2 -1
  55. package/dist/plugins/magic-link/index.mjs.map +1 -1
  56. package/dist/plugins/mcp/index.d.mts +11 -10
  57. package/dist/plugins/mcp/index.mjs +2 -1
  58. package/dist/plugins/mcp/index.mjs.map +1 -1
  59. package/dist/plugins/multi-session/index.d.mts +10 -9
  60. package/dist/plugins/multi-session/index.mjs +1 -0
  61. package/dist/plugins/multi-session/index.mjs.map +1 -1
  62. package/dist/plugins/oauth-proxy/index.d.mts +8 -8
  63. package/dist/plugins/oidc-provider/index.d.mts +13 -13
  64. package/dist/plugins/one-tap/index.d.mts +4 -3
  65. package/dist/plugins/one-tap/index.mjs +2 -1
  66. package/dist/plugins/one-tap/index.mjs.map +1 -1
  67. package/dist/plugins/one-time-token/index.d.mts +6 -5
  68. package/dist/plugins/one-time-token/index.mjs +2 -1
  69. package/dist/plugins/one-time-token/index.mjs.map +1 -1
  70. package/dist/plugins/open-api/index.d.mts +4 -3
  71. package/dist/plugins/open-api/index.mjs +2 -1
  72. package/dist/plugins/open-api/index.mjs.map +1 -1
  73. package/dist/plugins/organization/organization.d.mts +4 -4
  74. package/dist/plugins/organization/organization.mjs.map +1 -1
  75. package/dist/plugins/organization/routes/crud-access-control.d.mts +22 -22
  76. package/dist/plugins/organization/routes/crud-invites.d.mts +58 -58
  77. package/dist/plugins/organization/routes/crud-members.d.mts +62 -62
  78. package/dist/plugins/organization/routes/crud-org.d.mts +51 -51
  79. package/dist/plugins/organization/routes/crud-team.d.mts +76 -76
  80. package/dist/plugins/phone-number/index.d.mts +10 -9
  81. package/dist/plugins/phone-number/index.mjs +1 -0
  82. package/dist/plugins/phone-number/index.mjs.map +1 -1
  83. package/dist/plugins/siwe/index.d.mts +4 -3
  84. package/dist/plugins/siwe/index.mjs +2 -1
  85. package/dist/plugins/siwe/index.mjs.map +1 -1
  86. package/dist/plugins/two-factor/backup-codes/index.d.mts +5 -5
  87. package/dist/plugins/two-factor/index.d.mts +18 -18
  88. package/dist/plugins/two-factor/otp/index.d.mts +3 -3
  89. package/dist/plugins/two-factor/totp/index.d.mts +5 -5
  90. package/dist/plugins/username/index.d.mts +10 -9
  91. package/dist/plugins/username/index.mjs +1 -0
  92. package/dist/plugins/username/index.mjs.map +1 -1
  93. package/dist/test-utils/test-instance.d.mts +271 -271
  94. package/dist/utils/time.d.mts +29 -1
  95. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["verifyHandlers.cloudflareTurnstile","verifyHandlers.googleRecaptcha","verifyHandlers.hCaptcha","verifyHandlers.captchaFox"],"sources":["../../../src/plugins/captcha/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { getIp } from \"../../utils/get-request-ip\";\nimport { middlewareResponse } from \"../../utils/middleware-response\";\nimport { defaultEndpoints, Providers, siteVerifyMap } from \"./constants\";\nimport { EXTERNAL_ERROR_CODES, INTERNAL_ERROR_CODES } from \"./error-codes\";\nimport type { CaptchaOptions } from \"./types\";\nimport * as verifyHandlers from \"./verify-handlers\";\n\nexport const captcha = (options: CaptchaOptions) =>\n\t({\n\t\tid: \"captcha\",\n\t\tonRequest: async (request, ctx) => {\n\t\t\ttry {\n\t\t\t\tconst endpoints = options.endpoints?.length\n\t\t\t\t\t? options.endpoints\n\t\t\t\t\t: defaultEndpoints;\n\n\t\t\t\tif (!endpoints.some((endpoint) => request.url.includes(endpoint)))\n\t\t\t\t\treturn undefined;\n\n\t\t\t\tif (!options.secretKey) {\n\t\t\t\t\tthrow new Error(INTERNAL_ERROR_CODES.MISSING_SECRET_KEY);\n\t\t\t\t}\n\n\t\t\t\tconst captchaResponse = request.headers.get(\"x-captcha-response\");\n\t\t\t\tconst remoteUserIP = getIp(request, ctx.options) ?? undefined;\n\n\t\t\t\tif (!captchaResponse) {\n\t\t\t\t\treturn middlewareResponse({\n\t\t\t\t\t\tmessage: EXTERNAL_ERROR_CODES.MISSING_RESPONSE,\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst siteVerifyURL =\n\t\t\t\t\toptions.siteVerifyURLOverride || siteVerifyMap[options.provider];\n\n\t\t\t\tconst handlerParams = {\n\t\t\t\t\tsiteVerifyURL,\n\t\t\t\t\tcaptchaResponse,\n\t\t\t\t\tsecretKey: options.secretKey,\n\t\t\t\t\tremoteIP: remoteUserIP,\n\t\t\t\t};\n\n\t\t\t\tif (options.provider === Providers.CLOUDFLARE_TURNSTILE) {\n\t\t\t\t\treturn await verifyHandlers.cloudflareTurnstile(handlerParams);\n\t\t\t\t}\n\n\t\t\t\tif (options.provider === Providers.GOOGLE_RECAPTCHA) {\n\t\t\t\t\treturn await verifyHandlers.googleRecaptcha({\n\t\t\t\t\t\t...handlerParams,\n\t\t\t\t\t\tminScore: options.minScore,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (options.provider === Providers.HCAPTCHA) {\n\t\t\t\t\treturn await verifyHandlers.hCaptcha({\n\t\t\t\t\t\t...handlerParams,\n\t\t\t\t\t\tsiteKey: options.siteKey,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (options.provider === Providers.CAPTCHAFOX) {\n\t\t\t\t\treturn await verifyHandlers.captchaFox({\n\t\t\t\t\t\t...handlerParams,\n\t\t\t\t\t\tsiteKey: options.siteKey,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (_error) {\n\t\t\t\tconst errorMessage =\n\t\t\t\t\t_error instanceof Error ? _error.message : undefined;\n\n\t\t\t\tctx.logger.error(errorMessage ?? \"Unknown error\", {\n\t\t\t\t\tendpoint: request.url,\n\t\t\t\t\tmessage: _error,\n\t\t\t\t});\n\n\t\t\t\treturn middlewareResponse({\n\t\t\t\t\tmessage: EXTERNAL_ERROR_CODES.UNKNOWN_ERROR,\n\t\t\t\t\tstatus: 500,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t}) satisfies BetterAuthPlugin;\n"],"mappings":";;;;;;;;;;;AAQA,MAAa,WAAW,aACtB;CACA,IAAI;CACJ,WAAW,OAAO,SAAS,QAAQ;AAClC,MAAI;AAKH,OAAI,EAJc,QAAQ,WAAW,SAClC,QAAQ,YACR,kBAEY,MAAM,aAAa,QAAQ,IAAI,SAAS,SAAS,CAAC,CAChE,QAAO;AAER,OAAI,CAAC,QAAQ,UACZ,OAAM,IAAI,MAAM,qBAAqB,mBAAmB;GAGzD,MAAM,kBAAkB,QAAQ,QAAQ,IAAI,qBAAqB;GACjE,MAAM,eAAe,MAAM,SAAS,IAAI,QAAQ,IAAI;AAEpD,OAAI,CAAC,gBACJ,QAAO,mBAAmB;IACzB,SAAS,qBAAqB;IAC9B,QAAQ;IACR,CAAC;GAMH,MAAM,gBAAgB;IACrB,eAHA,QAAQ,yBAAyB,cAAc,QAAQ;IAIvD;IACA,WAAW,QAAQ;IACnB,UAAU;IACV;AAED,OAAI,QAAQ,aAAa,UAAU,qBAClC,QAAO,MAAMA,oBAAmC,cAAc;AAG/D,OAAI,QAAQ,aAAa,UAAU,iBAClC,QAAO,MAAMC,gBAA+B;IAC3C,GAAG;IACH,UAAU,QAAQ;IAClB,CAAC;AAGH,OAAI,QAAQ,aAAa,UAAU,SAClC,QAAO,MAAMC,SAAwB;IACpC,GAAG;IACH,SAAS,QAAQ;IACjB,CAAC;AAGH,OAAI,QAAQ,aAAa,UAAU,WAClC,QAAO,MAAMC,WAA0B;IACtC,GAAG;IACH,SAAS,QAAQ;IACjB,CAAC;WAEK,QAAQ;GAChB,MAAM,eACL,kBAAkB,QAAQ,OAAO,UAAU;AAE5C,OAAI,OAAO,MAAM,gBAAgB,iBAAiB;IACjD,UAAU,QAAQ;IAClB,SAAS;IACT,CAAC;AAEF,UAAO,mBAAmB;IACzB,SAAS,qBAAqB;IAC9B,QAAQ;IACR,CAAC;;;CAGJ"}
1
+ {"version":3,"file":"index.mjs","names":["verifyHandlers.cloudflareTurnstile","verifyHandlers.googleRecaptcha","verifyHandlers.hCaptcha","verifyHandlers.captchaFox"],"sources":["../../../src/plugins/captcha/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { getIp } from \"../../utils/get-request-ip\";\nimport { middlewareResponse } from \"../../utils/middleware-response\";\nimport { defaultEndpoints, Providers, siteVerifyMap } from \"./constants\";\nimport { EXTERNAL_ERROR_CODES, INTERNAL_ERROR_CODES } from \"./error-codes\";\nimport type { CaptchaOptions } from \"./types\";\nimport * as verifyHandlers from \"./verify-handlers\";\n\nexport const captcha = (options: CaptchaOptions) =>\n\t({\n\t\tid: \"captcha\",\n\t\tonRequest: async (request, ctx) => {\n\t\t\ttry {\n\t\t\t\tconst endpoints = options.endpoints?.length\n\t\t\t\t\t? options.endpoints\n\t\t\t\t\t: defaultEndpoints;\n\n\t\t\t\tif (!endpoints.some((endpoint) => request.url.includes(endpoint)))\n\t\t\t\t\treturn undefined;\n\n\t\t\t\tif (!options.secretKey) {\n\t\t\t\t\tthrow new Error(INTERNAL_ERROR_CODES.MISSING_SECRET_KEY);\n\t\t\t\t}\n\n\t\t\t\tconst captchaResponse = request.headers.get(\"x-captcha-response\");\n\t\t\t\tconst remoteUserIP = getIp(request, ctx.options) ?? undefined;\n\n\t\t\t\tif (!captchaResponse) {\n\t\t\t\t\treturn middlewareResponse({\n\t\t\t\t\t\tmessage: EXTERNAL_ERROR_CODES.MISSING_RESPONSE,\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst siteVerifyURL =\n\t\t\t\t\toptions.siteVerifyURLOverride || siteVerifyMap[options.provider];\n\n\t\t\t\tconst handlerParams = {\n\t\t\t\t\tsiteVerifyURL,\n\t\t\t\t\tcaptchaResponse,\n\t\t\t\t\tsecretKey: options.secretKey,\n\t\t\t\t\tremoteIP: remoteUserIP,\n\t\t\t\t};\n\n\t\t\t\tif (options.provider === Providers.CLOUDFLARE_TURNSTILE) {\n\t\t\t\t\treturn await verifyHandlers.cloudflareTurnstile(handlerParams);\n\t\t\t\t}\n\n\t\t\t\tif (options.provider === Providers.GOOGLE_RECAPTCHA) {\n\t\t\t\t\treturn await verifyHandlers.googleRecaptcha({\n\t\t\t\t\t\t...handlerParams,\n\t\t\t\t\t\tminScore: options.minScore,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (options.provider === Providers.HCAPTCHA) {\n\t\t\t\t\treturn await verifyHandlers.hCaptcha({\n\t\t\t\t\t\t...handlerParams,\n\t\t\t\t\t\tsiteKey: options.siteKey,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (options.provider === Providers.CAPTCHAFOX) {\n\t\t\t\t\treturn await verifyHandlers.captchaFox({\n\t\t\t\t\t\t...handlerParams,\n\t\t\t\t\t\tsiteKey: options.siteKey,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (_error) {\n\t\t\t\tconst errorMessage =\n\t\t\t\t\t_error instanceof Error ? _error.message : undefined;\n\n\t\t\t\tctx.logger.error(errorMessage ?? \"Unknown error\", {\n\t\t\t\t\tendpoint: request.url,\n\t\t\t\t\tmessage: _error,\n\t\t\t\t});\n\n\t\t\t\treturn middlewareResponse({\n\t\t\t\t\tmessage: EXTERNAL_ERROR_CODES.UNKNOWN_ERROR,\n\t\t\t\t\tstatus: 500,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\toptions,\n\t}) satisfies BetterAuthPlugin;\n"],"mappings":";;;;;;;;;;;AAQA,MAAa,WAAW,aACtB;CACA,IAAI;CACJ,WAAW,OAAO,SAAS,QAAQ;AAClC,MAAI;AAKH,OAAI,EAJc,QAAQ,WAAW,SAClC,QAAQ,YACR,kBAEY,MAAM,aAAa,QAAQ,IAAI,SAAS,SAAS,CAAC,CAChE,QAAO;AAER,OAAI,CAAC,QAAQ,UACZ,OAAM,IAAI,MAAM,qBAAqB,mBAAmB;GAGzD,MAAM,kBAAkB,QAAQ,QAAQ,IAAI,qBAAqB;GACjE,MAAM,eAAe,MAAM,SAAS,IAAI,QAAQ,IAAI;AAEpD,OAAI,CAAC,gBACJ,QAAO,mBAAmB;IACzB,SAAS,qBAAqB;IAC9B,QAAQ;IACR,CAAC;GAMH,MAAM,gBAAgB;IACrB,eAHA,QAAQ,yBAAyB,cAAc,QAAQ;IAIvD;IACA,WAAW,QAAQ;IACnB,UAAU;IACV;AAED,OAAI,QAAQ,aAAa,UAAU,qBAClC,QAAO,MAAMA,oBAAmC,cAAc;AAG/D,OAAI,QAAQ,aAAa,UAAU,iBAClC,QAAO,MAAMC,gBAA+B;IAC3C,GAAG;IACH,UAAU,QAAQ;IAClB,CAAC;AAGH,OAAI,QAAQ,aAAa,UAAU,SAClC,QAAO,MAAMC,SAAwB;IACpC,GAAG;IACH,SAAS,QAAQ;IACjB,CAAC;AAGH,OAAI,QAAQ,aAAa,UAAU,WAClC,QAAO,MAAMC,WAA0B;IACtC,GAAG;IACH,SAAS,QAAQ;IACjB,CAAC;WAEK,QAAQ;GAChB,MAAM,eACL,kBAAkB,QAAQ,OAAO,UAAU;AAE5C,OAAI,OAAO,MAAM,gBAAgB,iBAAiB;IACjD,UAAU,QAAQ;IAClB,SAAS;IACT,CAAC;AAEF,UAAO,mBAAmB;IACzB,SAAS,qBAAqB;IAC9B,QAAQ;IACR,CAAC;;;CAGJ;CACA"}
@@ -1,9 +1,9 @@
1
1
  import { InferSession, InferUser } from "../../types/models.mjs";
2
2
  import "../../types/index.mjs";
3
- import * as _better_auth_core3 from "@better-auth/core";
3
+ import * as _better_auth_core7 from "@better-auth/core";
4
4
  import { BetterAuthOptions, GenericEndpointContext } from "@better-auth/core";
5
5
  import * as z from "zod";
6
- import * as better_call132 from "better-call";
6
+ import * as better_call144 from "better-call";
7
7
 
8
8
  //#region src/plugins/custom-session/index.d.ts
9
9
  type CustomSessionPluginOptions = {
@@ -20,12 +20,12 @@ declare const customSession: <Returns extends Record<string, any>, O extends Bet
20
20
  id: "custom-session";
21
21
  hooks: {
22
22
  after: {
23
- matcher: (ctx: _better_auth_core3.HookEndpointContext) => boolean;
24
- handler: (inputContext: better_call132.MiddlewareInputContext<better_call132.MiddlewareOptions>) => Promise<Awaited<Returns>[] | undefined>;
23
+ matcher: (ctx: _better_auth_core7.HookEndpointContext) => boolean;
24
+ handler: (inputContext: better_call144.MiddlewareInputContext<better_call144.MiddlewareOptions>) => Promise<Awaited<Returns>[] | undefined>;
25
25
  }[];
26
26
  };
27
27
  endpoints: {
28
- getSession: better_call132.StrictEndpoint<"/get-session", {
28
+ getSession: better_call144.StrictEndpoint<"/get-session", {
29
29
  method: "GET";
30
30
  query: z.ZodOptional<z.ZodObject<{
31
31
  disableCookieCache: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodPipe<z.ZodString, z.ZodTransform<boolean, string>>]>>;
@@ -59,6 +59,7 @@ declare const customSession: <Returns extends Record<string, any>, O extends Bet
59
59
  $Infer: {
60
60
  Session: Awaited<ReturnType<typeof fn>>;
61
61
  };
62
+ options: CustomSessionPluginOptions | undefined;
62
63
  };
63
64
  //#endregion
64
65
  export { CustomSessionPluginOptions, customSession };
@@ -60,7 +60,8 @@ const customSession = (fn, options, pluginOptions) => {
60
60
  });
61
61
  return ctx.json(fnResult);
62
62
  }) },
63
- $Infer: { Session: {} }
63
+ $Infer: { Session: {} },
64
+ options: pluginOptions
64
65
  };
65
66
  };
66
67
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/custom-session/index.ts"],"sourcesContent":["import type {\n\tBetterAuthOptions,\n\tBetterAuthPlugin,\n\tGenericEndpointContext,\n} from \"@better-auth/core\";\nimport {\n\tcreateAuthEndpoint,\n\tcreateAuthMiddleware,\n} from \"@better-auth/core/api\";\nimport * as z from \"zod\";\nimport { getSession } from \"../../api\";\nimport type { InferSession, InferUser } from \"../../types\";\nimport { getEndpointResponse } from \"../../utils/plugin-helper\";\n\nconst getSessionQuerySchema = z.optional(\n\tz.object({\n\t\t/**\n\t\t * If cookie cache is enabled, it will disable the cache\n\t\t * and fetch the session from the database\n\t\t */\n\t\tdisableCookieCache: z\n\t\t\t.boolean()\n\t\t\t.meta({\n\t\t\t\tdescription: \"Disable cookie cache and fetch session from database\",\n\t\t\t})\n\t\t\t.or(z.string().transform((v) => v === \"true\"))\n\t\t\t.optional(),\n\t\tdisableRefresh: z\n\t\t\t.boolean()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Disable session refresh. Useful for checking session status, without updating the session\",\n\t\t\t})\n\t\t\t.optional(),\n\t}),\n);\n\nexport type CustomSessionPluginOptions = {\n\t/**\n\t * This option is used to determine if the list-device-sessions endpoint should be mutated to the custom session data.\n\t * @default false\n\t */\n\tshouldMutateListDeviceSessionsEndpoint?: boolean | undefined;\n};\n\nexport const customSession = <\n\tReturns extends Record<string, any>,\n\tO extends BetterAuthOptions = BetterAuthOptions,\n>(\n\tfn: (\n\t\tsession: {\n\t\t\tuser: InferUser<O>;\n\t\t\tsession: InferSession<O>;\n\t\t},\n\t\tctx: GenericEndpointContext,\n\t) => Promise<Returns>,\n\toptions?: O | undefined,\n\tpluginOptions?: CustomSessionPluginOptions | undefined,\n) => {\n\treturn {\n\t\tid: \"custom-session\",\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher: (ctx) =>\n\t\t\t\t\t\tctx.path === \"/multi-session/list-device-sessions\" &&\n\t\t\t\t\t\t(pluginOptions?.shouldMutateListDeviceSessionsEndpoint ?? false),\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tconst response = await getEndpointResponse<[]>(ctx);\n\t\t\t\t\t\tif (!response) return;\n\t\t\t\t\t\tconst newResponse = await Promise.all(\n\t\t\t\t\t\t\tresponse.map(async (v) => await fn(v, ctx)),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn ctx.json(newResponse);\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\tendpoints: {\n\t\t\tgetSession: createAuthEndpoint(\n\t\t\t\t\"/get-session\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tquery: getSessionQuerySchema,\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tCUSTOM_SESSION: true,\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Get custom session data\",\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Session\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\trequireHeaders: true,\n\t\t\t\t},\n\t\t\t\tasync (ctx): Promise<Returns | null> => {\n\t\t\t\t\tconst session = await getSession()({\n\t\t\t\t\t\t...ctx,\n\t\t\t\t\t\tasResponse: false,\n\t\t\t\t\t\theaders: ctx.headers,\n\t\t\t\t\t\treturnHeaders: true,\n\t\t\t\t\t}).catch((e) => {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t});\n\t\t\t\t\tif (!session?.response) {\n\t\t\t\t\t\treturn ctx.json(null);\n\t\t\t\t\t}\n\t\t\t\t\tconst fnResult = await fn(session.response as any, ctx);\n\n\t\t\t\t\tconst setCookie = session.headers.get(\"set-cookie\");\n\t\t\t\t\tif (setCookie) {\n\t\t\t\t\t\tctx.setHeader(\"set-cookie\", setCookie);\n\t\t\t\t\t\tsession.headers.delete(\"set-cookie\");\n\t\t\t\t\t}\n\n\t\t\t\t\tsession.headers.forEach((value, key) => {\n\t\t\t\t\t\tctx.setHeader(key, value);\n\t\t\t\t\t});\n\t\t\t\t\treturn ctx.json(fnResult);\n\t\t\t\t},\n\t\t\t),\n\t\t},\n\t\t$Infer: {\n\t\t\tSession: {} as Awaited<ReturnType<typeof fn>>,\n\t\t},\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":";;;;;;;AAcA,MAAM,wBAAwB,EAAE,SAC/B,EAAE,OAAO;CAKR,oBAAoB,EAClB,SAAS,CACT,KAAK,EACL,aAAa,wDACb,CAAC,CACD,GAAG,EAAE,QAAQ,CAAC,WAAW,MAAM,MAAM,OAAO,CAAC,CAC7C,UAAU;CACZ,gBAAgB,EACd,SAAS,CACT,KAAK,EACL,aACC,6FACD,CAAC,CACD,UAAU;CACZ,CAAC,CACF;AAUD,MAAa,iBAIZ,IAOA,SACA,kBACI;AACJ,QAAO;EACN,IAAI;EACJ,OAAO,EACN,OAAO,CACN;GACC,UAAU,QACT,IAAI,SAAS,0CACZ,eAAe,0CAA0C;GAC3D,SAAS,qBAAqB,OAAO,QAAQ;IAC5C,MAAM,WAAW,MAAM,oBAAwB,IAAI;AACnD,QAAI,CAAC,SAAU;IACf,MAAM,cAAc,MAAM,QAAQ,IACjC,SAAS,IAAI,OAAO,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,CAC3C;AACD,WAAO,IAAI,KAAK,YAAY;KAC3B;GACF,CACD,EACD;EACD,WAAW,EACV,YAAY,mBACX,gBACA;GACC,QAAQ;GACR,OAAO;GACP,UAAU;IACT,gBAAgB;IAChB,SAAS;KACR,aAAa;KACb,WAAW,EACV,OAAO;MACN,aAAa;MACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;OACP,MAAM;OACN,UAAU;OACV,OAAO,EACN,MAAM,gCACN;OACD,EACD,EACD;MACD,EACD;KACD;IACD;GACD,gBAAgB;GAChB,EACD,OAAO,QAAiC;GACvC,MAAM,UAAU,MAAM,YAAY,CAAC;IAClC,GAAG;IACH,YAAY;IACZ,SAAS,IAAI;IACb,eAAe;IACf,CAAC,CAAC,OAAO,MAAM;AACf,WAAO;KACN;AACF,OAAI,CAAC,SAAS,SACb,QAAO,IAAI,KAAK,KAAK;GAEtB,MAAM,WAAW,MAAM,GAAG,QAAQ,UAAiB,IAAI;GAEvD,MAAM,YAAY,QAAQ,QAAQ,IAAI,aAAa;AACnD,OAAI,WAAW;AACd,QAAI,UAAU,cAAc,UAAU;AACtC,YAAQ,QAAQ,OAAO,aAAa;;AAGrC,WAAQ,QAAQ,SAAS,OAAO,QAAQ;AACvC,QAAI,UAAU,KAAK,MAAM;KACxB;AACF,UAAO,IAAI,KAAK,SAAS;IAE1B,EACD;EACD,QAAQ,EACP,SAAS,EAAE,EACX;EACD"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/custom-session/index.ts"],"sourcesContent":["import type {\n\tBetterAuthOptions,\n\tBetterAuthPlugin,\n\tGenericEndpointContext,\n} from \"@better-auth/core\";\nimport {\n\tcreateAuthEndpoint,\n\tcreateAuthMiddleware,\n} from \"@better-auth/core/api\";\nimport * as z from \"zod\";\nimport { getSession } from \"../../api\";\nimport type { InferSession, InferUser } from \"../../types\";\nimport { getEndpointResponse } from \"../../utils/plugin-helper\";\n\nconst getSessionQuerySchema = z.optional(\n\tz.object({\n\t\t/**\n\t\t * If cookie cache is enabled, it will disable the cache\n\t\t * and fetch the session from the database\n\t\t */\n\t\tdisableCookieCache: z\n\t\t\t.boolean()\n\t\t\t.meta({\n\t\t\t\tdescription: \"Disable cookie cache and fetch session from database\",\n\t\t\t})\n\t\t\t.or(z.string().transform((v) => v === \"true\"))\n\t\t\t.optional(),\n\t\tdisableRefresh: z\n\t\t\t.boolean()\n\t\t\t.meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Disable session refresh. Useful for checking session status, without updating the session\",\n\t\t\t})\n\t\t\t.optional(),\n\t}),\n);\n\nexport type CustomSessionPluginOptions = {\n\t/**\n\t * This option is used to determine if the list-device-sessions endpoint should be mutated to the custom session data.\n\t * @default false\n\t */\n\tshouldMutateListDeviceSessionsEndpoint?: boolean | undefined;\n};\n\nexport const customSession = <\n\tReturns extends Record<string, any>,\n\tO extends BetterAuthOptions = BetterAuthOptions,\n>(\n\tfn: (\n\t\tsession: {\n\t\t\tuser: InferUser<O>;\n\t\t\tsession: InferSession<O>;\n\t\t},\n\t\tctx: GenericEndpointContext,\n\t) => Promise<Returns>,\n\toptions?: O | undefined,\n\tpluginOptions?: CustomSessionPluginOptions | undefined,\n) => {\n\treturn {\n\t\tid: \"custom-session\",\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher: (ctx) =>\n\t\t\t\t\t\tctx.path === \"/multi-session/list-device-sessions\" &&\n\t\t\t\t\t\t(pluginOptions?.shouldMutateListDeviceSessionsEndpoint ?? false),\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tconst response = await getEndpointResponse<[]>(ctx);\n\t\t\t\t\t\tif (!response) return;\n\t\t\t\t\t\tconst newResponse = await Promise.all(\n\t\t\t\t\t\t\tresponse.map(async (v) => await fn(v, ctx)),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn ctx.json(newResponse);\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\tendpoints: {\n\t\t\tgetSession: createAuthEndpoint(\n\t\t\t\t\"/get-session\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tquery: getSessionQuerySchema,\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tCUSTOM_SESSION: true,\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\tdescription: \"Get custom session data\",\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Session\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\trequireHeaders: true,\n\t\t\t\t},\n\t\t\t\tasync (ctx): Promise<Returns | null> => {\n\t\t\t\t\tconst session = await getSession()({\n\t\t\t\t\t\t...ctx,\n\t\t\t\t\t\tasResponse: false,\n\t\t\t\t\t\theaders: ctx.headers,\n\t\t\t\t\t\treturnHeaders: true,\n\t\t\t\t\t}).catch((e) => {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t});\n\t\t\t\t\tif (!session?.response) {\n\t\t\t\t\t\treturn ctx.json(null);\n\t\t\t\t\t}\n\t\t\t\t\tconst fnResult = await fn(session.response as any, ctx);\n\n\t\t\t\t\tconst setCookie = session.headers.get(\"set-cookie\");\n\t\t\t\t\tif (setCookie) {\n\t\t\t\t\t\tctx.setHeader(\"set-cookie\", setCookie);\n\t\t\t\t\t\tsession.headers.delete(\"set-cookie\");\n\t\t\t\t\t}\n\n\t\t\t\t\tsession.headers.forEach((value, key) => {\n\t\t\t\t\t\tctx.setHeader(key, value);\n\t\t\t\t\t});\n\t\t\t\t\treturn ctx.json(fnResult);\n\t\t\t\t},\n\t\t\t),\n\t\t},\n\t\t$Infer: {\n\t\t\tSession: {} as Awaited<ReturnType<typeof fn>>,\n\t\t},\n\t\toptions: pluginOptions,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":";;;;;;;AAcA,MAAM,wBAAwB,EAAE,SAC/B,EAAE,OAAO;CAKR,oBAAoB,EAClB,SAAS,CACT,KAAK,EACL,aAAa,wDACb,CAAC,CACD,GAAG,EAAE,QAAQ,CAAC,WAAW,MAAM,MAAM,OAAO,CAAC,CAC7C,UAAU;CACZ,gBAAgB,EACd,SAAS,CACT,KAAK,EACL,aACC,6FACD,CAAC,CACD,UAAU;CACZ,CAAC,CACF;AAUD,MAAa,iBAIZ,IAOA,SACA,kBACI;AACJ,QAAO;EACN,IAAI;EACJ,OAAO,EACN,OAAO,CACN;GACC,UAAU,QACT,IAAI,SAAS,0CACZ,eAAe,0CAA0C;GAC3D,SAAS,qBAAqB,OAAO,QAAQ;IAC5C,MAAM,WAAW,MAAM,oBAAwB,IAAI;AACnD,QAAI,CAAC,SAAU;IACf,MAAM,cAAc,MAAM,QAAQ,IACjC,SAAS,IAAI,OAAO,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,CAC3C;AACD,WAAO,IAAI,KAAK,YAAY;KAC3B;GACF,CACD,EACD;EACD,WAAW,EACV,YAAY,mBACX,gBACA;GACC,QAAQ;GACR,OAAO;GACP,UAAU;IACT,gBAAgB;IAChB,SAAS;KACR,aAAa;KACb,WAAW,EACV,OAAO;MACN,aAAa;MACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;OACP,MAAM;OACN,UAAU;OACV,OAAO,EACN,MAAM,gCACN;OACD,EACD,EACD;MACD,EACD;KACD;IACD;GACD,gBAAgB;GAChB,EACD,OAAO,QAAiC;GACvC,MAAM,UAAU,MAAM,YAAY,CAAC;IAClC,GAAG;IACH,YAAY;IACZ,SAAS,IAAI;IACb,eAAe;IACf,CAAC,CAAC,OAAO,MAAM;AACf,WAAO;KACN;AACF,OAAI,CAAC,SAAS,SACb,QAAO,IAAI,KAAK,KAAK;GAEtB,MAAM,WAAW,MAAM,GAAG,QAAQ,UAAiB,IAAI;GAEvD,MAAM,YAAY,QAAQ,QAAQ,IAAI,aAAa;AACnD,OAAI,WAAW;AACd,QAAI,UAAU,cAAc,UAAU;AACtC,YAAQ,QAAQ,OAAO,aAAa;;AAGrC,WAAQ,QAAQ,SAAS,OAAO,QAAQ;AACvC,QAAI,UAAU,KAAK,MAAM;KACxB;AACF,UAAO,IAAI,KAAK,SAAS;IAE1B,EACD;EACD,QAAQ,EACP,SAAS,EAAE,EACX;EACD,SAAS;EACT"}
@@ -1,6 +1,6 @@
1
- import { TimeString } from "../../utils/time.mjs";
1
+ import { TimeString, ms, sec } from "../../utils/time.mjs";
2
2
  import * as z from "zod";
3
- import * as better_call135 from "better-call";
3
+ import * as better_call147 from "better-call";
4
4
 
5
5
  //#region src/plugins/device-authorization/index.d.ts
6
6
  declare const deviceAuthorizationOptionsSchema: z.ZodObject<{
@@ -91,7 +91,7 @@ declare const deviceAuthorization: (options?: Partial<DeviceAuthorizationOptions
91
91
  };
92
92
  };
93
93
  endpoints: {
94
- deviceCode: better_call135.StrictEndpoint<"/device/code", {
94
+ deviceCode: better_call147.StrictEndpoint<"/device/code", {
95
95
  method: "POST";
96
96
  body: z.ZodObject<{
97
97
  client_id: z.ZodString;
@@ -176,7 +176,7 @@ declare const deviceAuthorization: (options?: Partial<DeviceAuthorizationOptions
176
176
  expires_in: number;
177
177
  interval: number;
178
178
  }>;
179
- deviceToken: better_call135.StrictEndpoint<"/device/token", {
179
+ deviceToken: better_call147.StrictEndpoint<"/device/token", {
180
180
  method: "POST";
181
181
  body: z.ZodObject<{
182
182
  grant_type: z.ZodLiteral<"urn:ietf:params:oauth:grant-type:device_code">;
@@ -244,7 +244,7 @@ declare const deviceAuthorization: (options?: Partial<DeviceAuthorizationOptions
244
244
  expires_in: number;
245
245
  scope: string;
246
246
  }>;
247
- deviceVerify: better_call135.StrictEndpoint<"/device", {
247
+ deviceVerify: better_call147.StrictEndpoint<"/device", {
248
248
  method: "GET";
249
249
  query: z.ZodObject<{
250
250
  user_code: z.ZodString;
@@ -287,7 +287,7 @@ declare const deviceAuthorization: (options?: Partial<DeviceAuthorizationOptions
287
287
  user_code: string;
288
288
  status: string;
289
289
  }>;
290
- deviceApprove: better_call135.StrictEndpoint<"/device/approve", {
290
+ deviceApprove: better_call147.StrictEndpoint<"/device/approve", {
291
291
  method: "POST";
292
292
  body: z.ZodObject<{
293
293
  userCode: z.ZodString;
@@ -326,7 +326,7 @@ declare const deviceAuthorization: (options?: Partial<DeviceAuthorizationOptions
326
326
  }, {
327
327
  success: boolean;
328
328
  }>;
329
- deviceDeny: better_call135.StrictEndpoint<"/device/deny", {
329
+ deviceDeny: better_call147.StrictEndpoint<"/device/deny", {
330
330
  method: "POST";
331
331
  body: z.ZodObject<{
332
332
  userCode: z.ZodString;
@@ -378,7 +378,34 @@ declare const deviceAuthorization: (options?: Partial<DeviceAuthorizationOptions
378
378
  readonly INVALID_DEVICE_CODE_STATUS: "Invalid device code status";
379
379
  readonly AUTHENTICATION_REQUIRED: "Authentication required";
380
380
  };
381
+ options: Partial<{
382
+ expiresIn: TimeString;
383
+ interval: TimeString;
384
+ deviceCodeLength: number;
385
+ userCodeLength: number;
386
+ schema: {
387
+ deviceCode?: {
388
+ modelName?: string | undefined;
389
+ fields?: {
390
+ deviceCode?: string | undefined;
391
+ userCode?: string | undefined;
392
+ userId?: string | undefined;
393
+ expiresAt?: string | undefined;
394
+ status?: string | undefined;
395
+ lastPolledAt?: string | undefined;
396
+ pollingInterval?: string | undefined;
397
+ clientId?: string | undefined;
398
+ scope?: string | undefined;
399
+ } | undefined;
400
+ } | undefined;
401
+ };
402
+ generateDeviceCode?: (() => string | Promise<string>) | undefined;
403
+ generateUserCode?: (() => string | Promise<string>) | undefined;
404
+ validateClient?: ((clientId: string) => boolean | Promise<boolean>) | undefined;
405
+ onDeviceAuthRequest?: ((clientId: string, scope: string | undefined) => void | Promise<void>) | undefined;
406
+ verificationUri?: string | undefined;
407
+ }>;
381
408
  };
382
409
  //#endregion
383
- export { DeviceAuthorizationOptions, deviceAuthorization, deviceAuthorizationOptionsSchema };
410
+ export { DeviceAuthorizationOptions, TimeString, deviceAuthorization, deviceAuthorizationOptionsSchema, ms, sec };
384
411
  //# sourceMappingURL=index.d.mts.map
@@ -40,7 +40,8 @@ const deviceAuthorization = (options = {}) => {
40
40
  deviceApprove,
41
41
  deviceDeny
42
42
  },
43
- $ERROR_CODES: DEVICE_AUTHORIZATION_ERROR_CODES
43
+ $ERROR_CODES: DEVICE_AUTHORIZATION_ERROR_CODES,
44
+ options
44
45
  };
45
46
  };
46
47
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/device-authorization/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport * as z from \"zod\";\nimport { mergeSchema } from \"../../db\";\nimport type { InferOptionSchema } from \"../../types/plugins\";\nimport type { TimeString } from \"../../utils/time\";\nimport { ms } from \"../../utils/time\";\nimport { DEVICE_AUTHORIZATION_ERROR_CODES } from \"./error-codes\";\nimport {\n\tdeviceApprove,\n\tdeviceCode,\n\tdeviceDeny,\n\tdeviceToken,\n\tdeviceVerify,\n} from \"./routes\";\nimport { schema } from \"./schema\";\n\nconst timeStringSchema = z.custom<TimeString>(\n\t(val) => {\n\t\tif (typeof val !== \"string\") return false;\n\t\ttry {\n\t\t\tms(val as TimeString);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\t{\n\t\tmessage:\n\t\t\t\"Invalid time string format. Use formats like '30m', '5s', '1h', etc.\",\n\t},\n);\n\nexport const deviceAuthorizationOptionsSchema = z.object({\n\texpiresIn: timeStringSchema\n\t\t.default(\"30m\")\n\t\t.describe(\n\t\t\t\"Time in seconds until the device code expires. Use formats like '30m', '5s', '1h', etc.\",\n\t\t),\n\tinterval: timeStringSchema\n\t\t.default(\"5s\")\n\t\t.describe(\n\t\t\t\"Time in seconds between polling attempts. Use formats like '30m', '5s', '1h', etc.\",\n\t\t),\n\tdeviceCodeLength: z\n\t\t.number()\n\t\t.int()\n\t\t.positive()\n\t\t.default(40)\n\t\t.describe(\n\t\t\t\"Length of the device code to be generated. Default is 40 characters.\",\n\t\t),\n\tuserCodeLength: z\n\t\t.number()\n\t\t.int()\n\t\t.positive()\n\t\t.default(8)\n\t\t.describe(\n\t\t\t\"Length of the user code to be generated. Default is 8 characters.\",\n\t\t),\n\tgenerateDeviceCode: z\n\t\t.custom<() => string | Promise<string>>(\n\t\t\t(val) => typeof val === \"function\",\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"generateDeviceCode must be a function that returns a string or a promise that resolves to a string.\",\n\t\t\t},\n\t\t)\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"Function to generate a device code. If not provided, a default random string generator will be used.\",\n\t\t),\n\tgenerateUserCode: z\n\t\t.custom<() => string | Promise<string>>(\n\t\t\t(val) => typeof val === \"function\",\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"generateUserCode must be a function that returns a string or a promise that resolves to a string.\",\n\t\t\t},\n\t\t)\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"Function to generate a user code. If not provided, a default random string generator will be used.\",\n\t\t),\n\tvalidateClient: z\n\t\t.custom<(clientId: string) => boolean | Promise<boolean>>(\n\t\t\t(val) => typeof val === \"function\",\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"validateClient must be a function that returns a boolean or a promise that resolves to a boolean.\",\n\t\t\t},\n\t\t)\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"Function to validate the client ID. If not provided, no validation will be performed.\",\n\t\t),\n\tonDeviceAuthRequest: z\n\t\t.custom<\n\t\t\t(clientId: string, scope: string | undefined) => void | Promise<void>\n\t\t>((val) => typeof val === \"function\", {\n\t\t\tmessage:\n\t\t\t\t\"onDeviceAuthRequest must be a function that returns void or a promise that resolves to void.\",\n\t\t})\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"Function to handle device authorization requests. If not provided, no additional actions will be taken.\",\n\t\t),\n\tverificationUri: z\n\t\t.string()\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"The URI where users verify their device code. Can be an absolute URL (https://example.com/device) or relative path (/custom-path). This will be returned as verification_uri in the device code response. If not provided, defaults to /device.\",\n\t\t),\n\tschema: z.custom<InferOptionSchema<typeof schema>>(() => true),\n});\n\nexport type DeviceAuthorizationOptions = z.infer<\n\ttypeof deviceAuthorizationOptionsSchema\n>;\n\nexport const deviceAuthorization = (\n\toptions: Partial<DeviceAuthorizationOptions> = {},\n) => {\n\tconst opts = deviceAuthorizationOptionsSchema.parse(options);\n\n\treturn {\n\t\tid: \"device-authorization\",\n\t\tschema: mergeSchema(schema, options?.schema),\n\t\tendpoints: {\n\t\t\tdeviceCode: deviceCode(opts),\n\t\t\tdeviceToken: deviceToken(opts),\n\t\t\tdeviceVerify,\n\t\t\tdeviceApprove,\n\t\t\tdeviceDeny,\n\t\t},\n\t\t$ERROR_CODES: DEVICE_AUTHORIZATION_ERROR_CODES,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":";;;;;;;;;AAgBA,MAAM,mBAAmB,EAAE,QACzB,QAAQ;AACR,KAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,KAAI;AACH,KAAG,IAAkB;AACrB,SAAO;SACA;AACP,SAAO;;GAGT,EACC,SACC,wEACD,CACD;AAED,MAAa,mCAAmC,EAAE,OAAO;CACxD,WAAW,iBACT,QAAQ,MAAM,CACd,SACA,0FACA;CACF,UAAU,iBACR,QAAQ,KAAK,CACb,SACA,qFACA;CACF,kBAAkB,EAChB,QAAQ,CACR,KAAK,CACL,UAAU,CACV,QAAQ,GAAG,CACX,SACA,uEACA;CACF,gBAAgB,EACd,QAAQ,CACR,KAAK,CACL,UAAU,CACV,QAAQ,EAAE,CACV,SACA,oEACA;CACF,oBAAoB,EAClB,QACC,QAAQ,OAAO,QAAQ,YACxB,EACC,SACC,uGACD,CACD,CACA,UAAU,CACV,SACA,uGACA;CACF,kBAAkB,EAChB,QACC,QAAQ,OAAO,QAAQ,YACxB,EACC,SACC,qGACD,CACD,CACA,UAAU,CACV,SACA,qGACA;CACF,gBAAgB,EACd,QACC,QAAQ,OAAO,QAAQ,YACxB,EACC,SACC,qGACD,CACD,CACA,UAAU,CACV,SACA,wFACA;CACF,qBAAqB,EACnB,QAEE,QAAQ,OAAO,QAAQ,YAAY,EACrC,SACC,gGACD,CAAC,CACD,UAAU,CACV,SACA,0GACA;CACF,iBAAiB,EACf,QAAQ,CACR,UAAU,CACV,SACA,kPACA;CACF,QAAQ,EAAE,aAA+C,KAAK;CAC9D,CAAC;AAMF,MAAa,uBACZ,UAA+C,EAAE,KAC7C;CACJ,MAAM,OAAO,iCAAiC,MAAM,QAAQ;AAE5D,QAAO;EACN,IAAI;EACJ,QAAQ,YAAY,QAAQ,SAAS,OAAO;EAC5C,WAAW;GACV,YAAY,WAAW,KAAK;GAC5B,aAAa,YAAY,KAAK;GAC9B;GACA;GACA;GACA;EACD,cAAc;EACd"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/device-authorization/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport * as z from \"zod\";\nimport { mergeSchema } from \"../../db\";\nimport type { InferOptionSchema } from \"../../types/plugins\";\nimport type { TimeString } from \"../../utils/time\";\nimport { ms } from \"../../utils/time\";\nimport { DEVICE_AUTHORIZATION_ERROR_CODES } from \"./error-codes\";\nimport {\n\tdeviceApprove,\n\tdeviceCode,\n\tdeviceDeny,\n\tdeviceToken,\n\tdeviceVerify,\n} from \"./routes\";\nimport { schema } from \"./schema\";\n\nconst timeStringSchema = z.custom<TimeString>(\n\t(val) => {\n\t\tif (typeof val !== \"string\") return false;\n\t\ttry {\n\t\t\tms(val as TimeString);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t},\n\t{\n\t\tmessage:\n\t\t\t\"Invalid time string format. Use formats like '30m', '5s', '1h', etc.\",\n\t},\n);\n\nexport const deviceAuthorizationOptionsSchema = z.object({\n\texpiresIn: timeStringSchema\n\t\t.default(\"30m\")\n\t\t.describe(\n\t\t\t\"Time in seconds until the device code expires. Use formats like '30m', '5s', '1h', etc.\",\n\t\t),\n\tinterval: timeStringSchema\n\t\t.default(\"5s\")\n\t\t.describe(\n\t\t\t\"Time in seconds between polling attempts. Use formats like '30m', '5s', '1h', etc.\",\n\t\t),\n\tdeviceCodeLength: z\n\t\t.number()\n\t\t.int()\n\t\t.positive()\n\t\t.default(40)\n\t\t.describe(\n\t\t\t\"Length of the device code to be generated. Default is 40 characters.\",\n\t\t),\n\tuserCodeLength: z\n\t\t.number()\n\t\t.int()\n\t\t.positive()\n\t\t.default(8)\n\t\t.describe(\n\t\t\t\"Length of the user code to be generated. Default is 8 characters.\",\n\t\t),\n\tgenerateDeviceCode: z\n\t\t.custom<() => string | Promise<string>>(\n\t\t\t(val) => typeof val === \"function\",\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"generateDeviceCode must be a function that returns a string or a promise that resolves to a string.\",\n\t\t\t},\n\t\t)\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"Function to generate a device code. If not provided, a default random string generator will be used.\",\n\t\t),\n\tgenerateUserCode: z\n\t\t.custom<() => string | Promise<string>>(\n\t\t\t(val) => typeof val === \"function\",\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"generateUserCode must be a function that returns a string or a promise that resolves to a string.\",\n\t\t\t},\n\t\t)\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"Function to generate a user code. If not provided, a default random string generator will be used.\",\n\t\t),\n\tvalidateClient: z\n\t\t.custom<(clientId: string) => boolean | Promise<boolean>>(\n\t\t\t(val) => typeof val === \"function\",\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"validateClient must be a function that returns a boolean or a promise that resolves to a boolean.\",\n\t\t\t},\n\t\t)\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"Function to validate the client ID. If not provided, no validation will be performed.\",\n\t\t),\n\tonDeviceAuthRequest: z\n\t\t.custom<\n\t\t\t(clientId: string, scope: string | undefined) => void | Promise<void>\n\t\t>((val) => typeof val === \"function\", {\n\t\t\tmessage:\n\t\t\t\t\"onDeviceAuthRequest must be a function that returns void or a promise that resolves to void.\",\n\t\t})\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"Function to handle device authorization requests. If not provided, no additional actions will be taken.\",\n\t\t),\n\tverificationUri: z\n\t\t.string()\n\t\t.optional()\n\t\t.describe(\n\t\t\t\"The URI where users verify their device code. Can be an absolute URL (https://example.com/device) or relative path (/custom-path). This will be returned as verification_uri in the device code response. If not provided, defaults to /device.\",\n\t\t),\n\tschema: z.custom<InferOptionSchema<typeof schema>>(() => true),\n});\n\nexport type DeviceAuthorizationOptions = z.infer<\n\ttypeof deviceAuthorizationOptionsSchema\n>;\n\nexport const deviceAuthorization = (\n\toptions: Partial<DeviceAuthorizationOptions> = {},\n) => {\n\tconst opts = deviceAuthorizationOptionsSchema.parse(options);\n\n\treturn {\n\t\tid: \"device-authorization\",\n\t\tschema: mergeSchema(schema, options?.schema),\n\t\tendpoints: {\n\t\t\tdeviceCode: deviceCode(opts),\n\t\t\tdeviceToken: deviceToken(opts),\n\t\t\tdeviceVerify,\n\t\t\tdeviceApprove,\n\t\t\tdeviceDeny,\n\t\t},\n\t\t$ERROR_CODES: DEVICE_AUTHORIZATION_ERROR_CODES,\n\t\toptions,\n\t} satisfies BetterAuthPlugin;\n};\n\nexport type * from \"../../utils/time\";\n"],"mappings":";;;;;;;;;AAgBA,MAAM,mBAAmB,EAAE,QACzB,QAAQ;AACR,KAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,KAAI;AACH,KAAG,IAAkB;AACrB,SAAO;SACA;AACP,SAAO;;GAGT,EACC,SACC,wEACD,CACD;AAED,MAAa,mCAAmC,EAAE,OAAO;CACxD,WAAW,iBACT,QAAQ,MAAM,CACd,SACA,0FACA;CACF,UAAU,iBACR,QAAQ,KAAK,CACb,SACA,qFACA;CACF,kBAAkB,EAChB,QAAQ,CACR,KAAK,CACL,UAAU,CACV,QAAQ,GAAG,CACX,SACA,uEACA;CACF,gBAAgB,EACd,QAAQ,CACR,KAAK,CACL,UAAU,CACV,QAAQ,EAAE,CACV,SACA,oEACA;CACF,oBAAoB,EAClB,QACC,QAAQ,OAAO,QAAQ,YACxB,EACC,SACC,uGACD,CACD,CACA,UAAU,CACV,SACA,uGACA;CACF,kBAAkB,EAChB,QACC,QAAQ,OAAO,QAAQ,YACxB,EACC,SACC,qGACD,CACD,CACA,UAAU,CACV,SACA,qGACA;CACF,gBAAgB,EACd,QACC,QAAQ,OAAO,QAAQ,YACxB,EACC,SACC,qGACD,CACD,CACA,UAAU,CACV,SACA,wFACA;CACF,qBAAqB,EACnB,QAEE,QAAQ,OAAO,QAAQ,YAAY,EACrC,SACC,gGACD,CAAC,CACD,UAAU,CACV,SACA,0GACA;CACF,iBAAiB,EACf,QAAQ,CACR,UAAU,CACV,SACA,kPACA;CACF,QAAQ,EAAE,aAA+C,KAAK;CAC9D,CAAC;AAMF,MAAa,uBACZ,UAA+C,EAAE,KAC7C;CACJ,MAAM,OAAO,iCAAiC,MAAM,QAAQ;AAE5D,QAAO;EACN,IAAI;EACJ,QAAQ,YAAY,QAAQ,SAAS,OAAO;EAC5C,WAAW;GACV,YAAY,WAAW,KAAK;GAC5B,aAAa,YAAY,KAAK;GAC9B;GACA;GACA;GACA;EACD,cAAc;EACd;EACA"}
@@ -1,14 +1,14 @@
1
1
  import { EmailOTPOptions } from "./types.mjs";
2
- import * as _better_auth_core4 from "@better-auth/core";
2
+ import * as _better_auth_core0 from "@better-auth/core";
3
3
  import * as _better_auth_core_db0 from "@better-auth/core/db";
4
- import * as zod437 from "zod";
5
- import * as better_call140 from "better-call";
6
- import * as zod_v4_core59 from "zod/v4/core";
4
+ import * as zod0 from "zod";
5
+ import * as better_call0 from "better-call";
6
+ import * as zod_v4_core0 from "zod/v4/core";
7
7
 
8
8
  //#region src/plugins/email-otp/index.d.ts
9
9
  declare const emailOTP: (options: EmailOTPOptions) => {
10
10
  id: "email-otp";
11
- init(ctx: _better_auth_core4.AuthContext): {
11
+ init(ctx: _better_auth_core0.AuthContext): {
12
12
  options: {
13
13
  emailVerification: {
14
14
  sendVerificationEmail(data: {
@@ -20,16 +20,16 @@ declare const emailOTP: (options: EmailOTPOptions) => {
20
20
  };
21
21
  } | undefined;
22
22
  endpoints: {
23
- sendVerificationOTP: better_call140.StrictEndpoint<"/email-otp/send-verification-otp", {
23
+ sendVerificationOTP: better_call0.StrictEndpoint<"/email-otp/send-verification-otp", {
24
24
  method: "POST";
25
- body: zod437.ZodObject<{
26
- email: zod437.ZodString;
27
- type: zod437.ZodEnum<{
25
+ body: zod0.ZodObject<{
26
+ email: zod0.ZodString;
27
+ type: zod0.ZodEnum<{
28
28
  "sign-in": "sign-in";
29
29
  "email-verification": "email-verification";
30
30
  "forget-password": "forget-password";
31
31
  }>;
32
- }, zod_v4_core59.$strip>;
32
+ }, zod_v4_core0.$strip>;
33
33
  metadata: {
34
34
  openapi: {
35
35
  operationId: string;
@@ -56,16 +56,16 @@ declare const emailOTP: (options: EmailOTPOptions) => {
56
56
  }, {
57
57
  success: boolean;
58
58
  }>;
59
- createVerificationOTP: better_call140.StrictEndpoint<string, {
59
+ createVerificationOTP: better_call0.StrictEndpoint<string, {
60
60
  method: "POST";
61
- body: zod437.ZodObject<{
62
- email: zod437.ZodString;
63
- type: zod437.ZodEnum<{
61
+ body: zod0.ZodObject<{
62
+ email: zod0.ZodString;
63
+ type: zod0.ZodEnum<{
64
64
  "sign-in": "sign-in";
65
65
  "email-verification": "email-verification";
66
66
  "forget-password": "forget-password";
67
67
  }>;
68
- }, zod_v4_core59.$strip>;
68
+ }, zod_v4_core0.$strip>;
69
69
  metadata: {
70
70
  openapi: {
71
71
  operationId: string;
@@ -85,16 +85,16 @@ declare const emailOTP: (options: EmailOTPOptions) => {
85
85
  };
86
86
  };
87
87
  }, string>;
88
- getVerificationOTP: better_call140.StrictEndpoint<string, {
88
+ getVerificationOTP: better_call0.StrictEndpoint<string, {
89
89
  method: "GET";
90
- query: zod437.ZodObject<{
91
- email: zod437.ZodString;
92
- type: zod437.ZodEnum<{
90
+ query: zod0.ZodObject<{
91
+ email: zod0.ZodString;
92
+ type: zod0.ZodEnum<{
93
93
  "sign-in": "sign-in";
94
94
  "email-verification": "email-verification";
95
95
  "forget-password": "forget-password";
96
96
  }>;
97
- }, zod_v4_core59.$strip>;
97
+ }, zod_v4_core0.$strip>;
98
98
  metadata: {
99
99
  openapi: {
100
100
  operationId: string;
@@ -126,17 +126,17 @@ declare const emailOTP: (options: EmailOTPOptions) => {
126
126
  } | {
127
127
  otp: string;
128
128
  }>;
129
- checkVerificationOTP: better_call140.StrictEndpoint<"/email-otp/check-verification-otp", {
129
+ checkVerificationOTP: better_call0.StrictEndpoint<"/email-otp/check-verification-otp", {
130
130
  method: "POST";
131
- body: zod437.ZodObject<{
132
- email: zod437.ZodString;
133
- type: zod437.ZodEnum<{
131
+ body: zod0.ZodObject<{
132
+ email: zod0.ZodString;
133
+ type: zod0.ZodEnum<{
134
134
  "sign-in": "sign-in";
135
135
  "email-verification": "email-verification";
136
136
  "forget-password": "forget-password";
137
137
  }>;
138
- otp: zod437.ZodString;
139
- }, zod_v4_core59.$strip>;
138
+ otp: zod0.ZodString;
139
+ }, zod_v4_core0.$strip>;
140
140
  metadata: {
141
141
  openapi: {
142
142
  operationId: string;
@@ -163,12 +163,12 @@ declare const emailOTP: (options: EmailOTPOptions) => {
163
163
  }, {
164
164
  success: boolean;
165
165
  }>;
166
- verifyEmailOTP: better_call140.StrictEndpoint<"/email-otp/verify-email", {
166
+ verifyEmailOTP: better_call0.StrictEndpoint<"/email-otp/verify-email", {
167
167
  method: "POST";
168
- body: zod437.ZodObject<{
169
- email: zod437.ZodString;
170
- otp: zod437.ZodString;
171
- }, zod_v4_core59.$strip>;
168
+ body: zod0.ZodObject<{
169
+ email: zod0.ZodString;
170
+ otp: zod0.ZodString;
171
+ }, zod_v4_core0.$strip>;
172
172
  metadata: {
173
173
  openapi: {
174
174
  description: string;
@@ -227,12 +227,12 @@ declare const emailOTP: (options: EmailOTPOptions) => {
227
227
  updatedAt: Date;
228
228
  };
229
229
  }>;
230
- signInEmailOTP: better_call140.StrictEndpoint<"/sign-in/email-otp", {
230
+ signInEmailOTP: better_call0.StrictEndpoint<"/sign-in/email-otp", {
231
231
  method: "POST";
232
- body: zod437.ZodObject<{
233
- email: zod437.ZodString;
234
- otp: zod437.ZodString;
235
- }, zod_v4_core59.$strip>;
232
+ body: zod0.ZodObject<{
233
+ email: zod0.ZodString;
234
+ otp: zod0.ZodString;
235
+ }, zod_v4_core0.$strip>;
236
236
  metadata: {
237
237
  openapi: {
238
238
  operationId: string;
@@ -273,11 +273,11 @@ declare const emailOTP: (options: EmailOTPOptions) => {
273
273
  updatedAt: Date;
274
274
  };
275
275
  }>;
276
- forgetPasswordEmailOTP: better_call140.StrictEndpoint<"/forget-password/email-otp", {
276
+ forgetPasswordEmailOTP: better_call0.StrictEndpoint<"/forget-password/email-otp", {
277
277
  method: "POST";
278
- body: zod437.ZodObject<{
279
- email: zod437.ZodString;
280
- }, zod_v4_core59.$strip>;
278
+ body: zod0.ZodObject<{
279
+ email: zod0.ZodString;
280
+ }, zod_v4_core0.$strip>;
281
281
  metadata: {
282
282
  openapi: {
283
283
  operationId: string;
@@ -305,13 +305,13 @@ declare const emailOTP: (options: EmailOTPOptions) => {
305
305
  }, {
306
306
  success: boolean;
307
307
  }>;
308
- resetPasswordEmailOTP: better_call140.StrictEndpoint<"/email-otp/reset-password", {
308
+ resetPasswordEmailOTP: better_call0.StrictEndpoint<"/email-otp/reset-password", {
309
309
  method: "POST";
310
- body: zod437.ZodObject<{
311
- email: zod437.ZodString;
312
- otp: zod437.ZodString;
313
- password: zod437.ZodString;
314
- }, zod_v4_core59.$strip>;
310
+ body: zod0.ZodObject<{
311
+ email: zod0.ZodString;
312
+ otp: zod0.ZodString;
313
+ password: zod0.ZodString;
314
+ }, zod_v4_core0.$strip>;
315
315
  metadata: {
316
316
  openapi: {
317
317
  operationId: string;
@@ -341,8 +341,8 @@ declare const emailOTP: (options: EmailOTPOptions) => {
341
341
  };
342
342
  hooks: {
343
343
  after: {
344
- matcher(context: _better_auth_core4.HookEndpointContext): boolean;
345
- handler: (inputContext: better_call140.MiddlewareInputContext<better_call140.MiddlewareOptions>) => Promise<void>;
344
+ matcher(context: _better_auth_core0.HookEndpointContext): boolean;
345
+ handler: (inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<void>;
346
346
  }[];
347
347
  };
348
348
  $ERROR_CODES: {
@@ -367,6 +367,7 @@ declare const emailOTP: (options: EmailOTPOptions) => {
367
367
  window: number;
368
368
  max: number;
369
369
  })[];
370
+ options: EmailOTPOptions;
370
371
  };
371
372
  //#endregion
372
373
  export { type EmailOTPOptions, emailOTP };
@@ -97,7 +97,8 @@ const emailOTP = (options) => {
97
97
  window: 60,
98
98
  max: 3
99
99
  }
100
- ]
100
+ ],
101
+ options
101
102
  };
102
103
  };
103
104
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/email-otp/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { createAuthMiddleware } from \"@better-auth/core/api\";\nimport { generateRandomString } from \"../../crypto\";\nimport { getDate } from \"../../utils/date\";\nimport { getEndpointResponse } from \"../../utils/plugin-helper\";\nimport { storeOTP } from \"./otp-token\";\nimport {\n\tcheckVerificationOTP,\n\tcreateVerificationOTP,\n\tERROR_CODES,\n\tforgetPasswordEmailOTP,\n\tgetVerificationOTP,\n\tresetPasswordEmailOTP,\n\tsendVerificationOTP,\n\tsignInEmailOTP,\n\tverifyEmailOTP,\n} from \"./routes\";\nimport type { EmailOTPOptions } from \"./types\";\n\nexport type { EmailOTPOptions } from \"./types\";\n\nconst defaultOTPGenerator = (options: EmailOTPOptions) =>\n\tgenerateRandomString(options.otpLength ?? 6, \"0-9\");\n\nexport const emailOTP = (options: EmailOTPOptions) => {\n\tconst opts = {\n\t\texpiresIn: 5 * 60,\n\t\tgenerateOTP: () => defaultOTPGenerator(options),\n\t\tstoreOTP: \"plain\",\n\t\t...options,\n\t} satisfies EmailOTPOptions;\n\n\tconst sendVerificationOTPAction = sendVerificationOTP(opts);\n\n\treturn {\n\t\tid: \"email-otp\",\n\t\tinit(ctx) {\n\t\t\tif (!opts.overrideDefaultEmailVerification) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\toptions: {\n\t\t\t\t\temailVerification: {\n\t\t\t\t\t\tasync sendVerificationEmail(data, request) {\n\t\t\t\t\t\t\tawait sendVerificationOTPAction({\n\t\t\t\t\t\t\t\t//@ts-expect-error - we need to pass the context\n\t\t\t\t\t\t\t\tcontext: ctx,\n\t\t\t\t\t\t\t\trequest: request,\n\t\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\temail: data.user.email,\n\t\t\t\t\t\t\t\t\ttype: \"email-verification\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tendpoints: {\n\t\t\tsendVerificationOTP: sendVerificationOTPAction,\n\t\t\tcreateVerificationOTP: createVerificationOTP(opts),\n\t\t\tgetVerificationOTP: getVerificationOTP(opts),\n\t\t\tcheckVerificationOTP: checkVerificationOTP(opts),\n\t\t\tverifyEmailOTP: verifyEmailOTP(opts),\n\t\t\tsignInEmailOTP: signInEmailOTP(opts),\n\t\t\tforgetPasswordEmailOTP: forgetPasswordEmailOTP(opts),\n\t\t\tresetPasswordEmailOTP: resetPasswordEmailOTP(opts),\n\t\t},\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher(context) {\n\t\t\t\t\t\treturn !!(\n\t\t\t\t\t\t\tcontext.path?.startsWith(\"/sign-up\") &&\n\t\t\t\t\t\t\topts.sendVerificationOnSignUp &&\n\t\t\t\t\t\t\t!opts.overrideDefaultEmailVerification\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tconst response = await getEndpointResponse<{\n\t\t\t\t\t\t\tuser: { email: string };\n\t\t\t\t\t\t}>(ctx);\n\t\t\t\t\t\tconst email = response?.user.email;\n\t\t\t\t\t\tif (email) {\n\t\t\t\t\t\t\tconst otp =\n\t\t\t\t\t\t\t\topts.generateOTP({ email, type: ctx.body.type }, ctx) ||\n\t\t\t\t\t\t\t\tdefaultOTPGenerator(opts);\n\t\t\t\t\t\t\tlet storedOTP = await storeOTP(ctx, opts, otp);\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\t\t\t\t\tidentifier: `email-verification-otp-${email}`,\n\t\t\t\t\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tawait options.sendVerificationOTP(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\temail,\n\t\t\t\t\t\t\t\t\totp,\n\t\t\t\t\t\t\t\t\ttype: \"email-verification\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t$ERROR_CODES: ERROR_CODES,\n\t\trateLimit: [\n\t\t\t{\n\t\t\t\tpathMatcher(path) {\n\t\t\t\t\treturn path === \"/email-otp/send-verification-otp\";\n\t\t\t\t},\n\t\t\t\twindow: 60,\n\t\t\t\tmax: 3,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpathMatcher(path) {\n\t\t\t\t\treturn path === \"/email-otp/check-verification-otp\";\n\t\t\t\t},\n\t\t\t\twindow: 60,\n\t\t\t\tmax: 3,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpathMatcher(path) {\n\t\t\t\t\treturn path === \"/email-otp/verify-email\";\n\t\t\t\t},\n\t\t\t\twindow: 60,\n\t\t\t\tmax: 3,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpathMatcher(path) {\n\t\t\t\t\treturn path === \"/sign-in/email-otp\";\n\t\t\t\t},\n\t\t\t\twindow: 60,\n\t\t\t\tmax: 3,\n\t\t\t},\n\t\t],\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":";;;;;;;;;AAqBA,MAAM,uBAAuB,YAC5B,qBAAqB,QAAQ,aAAa,GAAG,MAAM;AAEpD,MAAa,YAAY,YAA6B;CACrD,MAAM,OAAO;EACZ,WAAW;EACX,mBAAmB,oBAAoB,QAAQ;EAC/C,UAAU;EACV,GAAG;EACH;CAED,MAAM,4BAA4B,oBAAoB,KAAK;AAE3D,QAAO;EACN,IAAI;EACJ,KAAK,KAAK;AACT,OAAI,CAAC,KAAK,iCACT;AAED,UAAO,EACN,SAAS,EACR,mBAAmB,EAClB,MAAM,sBAAsB,MAAM,SAAS;AAC1C,UAAM,0BAA0B;KAE/B,SAAS;KACA;KACT,MAAM;MACL,OAAO,KAAK,KAAK;MACjB,MAAM;MACN;KACD;KACA,CAAC;MAEH,EACD,EACD;;EAEF,WAAW;GACV,qBAAqB;GACrB,uBAAuB,sBAAsB,KAAK;GAClD,oBAAoB,mBAAmB,KAAK;GAC5C,sBAAsB,qBAAqB,KAAK;GAChD,gBAAgB,eAAe,KAAK;GACpC,gBAAgB,eAAe,KAAK;GACpC,wBAAwB,uBAAuB,KAAK;GACpD,uBAAuB,sBAAsB,KAAK;GAClD;EACD,OAAO,EACN,OAAO,CACN;GACC,QAAQ,SAAS;AAChB,WAAO,CAAC,EACP,QAAQ,MAAM,WAAW,WAAW,IACpC,KAAK,4BACL,CAAC,KAAK;;GAGR,SAAS,qBAAqB,OAAO,QAAQ;IAI5C,MAAM,SAHW,MAAM,oBAEpB,IAAI,GACiB,KAAK;AAC7B,QAAI,OAAO;KACV,MAAM,MACL,KAAK,YAAY;MAAE;MAAO,MAAM,IAAI,KAAK;MAAM,EAAE,IAAI,IACrD,oBAAoB,KAAK;KAC1B,IAAI,YAAY,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9C,WAAM,IAAI,QAAQ,gBAAgB,wBAAwB;MACzD,OAAO,GAAG,UAAU;MACpB,YAAY,0BAA0B;MACtC,WAAW,QAAQ,KAAK,WAAW,MAAM;MACzC,CAAC;AACF,WAAM,QAAQ,oBACb;MACC;MACA;MACA,MAAM;MACN,EACD,IACA;;KAED;GACF,CACD,EACD;EACD,cAAc;EACd,WAAW;GACV;IACC,YAAY,MAAM;AACjB,YAAO,SAAS;;IAEjB,QAAQ;IACR,KAAK;IACL;GACD;IACC,YAAY,MAAM;AACjB,YAAO,SAAS;;IAEjB,QAAQ;IACR,KAAK;IACL;GACD;IACC,YAAY,MAAM;AACjB,YAAO,SAAS;;IAEjB,QAAQ;IACR,KAAK;IACL;GACD;IACC,YAAY,MAAM;AACjB,YAAO,SAAS;;IAEjB,QAAQ;IACR,KAAK;IACL;GACD;EACD"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/email-otp/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { createAuthMiddleware } from \"@better-auth/core/api\";\nimport { generateRandomString } from \"../../crypto\";\nimport { getDate } from \"../../utils/date\";\nimport { getEndpointResponse } from \"../../utils/plugin-helper\";\nimport { storeOTP } from \"./otp-token\";\nimport {\n\tcheckVerificationOTP,\n\tcreateVerificationOTP,\n\tERROR_CODES,\n\tforgetPasswordEmailOTP,\n\tgetVerificationOTP,\n\tresetPasswordEmailOTP,\n\tsendVerificationOTP,\n\tsignInEmailOTP,\n\tverifyEmailOTP,\n} from \"./routes\";\nimport type { EmailOTPOptions } from \"./types\";\n\nexport type { EmailOTPOptions } from \"./types\";\n\nconst defaultOTPGenerator = (options: EmailOTPOptions) =>\n\tgenerateRandomString(options.otpLength ?? 6, \"0-9\");\n\nexport const emailOTP = (options: EmailOTPOptions) => {\n\tconst opts = {\n\t\texpiresIn: 5 * 60,\n\t\tgenerateOTP: () => defaultOTPGenerator(options),\n\t\tstoreOTP: \"plain\",\n\t\t...options,\n\t} satisfies EmailOTPOptions;\n\n\tconst sendVerificationOTPAction = sendVerificationOTP(opts);\n\n\treturn {\n\t\tid: \"email-otp\",\n\t\tinit(ctx) {\n\t\t\tif (!opts.overrideDefaultEmailVerification) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\toptions: {\n\t\t\t\t\temailVerification: {\n\t\t\t\t\t\tasync sendVerificationEmail(data, request) {\n\t\t\t\t\t\t\tawait sendVerificationOTPAction({\n\t\t\t\t\t\t\t\t//@ts-expect-error - we need to pass the context\n\t\t\t\t\t\t\t\tcontext: ctx,\n\t\t\t\t\t\t\t\trequest: request,\n\t\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\temail: data.user.email,\n\t\t\t\t\t\t\t\t\ttype: \"email-verification\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tendpoints: {\n\t\t\tsendVerificationOTP: sendVerificationOTPAction,\n\t\t\tcreateVerificationOTP: createVerificationOTP(opts),\n\t\t\tgetVerificationOTP: getVerificationOTP(opts),\n\t\t\tcheckVerificationOTP: checkVerificationOTP(opts),\n\t\t\tverifyEmailOTP: verifyEmailOTP(opts),\n\t\t\tsignInEmailOTP: signInEmailOTP(opts),\n\t\t\tforgetPasswordEmailOTP: forgetPasswordEmailOTP(opts),\n\t\t\tresetPasswordEmailOTP: resetPasswordEmailOTP(opts),\n\t\t},\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher(context) {\n\t\t\t\t\t\treturn !!(\n\t\t\t\t\t\t\tcontext.path?.startsWith(\"/sign-up\") &&\n\t\t\t\t\t\t\topts.sendVerificationOnSignUp &&\n\t\t\t\t\t\t\t!opts.overrideDefaultEmailVerification\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tconst response = await getEndpointResponse<{\n\t\t\t\t\t\t\tuser: { email: string };\n\t\t\t\t\t\t}>(ctx);\n\t\t\t\t\t\tconst email = response?.user.email;\n\t\t\t\t\t\tif (email) {\n\t\t\t\t\t\t\tconst otp =\n\t\t\t\t\t\t\t\topts.generateOTP({ email, type: ctx.body.type }, ctx) ||\n\t\t\t\t\t\t\t\tdefaultOTPGenerator(opts);\n\t\t\t\t\t\t\tlet storedOTP = await storeOTP(ctx, opts, otp);\n\t\t\t\t\t\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\t\t\t\t\t\tvalue: `${storedOTP}:0`,\n\t\t\t\t\t\t\t\tidentifier: `email-verification-otp-${email}`,\n\t\t\t\t\t\t\t\texpiresAt: getDate(opts.expiresIn, \"sec\"),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tawait options.sendVerificationOTP(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\temail,\n\t\t\t\t\t\t\t\t\totp,\n\t\t\t\t\t\t\t\t\ttype: \"email-verification\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t$ERROR_CODES: ERROR_CODES,\n\t\trateLimit: [\n\t\t\t{\n\t\t\t\tpathMatcher(path) {\n\t\t\t\t\treturn path === \"/email-otp/send-verification-otp\";\n\t\t\t\t},\n\t\t\t\twindow: 60,\n\t\t\t\tmax: 3,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpathMatcher(path) {\n\t\t\t\t\treturn path === \"/email-otp/check-verification-otp\";\n\t\t\t\t},\n\t\t\t\twindow: 60,\n\t\t\t\tmax: 3,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpathMatcher(path) {\n\t\t\t\t\treturn path === \"/email-otp/verify-email\";\n\t\t\t\t},\n\t\t\t\twindow: 60,\n\t\t\t\tmax: 3,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpathMatcher(path) {\n\t\t\t\t\treturn path === \"/sign-in/email-otp\";\n\t\t\t\t},\n\t\t\t\twindow: 60,\n\t\t\t\tmax: 3,\n\t\t\t},\n\t\t],\n\t\toptions,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":";;;;;;;;;AAqBA,MAAM,uBAAuB,YAC5B,qBAAqB,QAAQ,aAAa,GAAG,MAAM;AAEpD,MAAa,YAAY,YAA6B;CACrD,MAAM,OAAO;EACZ,WAAW;EACX,mBAAmB,oBAAoB,QAAQ;EAC/C,UAAU;EACV,GAAG;EACH;CAED,MAAM,4BAA4B,oBAAoB,KAAK;AAE3D,QAAO;EACN,IAAI;EACJ,KAAK,KAAK;AACT,OAAI,CAAC,KAAK,iCACT;AAED,UAAO,EACN,SAAS,EACR,mBAAmB,EAClB,MAAM,sBAAsB,MAAM,SAAS;AAC1C,UAAM,0BAA0B;KAE/B,SAAS;KACA;KACT,MAAM;MACL,OAAO,KAAK,KAAK;MACjB,MAAM;MACN;KACD;KACA,CAAC;MAEH,EACD,EACD;;EAEF,WAAW;GACV,qBAAqB;GACrB,uBAAuB,sBAAsB,KAAK;GAClD,oBAAoB,mBAAmB,KAAK;GAC5C,sBAAsB,qBAAqB,KAAK;GAChD,gBAAgB,eAAe,KAAK;GACpC,gBAAgB,eAAe,KAAK;GACpC,wBAAwB,uBAAuB,KAAK;GACpD,uBAAuB,sBAAsB,KAAK;GAClD;EACD,OAAO,EACN,OAAO,CACN;GACC,QAAQ,SAAS;AAChB,WAAO,CAAC,EACP,QAAQ,MAAM,WAAW,WAAW,IACpC,KAAK,4BACL,CAAC,KAAK;;GAGR,SAAS,qBAAqB,OAAO,QAAQ;IAI5C,MAAM,SAHW,MAAM,oBAEpB,IAAI,GACiB,KAAK;AAC7B,QAAI,OAAO;KACV,MAAM,MACL,KAAK,YAAY;MAAE;MAAO,MAAM,IAAI,KAAK;MAAM,EAAE,IAAI,IACrD,oBAAoB,KAAK;KAC1B,IAAI,YAAY,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9C,WAAM,IAAI,QAAQ,gBAAgB,wBAAwB;MACzD,OAAO,GAAG,UAAU;MACpB,YAAY,0BAA0B;MACtC,WAAW,QAAQ,KAAK,WAAW,MAAM;MACzC,CAAC;AACF,WAAM,QAAQ,oBACb;MACC;MACA;MACA,MAAM;MACN,EACD,IACA;;KAED;GACF,CACD,EACD;EACD,cAAc;EACd,WAAW;GACV;IACC,YAAY,MAAM;AACjB,YAAO,SAAS;;IAEjB,QAAQ;IACR,KAAK;IACL;GACD;IACC,YAAY,MAAM;AACjB,YAAO,SAAS;;IAEjB,QAAQ;IACR,KAAK;IACL;GACD;IACC,YAAY,MAAM;AACjB,YAAO,SAAS;;IAEjB,QAAQ;IACR,KAAK;IACL;GACD;IACC,YAAY,MAAM;AACjB,YAAO,SAAS;;IAEjB,QAAQ;IACR,KAAK;IACL;GACD;EACD;EACA"}
@@ -175,6 +175,7 @@ declare const genericOAuth: (options: GenericOAuthOptions) => {
175
175
  redirect: boolean;
176
176
  }>;
177
177
  };
178
+ options: GenericOAuthOptions;
178
179
  $ERROR_CODES: {
179
180
  readonly INVALID_OAUTH_CONFIGURATION: "Invalid OAuth configuration";
180
181
  readonly TOKEN_URL_NOT_FOUND: "Invalid OAuth configuration. Token URL not found.";
@@ -126,6 +126,7 @@ const genericOAuth = (options) => {
126
126
  oAuth2Callback: oAuth2Callback(options),
127
127
  oAuth2LinkAccount: oAuth2LinkAccount(options)
128
128
  },
129
+ options,
129
130
  $ERROR_CODES: GENERIC_OAUTH_ERROR_CODES
130
131
  };
131
132
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/generic-oauth/index.ts"],"sourcesContent":["import type { AuthContext, BetterAuthPlugin } from \"@better-auth/core\";\nimport type { OAuth2Tokens, OAuthProvider } from \"@better-auth/core/oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"@better-auth/core/oauth2\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { GENERIC_OAUTH_ERROR_CODES } from \"./error-codes\";\nimport {\n\tgetUserInfo,\n\toAuth2Callback,\n\toAuth2LinkAccount,\n\tsignInWithOAuth2,\n} from \"./routes\";\nimport type { GenericOAuthConfig, GenericOAuthOptions } from \"./types\";\n\nexport * from \"./providers\";\nexport type { GenericOAuthConfig, GenericOAuthOptions } from \"./types\";\n\n/**\n * Base type for OAuth provider options.\n * Extracts common fields from GenericOAuthConfig and makes clientSecret required.\n */\nexport type BaseOAuthProviderOptions = Omit<\n\tPick<\n\t\tGenericOAuthConfig,\n\t\t| \"clientId\"\n\t\t| \"clientSecret\"\n\t\t| \"scopes\"\n\t\t| \"redirectURI\"\n\t\t| \"pkce\"\n\t\t| \"disableImplicitSignUp\"\n\t\t| \"disableSignUp\"\n\t\t| \"overrideUserInfo\"\n\t>,\n\t\"clientSecret\"\n> & {\n\t/** OAuth client secret (required for provider options) */\n\tclientSecret: string;\n};\n\n/**\n * A generic OAuth plugin that can be used to add OAuth support to any provider\n */\nexport const genericOAuth = (options: GenericOAuthOptions) => {\n\treturn {\n\t\tid: \"generic-oauth\",\n\t\tinit: (ctx: AuthContext) => {\n\t\t\tconst genericProviders = options.config.map((c) => {\n\t\t\t\tlet finalUserInfoUrl = c.userInfoUrl;\n\t\t\t\treturn {\n\t\t\t\t\tid: c.providerId,\n\t\t\t\t\tname: c.providerId,\n\t\t\t\t\tasync createAuthorizationURL(data: {\n\t\t\t\t\t\tstate: string;\n\t\t\t\t\t\tcodeVerifier: string;\n\t\t\t\t\t\tscopes?: string[] | undefined;\n\t\t\t\t\t\tredirectURI: string;\n\t\t\t\t\t\tdisplay?: string | undefined;\n\t\t\t\t\t\tloginHint?: string | undefined;\n\t\t\t\t\t}) {\n\t\t\t\t\t\tlet finalAuthUrl = c.authorizationUrl;\n\t\t\t\t\t\tif (!finalAuthUrl && c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\tauthorization_endpoint: string;\n\t\t\t\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalAuthUrl = discovery.data.authorization_endpoint;\n\t\t\t\t\t\t\t\tfinalUserInfoUrl =\n\t\t\t\t\t\t\t\t\tfinalUserInfoUrl ?? discovery.data.userinfo_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalAuthUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn createAuthorizationURL({\n\t\t\t\t\t\t\tid: c.providerId,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t\tredirectURI: c.redirectURI,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tauthorizationEndpoint: finalAuthUrl,\n\t\t\t\t\t\t\tstate: data.state,\n\t\t\t\t\t\t\tcodeVerifier: c.pkce ? data.codeVerifier : undefined,\n\t\t\t\t\t\t\tscopes: c.scopes || [],\n\t\t\t\t\t\t\tredirectURI: `${ctx.baseURL}/oauth2/callback/${c.providerId}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync validateAuthorizationCode(data: {\n\t\t\t\t\t\tcode: string;\n\t\t\t\t\t\tredirectURI: string;\n\t\t\t\t\t\tcodeVerifier?: string | undefined;\n\t\t\t\t\t\tdeviceId?: string | undefined;\n\t\t\t\t\t}) {\n\t\t\t\t\t\t// Use custom getToken if provided\n\t\t\t\t\t\tif (c.getToken) {\n\t\t\t\t\t\t\treturn c.getToken(data);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Standard token exchange flow\n\t\t\t\t\t\tlet finalTokenUrl = c.tokenUrl;\n\t\t\t\t\t\tif (c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\t\t\t\tfinalUserInfoUrl = discovery.data.userinfo_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.TOKEN_URL_NOT_FOUND,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn validateAuthorizationCode({\n\t\t\t\t\t\t\theaders: c.authorizationHeaders,\n\t\t\t\t\t\t\tcode: data.code,\n\t\t\t\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t\tredirectURI: c.redirectURI,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\t\tauthentication: c.authentication,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync refreshAccessToken(\n\t\t\t\t\t\trefreshToken: string,\n\t\t\t\t\t): Promise<OAuth2Tokens> {\n\t\t\t\t\t\tlet finalTokenUrl = c.tokenUrl;\n\t\t\t\t\t\tif (c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.TOKEN_URL_NOT_FOUND,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tauthentication: c.authentication,\n\t\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync getUserInfo(tokens: OAuth2Tokens) {\n\t\t\t\t\t\tconst userInfo = c.getUserInfo\n\t\t\t\t\t\t\t? await c.getUserInfo(tokens)\n\t\t\t\t\t\t\t: await getUserInfo(tokens, finalUserInfoUrl);\n\t\t\t\t\t\tif (!userInfo) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst userMap = await c.mapProfileToUser?.(userInfo);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: userInfo?.id,\n\t\t\t\t\t\t\t\temail: userInfo?.email,\n\t\t\t\t\t\t\t\temailVerified: userInfo?.emailVerified,\n\t\t\t\t\t\t\t\timage: userInfo?.image,\n\t\t\t\t\t\t\t\tname: userInfo?.name,\n\t\t\t\t\t\t\t\t...userMap,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdata: userInfo,\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\t\t\t\t\toptions: {\n\t\t\t\t\t\toverrideUserInfoOnSignIn: c.overrideUserInfo,\n\t\t\t\t\t},\n\t\t\t\t} as OAuthProvider;\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontext: {\n\t\t\t\t\tsocialProviders: genericProviders.concat(ctx.socialProviders),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tendpoints: {\n\t\t\tsignInWithOAuth2: signInWithOAuth2(options),\n\t\t\toAuth2Callback: oAuth2Callback(options),\n\t\t\toAuth2LinkAccount: oAuth2LinkAccount(options),\n\t\t},\n\t\t$ERROR_CODES: GENERIC_OAUTH_ERROR_CODES,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/generic-oauth/index.ts"],"sourcesContent":["import type { AuthContext, BetterAuthPlugin } from \"@better-auth/core\";\nimport type { OAuth2Tokens, OAuthProvider } from \"@better-auth/core/oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"@better-auth/core/oauth2\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { GENERIC_OAUTH_ERROR_CODES } from \"./error-codes\";\nimport {\n\tgetUserInfo,\n\toAuth2Callback,\n\toAuth2LinkAccount,\n\tsignInWithOAuth2,\n} from \"./routes\";\nimport type { GenericOAuthConfig, GenericOAuthOptions } from \"./types\";\n\nexport * from \"./providers\";\nexport type { GenericOAuthConfig, GenericOAuthOptions } from \"./types\";\n\n/**\n * Base type for OAuth provider options.\n * Extracts common fields from GenericOAuthConfig and makes clientSecret required.\n */\nexport type BaseOAuthProviderOptions = Omit<\n\tPick<\n\t\tGenericOAuthConfig,\n\t\t| \"clientId\"\n\t\t| \"clientSecret\"\n\t\t| \"scopes\"\n\t\t| \"redirectURI\"\n\t\t| \"pkce\"\n\t\t| \"disableImplicitSignUp\"\n\t\t| \"disableSignUp\"\n\t\t| \"overrideUserInfo\"\n\t>,\n\t\"clientSecret\"\n> & {\n\t/** OAuth client secret (required for provider options) */\n\tclientSecret: string;\n};\n\n/**\n * A generic OAuth plugin that can be used to add OAuth support to any provider\n */\nexport const genericOAuth = (options: GenericOAuthOptions) => {\n\treturn {\n\t\tid: \"generic-oauth\",\n\t\tinit: (ctx: AuthContext) => {\n\t\t\tconst genericProviders = options.config.map((c) => {\n\t\t\t\tlet finalUserInfoUrl = c.userInfoUrl;\n\t\t\t\treturn {\n\t\t\t\t\tid: c.providerId,\n\t\t\t\t\tname: c.providerId,\n\t\t\t\t\tasync createAuthorizationURL(data: {\n\t\t\t\t\t\tstate: string;\n\t\t\t\t\t\tcodeVerifier: string;\n\t\t\t\t\t\tscopes?: string[] | undefined;\n\t\t\t\t\t\tredirectURI: string;\n\t\t\t\t\t\tdisplay?: string | undefined;\n\t\t\t\t\t\tloginHint?: string | undefined;\n\t\t\t\t\t}) {\n\t\t\t\t\t\tlet finalAuthUrl = c.authorizationUrl;\n\t\t\t\t\t\tif (!finalAuthUrl && c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\tauthorization_endpoint: string;\n\t\t\t\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalAuthUrl = discovery.data.authorization_endpoint;\n\t\t\t\t\t\t\t\tfinalUserInfoUrl =\n\t\t\t\t\t\t\t\t\tfinalUserInfoUrl ?? discovery.data.userinfo_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalAuthUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.INVALID_OAUTH_CONFIGURATION,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn createAuthorizationURL({\n\t\t\t\t\t\t\tid: c.providerId,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t\tredirectURI: c.redirectURI,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tauthorizationEndpoint: finalAuthUrl,\n\t\t\t\t\t\t\tstate: data.state,\n\t\t\t\t\t\t\tcodeVerifier: c.pkce ? data.codeVerifier : undefined,\n\t\t\t\t\t\t\tscopes: c.scopes || [],\n\t\t\t\t\t\t\tredirectURI: `${ctx.baseURL}/oauth2/callback/${c.providerId}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync validateAuthorizationCode(data: {\n\t\t\t\t\t\tcode: string;\n\t\t\t\t\t\tredirectURI: string;\n\t\t\t\t\t\tcodeVerifier?: string | undefined;\n\t\t\t\t\t\tdeviceId?: string | undefined;\n\t\t\t\t\t}) {\n\t\t\t\t\t\t// Use custom getToken if provided\n\t\t\t\t\t\tif (c.getToken) {\n\t\t\t\t\t\t\treturn c.getToken(data);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Standard token exchange flow\n\t\t\t\t\t\tlet finalTokenUrl = c.tokenUrl;\n\t\t\t\t\t\tif (c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\t\t\t\tuserinfo_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\t\t\t\tfinalUserInfoUrl = discovery.data.userinfo_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.TOKEN_URL_NOT_FOUND,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn validateAuthorizationCode({\n\t\t\t\t\t\t\theaders: c.authorizationHeaders,\n\t\t\t\t\t\t\tcode: data.code,\n\t\t\t\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t\tredirectURI: c.redirectURI,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\t\tauthentication: c.authentication,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync refreshAccessToken(\n\t\t\t\t\t\trefreshToken: string,\n\t\t\t\t\t): Promise<OAuth2Tokens> {\n\t\t\t\t\t\tlet finalTokenUrl = c.tokenUrl;\n\t\t\t\t\t\tif (c.discoveryUrl) {\n\t\t\t\t\t\t\tconst discovery = await betterFetch<{\n\t\t\t\t\t\t\t\ttoken_endpoint: string;\n\t\t\t\t\t\t\t}>(c.discoveryUrl, {\n\t\t\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\t\t\theaders: c.discoveryHeaders,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (discovery.data) {\n\t\t\t\t\t\t\t\tfinalTokenUrl = discovery.data.token_endpoint;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!finalTokenUrl) {\n\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\t\tmessage: GENERIC_OAUTH_ERROR_CODES.TOKEN_URL_NOT_FOUND,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tclientId: c.clientId,\n\t\t\t\t\t\t\t\tclientSecret: c.clientSecret,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tauthentication: c.authentication,\n\t\t\t\t\t\t\ttokenEndpoint: finalTokenUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tasync getUserInfo(tokens: OAuth2Tokens) {\n\t\t\t\t\t\tconst userInfo = c.getUserInfo\n\t\t\t\t\t\t\t? await c.getUserInfo(tokens)\n\t\t\t\t\t\t\t: await getUserInfo(tokens, finalUserInfoUrl);\n\t\t\t\t\t\tif (!userInfo) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst userMap = await c.mapProfileToUser?.(userInfo);\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: userInfo?.id,\n\t\t\t\t\t\t\t\temail: userInfo?.email,\n\t\t\t\t\t\t\t\temailVerified: userInfo?.emailVerified,\n\t\t\t\t\t\t\t\timage: userInfo?.image,\n\t\t\t\t\t\t\t\tname: userInfo?.name,\n\t\t\t\t\t\t\t\t...userMap,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdata: userInfo,\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\t\t\t\t\toptions: {\n\t\t\t\t\t\toverrideUserInfoOnSignIn: c.overrideUserInfo,\n\t\t\t\t\t},\n\t\t\t\t} as OAuthProvider;\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontext: {\n\t\t\t\t\tsocialProviders: genericProviders.concat(ctx.socialProviders),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tendpoints: {\n\t\t\tsignInWithOAuth2: signInWithOAuth2(options),\n\t\t\toAuth2Callback: oAuth2Callback(options),\n\t\t\toAuth2LinkAccount: oAuth2LinkAccount(options),\n\t\t},\n\t\toptions,\n\t\t$ERROR_CODES: GENERIC_OAUTH_ERROR_CODES,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as _better_auth_core18 from "@better-auth/core";
1
+ import * as _better_auth_core11 from "@better-auth/core";
2
2
 
3
3
  //#region src/plugins/haveibeenpwned/index.d.ts
4
4
  interface HaveIBeenPwnedOptions {
@@ -12,7 +12,7 @@ interface HaveIBeenPwnedOptions {
12
12
  }
13
13
  declare const haveIBeenPwned: (options?: HaveIBeenPwnedOptions | undefined) => {
14
14
  id: "haveIBeenPwned";
15
- init(ctx: _better_auth_core18.AuthContext): {
15
+ init(ctx: _better_auth_core11.AuthContext): {
16
16
  context: {
17
17
  password: {
18
18
  hash(password: string): Promise<string>;
@@ -24,10 +24,11 @@ declare const haveIBeenPwned: (options?: HaveIBeenPwnedOptions | undefined) => {
24
24
  minPasswordLength: number;
25
25
  maxPasswordLength: number;
26
26
  };
27
- checkPassword: (userId: string, ctx: _better_auth_core18.GenericEndpointContext<_better_auth_core18.BetterAuthOptions>) => Promise<boolean>;
27
+ checkPassword: (userId: string, ctx: _better_auth_core11.GenericEndpointContext<_better_auth_core11.BetterAuthOptions>) => Promise<boolean>;
28
28
  };
29
29
  };
30
30
  };
31
+ options: HaveIBeenPwnedOptions | undefined;
31
32
  $ERROR_CODES: {
32
33
  readonly PASSWORD_COMPROMISED: "The password you entered has been compromised. Please choose a different password.";
33
34
  };
@@ -45,6 +45,7 @@ const haveIBeenPwned = (options) => {
45
45
  }
46
46
  } } };
47
47
  },
48
+ options,
48
49
  $ERROR_CODES: ERROR_CODES
49
50
  };
50
51
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/haveibeenpwned/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { getCurrentAuthContext } from \"@better-auth/core/context\";\nimport { defineErrorCodes } from \"@better-auth/core/utils\";\nimport { createHash } from \"@better-auth/utils/hash\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"../../api\";\n\nconst ERROR_CODES = defineErrorCodes({\n\tPASSWORD_COMPROMISED:\n\t\t\"The password you entered has been compromised. Please choose a different password.\",\n});\n\nasync function checkPasswordCompromise(\n\tpassword: string,\n\tcustomMessage?: string | undefined,\n) {\n\tif (!password) return;\n\n\tconst sha1Hash = (\n\t\tawait createHash(\"SHA-1\", \"hex\").digest(password)\n\t).toUpperCase();\n\tconst prefix = sha1Hash.substring(0, 5);\n\tconst suffix = sha1Hash.substring(5);\n\ttry {\n\t\tconst { data, error } = await betterFetch<string>(\n\t\t\t`https://api.pwnedpasswords.com/range/${prefix}`,\n\t\t\t{\n\t\t\t\theaders: {\n\t\t\t\t\t\"Add-Padding\": \"true\",\n\t\t\t\t\t\"User-Agent\": \"BetterAuth Password Checker\",\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tif (error) {\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\tmessage: `Failed to check password. Status: ${error.status}`,\n\t\t\t});\n\t\t}\n\t\tconst lines = data.split(\"\\n\");\n\t\tconst found = lines.some(\n\t\t\t(line) => line.split(\":\")[0]!.toUpperCase() === suffix.toUpperCase(),\n\t\t);\n\n\t\tif (found) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: customMessage || ERROR_CODES.PASSWORD_COMPROMISED,\n\t\t\t\tcode: \"PASSWORD_COMPROMISED\",\n\t\t\t});\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof APIError) throw error;\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\tmessage: \"Failed to check password. Please try again later.\",\n\t\t});\n\t}\n}\n\nexport interface HaveIBeenPwnedOptions {\n\tcustomPasswordCompromisedMessage?: string | undefined;\n\t/**\n\t * Paths to check for password\n\t *\n\t * @default [\"/sign-up/email\", \"/change-password\", \"/reset-password\"]\n\t */\n\tpaths?: string[];\n}\n\nexport const haveIBeenPwned = (options?: HaveIBeenPwnedOptions | undefined) => {\n\tconst paths = options?.paths || [\n\t\t\"/sign-up/email\",\n\t\t\"/change-password\",\n\t\t\"/reset-password\",\n\t];\n\n\treturn {\n\t\tid: \"haveIBeenPwned\",\n\t\tinit(ctx) {\n\t\t\treturn {\n\t\t\t\tcontext: {\n\t\t\t\t\tpassword: {\n\t\t\t\t\t\t...ctx.password,\n\t\t\t\t\t\tasync hash(password) {\n\t\t\t\t\t\t\tconst c = await getCurrentAuthContext();\n\t\t\t\t\t\t\tif (!c.path || !paths.includes(c.path)) {\n\t\t\t\t\t\t\t\treturn ctx.password.hash(password);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tawait checkPasswordCompromise(\n\t\t\t\t\t\t\t\tpassword,\n\t\t\t\t\t\t\t\toptions?.customPasswordCompromisedMessage,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn ctx.password.hash(password);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t$ERROR_CODES: ERROR_CODES,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":";;;;;;;AAOA,MAAM,cAAc,iBAAiB,EACpC,sBACC,sFACD,CAAC;AAEF,eAAe,wBACd,UACA,eACC;AACD,KAAI,CAAC,SAAU;CAEf,MAAM,YACL,MAAM,WAAW,SAAS,MAAM,CAAC,OAAO,SAAS,EAChD,aAAa;CACf,MAAM,SAAS,SAAS,UAAU,GAAG,EAAE;CACvC,MAAM,SAAS,SAAS,UAAU,EAAE;AACpC,KAAI;EACH,MAAM,EAAE,MAAM,UAAU,MAAM,YAC7B,wCAAwC,UACxC,EACC,SAAS;GACR,eAAe;GACf,cAAc;GACd,EACD,CACD;AAED,MAAI,MACH,OAAM,IAAI,SAAS,yBAAyB,EAC3C,SAAS,qCAAqC,MAAM,UACpD,CAAC;AAOH,MALc,KAAK,MAAM,KAAK,CACV,MAClB,SAAS,KAAK,MAAM,IAAI,CAAC,GAAI,aAAa,KAAK,OAAO,aAAa,CACpE,CAGA,OAAM,IAAI,SAAS,eAAe;GACjC,SAAS,iBAAiB,YAAY;GACtC,MAAM;GACN,CAAC;UAEK,OAAO;AACf,MAAI,iBAAiB,SAAU,OAAM;AACrC,QAAM,IAAI,SAAS,yBAAyB,EAC3C,SAAS,qDACT,CAAC;;;AAcJ,MAAa,kBAAkB,YAAgD;CAC9E,MAAM,QAAQ,SAAS,SAAS;EAC/B;EACA;EACA;EACA;AAED,QAAO;EACN,IAAI;EACJ,KAAK,KAAK;AACT,UAAO,EACN,SAAS,EACR,UAAU;IACT,GAAG,IAAI;IACP,MAAM,KAAK,UAAU;KACpB,MAAM,IAAI,MAAM,uBAAuB;AACvC,SAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,SAAS,EAAE,KAAK,CACrC,QAAO,IAAI,SAAS,KAAK,SAAS;AAEnC,WAAM,wBACL,UACA,SAAS,iCACT;AACD,YAAO,IAAI,SAAS,KAAK,SAAS;;IAEnC,EACD,EACD;;EAEF,cAAc;EACd"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugins/haveibeenpwned/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { getCurrentAuthContext } from \"@better-auth/core/context\";\nimport { defineErrorCodes } from \"@better-auth/core/utils\";\nimport { createHash } from \"@better-auth/utils/hash\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"../../api\";\n\nconst ERROR_CODES = defineErrorCodes({\n\tPASSWORD_COMPROMISED:\n\t\t\"The password you entered has been compromised. Please choose a different password.\",\n});\n\nasync function checkPasswordCompromise(\n\tpassword: string,\n\tcustomMessage?: string | undefined,\n) {\n\tif (!password) return;\n\n\tconst sha1Hash = (\n\t\tawait createHash(\"SHA-1\", \"hex\").digest(password)\n\t).toUpperCase();\n\tconst prefix = sha1Hash.substring(0, 5);\n\tconst suffix = sha1Hash.substring(5);\n\ttry {\n\t\tconst { data, error } = await betterFetch<string>(\n\t\t\t`https://api.pwnedpasswords.com/range/${prefix}`,\n\t\t\t{\n\t\t\t\theaders: {\n\t\t\t\t\t\"Add-Padding\": \"true\",\n\t\t\t\t\t\"User-Agent\": \"BetterAuth Password Checker\",\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tif (error) {\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\tmessage: `Failed to check password. Status: ${error.status}`,\n\t\t\t});\n\t\t}\n\t\tconst lines = data.split(\"\\n\");\n\t\tconst found = lines.some(\n\t\t\t(line) => line.split(\":\")[0]!.toUpperCase() === suffix.toUpperCase(),\n\t\t);\n\n\t\tif (found) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: customMessage || ERROR_CODES.PASSWORD_COMPROMISED,\n\t\t\t\tcode: \"PASSWORD_COMPROMISED\",\n\t\t\t});\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof APIError) throw error;\n\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\tmessage: \"Failed to check password. Please try again later.\",\n\t\t});\n\t}\n}\n\nexport interface HaveIBeenPwnedOptions {\n\tcustomPasswordCompromisedMessage?: string | undefined;\n\t/**\n\t * Paths to check for password\n\t *\n\t * @default [\"/sign-up/email\", \"/change-password\", \"/reset-password\"]\n\t */\n\tpaths?: string[];\n}\n\nexport const haveIBeenPwned = (options?: HaveIBeenPwnedOptions | undefined) => {\n\tconst paths = options?.paths || [\n\t\t\"/sign-up/email\",\n\t\t\"/change-password\",\n\t\t\"/reset-password\",\n\t];\n\n\treturn {\n\t\tid: \"haveIBeenPwned\",\n\t\tinit(ctx) {\n\t\t\treturn {\n\t\t\t\tcontext: {\n\t\t\t\t\tpassword: {\n\t\t\t\t\t\t...ctx.password,\n\t\t\t\t\t\tasync hash(password) {\n\t\t\t\t\t\t\tconst c = await getCurrentAuthContext();\n\t\t\t\t\t\t\tif (!c.path || !paths.includes(c.path)) {\n\t\t\t\t\t\t\t\treturn ctx.password.hash(password);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tawait checkPasswordCompromise(\n\t\t\t\t\t\t\t\tpassword,\n\t\t\t\t\t\t\t\toptions?.customPasswordCompromisedMessage,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn ctx.password.hash(password);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\toptions,\n\t\t$ERROR_CODES: ERROR_CODES,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":";;;;;;;AAOA,MAAM,cAAc,iBAAiB,EACpC,sBACC,sFACD,CAAC;AAEF,eAAe,wBACd,UACA,eACC;AACD,KAAI,CAAC,SAAU;CAEf,MAAM,YACL,MAAM,WAAW,SAAS,MAAM,CAAC,OAAO,SAAS,EAChD,aAAa;CACf,MAAM,SAAS,SAAS,UAAU,GAAG,EAAE;CACvC,MAAM,SAAS,SAAS,UAAU,EAAE;AACpC,KAAI;EACH,MAAM,EAAE,MAAM,UAAU,MAAM,YAC7B,wCAAwC,UACxC,EACC,SAAS;GACR,eAAe;GACf,cAAc;GACd,EACD,CACD;AAED,MAAI,MACH,OAAM,IAAI,SAAS,yBAAyB,EAC3C,SAAS,qCAAqC,MAAM,UACpD,CAAC;AAOH,MALc,KAAK,MAAM,KAAK,CACV,MAClB,SAAS,KAAK,MAAM,IAAI,CAAC,GAAI,aAAa,KAAK,OAAO,aAAa,CACpE,CAGA,OAAM,IAAI,SAAS,eAAe;GACjC,SAAS,iBAAiB,YAAY;GACtC,MAAM;GACN,CAAC;UAEK,OAAO;AACf,MAAI,iBAAiB,SAAU,OAAM;AACrC,QAAM,IAAI,SAAS,yBAAyB,EAC3C,SAAS,qDACT,CAAC;;;AAcJ,MAAa,kBAAkB,YAAgD;CAC9E,MAAM,QAAQ,SAAS,SAAS;EAC/B;EACA;EACA;EACA;AAED,QAAO;EACN,IAAI;EACJ,KAAK,KAAK;AACT,UAAO,EACN,SAAS,EACR,UAAU;IACT,GAAG,IAAI;IACP,MAAM,KAAK,UAAU;KACpB,MAAM,IAAI,MAAM,uBAAuB;AACvC,SAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,SAAS,EAAE,KAAK,CACrC,QAAO,IAAI,SAAS,KAAK,SAAS;AAEnC,WAAM,wBACL,UACA,SAAS,iCACT;AACD,YAAO,IAAI,SAAS,KAAK,SAAS;;IAEnC,EACD,EACD;;EAEF;EACA,cAAc;EACd"}