@draftlab/auth 0.15.0 → 0.16.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 (272) hide show
  1. package/dist/esm/allow.js +26 -0
  2. package/dist/esm/client.js +254 -0
  3. package/dist/esm/core.js +597 -0
  4. package/dist/esm/css.d.js +0 -0
  5. package/dist/esm/error.js +88 -0
  6. package/dist/esm/index.js +5 -0
  7. package/dist/esm/keys.js +126 -0
  8. package/dist/esm/mutex.js +53 -0
  9. package/dist/esm/pkce.js +87 -0
  10. package/dist/esm/provider/apple.js +15 -0
  11. package/dist/esm/provider/code.js +62 -0
  12. package/dist/esm/provider/discord.js +15 -0
  13. package/dist/esm/provider/facebook.js +15 -0
  14. package/dist/esm/provider/github.js +15 -0
  15. package/dist/esm/provider/gitlab.js +15 -0
  16. package/dist/esm/provider/google.js +16 -0
  17. package/dist/esm/provider/linkedin.js +15 -0
  18. package/dist/esm/provider/magiclink.js +83 -0
  19. package/dist/esm/provider/microsoft.js +15 -0
  20. package/dist/esm/provider/oauth2.js +130 -0
  21. package/dist/esm/provider/password.js +331 -0
  22. package/dist/esm/provider/provider.js +18 -0
  23. package/dist/esm/provider/reddit.js +15 -0
  24. package/dist/esm/provider/slack.js +15 -0
  25. package/dist/esm/provider/spotify.js +15 -0
  26. package/dist/esm/provider/twitch.js +15 -0
  27. package/dist/esm/provider/vercel.js +17 -0
  28. package/dist/esm/random.js +40 -0
  29. package/dist/esm/revocation.js +27 -0
  30. package/dist/esm/storage/memory.js +110 -0
  31. package/dist/esm/storage/storage.js +56 -0
  32. package/dist/esm/storage/turso.js +93 -0
  33. package/dist/esm/storage/unstorage.js +78 -0
  34. package/dist/esm/subject.js +7 -0
  35. package/dist/esm/themes/theme.js +115 -0
  36. package/dist/esm/toolkit/client.js +119 -0
  37. package/dist/esm/toolkit/index.js +25 -0
  38. package/dist/esm/toolkit/providers/facebook.js +11 -0
  39. package/dist/esm/toolkit/providers/github.js +11 -0
  40. package/dist/esm/toolkit/providers/google.js +11 -0
  41. package/dist/esm/toolkit/providers/strategy.js +0 -0
  42. package/dist/esm/toolkit/storage.js +81 -0
  43. package/dist/esm/toolkit/utils.js +18 -0
  44. package/dist/esm/types.js +0 -0
  45. package/dist/esm/ui/base.js +478 -0
  46. package/dist/esm/ui/code.js +186 -0
  47. package/dist/esm/ui/form.js +46 -0
  48. package/dist/esm/ui/icon.js +242 -0
  49. package/dist/esm/ui/magiclink.js +158 -0
  50. package/dist/esm/ui/password.js +435 -0
  51. package/dist/esm/ui/select.js +102 -0
  52. package/dist/esm/util.js +59 -0
  53. package/dist/{allow.d.mts → types/allow.d.ts} +9 -11
  54. package/dist/types/allow.d.ts.map +1 -0
  55. package/dist/types/client.d.ts +462 -0
  56. package/dist/types/client.d.ts.map +1 -0
  57. package/dist/types/core.d.ts +113 -0
  58. package/dist/types/core.d.ts.map +1 -0
  59. package/dist/{error.d.mts → types/error.d.ts} +95 -97
  60. package/dist/types/error.d.ts.map +1 -0
  61. package/dist/types/index.d.ts +2 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/{keys.d.mts → types/keys.d.ts} +20 -24
  64. package/dist/types/keys.d.ts.map +1 -0
  65. package/dist/types/mutex.d.ts +42 -0
  66. package/dist/types/mutex.d.ts.map +1 -0
  67. package/dist/{pkce.d.mts → types/pkce.d.ts} +10 -11
  68. package/dist/types/pkce.d.ts.map +1 -0
  69. package/dist/types/provider/apple.d.ts +197 -0
  70. package/dist/types/provider/apple.d.ts.map +1 -0
  71. package/dist/types/provider/code.d.ts +288 -0
  72. package/dist/types/provider/code.d.ts.map +1 -0
  73. package/dist/types/provider/discord.d.ts +206 -0
  74. package/dist/types/provider/discord.d.ts.map +1 -0
  75. package/dist/types/provider/facebook.d.ts +200 -0
  76. package/dist/types/provider/facebook.d.ts.map +1 -0
  77. package/dist/types/provider/github.d.ts +220 -0
  78. package/dist/types/provider/github.d.ts.map +1 -0
  79. package/dist/types/provider/gitlab.d.ts +180 -0
  80. package/dist/types/provider/gitlab.d.ts.map +1 -0
  81. package/dist/types/provider/google.d.ts +158 -0
  82. package/dist/types/provider/google.d.ts.map +1 -0
  83. package/dist/types/provider/linkedin.d.ts +190 -0
  84. package/dist/types/provider/linkedin.d.ts.map +1 -0
  85. package/dist/types/provider/magiclink.d.ts +141 -0
  86. package/dist/types/provider/magiclink.d.ts.map +1 -0
  87. package/dist/types/provider/microsoft.d.ts +247 -0
  88. package/dist/types/provider/microsoft.d.ts.map +1 -0
  89. package/dist/types/provider/oauth2.d.ts +229 -0
  90. package/dist/types/provider/oauth2.d.ts.map +1 -0
  91. package/dist/types/provider/password.d.ts +408 -0
  92. package/dist/types/provider/password.d.ts.map +1 -0
  93. package/dist/types/provider/provider.d.ts +226 -0
  94. package/dist/types/provider/provider.d.ts.map +1 -0
  95. package/dist/types/provider/reddit.d.ts +159 -0
  96. package/dist/types/provider/reddit.d.ts.map +1 -0
  97. package/dist/types/provider/slack.d.ts +171 -0
  98. package/dist/types/provider/slack.d.ts.map +1 -0
  99. package/dist/types/provider/spotify.d.ts +168 -0
  100. package/dist/types/provider/spotify.d.ts.map +1 -0
  101. package/dist/types/provider/twitch.d.ts +163 -0
  102. package/dist/types/provider/twitch.d.ts.map +1 -0
  103. package/dist/types/provider/vercel.d.ts +294 -0
  104. package/dist/types/provider/vercel.d.ts.map +1 -0
  105. package/dist/{random.d.mts → types/random.d.ts} +4 -6
  106. package/dist/types/random.d.ts.map +1 -0
  107. package/dist/types/revocation.d.ts +76 -0
  108. package/dist/types/revocation.d.ts.map +1 -0
  109. package/dist/{storage/memory.d.mts → types/storage/memory.d.ts} +17 -21
  110. package/dist/types/storage/memory.d.ts.map +1 -0
  111. package/dist/types/storage/storage.d.ts +177 -0
  112. package/dist/types/storage/storage.d.ts.map +1 -0
  113. package/dist/{storage/turso.d.mts → types/storage/turso.d.ts} +4 -8
  114. package/dist/types/storage/turso.d.ts.map +1 -0
  115. package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -11
  116. package/dist/types/storage/unstorage.d.ts.map +1 -0
  117. package/dist/types/subject.d.ts +115 -0
  118. package/dist/types/subject.d.ts.map +1 -0
  119. package/dist/types/themes/theme.d.ts +207 -0
  120. package/dist/types/themes/theme.d.ts.map +1 -0
  121. package/dist/types/toolkit/client.d.ts +235 -0
  122. package/dist/types/toolkit/client.d.ts.map +1 -0
  123. package/dist/types/toolkit/index.d.ts +45 -0
  124. package/dist/types/toolkit/index.d.ts.map +1 -0
  125. package/dist/types/toolkit/providers/facebook.d.ts +8 -0
  126. package/dist/types/toolkit/providers/facebook.d.ts.map +1 -0
  127. package/dist/types/toolkit/providers/github.d.ts +8 -0
  128. package/dist/types/toolkit/providers/github.d.ts.map +1 -0
  129. package/dist/types/toolkit/providers/google.d.ts +8 -0
  130. package/dist/types/toolkit/providers/google.d.ts.map +1 -0
  131. package/dist/types/toolkit/providers/strategy.d.ts +38 -0
  132. package/dist/types/toolkit/providers/strategy.d.ts.map +1 -0
  133. package/dist/{toolkit/storage.d.mts → types/toolkit/storage.d.ts} +37 -39
  134. package/dist/types/toolkit/storage.d.ts.map +1 -0
  135. package/dist/{toolkit/utils.d.mts → types/toolkit/utils.d.ts} +2 -4
  136. package/dist/types/toolkit/utils.d.ts.map +1 -0
  137. package/dist/types/types.d.ts +92 -0
  138. package/dist/types/types.d.ts.map +1 -0
  139. package/dist/types/ui/base.d.ts +18 -0
  140. package/dist/types/ui/base.d.ts.map +1 -0
  141. package/dist/types/ui/code.d.ts +43 -0
  142. package/dist/types/ui/code.d.ts.map +1 -0
  143. package/dist/types/ui/form.d.ts +24 -0
  144. package/dist/types/ui/form.d.ts.map +1 -0
  145. package/dist/types/ui/icon.d.ts +60 -0
  146. package/dist/types/ui/icon.d.ts.map +1 -0
  147. package/dist/types/ui/magiclink.d.ts +41 -0
  148. package/dist/types/ui/magiclink.d.ts.map +1 -0
  149. package/dist/types/ui/password.d.ts +43 -0
  150. package/dist/types/ui/password.d.ts.map +1 -0
  151. package/dist/types/ui/select.d.ts +33 -0
  152. package/dist/types/ui/select.d.ts.map +1 -0
  153. package/dist/{util.d.mts → types/util.d.ts} +11 -13
  154. package/dist/types/util.d.ts.map +1 -0
  155. package/package.json +10 -16
  156. package/dist/adapters/node.d.mts +0 -18
  157. package/dist/adapters/node.mjs +0 -69
  158. package/dist/allow.mjs +0 -63
  159. package/dist/client.d.mts +0 -456
  160. package/dist/client.mjs +0 -283
  161. package/dist/core.d.mts +0 -110
  162. package/dist/core.mjs +0 -595
  163. package/dist/error.mjs +0 -237
  164. package/dist/index.d.mts +0 -2
  165. package/dist/index.mjs +0 -3
  166. package/dist/keys.mjs +0 -146
  167. package/dist/mutex.d.mts +0 -44
  168. package/dist/mutex.mjs +0 -110
  169. package/dist/pkce.mjs +0 -157
  170. package/dist/provider/apple.d.mts +0 -111
  171. package/dist/provider/apple.mjs +0 -164
  172. package/dist/provider/code.d.mts +0 -228
  173. package/dist/provider/code.mjs +0 -246
  174. package/dist/provider/discord.d.mts +0 -146
  175. package/dist/provider/discord.mjs +0 -156
  176. package/dist/provider/facebook.d.mts +0 -142
  177. package/dist/provider/facebook.mjs +0 -150
  178. package/dist/provider/github.d.mts +0 -140
  179. package/dist/provider/github.mjs +0 -169
  180. package/dist/provider/gitlab.d.mts +0 -106
  181. package/dist/provider/gitlab.mjs +0 -147
  182. package/dist/provider/google.d.mts +0 -112
  183. package/dist/provider/google.mjs +0 -109
  184. package/dist/provider/linkedin.d.mts +0 -132
  185. package/dist/provider/linkedin.mjs +0 -142
  186. package/dist/provider/magiclink.d.mts +0 -89
  187. package/dist/provider/magiclink.mjs +0 -143
  188. package/dist/provider/microsoft.d.mts +0 -178
  189. package/dist/provider/microsoft.mjs +0 -177
  190. package/dist/provider/oauth2.d.mts +0 -176
  191. package/dist/provider/oauth2.mjs +0 -222
  192. package/dist/provider/passkey.d.mts +0 -104
  193. package/dist/provider/passkey.mjs +0 -320
  194. package/dist/provider/password.d.mts +0 -412
  195. package/dist/provider/password.mjs +0 -363
  196. package/dist/provider/provider.d.mts +0 -227
  197. package/dist/provider/provider.mjs +0 -44
  198. package/dist/provider/reddit.d.mts +0 -107
  199. package/dist/provider/reddit.mjs +0 -127
  200. package/dist/provider/slack.d.mts +0 -114
  201. package/dist/provider/slack.mjs +0 -138
  202. package/dist/provider/spotify.d.mts +0 -113
  203. package/dist/provider/spotify.mjs +0 -135
  204. package/dist/provider/totp.d.mts +0 -112
  205. package/dist/provider/totp.mjs +0 -191
  206. package/dist/provider/twitch.d.mts +0 -108
  207. package/dist/provider/twitch.mjs +0 -131
  208. package/dist/provider/vercel.d.mts +0 -177
  209. package/dist/provider/vercel.mjs +0 -230
  210. package/dist/random.mjs +0 -86
  211. package/dist/revocation.d.mts +0 -55
  212. package/dist/revocation.mjs +0 -63
  213. package/dist/router/context.d.mts +0 -21
  214. package/dist/router/context.mjs +0 -193
  215. package/dist/router/cookies.d.mts +0 -8
  216. package/dist/router/cookies.mjs +0 -13
  217. package/dist/router/index.d.mts +0 -21
  218. package/dist/router/index.mjs +0 -107
  219. package/dist/router/matcher.d.mts +0 -15
  220. package/dist/router/matcher.mjs +0 -76
  221. package/dist/router/middleware/cors.d.mts +0 -15
  222. package/dist/router/middleware/cors.mjs +0 -114
  223. package/dist/router/safe-request.d.mts +0 -52
  224. package/dist/router/safe-request.mjs +0 -160
  225. package/dist/router/types.d.mts +0 -67
  226. package/dist/router/types.mjs +0 -1
  227. package/dist/router/variables.d.mts +0 -12
  228. package/dist/router/variables.mjs +0 -20
  229. package/dist/storage/memory.mjs +0 -125
  230. package/dist/storage/storage.d.mts +0 -179
  231. package/dist/storage/storage.mjs +0 -104
  232. package/dist/storage/turso.mjs +0 -117
  233. package/dist/storage/unstorage.mjs +0 -103
  234. package/dist/subject.d.mts +0 -62
  235. package/dist/subject.mjs +0 -36
  236. package/dist/themes/theme.d.mts +0 -209
  237. package/dist/themes/theme.mjs +0 -120
  238. package/dist/toolkit/client.d.mts +0 -169
  239. package/dist/toolkit/client.mjs +0 -209
  240. package/dist/toolkit/index.d.mts +0 -9
  241. package/dist/toolkit/index.mjs +0 -9
  242. package/dist/toolkit/providers/facebook.d.mts +0 -12
  243. package/dist/toolkit/providers/facebook.mjs +0 -16
  244. package/dist/toolkit/providers/github.d.mts +0 -12
  245. package/dist/toolkit/providers/github.mjs +0 -16
  246. package/dist/toolkit/providers/google.d.mts +0 -12
  247. package/dist/toolkit/providers/google.mjs +0 -20
  248. package/dist/toolkit/providers/strategy.d.mts +0 -40
  249. package/dist/toolkit/providers/strategy.mjs +0 -1
  250. package/dist/toolkit/storage.mjs +0 -157
  251. package/dist/toolkit/utils.mjs +0 -30
  252. package/dist/types.d.mts +0 -94
  253. package/dist/types.mjs +0 -1
  254. package/dist/ui/base.d.mts +0 -30
  255. package/dist/ui/base.mjs +0 -407
  256. package/dist/ui/code.d.mts +0 -43
  257. package/dist/ui/code.mjs +0 -173
  258. package/dist/ui/form.d.mts +0 -32
  259. package/dist/ui/form.mjs +0 -49
  260. package/dist/ui/icon.d.mts +0 -58
  261. package/dist/ui/icon.mjs +0 -247
  262. package/dist/ui/magiclink.d.mts +0 -41
  263. package/dist/ui/magiclink.mjs +0 -152
  264. package/dist/ui/passkey.d.mts +0 -27
  265. package/dist/ui/passkey.mjs +0 -323
  266. package/dist/ui/password.d.mts +0 -42
  267. package/dist/ui/password.mjs +0 -402
  268. package/dist/ui/select.d.mts +0 -34
  269. package/dist/ui/select.mjs +0 -98
  270. package/dist/ui/totp.d.mts +0 -34
  271. package/dist/ui/totp.mjs +0 -270
  272. package/dist/util.mjs +0 -128
@@ -1,160 +0,0 @@
1
- //#region src/router/safe-request.ts
2
- var SafeRequest = class SafeRequest {
3
- cachedBody = null;
4
- bodyBuffer = null;
5
- textDecoder = new TextDecoder();
6
- cache;
7
- credentials;
8
- destination;
9
- headers;
10
- integrity;
11
- keepalive;
12
- method;
13
- mode;
14
- redirect;
15
- referrer;
16
- referrerPolicy;
17
- signal;
18
- url;
19
- constructor(url, method, headers, body, options) {
20
- this.url = url;
21
- this.method = method;
22
- this.headers = headers;
23
- this.bodyBuffer = body;
24
- this.cache = options?.cache ?? "default";
25
- this.credentials = options?.credentials ?? "same-origin";
26
- this.destination = options?.destination ?? "";
27
- this.integrity = options?.integrity ?? "";
28
- this.keepalive = options?.keepalive ?? false;
29
- this.mode = options?.mode ?? "cors";
30
- this.redirect = options?.redirect ?? "follow";
31
- this.referrer = options?.referrer ?? "";
32
- this.referrerPolicy = options?.referrerPolicy ?? "";
33
- this.signal = options?.signal ?? new AbortController().signal;
34
- }
35
- async arrayBuffer() {
36
- return this.bodyBuffer ?? /* @__PURE__ */ new ArrayBuffer(0);
37
- }
38
- async blob() {
39
- const buffer = await this.arrayBuffer();
40
- return new Blob([buffer]);
41
- }
42
- async formData() {
43
- const buffer = await this.arrayBuffer();
44
- const blob = new Blob([buffer], { type: this.headers.get("content-type") || "application/x-www-form-urlencoded" });
45
- return new Request(this.url, {
46
- method: this.method,
47
- headers: this.headers,
48
- body: blob
49
- }).formData();
50
- }
51
- async json() {
52
- const text = await this.text();
53
- return JSON.parse(text);
54
- }
55
- async text() {
56
- const buffer = await this.arrayBuffer();
57
- return this.textDecoder.decode(buffer);
58
- }
59
- async bytes() {
60
- return this.arrayBuffer().then((buffer) => new Uint8Array(buffer));
61
- }
62
- get body() {
63
- if (this.cachedBody) return this.cachedBody;
64
- if (this.bodyBuffer) {
65
- const buffer = this.bodyBuffer;
66
- this.cachedBody = new ReadableStream({ start(controller) {
67
- controller.enqueue(new Uint8Array(buffer));
68
- controller.close();
69
- } });
70
- return this.cachedBody;
71
- }
72
- return null;
73
- }
74
- get bodyUsed() {
75
- return false;
76
- }
77
- clone() {
78
- return new SafeRequest(this.url, this.method, this.headers, this.bodyBuffer, {
79
- cache: this.cache,
80
- credentials: this.credentials,
81
- destination: this.destination,
82
- integrity: this.integrity,
83
- keepalive: this.keepalive,
84
- mode: this.mode,
85
- redirect: this.redirect,
86
- referrer: this.referrer,
87
- referrerPolicy: this.referrerPolicy,
88
- signal: this.signal
89
- });
90
- }
91
- };
92
- /**
93
- * Extracts data from a Request and creates a SafeRequest.
94
- * Uses ReadableStream to safely read the body and avoid issues with certain Request implementations.
95
- */
96
- async function makeSafeRequest(request) {
97
- if (request instanceof SafeRequest) return request;
98
- const url = request.url;
99
- const method = request.method;
100
- const headers = new Headers(request.headers);
101
- let bodyBuffer = null;
102
- const requestMethod = method.toUpperCase();
103
- if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") try {
104
- const body = request.body;
105
- if (body) {
106
- const reader = body.getReader();
107
- const chunks = [];
108
- while (true) {
109
- const { done, value } = await reader.read();
110
- if (done) break;
111
- if (value) chunks.push(value);
112
- }
113
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
114
- const combined = new Uint8Array(totalLength);
115
- let offset = 0;
116
- for (const chunk of chunks) {
117
- combined.set(chunk, offset);
118
- offset += chunk.length;
119
- }
120
- bodyBuffer = combined.buffer;
121
- }
122
- } catch (error) {
123
- console.warn("Failed to read request body via stream:", error);
124
- }
125
- const options = {};
126
- try {
127
- options.cache = request.cache;
128
- } catch {}
129
- try {
130
- options.credentials = request.credentials;
131
- } catch {}
132
- try {
133
- options.destination = request.destination;
134
- } catch {}
135
- try {
136
- options.integrity = request.integrity;
137
- } catch {}
138
- try {
139
- options.keepalive = request.keepalive;
140
- } catch {}
141
- try {
142
- options.mode = request.mode;
143
- } catch {}
144
- try {
145
- options.redirect = request.redirect;
146
- } catch {}
147
- try {
148
- options.referrer = request.referrer;
149
- } catch {}
150
- try {
151
- options.referrerPolicy = request.referrerPolicy;
152
- } catch {}
153
- try {
154
- options.signal = request.signal;
155
- } catch {}
156
- return new SafeRequest(url, method, headers, bodyBuffer, options);
157
- }
158
-
159
- //#endregion
160
- export { SafeRequest, makeSafeRequest };
@@ -1,67 +0,0 @@
1
- //#region src/router/types.d.ts
2
- type ExtractParams<T extends string> = string extends T ? Record<string, string> : T extends `${string}:${infer Param}/${infer Rest}` ? { readonly [K in Param]: string } & ExtractParams<`/${Rest}`> : T extends `${string}:${infer Param}` ? { readonly [K in Param]: string } : Record<string, never>;
3
- type VariableMap = Record<string, unknown>;
4
- interface RouterEnvironment<TVariables extends VariableMap = VariableMap> {
5
- Variables: TVariables;
6
- }
7
- interface CookieOptions {
8
- domain?: string;
9
- path?: string;
10
- expires?: Date;
11
- maxAge?: number;
12
- httpOnly?: boolean;
13
- secure?: boolean;
14
- sameSite?: "Strict" | "Lax" | "None";
15
- }
16
- interface RouterContext<TParams extends Record<string, string> = Record<string, string>, TVariables extends VariableMap = VariableMap> {
17
- readonly request: Request;
18
- readonly params: Readonly<TParams>;
19
- readonly searchParams: Readonly<URLSearchParams>;
20
- query<K extends string>(key: K): string | undefined;
21
- header<K extends string>(key: K): string | undefined;
22
- cookie<K extends string>(key: K): string | undefined;
23
- formData(): Promise<FormData>;
24
- parseJson<T = unknown>(): Promise<T>;
25
- json<T>(data: T, init?: ResponseInit): Response;
26
- redirect(url: string | URL, status?: 300 | 301 | 302 | 303 | 307 | 308): Response;
27
- text(data: string, init?: ResponseInit): Response;
28
- setCookie(name: string, value: string, options?: CookieOptions): void;
29
- deleteCookie(name: string, options?: Pick<CookieOptions, "domain" | "path">): void;
30
- newResponse(body?: BodyInit, init?: ResponseInit): Response;
31
- set<K extends keyof TVariables>(key: K, value: TVariables[K]): void;
32
- get<K extends keyof TVariables>(key: K): TVariables[K];
33
- has<K extends keyof TVariables>(key: K): key is K;
34
- }
35
- type RouteHandler<TParams extends Record<string, string> = Record<string, string>, TVariables extends VariableMap = VariableMap> = (ctx: RouterContext<TParams, TVariables>) => Promise<Response> | Response;
36
- type MiddlewareHandler<TParams extends Record<string, string> = Record<string, string>, TVariables extends VariableMap = VariableMap> = (ctx: RouterContext<TParams, TVariables>, next: () => Promise<Response> | Response) => Promise<Response> | Response;
37
- type EnhancedRouteHandler<TParams extends Record<string, string> = Record<string, string>, TVariables extends VariableMap = VariableMap> = {
38
- handler: RouteHandler<TParams, TVariables>;
39
- middleware?: MiddlewareHandler<TParams, TVariables>[];
40
- };
41
- type AnyHandler<TParams extends Record<string, string>, TVariables extends VariableMap = VariableMap> = RouteHandler<TParams, TVariables> | EnhancedRouteHandler<TParams, TVariables>;
42
- type HttpMethod = "GET" | "POST";
43
- interface CompiledRoute {
44
- regex: RegExp;
45
- paramNames: string[];
46
- pattern: string;
47
- }
48
- interface MatchResult {
49
- params: Record<string, string>;
50
- pattern: string;
51
- }
52
- interface RouteDefinition<TVariables extends VariableMap = VariableMap> {
53
- method: HttpMethod;
54
- pattern: string;
55
- handler: RouteHandler<Record<string, string>, TVariables>;
56
- middleware: MiddlewareHandler<Record<string, string>, TVariables>[];
57
- compiled: CompiledRoute;
58
- }
59
- interface RouterOptions {
60
- caseSensitive?: boolean;
61
- strict?: boolean;
62
- basePath?: string;
63
- }
64
- type ErrorHandler<TVariables extends VariableMap = VariableMap> = (error: Error, ctx: RouterContext<Record<string, string>, TVariables>) => Promise<Response> | Response;
65
- type GlobalMiddleware<TVariables extends VariableMap = VariableMap> = (ctx: RouterContext<Record<string, string>, TVariables>, next: () => Promise<Response> | Response) => Promise<Response> | Response;
66
- //#endregion
67
- export { AnyHandler, CompiledRoute, CookieOptions, EnhancedRouteHandler, ErrorHandler, ExtractParams, GlobalMiddleware, HttpMethod, MatchResult, MiddlewareHandler, RouteDefinition, RouteHandler, RouterContext, RouterEnvironment, RouterOptions, VariableMap };
@@ -1 +0,0 @@
1
- export { };
@@ -1,12 +0,0 @@
1
- import { VariableMap } from "./types.mjs";
2
-
3
- //#region src/router/variables.d.ts
4
- declare class ContextVariableManager<TVariables extends VariableMap = VariableMap> {
5
- private readonly state;
6
- constructor(initialVariables?: Partial<TVariables>);
7
- set<K extends keyof TVariables>(key: K, value: TVariables[K]): void;
8
- get<K extends keyof TVariables>(key: K): TVariables[K];
9
- has<K extends keyof TVariables>(key: K): key is K;
10
- }
11
- //#endregion
12
- export { ContextVariableManager };
@@ -1,20 +0,0 @@
1
- //#region src/router/variables.ts
2
- var ContextVariableManager = class {
3
- state = /* @__PURE__ */ new Map();
4
- constructor(initialVariables) {
5
- if (initialVariables) for (const [key, value] of Object.entries(initialVariables)) this.state.set(key, value);
6
- }
7
- set(key, value) {
8
- if (typeof key !== "string" || key.length === 0) throw new Error("Variable key must be a non-empty string");
9
- this.state.set(key, value);
10
- }
11
- get(key) {
12
- return this.state.get(key);
13
- }
14
- has(key) {
15
- return this.state.has(key);
16
- }
17
- };
18
-
19
- //#endregion
20
- export { ContextVariableManager };
@@ -1,125 +0,0 @@
1
- import { joinKey, splitKey } from "./storage.mjs";
2
- import { existsSync, readFileSync } from "node:fs";
3
- import { writeFile } from "node:fs/promises";
4
-
5
- //#region src/storage/memory.ts
6
- /**
7
- * Creates an in-memory storage adapter with optional file persistence.
8
- * Uses binary search for efficient key lookups and maintains sorted order.
9
- *
10
- * @param options - Configuration options for the memory storage
11
- * @returns Storage adapter implementing the StorageAdapter interface
12
- *
13
- * @example
14
- * ```ts
15
- * // Development storage (data lost on restart)
16
- * const devStorage = MemoryStorage()
17
- *
18
- * // Persistent storage (survives restarts)
19
- * const persistentStorage = MemoryStorage({
20
- * persist: "./auth-data.json"
21
- * })
22
- *
23
- * // Use with issuer
24
- * export default issuer({
25
- * storage: persistentStorage,
26
- * providers: { ... }
27
- * })
28
- * ```
29
- */
30
- const MemoryStorage = (options) => {
31
- const store = [];
32
- /**
33
- * Type guard to validate loaded store data structure.
34
- */
35
- const isValidStoreData = (data) => {
36
- return Array.isArray(data) && data.every((item) => Array.isArray(item) && item.length === 2 && typeof item[0] === "string" && typeof item[1] === "object" && item[1] !== null && "value" in item[1]);
37
- };
38
- if (options?.persist && existsSync(options.persist)) try {
39
- const fileContent = readFileSync(options.persist, "utf8");
40
- const parsed = JSON.parse(fileContent);
41
- if (isValidStoreData(parsed)) store.push(...parsed);
42
- } catch {}
43
- /**
44
- * Saves the current store state to the persistence file if configured.
45
- */
46
- const save = async () => {
47
- if (!options?.persist) return;
48
- try {
49
- const serialized = JSON.stringify(store, null, 2);
50
- await writeFile(options.persist, serialized, "utf8");
51
- } catch {}
52
- };
53
- /**
54
- * Performs binary search to find a key in the sorted store.
55
- * Returns both whether the key was found and the insertion index.
56
- */
57
- const search = (key) => {
58
- let left = 0;
59
- let right = store.length - 1;
60
- while (left <= right) {
61
- const mid = Math.floor((left + right) / 2);
62
- const midEntry = store[mid];
63
- if (!midEntry) return {
64
- found: false,
65
- index: left
66
- };
67
- const comparison = key.localeCompare(midEntry[0]);
68
- if (comparison === 0) return {
69
- found: true,
70
- index: mid
71
- };
72
- if (comparison < 0) right = mid - 1;
73
- else left = mid + 1;
74
- }
75
- return {
76
- found: false,
77
- index: left
78
- };
79
- };
80
- return {
81
- async get(key) {
82
- const match = search(joinKey(key));
83
- if (!match.found) return;
84
- const storeEntry = store[match.index];
85
- if (!storeEntry) return;
86
- const entry = storeEntry[1];
87
- if (entry.expiry && Date.now() >= entry.expiry) {
88
- store.splice(match.index, 1);
89
- await save();
90
- return;
91
- }
92
- return entry.value;
93
- },
94
- async set(key, value, expiry) {
95
- const searchKey = joinKey(key);
96
- const match = search(searchKey);
97
- const entry = [searchKey, {
98
- value,
99
- expiry: expiry?.getTime()
100
- }];
101
- if (match.found) store[match.index] = entry;
102
- else store.splice(match.index, 0, entry);
103
- await save();
104
- },
105
- async remove(key) {
106
- const match = search(joinKey(key));
107
- if (match.found) {
108
- store.splice(match.index, 1);
109
- await save();
110
- }
111
- },
112
- async *scan(prefix) {
113
- const now = Date.now();
114
- const prefixStr = joinKey(prefix);
115
- for (const [key, entry] of store) {
116
- if (!key.startsWith(prefixStr)) continue;
117
- if (entry.expiry && now >= entry.expiry) continue;
118
- yield [splitKey(key), entry.value];
119
- }
120
- }
121
- };
122
- };
123
-
124
- //#endregion
125
- export { MemoryStorage };
@@ -1,179 +0,0 @@
1
- //#region src/storage/storage.d.ts
2
- /**
3
- * Storage abstraction layer for Draft Auth persistence operations.
4
- * Provides a unified interface for different storage backends with key encoding,
5
- * TTL support, and type-safe operations.
6
- */
7
- /**
8
- * Abstract storage adapter interface that must be implemented by all storage backends.
9
- * Defines the core operations needed for OAuth data persistence.
10
- */
11
- interface StorageAdapter {
12
- /**
13
- * Retrieves a value by its key path.
14
- *
15
- * @param key - Array of key segments forming the storage path
16
- * @returns Promise resolving to the stored value or undefined if not found
17
- */
18
- get(key: string[]): Promise<Record<string, unknown> | undefined>;
19
- /**
20
- * Removes a value by its key path.
21
- *
22
- * @param key - Array of key segments forming the storage path
23
- * @returns Promise that resolves when removal is complete
24
- */
25
- remove(key: string[]): Promise<void>;
26
- /**
27
- * Stores a value with an optional expiration date.
28
- *
29
- * @param key - Array of key segments forming the storage path
30
- * @param value - The value to store
31
- * @param expiry - Optional expiration date for automatic cleanup
32
- * @returns Promise that resolves when storage is complete
33
- */
34
- set(key: string[], value: unknown, expiry?: Date): Promise<void>;
35
- /**
36
- * Scans for keys matching a prefix pattern.
37
- *
38
- * @param prefix - Array of key segments to use as prefix filter
39
- * @returns Async iterable of key-value pairs matching the prefix
40
- */
41
- scan(prefix: string[]): AsyncIterable<readonly [string[], unknown]>;
42
- }
43
- /**
44
- * Joins an array of key segments into a single string using the separator.
45
- * Segments are properly escaped to handle any input, including separators and escape characters.
46
- *
47
- * @param key - Array of key segments to join
48
- * @returns Single string representing the full key path
49
- *
50
- * @example
51
- * ```ts
52
- * joinKey(['user', 'data\x1fwith\x1fseparators'])
53
- * // Returns: "user\x1fdata\\x1fwith\\x1fseparators"
54
- * ```
55
- */
56
- declare const joinKey: (key: string[]) => string;
57
- /**
58
- * Splits a joined key string back into its component segments.
59
- * Handles escaped characters properly.
60
- *
61
- * @param key - Joined key string to split
62
- * @returns Array of individual key segments
63
- *
64
- * @example
65
- * ```ts
66
- * splitKey("user\x1fdata\\x1fwith\\x1fseparators")
67
- * // Returns: ['user', 'data\x1fwith\x1fseparators']
68
- * ```
69
- */
70
- declare const splitKey: (key: string) => string[];
71
- /**
72
- * High-level storage operations with key encoding and type safety.
73
- * Provides a convenient interface over storage adapters with additional features
74
- * like TTL validation and secure key encoding to prevent collisions.
75
- */
76
- declare const Storage: {
77
- /**
78
- * Encodes key segments by escaping special characters.
79
- * Ensures storage keys don't contain unescaped separator characters that could cause collisions.
80
- *
81
- * @param key - Array of key segments to encode
82
- * @returns Array of properly escaped key segments
83
- *
84
- * @throws {Error} If any segment is empty or whitespace-only
85
- *
86
- * @example
87
- * ```ts
88
- * Storage.encode(['user', 'data\x1fwith\x1fseparators'])
89
- * // Returns: ['user', 'data\\x1fwith\\x1fseparators']
90
- * ```
91
- */
92
- readonly encode: (key: string[]) => string[];
93
- /**
94
- * Decodes key segments by unescaping special characters.
95
- * Reverse operation of encode().
96
- *
97
- * @param key - Array of encoded key segments
98
- * @returns Array of decoded key segments
99
- *
100
- * @internal
101
- */
102
- readonly decode: (key: string[]) => string[];
103
- /**
104
- * Retrieves a typed value from storage.
105
- *
106
- * @template T - Expected type of the stored value
107
- * @param adapter - Storage adapter to use
108
- * @param key - Array of key segments identifying the value
109
- * @returns Promise resolving to the typed value or null if not found
110
- *
111
- * @example
112
- * ```ts
113
- * interface UserSession {
114
- * userId: string
115
- * expiresAt: number
116
- * }
117
- *
118
- * const session = await Storage.get<UserSession>(adapter, ['sessions', sessionId])
119
- * if (session) {
120
- * // Fully typed: session.userId
121
- * }
122
- * ```
123
- */
124
- readonly get: <T = Record<string, unknown>>(adapter: StorageAdapter, key: string[]) => Promise<T | null>;
125
- /**
126
- * Stores a value with optional time-to-live in seconds.
127
- * Validates that TTL is a positive integer to prevent edge cases like negative or overflow values.
128
- *
129
- * @param adapter - Storage adapter to use
130
- * @param key - Array of key segments identifying where to store
131
- * @param value - The value to store
132
- * @param ttlSeconds - Optional TTL in seconds for automatic expiration
133
- * @returns Promise that resolves when storage is complete
134
- *
135
- * @throws {RangeError} If TTL is invalid (negative, non-integer, or exceeds maximum)
136
- *
137
- * @example
138
- * ```ts
139
- * // Store with 1 hour TTL
140
- * await Storage.set(adapter, ['sessions', sessionId], sessionData, 3600)
141
- *
142
- * // Store permanently (no expiration)
143
- * await Storage.set(adapter, ['users', userId], userData)
144
- * ```
145
- */
146
- readonly set: (adapter: StorageAdapter, key: string[], value: unknown, ttlSeconds?: number) => Promise<void>;
147
- /**
148
- * Removes a value from storage.
149
- *
150
- * @param adapter - Storage adapter to use
151
- * @param key - Array of key segments identifying the value to remove
152
- * @returns Promise that resolves when removal is complete
153
- *
154
- * @example
155
- * ```ts
156
- * await Storage.remove(adapter, ['sessions', expiredSessionId])
157
- * ```
158
- */
159
- readonly remove: (adapter: StorageAdapter, key: string[]) => Promise<void>;
160
- /**
161
- * Scans for entries matching a key prefix with type safety.
162
- *
163
- * @template T - Expected type of the stored values
164
- * @param adapter - Storage adapter to use
165
- * @param prefix - Array of key segments to use as prefix filter
166
- * @returns Async iterable of typed key-value pairs
167
- *
168
- * @example
169
- * ```ts
170
- * // Find all user sessions
171
- * for await (const [key, session] of Storage.scan<UserSession>(adapter, ['sessions'])) {
172
- * // Session: `${key.join('/')} expires at ${session.expiresAt}`
173
- * }
174
- * ```
175
- */
176
- readonly scan: <T = Record<string, unknown>>(adapter: StorageAdapter, prefix: string[]) => AsyncIterable<readonly [string[], T]>;
177
- };
178
- //#endregion
179
- export { Storage, StorageAdapter, joinKey, splitKey };
@@ -1,104 +0,0 @@
1
- //#region src/storage/storage.ts
2
- /**
3
- * ASCII unit separator character used to join key segments.
4
- * Using a control character ensures it won't conflict with user data.
5
- */
6
- const SEPARATOR = String.fromCharCode(31);
7
- /**
8
- * Escape character used to escape SEPARATOR characters in key segments.
9
- * Uses backslash as the escape character, which is then itself escaped when appearing.
10
- */
11
- const ESCAPE = "\\";
12
- /**
13
- * Joins an array of key segments into a single string using the separator.
14
- * Segments are properly escaped to handle any input, including separators and escape characters.
15
- *
16
- * @param key - Array of key segments to join
17
- * @returns Single string representing the full key path
18
- *
19
- * @example
20
- * ```ts
21
- * joinKey(['user', 'data\x1fwith\x1fseparators'])
22
- * // Returns: "user\x1fdata\\x1fwith\\x1fseparators"
23
- * ```
24
- */
25
- const joinKey = (key) => {
26
- return key.join(SEPARATOR);
27
- };
28
- /**
29
- * Splits a joined key string back into its component segments.
30
- * Handles escaped characters properly.
31
- *
32
- * @param key - Joined key string to split
33
- * @returns Array of individual key segments
34
- *
35
- * @example
36
- * ```ts
37
- * splitKey("user\x1fdata\\x1fwith\\x1fseparators")
38
- * // Returns: ['user', 'data\x1fwith\x1fseparators']
39
- * ```
40
- */
41
- const splitKey = (key) => {
42
- return key.split(SEPARATOR);
43
- };
44
- /**
45
- * Encodes a single key segment by escaping special characters.
46
- * Prevents collisions by properly escaping separator and escape characters.
47
- *
48
- * @param segment - The key segment to encode
49
- * @returns Encoded segment with special characters escaped
50
- * @throws {Error} If segment is empty or whitespace-only
51
- *
52
- * @internal
53
- */
54
- const encodeSegment = (segment) => {
55
- if (!segment || !segment.trim()) throw new Error(`Storage key segment cannot be empty or whitespace-only: "${segment}"`);
56
- return segment.replaceAll(ESCAPE, ESCAPE + ESCAPE).replaceAll(SEPARATOR, ESCAPE + SEPARATOR);
57
- };
58
- /**
59
- * Decodes a key segment by unescaping special characters.
60
- * Reverse of encodeSegment operation.
61
- *
62
- * @param segment - The encoded segment to decode
63
- * @returns Decoded segment with special characters restored
64
- *
65
- * @internal
66
- */
67
- const decodeSegment = (segment) => {
68
- return segment.replaceAll(ESCAPE + SEPARATOR, SEPARATOR).replaceAll(ESCAPE + ESCAPE, ESCAPE);
69
- };
70
- /**
71
- * High-level storage operations with key encoding and type safety.
72
- * Provides a convenient interface over storage adapters with additional features
73
- * like TTL validation and secure key encoding to prevent collisions.
74
- */
75
- const Storage = {
76
- encode: (key) => {
77
- return key.map(encodeSegment);
78
- },
79
- decode: (key) => {
80
- return key.map(decodeSegment);
81
- },
82
- get: (adapter, key) => {
83
- return adapter.get(Storage.encode(key));
84
- },
85
- set: (adapter, key, value, ttlSeconds) => {
86
- if (ttlSeconds !== void 0 && ttlSeconds !== null) {
87
- if (!Number.isInteger(ttlSeconds)) throw new RangeError(`Storage TTL must be an integer in seconds, received ${typeof ttlSeconds}`);
88
- if (ttlSeconds <= 0) throw new RangeError(`Storage TTL must be positive, received ${ttlSeconds}`);
89
- const maxTtlSeconds = 3600 * 24 * 365 * 10;
90
- if (ttlSeconds > maxTtlSeconds) throw new RangeError(`Storage TTL exceeds maximum (${maxTtlSeconds}s = 10 years), received ${ttlSeconds}s`);
91
- }
92
- const expiry = ttlSeconds ? new Date(Date.now() + ttlSeconds * 1e3) : void 0;
93
- return adapter.set(Storage.encode(key), value, expiry);
94
- },
95
- remove: (adapter, key) => {
96
- return adapter.remove(Storage.encode(key));
97
- },
98
- scan: (adapter, prefix) => {
99
- return adapter.scan(Storage.encode(prefix));
100
- }
101
- };
102
-
103
- //#endregion
104
- export { Storage, joinKey, splitKey };