@better-auth/core 1.5.6 → 1.6.0-beta.0

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 (281) hide show
  1. package/dist/api/index.d.mts +42 -13
  2. package/dist/api/index.mjs +0 -4
  3. package/dist/async_hooks/index.d.mts +1 -2
  4. package/dist/async_hooks/index.mjs +0 -2
  5. package/dist/async_hooks/pure.index.d.mts +1 -2
  6. package/dist/async_hooks/pure.index.mjs +0 -2
  7. package/dist/context/endpoint-context.d.mts +2 -3
  8. package/dist/context/endpoint-context.mjs +0 -3
  9. package/dist/context/global.d.mts +1 -2
  10. package/dist/context/global.mjs +1 -3
  11. package/dist/context/index.mjs +1 -2
  12. package/dist/context/request-state.d.mts +1 -2
  13. package/dist/context/request-state.mjs +0 -3
  14. package/dist/context/transaction.d.mts +1 -2
  15. package/dist/context/transaction.mjs +0 -3
  16. package/dist/db/adapter/factory.d.mts +1 -2
  17. package/dist/db/adapter/factory.mjs +3 -7
  18. package/dist/db/adapter/get-default-field-name.d.mts +1 -2
  19. package/dist/db/adapter/get-default-field-name.mjs +0 -3
  20. package/dist/db/adapter/get-default-model-name.d.mts +1 -2
  21. package/dist/db/adapter/get-default-model-name.mjs +0 -3
  22. package/dist/db/adapter/get-field-attributes.d.mts +1 -2
  23. package/dist/db/adapter/get-field-attributes.mjs +0 -3
  24. package/dist/db/adapter/get-field-name.d.mts +1 -2
  25. package/dist/db/adapter/get-field-name.mjs +0 -3
  26. package/dist/db/adapter/get-id-field.d.mts +1 -2
  27. package/dist/db/adapter/get-id-field.mjs +0 -4
  28. package/dist/db/adapter/get-model-name.d.mts +1 -2
  29. package/dist/db/adapter/get-model-name.mjs +0 -3
  30. package/dist/db/adapter/index.d.mts +9 -2
  31. package/dist/db/adapter/index.mjs +0 -3
  32. package/dist/db/adapter/types.d.mts +1 -2
  33. package/dist/db/adapter/utils.d.mts +1 -2
  34. package/dist/db/adapter/utils.mjs +0 -2
  35. package/dist/db/get-tables.d.mts +1 -2
  36. package/dist/db/get-tables.mjs +0 -2
  37. package/dist/db/index.mjs +1 -2
  38. package/dist/db/plugin.d.mts +1 -2
  39. package/dist/db/schema/account.d.mts +1 -2
  40. package/dist/db/schema/account.mjs +0 -3
  41. package/dist/db/schema/rate-limit.d.mts +1 -2
  42. package/dist/db/schema/rate-limit.mjs +0 -3
  43. package/dist/db/schema/session.d.mts +1 -2
  44. package/dist/db/schema/session.mjs +0 -3
  45. package/dist/db/schema/shared.d.mts +1 -2
  46. package/dist/db/schema/shared.mjs +0 -3
  47. package/dist/db/schema/user.d.mts +1 -2
  48. package/dist/db/schema/user.mjs +0 -3
  49. package/dist/db/schema/verification.d.mts +1 -2
  50. package/dist/db/schema/verification.mjs +0 -3
  51. package/dist/db/type.d.mts +1 -2
  52. package/dist/env/color-depth.d.mts +1 -2
  53. package/dist/env/color-depth.mjs +0 -3
  54. package/dist/env/env-impl.d.mts +1 -2
  55. package/dist/env/env-impl.mjs +0 -2
  56. package/dist/env/index.mjs +1 -2
  57. package/dist/env/logger.d.mts +1 -2
  58. package/dist/env/logger.mjs +0 -3
  59. package/dist/error/codes.d.mts +1 -2
  60. package/dist/error/codes.mjs +0 -3
  61. package/dist/error/index.d.mts +1 -2
  62. package/dist/error/index.mjs +0 -3
  63. package/dist/index.mjs +1 -1
  64. package/dist/instrumentation/attributes.d.mts +1 -2
  65. package/dist/instrumentation/attributes.mjs +0 -3
  66. package/dist/instrumentation/index.mjs +1 -2
  67. package/dist/instrumentation/tracer.d.mts +1 -2
  68. package/dist/instrumentation/tracer.mjs +29 -16
  69. package/dist/oauth2/client-credentials-token.d.mts +1 -2
  70. package/dist/oauth2/client-credentials-token.mjs +0 -3
  71. package/dist/oauth2/create-authorization-url.d.mts +1 -2
  72. package/dist/oauth2/create-authorization-url.mjs +0 -3
  73. package/dist/oauth2/index.mjs +1 -2
  74. package/dist/oauth2/oauth-provider.d.mts +1 -2
  75. package/dist/oauth2/refresh-access-token.d.mts +1 -2
  76. package/dist/oauth2/refresh-access-token.mjs +0 -3
  77. package/dist/oauth2/utils.d.mts +1 -2
  78. package/dist/oauth2/utils.mjs +0 -3
  79. package/dist/oauth2/validate-authorization-code.d.mts +1 -2
  80. package/dist/oauth2/validate-authorization-code.mjs +0 -4
  81. package/dist/oauth2/verify.d.mts +1 -2
  82. package/dist/oauth2/verify.mjs +0 -4
  83. package/dist/social-providers/apple.d.mts +1 -2
  84. package/dist/social-providers/apple.mjs +0 -4
  85. package/dist/social-providers/atlassian.d.mts +1 -2
  86. package/dist/social-providers/atlassian.mjs +0 -5
  87. package/dist/social-providers/cognito.d.mts +1 -2
  88. package/dist/social-providers/cognito.mjs +0 -5
  89. package/dist/social-providers/discord.d.mts +1 -2
  90. package/dist/social-providers/discord.mjs +0 -4
  91. package/dist/social-providers/dropbox.d.mts +1 -2
  92. package/dist/social-providers/dropbox.mjs +0 -4
  93. package/dist/social-providers/facebook.d.mts +1 -2
  94. package/dist/social-providers/facebook.mjs +0 -4
  95. package/dist/social-providers/figma.d.mts +1 -2
  96. package/dist/social-providers/figma.mjs +0 -5
  97. package/dist/social-providers/github.d.mts +1 -2
  98. package/dist/social-providers/github.mjs +0 -5
  99. package/dist/social-providers/gitlab.d.mts +1 -2
  100. package/dist/social-providers/gitlab.mjs +0 -4
  101. package/dist/social-providers/google.d.mts +1 -2
  102. package/dist/social-providers/google.mjs +0 -5
  103. package/dist/social-providers/huggingface.d.mts +1 -2
  104. package/dist/social-providers/huggingface.mjs +0 -4
  105. package/dist/social-providers/index.d.mts +1 -2
  106. package/dist/social-providers/index.mjs +0 -3
  107. package/dist/social-providers/kakao.d.mts +1 -2
  108. package/dist/social-providers/kakao.mjs +0 -4
  109. package/dist/social-providers/kick.d.mts +1 -2
  110. package/dist/social-providers/kick.mjs +0 -4
  111. package/dist/social-providers/line.d.mts +1 -2
  112. package/dist/social-providers/line.mjs +0 -4
  113. package/dist/social-providers/linear.d.mts +1 -2
  114. package/dist/social-providers/linear.mjs +0 -4
  115. package/dist/social-providers/linkedin.d.mts +1 -2
  116. package/dist/social-providers/linkedin.mjs +0 -4
  117. package/dist/social-providers/microsoft-entra-id.d.mts +1 -2
  118. package/dist/social-providers/microsoft-entra-id.mjs +0 -5
  119. package/dist/social-providers/naver.d.mts +1 -2
  120. package/dist/social-providers/naver.mjs +0 -4
  121. package/dist/social-providers/notion.d.mts +1 -2
  122. package/dist/social-providers/notion.mjs +0 -4
  123. package/dist/social-providers/paybin.d.mts +1 -2
  124. package/dist/social-providers/paybin.mjs +0 -5
  125. package/dist/social-providers/paypal.d.mts +1 -2
  126. package/dist/social-providers/paypal.mjs +0 -5
  127. package/dist/social-providers/polar.d.mts +1 -2
  128. package/dist/social-providers/polar.mjs +0 -4
  129. package/dist/social-providers/railway.d.mts +1 -2
  130. package/dist/social-providers/railway.mjs +0 -4
  131. package/dist/social-providers/reddit.d.mts +1 -2
  132. package/dist/social-providers/reddit.mjs +0 -4
  133. package/dist/social-providers/roblox.d.mts +1 -2
  134. package/dist/social-providers/roblox.mjs +0 -4
  135. package/dist/social-providers/salesforce.d.mts +1 -2
  136. package/dist/social-providers/salesforce.mjs +0 -5
  137. package/dist/social-providers/slack.d.mts +1 -2
  138. package/dist/social-providers/slack.mjs +0 -4
  139. package/dist/social-providers/spotify.d.mts +1 -2
  140. package/dist/social-providers/spotify.mjs +0 -4
  141. package/dist/social-providers/tiktok.d.mts +1 -2
  142. package/dist/social-providers/tiktok.mjs +0 -4
  143. package/dist/social-providers/twitch.d.mts +1 -2
  144. package/dist/social-providers/twitch.mjs +0 -5
  145. package/dist/social-providers/twitter.d.mts +1 -2
  146. package/dist/social-providers/twitter.mjs +0 -4
  147. package/dist/social-providers/vercel.d.mts +1 -2
  148. package/dist/social-providers/vercel.mjs +0 -4
  149. package/dist/social-providers/vk.d.mts +1 -2
  150. package/dist/social-providers/vk.mjs +0 -4
  151. package/dist/social-providers/wechat.d.mts +1 -2
  152. package/dist/social-providers/wechat.mjs +0 -3
  153. package/dist/social-providers/zoom.d.mts +1 -2
  154. package/dist/social-providers/zoom.mjs +0 -4
  155. package/dist/types/context.d.mts +3 -5
  156. package/dist/types/cookie.d.mts +1 -2
  157. package/dist/types/helper.d.mts +1 -2
  158. package/dist/types/init-options.d.mts +14 -6
  159. package/dist/types/plugin-client.d.mts +2 -2
  160. package/dist/types/plugin.d.mts +6 -3
  161. package/dist/types/secret.d.mts +1 -2
  162. package/dist/utils/db.d.mts +1 -2
  163. package/dist/utils/db.mjs +0 -2
  164. package/dist/utils/deprecate.d.mts +1 -2
  165. package/dist/utils/deprecate.mjs +0 -2
  166. package/dist/utils/error-codes.d.mts +1 -2
  167. package/dist/utils/error-codes.mjs +0 -2
  168. package/dist/utils/fetch-metadata.d.mts +1 -2
  169. package/dist/utils/fetch-metadata.mjs +0 -2
  170. package/dist/utils/id.d.mts +1 -2
  171. package/dist/utils/id.mjs +0 -3
  172. package/dist/utils/ip.d.mts +1 -2
  173. package/dist/utils/ip.mjs +0 -3
  174. package/dist/utils/json.d.mts +1 -2
  175. package/dist/utils/json.mjs +0 -4
  176. package/dist/utils/string.d.mts +1 -2
  177. package/dist/utils/string.mjs +0 -2
  178. package/dist/utils/url.d.mts +1 -2
  179. package/dist/utils/url.mjs +0 -2
  180. package/package.json +11 -9
  181. package/src/api/index.ts +151 -41
  182. package/src/context/endpoint-context.ts +2 -1
  183. package/src/db/adapter/factory.ts +2 -0
  184. package/src/db/adapter/index.ts +8 -0
  185. package/src/instrumentation/tracer.ts +40 -12
  186. package/src/social-providers/index.ts +0 -2
  187. package/src/types/context.ts +2 -3
  188. package/src/types/init-options.ts +13 -4
  189. package/src/types/plugin-client.ts +1 -0
  190. package/src/types/plugin.ts +15 -1
  191. package/dist/api/index.mjs.map +0 -1
  192. package/dist/async_hooks/index.mjs.map +0 -1
  193. package/dist/async_hooks/pure.index.mjs.map +0 -1
  194. package/dist/context/endpoint-context.mjs.map +0 -1
  195. package/dist/context/global.mjs.map +0 -1
  196. package/dist/context/request-state.mjs.map +0 -1
  197. package/dist/context/transaction.mjs.map +0 -1
  198. package/dist/db/adapter/factory.mjs.map +0 -1
  199. package/dist/db/adapter/get-default-field-name.mjs.map +0 -1
  200. package/dist/db/adapter/get-default-model-name.mjs.map +0 -1
  201. package/dist/db/adapter/get-field-attributes.mjs.map +0 -1
  202. package/dist/db/adapter/get-field-name.mjs.map +0 -1
  203. package/dist/db/adapter/get-id-field.mjs.map +0 -1
  204. package/dist/db/adapter/get-model-name.mjs.map +0 -1
  205. package/dist/db/adapter/index.mjs.map +0 -1
  206. package/dist/db/adapter/utils.mjs.map +0 -1
  207. package/dist/db/get-tables.mjs.map +0 -1
  208. package/dist/db/schema/account.mjs.map +0 -1
  209. package/dist/db/schema/rate-limit.mjs.map +0 -1
  210. package/dist/db/schema/session.mjs.map +0 -1
  211. package/dist/db/schema/shared.mjs.map +0 -1
  212. package/dist/db/schema/user.mjs.map +0 -1
  213. package/dist/db/schema/verification.mjs.map +0 -1
  214. package/dist/env/color-depth.mjs.map +0 -1
  215. package/dist/env/env-impl.mjs.map +0 -1
  216. package/dist/env/logger.mjs.map +0 -1
  217. package/dist/error/codes.mjs.map +0 -1
  218. package/dist/error/index.mjs.map +0 -1
  219. package/dist/instrumentation/attributes.mjs.map +0 -1
  220. package/dist/instrumentation/tracer.mjs.map +0 -1
  221. package/dist/oauth2/client-credentials-token.mjs.map +0 -1
  222. package/dist/oauth2/create-authorization-url.mjs.map +0 -1
  223. package/dist/oauth2/refresh-access-token.mjs.map +0 -1
  224. package/dist/oauth2/utils.mjs.map +0 -1
  225. package/dist/oauth2/validate-authorization-code.mjs.map +0 -1
  226. package/dist/oauth2/verify.mjs.map +0 -1
  227. package/dist/social-providers/apple.mjs.map +0 -1
  228. package/dist/social-providers/atlassian.mjs.map +0 -1
  229. package/dist/social-providers/cognito.mjs.map +0 -1
  230. package/dist/social-providers/discord.mjs.map +0 -1
  231. package/dist/social-providers/dropbox.mjs.map +0 -1
  232. package/dist/social-providers/facebook.mjs.map +0 -1
  233. package/dist/social-providers/figma.mjs.map +0 -1
  234. package/dist/social-providers/github.mjs.map +0 -1
  235. package/dist/social-providers/gitlab.mjs.map +0 -1
  236. package/dist/social-providers/google.mjs.map +0 -1
  237. package/dist/social-providers/huggingface.mjs.map +0 -1
  238. package/dist/social-providers/index.mjs.map +0 -1
  239. package/dist/social-providers/kakao.mjs.map +0 -1
  240. package/dist/social-providers/kick.mjs.map +0 -1
  241. package/dist/social-providers/line.mjs.map +0 -1
  242. package/dist/social-providers/linear.mjs.map +0 -1
  243. package/dist/social-providers/linkedin.mjs.map +0 -1
  244. package/dist/social-providers/microsoft-entra-id.mjs.map +0 -1
  245. package/dist/social-providers/naver.mjs.map +0 -1
  246. package/dist/social-providers/notion.mjs.map +0 -1
  247. package/dist/social-providers/paybin.mjs.map +0 -1
  248. package/dist/social-providers/paypal.mjs.map +0 -1
  249. package/dist/social-providers/polar.mjs.map +0 -1
  250. package/dist/social-providers/railway.mjs.map +0 -1
  251. package/dist/social-providers/reddit.mjs.map +0 -1
  252. package/dist/social-providers/roblox.mjs.map +0 -1
  253. package/dist/social-providers/salesforce.mjs.map +0 -1
  254. package/dist/social-providers/slack.mjs.map +0 -1
  255. package/dist/social-providers/spotify.mjs.map +0 -1
  256. package/dist/social-providers/tiktok.mjs.map +0 -1
  257. package/dist/social-providers/twitch.mjs.map +0 -1
  258. package/dist/social-providers/twitter.mjs.map +0 -1
  259. package/dist/social-providers/vercel.mjs.map +0 -1
  260. package/dist/social-providers/vk.mjs.map +0 -1
  261. package/dist/social-providers/wechat.mjs.map +0 -1
  262. package/dist/social-providers/zoom.mjs.map +0 -1
  263. package/dist/utils/db.mjs.map +0 -1
  264. package/dist/utils/deprecate.mjs.map +0 -1
  265. package/dist/utils/error-codes.mjs.map +0 -1
  266. package/dist/utils/fetch-metadata.mjs.map +0 -1
  267. package/dist/utils/id.mjs.map +0 -1
  268. package/dist/utils/ip.mjs.map +0 -1
  269. package/dist/utils/json.mjs.map +0 -1
  270. package/dist/utils/string.mjs.map +0 -1
  271. package/dist/utils/url.mjs.map +0 -1
  272. package/src/context/request-state.test.ts +0 -94
  273. package/src/db/adapter/get-id-field.test.ts +0 -222
  274. package/src/db/test/get-tables.test.ts +0 -116
  275. package/src/env/logger.test.ts +0 -34
  276. package/src/instrumentation/instrumentation.test.ts +0 -139
  277. package/src/oauth2/refresh-access-token.test.ts +0 -90
  278. package/src/oauth2/validate-token.test.ts +0 -229
  279. package/src/utils/deprecate.test.ts +0 -71
  280. package/src/utils/fetch-metadata.test.ts +0 -28
  281. package/src/utils/ip.test.ts +0 -255
@@ -1,139 +0,0 @@
1
- import { trace } from "@opentelemetry/api";
2
- import {
3
- InMemorySpanExporter,
4
- SimpleSpanProcessor,
5
- } from "@opentelemetry/sdk-trace-base";
6
- import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
7
- import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
8
- import { withSpan } from ".";
9
- import { ATTR_DB_COLLECTION_NAME, ATTR_DB_OPERATION_NAME } from "./attributes";
10
-
11
- describe("instrumentation", () => {
12
- let provider: NodeTracerProvider;
13
- let exporter: InMemorySpanExporter;
14
-
15
- beforeAll(async () => {
16
- exporter = new InMemorySpanExporter();
17
- provider = new NodeTracerProvider({
18
- spanProcessors: [new SimpleSpanProcessor(exporter)],
19
- });
20
- trace.setGlobalTracerProvider(provider);
21
- });
22
-
23
- afterAll(async () => {
24
- await provider.shutdown();
25
- });
26
-
27
- beforeEach(() => {
28
- exporter.reset();
29
- });
30
-
31
- it("creates a span with name and attributes for sync function", () => {
32
- const result = withSpan(
33
- "test.sync",
34
- {
35
- [ATTR_DB_OPERATION_NAME]: "findOne",
36
- [ATTR_DB_COLLECTION_NAME]: "user",
37
- },
38
- () => 42,
39
- );
40
-
41
- expect(result).toBe(42);
42
-
43
- const spans = exporter.getFinishedSpans();
44
- expect(spans).toHaveLength(1);
45
- expect(spans[0]?.name).toBe("test.sync");
46
- expect(spans[0]?.attributes).toMatchObject({
47
- [ATTR_DB_OPERATION_NAME]: "findOne",
48
- [ATTR_DB_COLLECTION_NAME]: "user",
49
- });
50
- });
51
-
52
- it("creates a span for async function", async () => {
53
- const result = await withSpan(
54
- "test.async",
55
- { endpoint: "getSession" },
56
- async () => {
57
- await new Promise((r) => setTimeout(r, 5));
58
- return "session-id";
59
- },
60
- );
61
-
62
- expect(result).toBe("session-id");
63
-
64
- const spans = exporter.getFinishedSpans();
65
- expect(spans).toHaveLength(1);
66
- expect(spans[0]?.name).toBe("test.async");
67
- expect(spans[0]?.attributes).toMatchObject({ endpoint: "getSession" });
68
- });
69
-
70
- it("records error status and exception when sync function throws", () => {
71
- const err = new Error("sync failure");
72
-
73
- expect(() =>
74
- withSpan("test.sync.error", { foo: "bar" }, () => {
75
- throw err;
76
- }),
77
- ).toThrow("sync failure");
78
-
79
- const spans = exporter.getFinishedSpans();
80
- expect(spans).toHaveLength(1);
81
- expect(spans[0]?.name).toBe("test.sync.error");
82
- expect(spans[0]?.status).toMatchObject({
83
- code: 2,
84
- message: "sync failure",
85
- });
86
- });
87
-
88
- it("records error status and exception when async function rejects", async () => {
89
- const err = new Error("async failure");
90
-
91
- await expect(
92
- withSpan("test.async.error", { baz: 1 }, async () => {
93
- await Promise.resolve();
94
- throw err;
95
- }),
96
- ).rejects.toThrow("async failure");
97
-
98
- const spans = exporter.getFinishedSpans();
99
- expect(spans).toHaveLength(1);
100
- expect(spans[0]?.name).toBe("test.async.error");
101
- expect(spans[0]?.status).toMatchObject({
102
- code: 2,
103
- message: "async failure",
104
- });
105
- });
106
-
107
- it("creates multiple sequential spans", () => {
108
- void withSpan("first", { order: 1 }, () => 1);
109
- void withSpan("second", { order: 2 }, () => 2);
110
-
111
- const spans = exporter.getFinishedSpans();
112
- expect(spans).toHaveLength(2);
113
- expect(spans.map((s) => s.name)).toEqual(
114
- expect.arrayContaining(["first", "second"]),
115
- );
116
- });
117
-
118
- it("creates nested spans when withSpan is composed", () => {
119
- const result = withSpan("outer", { depth: 0 }, () => {
120
- return withSpan("inner", { depth: 1 }, () => "ok");
121
- });
122
-
123
- expect(result).toBe("ok");
124
-
125
- const spans = exporter.getFinishedSpans();
126
- expect(spans).toHaveLength(2);
127
- expect(spans.map((s) => s.name).sort()).toEqual(["inner", "outer"]);
128
- });
129
-
130
- it("uses better-auth instrumentation scope", () => {
131
- void withSpan("scope.check", {}, () => undefined);
132
-
133
- const spans = exporter.getFinishedSpans();
134
- expect(spans).toHaveLength(1);
135
-
136
- const span = spans[0];
137
- expect(span?.instrumentationLibrary?.name).toBe("better-auth");
138
- });
139
- });
@@ -1,90 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
-
3
- vi.mock("@better-fetch/fetch", () => ({
4
- betterFetch: vi.fn(),
5
- }));
6
-
7
- import { betterFetch } from "@better-fetch/fetch";
8
- import { refreshAccessToken } from "./refresh-access-token";
9
-
10
- const mockedBetterFetch = vi.mocked(betterFetch);
11
-
12
- describe("refreshAccessToken", () => {
13
- it("should set accessTokenExpiresAt when expires_in is returned", async () => {
14
- const now = Date.now();
15
- mockedBetterFetch.mockResolvedValueOnce({
16
- data: {
17
- access_token: "new-access-token",
18
- refresh_token: "new-refresh-token",
19
- expires_in: 3600,
20
- token_type: "Bearer",
21
- },
22
- error: null,
23
- });
24
-
25
- const tokens = await refreshAccessToken({
26
- refreshToken: "old-refresh-token",
27
- options: { clientId: "test-client", clientSecret: "test-secret" },
28
- tokenEndpoint: "https://example.com/token",
29
- });
30
-
31
- expect(tokens.accessToken).toBe("new-access-token");
32
- expect(tokens.refreshToken).toBe("new-refresh-token");
33
- expect(tokens.accessTokenExpiresAt).toBeInstanceOf(Date);
34
- expect(tokens.accessTokenExpiresAt!.getTime()).toBeGreaterThanOrEqual(
35
- now + 3600 * 1000 - 1000,
36
- );
37
- expect(tokens.refreshTokenExpiresAt).toBeUndefined();
38
- });
39
-
40
- /**
41
- * @see https://github.com/better-auth/better-auth/issues/7682
42
- */
43
- it("should set refreshTokenExpiresAt when refresh_token_expires_in is returned", async () => {
44
- const now = Date.now();
45
- mockedBetterFetch.mockResolvedValueOnce({
46
- data: {
47
- access_token: "new-access-token",
48
- refresh_token: "new-refresh-token",
49
- expires_in: 3600,
50
- refresh_token_expires_in: 86400,
51
- token_type: "Bearer",
52
- },
53
- error: null,
54
- });
55
-
56
- const tokens = await refreshAccessToken({
57
- refreshToken: "old-refresh-token",
58
- options: { clientId: "test-client", clientSecret: "test-secret" },
59
- tokenEndpoint: "https://example.com/token",
60
- });
61
-
62
- expect(tokens.accessToken).toBe("new-access-token");
63
- expect(tokens.refreshToken).toBe("new-refresh-token");
64
- expect(tokens.accessTokenExpiresAt).toBeInstanceOf(Date);
65
- expect(tokens.refreshTokenExpiresAt).toBeInstanceOf(Date);
66
- expect(tokens.refreshTokenExpiresAt!.getTime()).toBeGreaterThanOrEqual(
67
- now + 86400 * 1000 - 1000,
68
- );
69
- });
70
-
71
- it("should not set refreshTokenExpiresAt when refresh_token_expires_in is not returned", async () => {
72
- mockedBetterFetch.mockResolvedValueOnce({
73
- data: {
74
- access_token: "new-access-token",
75
- refresh_token: "new-refresh-token",
76
- expires_in: 3600,
77
- token_type: "Bearer",
78
- },
79
- error: null,
80
- });
81
-
82
- const tokens = await refreshAccessToken({
83
- refreshToken: "old-refresh-token",
84
- options: { clientId: "test-client", clientSecret: "test-secret" },
85
- tokenEndpoint: "https://example.com/token",
86
- });
87
-
88
- expect(tokens.refreshTokenExpiresAt).toBeUndefined();
89
- });
90
- });
@@ -1,229 +0,0 @@
1
- import type { JWK } from "jose";
2
- import { exportJWK, generateKeyPair, SignJWT } from "jose";
3
- import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
4
- import { validateToken } from "./validate-authorization-code";
5
-
6
- describe("validateToken", () => {
7
- const originalFetch = globalThis.fetch;
8
- const mockedFetch = vi.fn() as unknown as typeof fetch &
9
- ReturnType<typeof vi.fn>;
10
-
11
- beforeAll(() => {
12
- globalThis.fetch = mockedFetch;
13
- });
14
-
15
- afterAll(() => {
16
- globalThis.fetch = originalFetch;
17
- });
18
-
19
- async function createTestJWKS(alg: string, crv?: string) {
20
- const { publicKey, privateKey } = await generateKeyPair(alg, {
21
- crv,
22
- extractable: true,
23
- });
24
- const publicJWK = await exportJWK(publicKey);
25
- const privateJWK = await exportJWK(privateKey);
26
- const kid = `test-key-${Date.now()}`;
27
- publicJWK.kid = kid;
28
- publicJWK.alg = alg;
29
- privateJWK.kid = kid;
30
- privateJWK.alg = alg;
31
- return { publicJWK, privateJWK, kid, publicKey, privateKey };
32
- }
33
-
34
- async function createSignedToken(
35
- privateKey: CryptoKey,
36
- alg: string,
37
- kid: string,
38
- payload: Record<string, unknown> = {},
39
- ) {
40
- return await new SignJWT({
41
- sub: "user-123",
42
- email: "test@example.com",
43
- iss: "https://example.com",
44
- aud: "test-client",
45
- ...payload,
46
- })
47
- .setProtectedHeader({ alg, kid })
48
- .setIssuedAt()
49
- .setExpirationTime("1h")
50
- .sign(privateKey);
51
- }
52
-
53
- function mockJWKSResponse(...publicJWKs: JWK[]) {
54
- mockedFetch.mockResolvedValueOnce(
55
- new Response(JSON.stringify({ keys: publicJWKs }), {
56
- status: 200,
57
- headers: { "content-type": "application/json" },
58
- }),
59
- );
60
- }
61
-
62
- it("should verify RS256 signed token", async () => {
63
- const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
64
- const token = await createSignedToken(privateKey, "RS256", kid);
65
- mockJWKSResponse(publicJWK);
66
-
67
- const result = await validateToken(
68
- token,
69
- "https://example.com/.well-known/jwks",
70
- );
71
-
72
- expect(result).toBeDefined();
73
- expect(result.payload.sub).toBe("user-123");
74
- expect(result.payload.email).toBe("test@example.com");
75
- });
76
-
77
- it("should verify ES256 signed token", async () => {
78
- const { publicJWK, privateKey, kid } = await createTestJWKS("ES256");
79
- const token = await createSignedToken(privateKey, "ES256", kid);
80
- mockJWKSResponse(publicJWK);
81
-
82
- const result = await validateToken(
83
- token,
84
- "https://example.com/.well-known/jwks",
85
- );
86
-
87
- expect(result).toBeDefined();
88
- expect(result.payload.sub).toBe("user-123");
89
- });
90
-
91
- it("should verify EdDSA (Ed25519) signed token", async () => {
92
- const { publicJWK, privateKey, kid } = await createTestJWKS(
93
- "EdDSA",
94
- "Ed25519",
95
- );
96
- const token = await createSignedToken(privateKey, "EdDSA", kid);
97
- mockJWKSResponse(publicJWK);
98
-
99
- const result = await validateToken(
100
- token,
101
- "https://example.com/.well-known/jwks",
102
- );
103
-
104
- expect(result).toBeDefined();
105
- expect(result.payload.sub).toBe("user-123");
106
- });
107
-
108
- it("should throw when kid doesn't match any key", async () => {
109
- const { publicJWK, privateKey } = await createTestJWKS("RS256");
110
- publicJWK.kid = "different-kid";
111
- const token = await createSignedToken(privateKey, "RS256", "original-kid");
112
- mockJWKSResponse(publicJWK);
113
-
114
- await expect(
115
- validateToken(token, "https://example.com/.well-known/jwks"),
116
- ).rejects.toThrow();
117
- });
118
-
119
- it("should find correct key when multiple keys exist", async () => {
120
- const key1 = await createTestJWKS("RS256");
121
- const key2 = await createTestJWKS("RS256");
122
- const key3 = await createTestJWKS("ES256");
123
- const token = await createSignedToken(key2.privateKey, "RS256", key2.kid);
124
- mockJWKSResponse(key1.publicJWK, key2.publicJWK, key3.publicJWK);
125
-
126
- const result = await validateToken(
127
- token,
128
- "https://example.com/.well-known/jwks",
129
- );
130
-
131
- expect(result).toBeDefined();
132
- expect(result.payload.sub).toBe("user-123");
133
- });
134
-
135
- it("should throw when JWKS returns empty keys array", async () => {
136
- const { privateKey, kid } = await createTestJWKS("RS256");
137
- const token = await createSignedToken(privateKey, "RS256", kid);
138
- mockJWKSResponse();
139
-
140
- await expect(
141
- validateToken(token, "https://example.com/.well-known/jwks"),
142
- ).rejects.toThrow();
143
- });
144
-
145
- it("should throw when JWKS fetch fails", async () => {
146
- const { privateKey, kid } = await createTestJWKS("RS256");
147
- const token = await createSignedToken(privateKey, "RS256", kid);
148
- mockedFetch.mockResolvedValueOnce(
149
- new Response("Internal Server Error", { status: 500 }),
150
- );
151
-
152
- await expect(
153
- validateToken(token, "https://example.com/.well-known/jwks"),
154
- ).rejects.toBeDefined();
155
- });
156
-
157
- it("should verify token with matching audience", async () => {
158
- const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
159
- const token = await createSignedToken(privateKey, "RS256", kid);
160
- mockJWKSResponse(publicJWK);
161
-
162
- const result = await validateToken(
163
- token,
164
- "https://example.com/.well-known/jwks",
165
- { audience: "test-client" },
166
- );
167
-
168
- expect(result).toBeDefined();
169
- expect(result.payload.aud).toBe("test-client");
170
- });
171
-
172
- it("should reject token with mismatched audience", async () => {
173
- const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
174
- const token = await createSignedToken(privateKey, "RS256", kid);
175
- mockJWKSResponse(publicJWK);
176
-
177
- await expect(
178
- validateToken(token, "https://example.com/.well-known/jwks", {
179
- audience: "wrong-client",
180
- }),
181
- ).rejects.toThrow();
182
- });
183
-
184
- it("should verify token with matching issuer", async () => {
185
- const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
186
- const token = await createSignedToken(privateKey, "RS256", kid);
187
- mockJWKSResponse(publicJWK);
188
-
189
- const result = await validateToken(
190
- token,
191
- "https://example.com/.well-known/jwks",
192
- { issuer: "https://example.com" },
193
- );
194
-
195
- expect(result).toBeDefined();
196
- expect(result.payload.iss).toBe("https://example.com");
197
- });
198
-
199
- it("should reject token with mismatched issuer", async () => {
200
- const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
201
- const token = await createSignedToken(privateKey, "RS256", kid);
202
- mockJWKSResponse(publicJWK);
203
-
204
- await expect(
205
- validateToken(token, "https://example.com/.well-known/jwks", {
206
- issuer: "https://wrong-issuer.com",
207
- }),
208
- ).rejects.toThrow();
209
- });
210
-
211
- it("should verify token with both audience and issuer", async () => {
212
- const { publicJWK, privateKey, kid } = await createTestJWKS("RS256");
213
- const token = await createSignedToken(privateKey, "RS256", kid);
214
- mockJWKSResponse(publicJWK);
215
-
216
- const result = await validateToken(
217
- token,
218
- "https://example.com/.well-known/jwks",
219
- {
220
- audience: "test-client",
221
- issuer: "https://example.com",
222
- },
223
- );
224
-
225
- expect(result).toBeDefined();
226
- expect(result.payload.aud).toBe("test-client");
227
- expect(result.payload.iss).toBe("https://example.com");
228
- });
229
- });
@@ -1,71 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { deprecate } from "./deprecate";
3
-
4
- describe("deprecate", () => {
5
- it("should warn once when called multiple times", () => {
6
- const warn = vi.fn();
7
- const logger = { warn } as any;
8
- const fn = vi.fn();
9
- const deprecatedFn = deprecate(fn, "test message", logger);
10
-
11
- deprecatedFn();
12
- deprecatedFn();
13
- deprecatedFn();
14
-
15
- expect(warn).toHaveBeenCalledTimes(1);
16
- expect(warn).toHaveBeenCalledWith("[Deprecation] test message");
17
- expect(fn).toHaveBeenCalledTimes(3);
18
- });
19
-
20
- it("should use provided logger if available", () => {
21
- const warn = vi.fn();
22
- const logger = { warn } as any;
23
- const fn = vi.fn();
24
- const deprecatedFn = deprecate(fn, "test message", logger);
25
-
26
- deprecatedFn();
27
-
28
- expect(warn).toHaveBeenCalledWith("[Deprecation] test message");
29
- });
30
-
31
- it("should fall back to console.warn if no logger provided", () => {
32
- const consoleWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
33
- const fn = vi.fn();
34
- const deprecatedFn = deprecate(fn, "test message");
35
-
36
- deprecatedFn();
37
-
38
- expect(consoleWarn).toHaveBeenCalledWith("[Deprecation] test message");
39
- });
40
-
41
- it("should pass arguments and return value correctly", () => {
42
- const fn = vi.fn((a: number, b: number) => a + b);
43
- const deprecatedFn = deprecate(fn, "test message", {
44
- warn: vi.fn(),
45
- } as any);
46
-
47
- const result = deprecatedFn(1, 2);
48
-
49
- expect(result).toBe(3);
50
- expect(fn).toHaveBeenCalledWith(1, 2);
51
- });
52
-
53
- it("should preserve this context", () => {
54
- class TestClass {
55
- value = 10;
56
- method(a: number) {
57
- return this.value + a;
58
- }
59
- }
60
-
61
- const instance = new TestClass();
62
- const originalMethod = instance.method;
63
- instance.method = deprecate(originalMethod, "test message", {
64
- warn: vi.fn(),
65
- } as any);
66
-
67
- const result = instance.method(5);
68
-
69
- expect(result).toBe(15);
70
- });
71
- });
@@ -1,28 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { isBrowserFetchRequest } from "./fetch-metadata";
3
-
4
- describe("isBrowserFetchRequest", () => {
5
- it("returns true for browser fetch requests", () => {
6
- expect(
7
- isBrowserFetchRequest(
8
- new Headers({
9
- "Sec-Fetch-Mode": "cors",
10
- }),
11
- ),
12
- ).toBe(true);
13
- });
14
-
15
- it("returns false for navigation requests", () => {
16
- expect(
17
- isBrowserFetchRequest(
18
- new Headers({
19
- "Sec-Fetch-Mode": "navigate",
20
- }),
21
- ),
22
- ).toBe(false);
23
- });
24
-
25
- it("returns false without fetch metadata", () => {
26
- expect(isBrowserFetchRequest()).toBe(false);
27
- });
28
- });