@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,193 +0,0 @@
1
- import { ContextVariableManager } from "./variables.mjs";
2
-
3
- //#region src/router/context.ts
4
- const parseCookies = (request) => {
5
- const cookies = /* @__PURE__ */ new Map();
6
- const cookieHeader = request.headers.get("cookie");
7
- if (!cookieHeader) return cookies;
8
- try {
9
- for (const cookie of cookieHeader.split(";")) {
10
- const trimmedCookie = cookie.trim();
11
- if (!trimmedCookie) continue;
12
- const [name, ...valueParts] = trimmedCookie.split("=");
13
- if (!name || name.trim() === "") continue;
14
- const trimmedName = name.trim();
15
- if (!/^[!#$%&'*+\-.0-9A-Z^_`a-z|~]+$/.test(trimmedName)) {
16
- console.warn(`Invalid cookie name: ${trimmedName}`);
17
- continue;
18
- }
19
- const value = valueParts.join("=");
20
- try {
21
- cookies.set(trimmedName, decodeURIComponent(value));
22
- } catch {
23
- cookies.set(trimmedName, value);
24
- }
25
- }
26
- } catch (error) {
27
- console.error("Failed to parse cookies:", error);
28
- }
29
- return cookies;
30
- };
31
- const serializeCookie = (name, value, options = {}) => {
32
- if (!/^[!#$%&'*+\-.0-9A-Z^_`a-z|~]+$/.test(name)) throw new Error(`Invalid cookie name: ${name}`);
33
- const parts = [`${name}=${encodeURIComponent(value)}`];
34
- if (options.domain) parts.push(`Domain=${options.domain}`);
35
- if (options.path) parts.push(`Path=${options.path}`);
36
- if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
37
- if (options.maxAge) parts.push(`Max-Age=${options.maxAge}`);
38
- if (options.httpOnly) parts.push("HttpOnly");
39
- if (options.secure) parts.push("Secure");
40
- if (options.sameSite) parts.push(`SameSite=${options.sameSite}`);
41
- return parts.join("; ");
42
- };
43
- const validateRedirectStatus = (status) => {
44
- if (![
45
- 300,
46
- 301,
47
- 302,
48
- 303,
49
- 307,
50
- 308
51
- ].includes(status)) throw new Error(`Invalid redirect status code: ${status}.`);
52
- return true;
53
- };
54
- var ContextBuilder = class {
55
- request;
56
- matchedParams;
57
- searchParams;
58
- cookies;
59
- variableManager;
60
- responseHeaders = new Headers();
61
- status = 200;
62
- finalized = false;
63
- cachedFormData = null;
64
- formDataPromise = null;
65
- bodyText = null;
66
- constructor(request, matchedParams, initialVariables) {
67
- if (!request || typeof request !== "object" || !request.url || !request.method) throw new Error("Invalid request object provided to ContextBuilder.");
68
- this.request = request;
69
- this.matchedParams = matchedParams;
70
- this.searchParams = new URL(request.url).searchParams;
71
- this.cookies = parseCookies(request);
72
- this.variableManager = new ContextVariableManager(initialVariables);
73
- Object.freeze(this.matchedParams);
74
- }
75
- build() {
76
- return {
77
- request: this.request,
78
- params: this.matchedParams,
79
- searchParams: this.searchParams,
80
- query: (key) => this.searchParams.get(key) ?? void 0,
81
- header: (key) => this.request.headers.get(key) ?? void 0,
82
- cookie: (key) => this.cookies.get(key),
83
- formData: async () => {
84
- if (this.cachedFormData) return this.cachedFormData;
85
- if (this.formDataPromise) try {
86
- return await this.formDataPromise;
87
- } catch {
88
- this.formDataPromise = null;
89
- }
90
- this.formDataPromise = (async () => {
91
- try {
92
- const formData = await this.request.formData();
93
- this.cachedFormData = formData;
94
- return formData;
95
- } catch (error) {
96
- this.formDataPromise = null;
97
- throw new Error(`Failed to read form data: ${error instanceof Error ? error.message : "Unknown error"}`);
98
- }
99
- })();
100
- return this.formDataPromise;
101
- },
102
- parseJson: async () => {
103
- try {
104
- if (this.bodyText !== null) {
105
- if (!this.bodyText) throw new Error("Request body is empty.");
106
- return JSON.parse(this.bodyText);
107
- }
108
- const text = await this.request.text();
109
- this.bodyText = text;
110
- if (!text) throw new Error("Request body is empty.");
111
- return JSON.parse(text);
112
- } catch (error) {
113
- throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : "Unknown error"}`);
114
- }
115
- },
116
- redirect: (url, status = 302) => {
117
- validateRedirectStatus(status);
118
- const location = url instanceof URL ? url.toString() : url;
119
- return this.newResponse(void 0, {
120
- status,
121
- headers: { location }
122
- });
123
- },
124
- json: (data, init) => {
125
- const finalInit = {
126
- ...init,
127
- headers: {
128
- "content-type": "application/json; charset=utf-8",
129
- ...init?.headers
130
- }
131
- };
132
- return this.newResponse(JSON.stringify(data), finalInit);
133
- },
134
- text: (data, init) => {
135
- const finalInit = {
136
- ...init,
137
- headers: {
138
- "content-type": "text/plain; charset=utf-8",
139
- ...init?.headers
140
- }
141
- };
142
- return this.newResponse(data, finalInit);
143
- },
144
- setCookie: (name, value, options) => {
145
- try {
146
- const cookie = serializeCookie(name, value, options);
147
- this.responseHeaders.append("Set-Cookie", cookie);
148
- } catch (error) {
149
- console.error(`Failed to set cookie "${name}":`, error);
150
- }
151
- },
152
- deleteCookie: (name, options) => {
153
- try {
154
- const cookie = serializeCookie(name, "", {
155
- ...options,
156
- expires: /* @__PURE__ */ new Date(0)
157
- });
158
- this.responseHeaders.append("Set-Cookie", cookie);
159
- } catch (error) {
160
- console.error(`Failed to delete cookie "${name}":`, error);
161
- }
162
- },
163
- newResponse: (body, init) => this.newResponse(body, init),
164
- set: (key, value) => {
165
- this.variableManager.set(key, value);
166
- },
167
- get: (key) => {
168
- return this.variableManager.get(key);
169
- },
170
- has: (key) => {
171
- return this.variableManager.has(key);
172
- }
173
- };
174
- }
175
- newResponse(body, init) {
176
- if (this.finalized) throw new Error("Response already finalized");
177
- const finalHeaders = new Headers(this.responseHeaders);
178
- if (init?.headers) new Headers(init.headers).forEach((value, key) => {
179
- if (key.toLowerCase() === "set-cookie") finalHeaders.append(key, value);
180
- else finalHeaders.set(key, value);
181
- });
182
- const response = new Response(body, {
183
- status: init?.status || this.status,
184
- statusText: init?.statusText,
185
- headers: finalHeaders
186
- });
187
- this.finalized = true;
188
- return response;
189
- }
190
- };
191
-
192
- //#endregion
193
- export { ContextBuilder };
@@ -1,8 +0,0 @@
1
- import { CookieOptions, RouterContext, VariableMap } from "./types.mjs";
2
-
3
- //#region src/router/cookies.d.ts
4
- declare const getCookie: <TVariables extends VariableMap = VariableMap>(ctx: RouterContext<Record<string, string>, TVariables>, name: string) => string | undefined;
5
- declare const setCookie: <TVariables extends VariableMap = VariableMap>(ctx: RouterContext<Record<string, string>, TVariables>, name: string, value: string, options?: CookieOptions) => void;
6
- declare const deleteCookie: <TVariables extends VariableMap = VariableMap>(ctx: RouterContext<Record<string, string>, TVariables>, name: string, options?: Pick<CookieOptions, "domain" | "path">) => void;
7
- //#endregion
8
- export { deleteCookie, getCookie, setCookie };
@@ -1,13 +0,0 @@
1
- //#region src/router/cookies.ts
2
- const getCookie = (ctx, name) => {
3
- return ctx.cookie(name);
4
- };
5
- const setCookie = (ctx, name, value, options) => {
6
- ctx.setCookie(name, value, options);
7
- };
8
- const deleteCookie = (ctx, name, options) => {
9
- ctx.deleteCookie(name, options);
10
- };
11
-
12
- //#endregion
13
- export { deleteCookie, getCookie, setCookie };
@@ -1,21 +0,0 @@
1
- import { AnyHandler, ErrorHandler, ExtractParams, GlobalMiddleware, RouterEnvironment, RouterOptions } from "./types.mjs";
2
-
3
- //#region src/router/index.d.ts
4
- declare class Router<TEnvironment extends RouterEnvironment = RouterEnvironment> {
5
- private readonly routes;
6
- private readonly matcher;
7
- private readonly globalMiddleware;
8
- private errorHandler?;
9
- constructor(routerOptions?: RouterOptions);
10
- private addRoute;
11
- get<TPath extends string>(path: TPath, handler: AnyHandler<ExtractParams<TPath>, TEnvironment["Variables"]>): this;
12
- post<TPath extends string>(path: TPath, handler: AnyHandler<ExtractParams<TPath>, TEnvironment["Variables"]>): this;
13
- use(middleware: GlobalMiddleware<TEnvironment["Variables"]>): this;
14
- onError(handler: ErrorHandler<TEnvironment["Variables"]>): this;
15
- mount<TMountedEnvironment extends RouterEnvironment>(path: string, router: Router<TMountedEnvironment>): this;
16
- handle(request: Request, initialVariables?: Partial<TEnvironment["Variables"]>): Promise<Response>;
17
- get fetch(): (request: Request) => Promise<Response>;
18
- private createErrorResponse;
19
- }
20
- //#endregion
21
- export { Router };
@@ -1,107 +0,0 @@
1
- import { ContextBuilder } from "./context.mjs";
2
- import { RouteMatcher } from "./matcher.mjs";
3
- import { makeSafeRequest } from "./safe-request.mjs";
4
-
5
- //#region src/router/index.ts
6
- var Router = class {
7
- routes = /* @__PURE__ */ new Map();
8
- matcher;
9
- globalMiddleware = [];
10
- errorHandler;
11
- constructor(routerOptions = {}) {
12
- this.matcher = new RouteMatcher(routerOptions);
13
- }
14
- addRoute(method, path, handler) {
15
- const { handler: mainHandler, middleware = [] } = typeof handler === "function" ? { handler } : handler;
16
- if (typeof mainHandler !== "function") throw new Error(`Handler for ${method} ${path} must be a function.`);
17
- const route = {
18
- method,
19
- pattern: path,
20
- handler: mainHandler,
21
- middleware: [...this.globalMiddleware, ...middleware],
22
- compiled: this.matcher.compile(path)
23
- };
24
- const methodRoutes = this.routes.get(method) ?? [];
25
- if (methodRoutes.some((r) => r.pattern === path)) console.warn(`Route already exists: ${method} ${path}. Overwriting.`);
26
- const newRoutes = [...methodRoutes.filter((r) => r.pattern !== path), route];
27
- const sortedPatterns = this.matcher.sortRoutesBySpecificity(newRoutes.map((r) => r.pattern));
28
- newRoutes.sort((a, b) => sortedPatterns.indexOf(a.pattern) - sortedPatterns.indexOf(b.pattern));
29
- this.routes.set(method, newRoutes);
30
- return this;
31
- }
32
- get(path, handler) {
33
- return this.addRoute("GET", path, handler);
34
- }
35
- post(path, handler) {
36
- return this.addRoute("POST", path, handler);
37
- }
38
- use(middleware) {
39
- this.globalMiddleware.push(middleware);
40
- return this;
41
- }
42
- onError(handler) {
43
- this.errorHandler = handler;
44
- return this;
45
- }
46
- mount(path, router) {
47
- const normalizedPath = path.endsWith("/") ? path.slice(0, -1) : path;
48
- for (const [method, routes] of router.routes) for (const route of routes) this.addRoute(method, `${normalizedPath}${route.pattern}`, {
49
- handler: route.handler,
50
- middleware: route.middleware
51
- });
52
- return this;
53
- }
54
- async handle(request, initialVariables) {
55
- const safeRequest = await makeSafeRequest(request);
56
- try {
57
- const url = new URL(safeRequest.url);
58
- const method = safeRequest.method.toUpperCase();
59
- const pathname = this.matcher.normalizePath(url.pathname);
60
- const methodRoutes = this.routes.get(method);
61
- if (!methodRoutes) return this.createErrorResponse("Not Found", 404);
62
- for (const route of methodRoutes) {
63
- const match = this.matcher.match(route.pattern, pathname);
64
- if (match) {
65
- const context = new ContextBuilder(safeRequest, match.params, initialVariables).build();
66
- const allMiddleware = [...this.globalMiddleware, ...route.middleware];
67
- const run = async (index, ctx) => {
68
- if (index < allMiddleware.length) {
69
- const middleware = allMiddleware[index];
70
- if (middleware) return middleware(ctx, () => run(index + 1, ctx));
71
- }
72
- return route.handler(ctx);
73
- };
74
- return await run(0, context);
75
- }
76
- }
77
- return this.createErrorResponse(`Route not found: ${method} ${pathname}`, 404);
78
- } catch (error) {
79
- console.error("Router handle error:", error);
80
- if (this.errorHandler) try {
81
- const errorContext = new ContextBuilder(safeRequest, {}, initialVariables).build();
82
- return await this.errorHandler(error, errorContext);
83
- } catch (handlerError) {
84
- console.error("Error handler failed:", handlerError);
85
- }
86
- const message = error instanceof Error ? error.message : "Internal Server Error";
87
- return this.createErrorResponse(message, 500);
88
- }
89
- }
90
- get fetch() {
91
- return (request) => {
92
- return this.handle(request);
93
- };
94
- }
95
- createErrorResponse(message, status) {
96
- return new Response(JSON.stringify({
97
- error: message,
98
- status
99
- }), {
100
- status,
101
- headers: { "Content-Type": "application/json" }
102
- });
103
- }
104
- };
105
-
106
- //#endregion
107
- export { Router };
@@ -1,15 +0,0 @@
1
- import { CompiledRoute, MatchResult, RouterOptions } from "./types.mjs";
2
-
3
- //#region src/router/matcher.d.ts
4
- declare class RouteMatcher {
5
- private readonly compiledRoutes;
6
- private readonly options;
7
- constructor(options?: RouterOptions);
8
- compile(pattern: string): CompiledRoute;
9
- match(pattern: string, pathname: string): MatchResult | null;
10
- sortRoutesBySpecificity(patterns: string[]): string[];
11
- private calculateSpecificity;
12
- normalizePath(pathname: string): string;
13
- }
14
- //#endregion
15
- export { RouteMatcher };
@@ -1,76 +0,0 @@
1
- //#region src/router/matcher.ts
2
- var RouteMatcher = class {
3
- compiledRoutes = /* @__PURE__ */ new Map();
4
- options;
5
- constructor(options = {}) {
6
- this.options = {
7
- caseSensitive: false,
8
- strict: false,
9
- basePath: "",
10
- ...options
11
- };
12
- }
13
- compile(pattern) {
14
- const cacheKey = `${pattern}:${this.options.caseSensitive}:${this.options.strict}`;
15
- const cached = this.compiledRoutes.get(cacheKey);
16
- if (cached) return cached;
17
- const paramNames = [];
18
- let regexPattern = pattern.replace(/:([^/]+)/g, (_, name) => {
19
- paramNames.push(name);
20
- return "([^/]+)";
21
- });
22
- regexPattern = regexPattern.replace(/\*/g, "(.*)");
23
- const finalPattern = this.options.strict || pattern === "/" ? regexPattern : `${regexPattern.replace(/\/$/, "")}/?`;
24
- const compiled = {
25
- regex: new RegExp(`^${finalPattern}$`, this.options.caseSensitive ? "" : "i"),
26
- paramNames,
27
- pattern
28
- };
29
- this.compiledRoutes.set(cacheKey, compiled);
30
- return compiled;
31
- }
32
- match(pattern, pathname) {
33
- const compiled = this.compile(pattern);
34
- const match = pathname.match(compiled.regex);
35
- if (!match) return null;
36
- const params = {};
37
- for (let i = 0; i < compiled.paramNames.length; i++) {
38
- const name = compiled.paramNames[i];
39
- const value = match[i + 1];
40
- if (name && value !== void 0) try {
41
- params[name] = decodeURIComponent(value);
42
- } catch {
43
- params[name] = value;
44
- }
45
- }
46
- return {
47
- params: Object.freeze(params),
48
- pattern
49
- };
50
- }
51
- sortRoutesBySpecificity(patterns) {
52
- return [...patterns].sort((a, b) => {
53
- const aScore = this.calculateSpecificity(a);
54
- return this.calculateSpecificity(b) - aScore;
55
- });
56
- }
57
- calculateSpecificity(pattern) {
58
- const segments = pattern.split("/").filter(Boolean);
59
- let score = 0;
60
- for (const segment of segments) if (segment.startsWith(":")) score += 2;
61
- else if (segment === "*") score += 1;
62
- else score += 4;
63
- return score;
64
- }
65
- normalizePath(pathname) {
66
- let normalized = pathname;
67
- const { basePath, strict } = this.options;
68
- if (basePath && normalized.startsWith(basePath)) normalized = normalized.slice(basePath.length) || "/";
69
- if (!normalized.startsWith("/")) normalized = `/${normalized}`;
70
- if (!strict && normalized.length > 1 && normalized.endsWith("/")) normalized = normalized.slice(0, -1);
71
- return normalized;
72
- }
73
- };
74
-
75
- //#endregion
76
- export { RouteMatcher };
@@ -1,15 +0,0 @@
1
- import { MiddlewareHandler, RouterContext, VariableMap } from "../types.mjs";
2
-
3
- //#region src/router/middleware/cors.d.ts
4
- interface CORSOptions {
5
- origin?: "*" | string | readonly string[] | ((origin: string, ctx: RouterContext<Record<string, string>, VariableMap>) => string | null);
6
- allowMethods?: readonly string[] | ((origin: string, ctx: RouterContext<Record<string, string>, VariableMap>) => readonly string[]);
7
- allowHeaders?: readonly string[];
8
- maxAge?: number;
9
- credentials?: boolean;
10
- exposeHeaders?: readonly string[];
11
- preflightHandler?: <TVariables extends VariableMap>(ctx: RouterContext<Record<string, string>, TVariables>) => Promise<Response> | Response;
12
- }
13
- declare const cors: <TVariables extends VariableMap = VariableMap>(options?: CORSOptions) => MiddlewareHandler<Record<string, string>, TVariables>;
14
- //#endregion
15
- export { CORSOptions, cors };
@@ -1,114 +0,0 @@
1
- //#region src/router/middleware/cors.ts
2
- const DEFAULT_CORS_OPTIONS = {
3
- origin: "*",
4
- allowMethods: [
5
- "GET",
6
- "HEAD",
7
- "PUT",
8
- "POST",
9
- "DELETE",
10
- "PATCH",
11
- "OPTIONS"
12
- ],
13
- allowHeaders: [],
14
- maxAge: 86400,
15
- credentials: false,
16
- exposeHeaders: []
17
- };
18
- const createOriginResolver = (origin) => {
19
- if (!origin || origin === "*") return () => "*";
20
- if (typeof origin === "string") return (requestOrigin) => origin === requestOrigin ? origin : null;
21
- if (typeof origin === "function") return origin;
22
- if (Array.isArray(origin)) {
23
- const allowedOrigins = new Set(origin);
24
- return (requestOrigin) => allowedOrigins.has(requestOrigin) ? requestOrigin : null;
25
- }
26
- return () => null;
27
- };
28
- const createMethodsResolver = (methods) => {
29
- if (typeof methods === "function") return methods;
30
- if (Array.isArray(methods)) return () => methods;
31
- return () => DEFAULT_CORS_OPTIONS.allowMethods;
32
- };
33
- const normalizeCORSOptions = (options = {}) => {
34
- const opts = {
35
- ...DEFAULT_CORS_OPTIONS,
36
- ...options
37
- };
38
- if (opts.maxAge < 0) throw new Error("CORS maxAge must be non-negative");
39
- if (Array.isArray(opts.allowMethods)) {
40
- const validMethods = new Set([
41
- "GET",
42
- "HEAD",
43
- "PUT",
44
- "POST",
45
- "DELETE",
46
- "PATCH",
47
- "OPTIONS"
48
- ]);
49
- const invalidMethods = opts.allowMethods.filter((method) => !validMethods.has(method.toUpperCase()));
50
- if (invalidMethods.length > 0) console.warn(`CORS: Invalid HTTP methods detected: ${invalidMethods.join(", ")}`);
51
- }
52
- return {
53
- ...opts,
54
- _originResolver: createOriginResolver(options.origin),
55
- _methodsResolver: createMethodsResolver(options.allowMethods)
56
- };
57
- };
58
- const cors = (options = {}) => {
59
- const opts = normalizeCORSOptions(options);
60
- return async (ctx, next) => {
61
- const requestOrigin = ctx.header("origin") || "";
62
- const requestMethod = ctx.request.method.toUpperCase();
63
- const allowedOrigin = opts._originResolver(requestOrigin, ctx);
64
- const corsHeaders = {};
65
- if (allowedOrigin) corsHeaders["Access-Control-Allow-Origin"] = allowedOrigin;
66
- if (opts.origin !== "*" && allowedOrigin) {
67
- const existingVary = ctx.header("vary");
68
- corsHeaders.Vary = existingVary ? `${existingVary}, Origin` : "Origin";
69
- }
70
- if (opts.credentials) corsHeaders["Access-Control-Allow-Credentials"] = "true";
71
- if (opts.exposeHeaders && opts.exposeHeaders.length > 0) corsHeaders["Access-Control-Expose-Headers"] = opts.exposeHeaders.join(",");
72
- if (requestMethod === "OPTIONS") {
73
- if (opts.preflightHandler) return await opts.preflightHandler(ctx);
74
- if (opts.maxAge != null) corsHeaders["Access-Control-Max-Age"] = opts.maxAge.toString();
75
- const allowedMethods = opts._methodsResolver(requestOrigin, ctx);
76
- if (allowedMethods.length > 0) corsHeaders["Access-Control-Allow-Methods"] = allowedMethods.join(",");
77
- let allowedHeaders = opts.allowHeaders;
78
- if (!allowedHeaders || allowedHeaders.length === 0) {
79
- const requestHeaders = ctx.header("access-control-request-headers");
80
- if (requestHeaders) allowedHeaders = requestHeaders.split(/\s*,\s*/);
81
- }
82
- if (allowedHeaders && allowedHeaders.length > 0) {
83
- corsHeaders["Access-Control-Allow-Headers"] = allowedHeaders.join(",");
84
- const existingVary = corsHeaders.Vary || ctx.header("vary");
85
- corsHeaders.Vary = existingVary ? `${existingVary}, Access-Control-Request-Headers` : "Access-Control-Request-Headers";
86
- }
87
- const headers = new Headers();
88
- Object.entries(corsHeaders).forEach(([key, value]) => {
89
- headers.set(key, value);
90
- });
91
- return new Response(null, {
92
- status: 204,
93
- statusText: "No Content",
94
- headers
95
- });
96
- }
97
- return applyCORSHeaders(await next(), corsHeaders);
98
- };
99
- };
100
- const applyCORSHeaders = (response, corsHeaders) => {
101
- if (Object.keys(corsHeaders).length === 0) return response;
102
- const newHeaders = new Headers(response.headers);
103
- Object.entries(corsHeaders).forEach(([key, value]) => {
104
- newHeaders.set(key, value);
105
- });
106
- return new Response(response.body, {
107
- status: response.status,
108
- statusText: response.statusText,
109
- headers: newHeaders
110
- });
111
- };
112
-
113
- //#endregion
114
- export { cors };
@@ -1,52 +0,0 @@
1
- //#region src/router/safe-request.d.ts
2
- /**
3
- * SafeRequest wraps a Request to cache the body and allow multiple reads.
4
- * This solves issues with Request implementations that don't support multiple body reads.
5
- */
6
- interface SafeRequestOptions {
7
- cache?: RequestCache;
8
- credentials?: RequestCredentials;
9
- destination?: RequestDestination;
10
- integrity?: string;
11
- keepalive?: boolean;
12
- mode?: RequestMode;
13
- redirect?: RequestRedirect;
14
- referrer?: string;
15
- referrerPolicy?: ReferrerPolicy;
16
- signal?: AbortSignal;
17
- }
18
- declare class SafeRequest implements Request {
19
- private cachedBody;
20
- private bodyBuffer;
21
- private readonly textDecoder;
22
- readonly cache: RequestCache;
23
- readonly credentials: RequestCredentials;
24
- readonly destination: RequestDestination;
25
- readonly headers: Headers;
26
- readonly integrity: string;
27
- readonly keepalive: boolean;
28
- readonly method: string;
29
- readonly mode: RequestMode;
30
- readonly redirect: RequestRedirect;
31
- readonly referrer: string;
32
- readonly referrerPolicy: ReferrerPolicy;
33
- readonly signal: AbortSignal;
34
- readonly url: string;
35
- constructor(url: string, method: string, headers: Headers, body: ArrayBuffer | null, options?: SafeRequestOptions);
36
- arrayBuffer(): Promise<ArrayBuffer>;
37
- blob(): Promise<Blob>;
38
- formData(): Promise<FormData>;
39
- json<T = unknown>(): Promise<T>;
40
- text(): Promise<string>;
41
- bytes(): Promise<Uint8Array<ArrayBuffer>>;
42
- get body(): ReadableStream<Uint8Array<ArrayBuffer>> | null;
43
- get bodyUsed(): boolean;
44
- clone(): Request;
45
- }
46
- /**
47
- * Extracts data from a Request and creates a SafeRequest.
48
- * Uses ReadableStream to safely read the body and avoid issues with certain Request implementations.
49
- */
50
- declare function makeSafeRequest(request: Request): Promise<Request>;
51
- //#endregion
52
- export { SafeRequest, makeSafeRequest };