@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
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Token revocation management for Draft Auth.
3
+ * Handles blacklisting of revoked tokens to prevent their use.
4
+ *
5
+ * ## Overview
6
+ *
7
+ * Revocation allows users to invalidate specific tokens before their natural expiration.
8
+ * This is essential for logout functionality and security in case of token compromise.
9
+ *
10
+ * ## Storage Structure
11
+ *
12
+ * Revoked tokens are stored with their expiration time to allow automatic cleanup:
13
+ * ```
14
+ * revocation:token:{tokenHash} → { revokedAt: timestamp, expiresAt: timestamp }
15
+ * ```
16
+ *
17
+ * ## Security Considerations
18
+ *
19
+ * - Revoked tokens are checked on every use
20
+ * - Storage automatically cleans up expired revocations
21
+ * - Hash tokens for storage to reduce memory usage
22
+ * - Use constant-time comparison for hash verification
23
+ *
24
+ * @packageDocumentation
25
+ */
26
+ import { type StorageAdapter } from "./storage/storage";
27
+ /**
28
+ * Data stored for a revoked token.
29
+ * Tracks when the token was revoked and when it naturally expires.
30
+ */
31
+ export interface RevocationRecord {
32
+ /** Timestamp when the token was revoked (milliseconds) */
33
+ revokedAt: number;
34
+ /** Timestamp when the token naturally expires (milliseconds) */
35
+ expiresAt: number;
36
+ }
37
+ /**
38
+ * Token revocation manager.
39
+ * Provides methods to revoke tokens and check if a token has been revoked.
40
+ */
41
+ export declare const Revocation: {
42
+ /**
43
+ * Revokes a token, preventing it from being used even if not yet expired.
44
+ *
45
+ * @param storage - Storage adapter to use
46
+ * @param token - The token to revoke (access or refresh token)
47
+ * @param expiresAt - When the token naturally expires (milliseconds since epoch)
48
+ * @returns Promise that resolves when revocation is stored
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * // Revoke a refresh token on logout
53
+ * await Revocation.revoke(storage, refreshToken, expiresAt)
54
+ * ```
55
+ */
56
+ readonly revoke: (storage: StorageAdapter, token: string, expiresAt: number) => Promise<void>;
57
+ /**
58
+ * Checks if a token has been revoked.
59
+ * Returns false if token is not in revocation list (never revoked or already expired).
60
+ *
61
+ * @param storage - Storage adapter to use
62
+ * @param token - The token to check
63
+ * @returns Promise resolving to true if token is revoked, false otherwise
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * // Check if token was revoked before using it
68
+ * const isRevoked = await Revocation.isRevoked(storage, accessToken)
69
+ * if (isRevoked) {
70
+ * throw new InvalidAccessTokenError()
71
+ * }
72
+ * ```
73
+ */
74
+ readonly isRevoked: (storage: StorageAdapter, token: string) => Promise<boolean>;
75
+ };
76
+ //# sourceMappingURL=revocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revocation.d.ts","sourceRoot":"","sources":["../../src/revocation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEhE;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAA;CACjB;AAeD;;;GAGG;AACH,eAAO,MAAM,UAAU;IACtB;;;;;;;;;;;;;OAaG;+BACqB,cAAc,SAAS,MAAM,aAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;IAgBxF;;;;;;;;;;;;;;;;OAgBG;kCACwB,cAAc,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;CASlE,CAAA"}
@@ -1,7 +1,4 @@
1
- import { StorageAdapter } from "./storage.mjs";
2
-
3
- //#region src/storage/memory.d.ts
4
-
1
+ import { type StorageAdapter } from "./storage";
5
2
  /**
6
3
  * In-memory storage adapter for Draft Auth with optional file persistence.
7
4
  *
@@ -38,20 +35,20 @@ import { StorageAdapter } from "./storage.mjs";
38
35
  /**
39
36
  * Configuration options for the memory storage adapter.
40
37
  */
41
- interface MemoryStorageOptions {
42
- /**
43
- * File path for persisting the in-memory store to disk.
44
- * When specified, the store will be saved to this file on changes
45
- * and loaded from it on startup if it exists.
46
- *
47
- * @example
48
- * ```ts
49
- * {
50
- * persist: "./data/auth-storage.json"
51
- * }
52
- * ```
53
- */
54
- readonly persist?: string;
38
+ export interface MemoryStorageOptions {
39
+ /**
40
+ * File path for persisting the in-memory store to disk.
41
+ * When specified, the store will be saved to this file on changes
42
+ * and loaded from it on startup if it exists.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * {
47
+ * persist: "./data/auth-storage.json"
48
+ * }
49
+ * ```
50
+ */
51
+ readonly persist?: string;
55
52
  }
56
53
  /**
57
54
  * Creates an in-memory storage adapter with optional file persistence.
@@ -77,6 +74,5 @@ interface MemoryStorageOptions {
77
74
  * })
78
75
  * ```
79
76
  */
80
- declare const MemoryStorage: (options?: MemoryStorageOptions) => StorageAdapter;
81
- //#endregion
82
- export { MemoryStorage, MemoryStorageOptions };
77
+ export declare const MemoryStorage: (options?: MemoryStorageOptions) => StorageAdapter;
78
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/storage/memory.ts"],"names":[],"mappings":"AAEA,OAAO,EAAW,KAAK,cAAc,EAAY,MAAM,WAAW,CAAA;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CACzB;AAaD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,aAAa,GAAI,UAAU,oBAAoB,KAAG,cA2J9D,CAAA"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Storage abstraction layer for Draft Auth persistence operations.
3
+ * Provides a unified interface for different storage backends with key encoding,
4
+ * TTL support, and type-safe operations.
5
+ */
6
+ /**
7
+ * Abstract storage adapter interface that must be implemented by all storage backends.
8
+ * Defines the core operations needed for OAuth data persistence.
9
+ */
10
+ export interface StorageAdapter {
11
+ /**
12
+ * Retrieves a value by its key path.
13
+ *
14
+ * @param key - Array of key segments forming the storage path
15
+ * @returns Promise resolving to the stored value or undefined if not found
16
+ */
17
+ get(key: string[]): Promise<Record<string, unknown> | undefined>;
18
+ /**
19
+ * Removes a value by its key path.
20
+ *
21
+ * @param key - Array of key segments forming the storage path
22
+ * @returns Promise that resolves when removal is complete
23
+ */
24
+ remove(key: string[]): Promise<void>;
25
+ /**
26
+ * Stores a value with an optional expiration date.
27
+ *
28
+ * @param key - Array of key segments forming the storage path
29
+ * @param value - The value to store
30
+ * @param expiry - Optional expiration date for automatic cleanup
31
+ * @returns Promise that resolves when storage is complete
32
+ */
33
+ set(key: string[], value: unknown, expiry?: Date): Promise<void>;
34
+ /**
35
+ * Scans for keys matching a prefix pattern.
36
+ *
37
+ * @param prefix - Array of key segments to use as prefix filter
38
+ * @returns Async iterable of key-value pairs matching the prefix
39
+ */
40
+ scan(prefix: string[]): AsyncIterable<readonly [string[], unknown]>;
41
+ }
42
+ /**
43
+ * Joins an array of key segments into a single string using the separator.
44
+ * Segments are properly escaped to handle any input, including separators and escape characters.
45
+ *
46
+ * @param key - Array of key segments to join
47
+ * @returns Single string representing the full key path
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * joinKey(['user', 'data\x1fwith\x1fseparators'])
52
+ * // Returns: "user\x1fdata\\x1fwith\\x1fseparators"
53
+ * ```
54
+ */
55
+ export declare const joinKey: (key: string[]) => string;
56
+ /**
57
+ * Splits a joined key string back into its component segments.
58
+ * Handles escaped characters properly.
59
+ *
60
+ * @param key - Joined key string to split
61
+ * @returns Array of individual key segments
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * splitKey("user\x1fdata\\x1fwith\\x1fseparators")
66
+ * // Returns: ['user', 'data\x1fwith\x1fseparators']
67
+ * ```
68
+ */
69
+ export declare const splitKey: (key: string) => string[];
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
+ export declare const Storage: {
76
+ /**
77
+ * Encodes key segments by escaping special characters.
78
+ * Ensures storage keys don't contain unescaped separator characters that could cause collisions.
79
+ *
80
+ * @param key - Array of key segments to encode
81
+ * @returns Array of properly escaped key segments
82
+ *
83
+ * @throws {Error} If any segment is empty or whitespace-only
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * Storage.encode(['user', 'data\x1fwith\x1fseparators'])
88
+ * // Returns: ['user', 'data\\x1fwith\\x1fseparators']
89
+ * ```
90
+ */
91
+ readonly encode: (key: string[]) => string[];
92
+ /**
93
+ * Decodes key segments by unescaping special characters.
94
+ * Reverse operation of encode().
95
+ *
96
+ * @param key - Array of encoded key segments
97
+ * @returns Array of decoded key segments
98
+ *
99
+ * @internal
100
+ */
101
+ readonly decode: (key: string[]) => string[];
102
+ /**
103
+ * Retrieves a typed value from storage.
104
+ *
105
+ * @template T - Expected type of the stored value
106
+ * @param adapter - Storage adapter to use
107
+ * @param key - Array of key segments identifying the value
108
+ * @returns Promise resolving to the typed value or null if not found
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * interface UserSession {
113
+ * userId: string
114
+ * expiresAt: number
115
+ * }
116
+ *
117
+ * const session = await Storage.get<UserSession>(adapter, ['sessions', sessionId])
118
+ * if (session) {
119
+ * // Fully typed: session.userId
120
+ * }
121
+ * ```
122
+ */
123
+ readonly get: <T = Record<string, unknown>>(adapter: StorageAdapter, key: string[]) => Promise<T | null>;
124
+ /**
125
+ * Stores a value with optional time-to-live in seconds.
126
+ * Validates that TTL is a positive integer to prevent edge cases like negative or overflow values.
127
+ *
128
+ * @param adapter - Storage adapter to use
129
+ * @param key - Array of key segments identifying where to store
130
+ * @param value - The value to store
131
+ * @param ttlSeconds - Optional TTL in seconds for automatic expiration
132
+ * @returns Promise that resolves when storage is complete
133
+ *
134
+ * @throws {RangeError} If TTL is invalid (negative, non-integer, or exceeds maximum)
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * // Store with 1 hour TTL
139
+ * await Storage.set(adapter, ['sessions', sessionId], sessionData, 3600)
140
+ *
141
+ * // Store permanently (no expiration)
142
+ * await Storage.set(adapter, ['users', userId], userData)
143
+ * ```
144
+ */
145
+ readonly set: (adapter: StorageAdapter, key: string[], value: unknown, ttlSeconds?: number) => Promise<void>;
146
+ /**
147
+ * Removes a value from storage.
148
+ *
149
+ * @param adapter - Storage adapter to use
150
+ * @param key - Array of key segments identifying the value to remove
151
+ * @returns Promise that resolves when removal is complete
152
+ *
153
+ * @example
154
+ * ```ts
155
+ * await Storage.remove(adapter, ['sessions', expiredSessionId])
156
+ * ```
157
+ */
158
+ readonly remove: (adapter: StorageAdapter, key: string[]) => Promise<void>;
159
+ /**
160
+ * Scans for entries matching a key prefix with type safety.
161
+ *
162
+ * @template T - Expected type of the stored values
163
+ * @param adapter - Storage adapter to use
164
+ * @param prefix - Array of key segments to use as prefix filter
165
+ * @returns Async iterable of typed key-value pairs
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * // Find all user sessions
170
+ * for await (const [key, session] of Storage.scan<UserSession>(adapter, ['sessions'])) {
171
+ * // Session: `${key.join('/')} expires at ${session.expiresAt}`
172
+ * }
173
+ * ```
174
+ */
175
+ readonly scan: <T = Record<string, unknown>>(adapter: StorageAdapter, prefix: string[]) => AsyncIterable<readonly [string[], T]>;
176
+ };
177
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/storage/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAAA;IAEhE;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEpC;;;;;;;OAOG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEhE;;;;;OAKG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;CACnE;AAcD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,EAAE,KAAG,MAEvC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,KAAG,MAAM,EAE5C,CAAA;AAsCD;;;;GAIG;AACH,eAAO,MAAM,OAAO;IACnB;;;;;;;;;;;;;;OAcG;2BACW,MAAM,EAAE,KAAG,MAAM,EAAE;IAIjC;;;;;;;;OAQG;2BACW,MAAM,EAAE,KAAG,MAAM,EAAE;IAIjC;;;;;;;;;;;;;;;;;;;;OAoBG;mBACG,CAAC,qCACG,cAAc,OAClB,MAAM,EAAE,KACX,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAIpB;;;;;;;;;;;;;;;;;;;;OAoBG;4BAEO,cAAc,OAClB,MAAM,EAAE,SACN,OAAO,eACD,MAAM,KACjB,OAAO,CAAC,IAAI,CAAC;IAwBhB;;;;;;;;;;;OAWG;+BACe,cAAc,OAAO,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC;IAI/D;;;;;;;;;;;;;;;OAeG;oBACI,CAAC,qCACE,cAAc,UACf,MAAM,EAAE,KACd,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;CAG/B,CAAA"}
@@ -1,8 +1,5 @@
1
- import { StorageAdapter } from "./storage.mjs";
2
- import { Client } from "@libsql/client";
3
-
4
- //#region src/storage/turso.d.ts
5
-
1
+ import type { Client } from "@libsql/client";
2
+ import { type StorageAdapter } from "./storage";
6
3
  /**
7
4
  * Creates a Turso storage adapter using the provided LibSQL client.
8
5
  * Automatically initializes the required database table and implements
@@ -26,6 +23,5 @@ import { Client } from "@libsql/client";
26
23
  * const app = issuer({ storage, ... })
27
24
  * ```
28
25
  */
29
- declare const TursoStorage: (client: Client) => StorageAdapter;
30
- //#endregion
31
- export { TursoStorage };
26
+ export declare const TursoStorage: (client: Client) => StorageAdapter;
27
+ //# sourceMappingURL=turso.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turso.d.ts","sourceRoot":"","sources":["../../../src/storage/turso.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAW,KAAK,cAAc,EAAY,MAAM,WAAW,CAAA;AAyClE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,KAAG,cA2H7C,CAAA"}
@@ -1,8 +1,12 @@
1
- import { StorageAdapter } from "./storage.mjs";
2
- import { Driver } from "unstorage";
3
-
4
- //#region src/storage/unstorage.d.ts
5
-
1
+ /**
2
+ * Universal storage adapter for Draft Auth using Unstorage drivers.
3
+ * Provides seamless integration with any Unstorage-compatible backend including
4
+ * Redis, Cloudflare KV, Vercel KV, and more.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import { type Driver as UnstorageDriver } from "unstorage";
9
+ import { type StorageAdapter } from "./storage";
6
10
  /**
7
11
  * Creates a Draft Auth storage adapter using Unstorage drivers.
8
12
  * Supports automatic expiration, error handling, and any Unstorage driver.
@@ -29,10 +33,7 @@ import { Driver } from "unstorage";
29
33
  * const memoryStorage = UnStorage()
30
34
  * ```
31
35
  */
32
- declare const UnStorage: ({
33
- driver
34
- }?: {
35
- driver?: Driver;
36
+ export declare const UnStorage: ({ driver }?: {
37
+ driver?: UnstorageDriver;
36
38
  }) => StorageAdapter;
37
- //#endregion
38
- export { UnStorage };
39
+ //# sourceMappingURL=unstorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unstorage.d.ts","sourceRoot":"","sources":["../../../src/storage/unstorage.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAiB,KAAK,MAAM,IAAI,eAAe,EAAE,MAAM,WAAW,CAAA;AACzE,OAAO,EAAW,KAAK,cAAc,EAAY,MAAM,WAAW,CAAA;AAalE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,SAAS,GAAI,aAAY;IAAE,MAAM,CAAC,EAAE,eAAe,CAAA;CAAO,KAAG,cA6GzE,CAAA"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Subjects define the structure of data stored in access tokens after successful authentication.
3
+ * They represent the different types of entities that can be authenticated (users, admins, etc.)
4
+ * and are encoded as JWT claims in the resulting access tokens.
5
+ *
6
+ * ## Quick Start
7
+ *
8
+ * ### 1. Define your subjects
9
+ * ```ts title="subjects.ts"
10
+ * import { object, string } from "valibot"
11
+ * import { createSubjects } from "@draftlab/auth/subject"
12
+ *
13
+ * export const subjects = createSubjects({
14
+ * user: object({
15
+ * userID: string()
16
+ * }),
17
+ * admin: object({
18
+ * userID: string(),
19
+ * workspaceID: string()
20
+ * })
21
+ * })
22
+ * ```
23
+ *
24
+ * ### 2. Use in your issuer
25
+ * ```ts title="issuer.ts"
26
+ * import { subjects } from "./subjects"
27
+ *
28
+ * const app = issuer({
29
+ * { ... }
30
+ * subjects,
31
+ * async success(ctx, value) {
32
+ * const userID = await lookupUser(value.email)
33
+ * return ctx.subject("user", { userID })
34
+ * }
35
+ * })
36
+ * ```
37
+ *
38
+ * ### 3. Verify tokens in your app
39
+ * ```ts title="middleware.ts"
40
+ * import { subjects } from "./subjects"
41
+ *
42
+ * const verified = await client.verify(subjects, accessToken)
43
+ * if (verified.success) {
44
+ * // Fully typed: verified.data.subject.properties.userID
45
+ * }
46
+ * ```
47
+ *
48
+ * ## Important Notes
49
+ *
50
+ * - Only store data that doesn't change frequently (avoid usernames, emails that might change)
51
+ * - Keep payload small as it's embedded in every access token
52
+ * - Use any validation library compatible with standard-schema specification
53
+ *
54
+ * @packageDocumentation
55
+ */
56
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
57
+ import type { Prettify } from "./util";
58
+ /**
59
+ * Schema definition for subjects, mapping subject type names to their validation schemas.
60
+ * Each key represents a subject type, and each value is a schema that validates
61
+ * the properties for that subject type.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const schema: SubjectSchema = {
66
+ * user: object({ userID: string() }),
67
+ * admin: object({ userID: string(), workspaceID: string() })
68
+ * }
69
+ * ```
70
+ */
71
+ export type SubjectSchema = Record<string, StandardSchemaV1>;
72
+ /**
73
+ * Internal type that transforms a SubjectSchema into a union of subject payload objects.
74
+ * Each payload contains the subject type and its validated properties.
75
+ *
76
+ * @template T - The subject schema to transform
77
+ * @internal
78
+ */
79
+ export type SubjectPayload<T extends SubjectSchema> = Prettify<{
80
+ [K in keyof T & string]: {
81
+ type: K;
82
+ properties: StandardSchemaV1.InferOutput<T[K]>;
83
+ };
84
+ }[keyof T & string]>;
85
+ /**
86
+ * Creates a strongly-typed subject schema that can be used throughout your application.
87
+ * The returned schema maintains type information for excellent IDE support and runtime validation.
88
+ *
89
+ * @template Schema - The subject schema type being created
90
+ * @param types - Object mapping subject type names to their validation schemas
91
+ * @returns The same schema object with preserved type information
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * import { object, string, number } from "valibot"
96
+ *
97
+ * const subjects = createSubjects({
98
+ * user: object({
99
+ * userID: string(),
100
+ * createdAt: number()
101
+ * }),
102
+ * admin: object({
103
+ * userID: string(),
104
+ * workspaceID: string(),
105
+ * permissions: array(string())
106
+ * }),
107
+ * service: object({
108
+ * serviceID: string(),
109
+ * apiVersion: string()
110
+ * })
111
+ * })
112
+ * ```
113
+ */
114
+ export declare const createSubjects: <Schema extends SubjectSchema>(types: Schema) => Schema;
115
+ //# sourceMappingURL=subject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subject.d.ts","sourceRoot":"","sources":["../../src/subject.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEtC;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;AAE5D;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,aAAa,IAAI,QAAQ,CAC7D;KACE,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAAG;QACxB,IAAI,EAAE,CAAC,CAAA;QACP,UAAU,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAC9C;CACD,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,aAAa,EAAE,OAAO,MAAM,KAAG,MAE5E,CAAA"}