@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.
- package/dist/esm/allow.js +26 -0
- package/dist/esm/client.js +254 -0
- package/dist/esm/core.js +597 -0
- package/dist/esm/css.d.js +0 -0
- package/dist/esm/error.js +88 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/keys.js +126 -0
- package/dist/esm/mutex.js +53 -0
- package/dist/esm/pkce.js +87 -0
- package/dist/esm/provider/apple.js +15 -0
- package/dist/esm/provider/code.js +62 -0
- package/dist/esm/provider/discord.js +15 -0
- package/dist/esm/provider/facebook.js +15 -0
- package/dist/esm/provider/github.js +15 -0
- package/dist/esm/provider/gitlab.js +15 -0
- package/dist/esm/provider/google.js +16 -0
- package/dist/esm/provider/linkedin.js +15 -0
- package/dist/esm/provider/magiclink.js +83 -0
- package/dist/esm/provider/microsoft.js +15 -0
- package/dist/esm/provider/oauth2.js +130 -0
- package/dist/esm/provider/password.js +331 -0
- package/dist/esm/provider/provider.js +18 -0
- package/dist/esm/provider/reddit.js +15 -0
- package/dist/esm/provider/slack.js +15 -0
- package/dist/esm/provider/spotify.js +15 -0
- package/dist/esm/provider/twitch.js +15 -0
- package/dist/esm/provider/vercel.js +17 -0
- package/dist/esm/random.js +40 -0
- package/dist/esm/revocation.js +27 -0
- package/dist/esm/storage/memory.js +110 -0
- package/dist/esm/storage/storage.js +56 -0
- package/dist/esm/storage/turso.js +93 -0
- package/dist/esm/storage/unstorage.js +78 -0
- package/dist/esm/subject.js +7 -0
- package/dist/esm/themes/theme.js +115 -0
- package/dist/esm/toolkit/client.js +119 -0
- package/dist/esm/toolkit/index.js +25 -0
- package/dist/esm/toolkit/providers/facebook.js +11 -0
- package/dist/esm/toolkit/providers/github.js +11 -0
- package/dist/esm/toolkit/providers/google.js +11 -0
- package/dist/esm/toolkit/providers/strategy.js +0 -0
- package/dist/esm/toolkit/storage.js +81 -0
- package/dist/esm/toolkit/utils.js +18 -0
- package/dist/esm/types.js +0 -0
- package/dist/esm/ui/base.js +478 -0
- package/dist/esm/ui/code.js +186 -0
- package/dist/esm/ui/form.js +46 -0
- package/dist/esm/ui/icon.js +242 -0
- package/dist/esm/ui/magiclink.js +158 -0
- package/dist/esm/ui/password.js +435 -0
- package/dist/esm/ui/select.js +102 -0
- package/dist/esm/util.js +59 -0
- package/dist/{allow.d.mts → types/allow.d.ts} +9 -11
- package/dist/types/allow.d.ts.map +1 -0
- package/dist/types/client.d.ts +462 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/core.d.ts +113 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/{error.d.mts → types/error.d.ts} +95 -97
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{keys.d.mts → types/keys.d.ts} +20 -24
- package/dist/types/keys.d.ts.map +1 -0
- package/dist/types/mutex.d.ts +42 -0
- package/dist/types/mutex.d.ts.map +1 -0
- package/dist/{pkce.d.mts → types/pkce.d.ts} +10 -11
- package/dist/types/pkce.d.ts.map +1 -0
- package/dist/types/provider/apple.d.ts +197 -0
- package/dist/types/provider/apple.d.ts.map +1 -0
- package/dist/types/provider/code.d.ts +288 -0
- package/dist/types/provider/code.d.ts.map +1 -0
- package/dist/types/provider/discord.d.ts +206 -0
- package/dist/types/provider/discord.d.ts.map +1 -0
- package/dist/types/provider/facebook.d.ts +200 -0
- package/dist/types/provider/facebook.d.ts.map +1 -0
- package/dist/types/provider/github.d.ts +220 -0
- package/dist/types/provider/github.d.ts.map +1 -0
- package/dist/types/provider/gitlab.d.ts +180 -0
- package/dist/types/provider/gitlab.d.ts.map +1 -0
- package/dist/types/provider/google.d.ts +158 -0
- package/dist/types/provider/google.d.ts.map +1 -0
- package/dist/types/provider/linkedin.d.ts +190 -0
- package/dist/types/provider/linkedin.d.ts.map +1 -0
- package/dist/types/provider/magiclink.d.ts +141 -0
- package/dist/types/provider/magiclink.d.ts.map +1 -0
- package/dist/types/provider/microsoft.d.ts +247 -0
- package/dist/types/provider/microsoft.d.ts.map +1 -0
- package/dist/types/provider/oauth2.d.ts +229 -0
- package/dist/types/provider/oauth2.d.ts.map +1 -0
- package/dist/types/provider/password.d.ts +408 -0
- package/dist/types/provider/password.d.ts.map +1 -0
- package/dist/types/provider/provider.d.ts +226 -0
- package/dist/types/provider/provider.d.ts.map +1 -0
- package/dist/types/provider/reddit.d.ts +159 -0
- package/dist/types/provider/reddit.d.ts.map +1 -0
- package/dist/types/provider/slack.d.ts +171 -0
- package/dist/types/provider/slack.d.ts.map +1 -0
- package/dist/types/provider/spotify.d.ts +168 -0
- package/dist/types/provider/spotify.d.ts.map +1 -0
- package/dist/types/provider/twitch.d.ts +163 -0
- package/dist/types/provider/twitch.d.ts.map +1 -0
- package/dist/types/provider/vercel.d.ts +294 -0
- package/dist/types/provider/vercel.d.ts.map +1 -0
- package/dist/{random.d.mts → types/random.d.ts} +4 -6
- package/dist/types/random.d.ts.map +1 -0
- package/dist/types/revocation.d.ts +76 -0
- package/dist/types/revocation.d.ts.map +1 -0
- package/dist/{storage/memory.d.mts → types/storage/memory.d.ts} +17 -21
- package/dist/types/storage/memory.d.ts.map +1 -0
- package/dist/types/storage/storage.d.ts +177 -0
- package/dist/types/storage/storage.d.ts.map +1 -0
- package/dist/{storage/turso.d.mts → types/storage/turso.d.ts} +4 -8
- package/dist/types/storage/turso.d.ts.map +1 -0
- package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -11
- package/dist/types/storage/unstorage.d.ts.map +1 -0
- package/dist/types/subject.d.ts +115 -0
- package/dist/types/subject.d.ts.map +1 -0
- package/dist/types/themes/theme.d.ts +207 -0
- package/dist/types/themes/theme.d.ts.map +1 -0
- package/dist/types/toolkit/client.d.ts +235 -0
- package/dist/types/toolkit/client.d.ts.map +1 -0
- package/dist/types/toolkit/index.d.ts +45 -0
- package/dist/types/toolkit/index.d.ts.map +1 -0
- package/dist/types/toolkit/providers/facebook.d.ts +8 -0
- package/dist/types/toolkit/providers/facebook.d.ts.map +1 -0
- package/dist/types/toolkit/providers/github.d.ts +8 -0
- package/dist/types/toolkit/providers/github.d.ts.map +1 -0
- package/dist/types/toolkit/providers/google.d.ts +8 -0
- package/dist/types/toolkit/providers/google.d.ts.map +1 -0
- package/dist/types/toolkit/providers/strategy.d.ts +38 -0
- package/dist/types/toolkit/providers/strategy.d.ts.map +1 -0
- package/dist/{toolkit/storage.d.mts → types/toolkit/storage.d.ts} +37 -39
- package/dist/types/toolkit/storage.d.ts.map +1 -0
- package/dist/{toolkit/utils.d.mts → types/toolkit/utils.d.ts} +2 -4
- package/dist/types/toolkit/utils.d.ts.map +1 -0
- package/dist/types/types.d.ts +92 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/ui/base.d.ts +18 -0
- package/dist/types/ui/base.d.ts.map +1 -0
- package/dist/types/ui/code.d.ts +43 -0
- package/dist/types/ui/code.d.ts.map +1 -0
- package/dist/types/ui/form.d.ts +24 -0
- package/dist/types/ui/form.d.ts.map +1 -0
- package/dist/types/ui/icon.d.ts +60 -0
- package/dist/types/ui/icon.d.ts.map +1 -0
- package/dist/types/ui/magiclink.d.ts +41 -0
- package/dist/types/ui/magiclink.d.ts.map +1 -0
- package/dist/types/ui/password.d.ts +43 -0
- package/dist/types/ui/password.d.ts.map +1 -0
- package/dist/types/ui/select.d.ts +33 -0
- package/dist/types/ui/select.d.ts.map +1 -0
- package/dist/{util.d.mts → types/util.d.ts} +11 -13
- package/dist/types/util.d.ts.map +1 -0
- package/package.json +10 -16
- package/dist/adapters/node.d.mts +0 -18
- package/dist/adapters/node.mjs +0 -69
- package/dist/allow.mjs +0 -63
- package/dist/client.d.mts +0 -456
- package/dist/client.mjs +0 -283
- package/dist/core.d.mts +0 -110
- package/dist/core.mjs +0 -595
- package/dist/error.mjs +0 -237
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -3
- package/dist/keys.mjs +0 -146
- package/dist/mutex.d.mts +0 -44
- package/dist/mutex.mjs +0 -110
- package/dist/pkce.mjs +0 -157
- package/dist/provider/apple.d.mts +0 -111
- package/dist/provider/apple.mjs +0 -164
- package/dist/provider/code.d.mts +0 -228
- package/dist/provider/code.mjs +0 -246
- package/dist/provider/discord.d.mts +0 -146
- package/dist/provider/discord.mjs +0 -156
- package/dist/provider/facebook.d.mts +0 -142
- package/dist/provider/facebook.mjs +0 -150
- package/dist/provider/github.d.mts +0 -140
- package/dist/provider/github.mjs +0 -169
- package/dist/provider/gitlab.d.mts +0 -106
- package/dist/provider/gitlab.mjs +0 -147
- package/dist/provider/google.d.mts +0 -112
- package/dist/provider/google.mjs +0 -109
- package/dist/provider/linkedin.d.mts +0 -132
- package/dist/provider/linkedin.mjs +0 -142
- package/dist/provider/magiclink.d.mts +0 -89
- package/dist/provider/magiclink.mjs +0 -143
- package/dist/provider/microsoft.d.mts +0 -178
- package/dist/provider/microsoft.mjs +0 -177
- package/dist/provider/oauth2.d.mts +0 -176
- package/dist/provider/oauth2.mjs +0 -222
- package/dist/provider/passkey.d.mts +0 -104
- package/dist/provider/passkey.mjs +0 -320
- package/dist/provider/password.d.mts +0 -412
- package/dist/provider/password.mjs +0 -363
- package/dist/provider/provider.d.mts +0 -227
- package/dist/provider/provider.mjs +0 -44
- package/dist/provider/reddit.d.mts +0 -107
- package/dist/provider/reddit.mjs +0 -127
- package/dist/provider/slack.d.mts +0 -114
- package/dist/provider/slack.mjs +0 -138
- package/dist/provider/spotify.d.mts +0 -113
- package/dist/provider/spotify.mjs +0 -135
- package/dist/provider/totp.d.mts +0 -112
- package/dist/provider/totp.mjs +0 -191
- package/dist/provider/twitch.d.mts +0 -108
- package/dist/provider/twitch.mjs +0 -131
- package/dist/provider/vercel.d.mts +0 -177
- package/dist/provider/vercel.mjs +0 -230
- package/dist/random.mjs +0 -86
- package/dist/revocation.d.mts +0 -55
- package/dist/revocation.mjs +0 -63
- package/dist/router/context.d.mts +0 -21
- package/dist/router/context.mjs +0 -193
- package/dist/router/cookies.d.mts +0 -8
- package/dist/router/cookies.mjs +0 -13
- package/dist/router/index.d.mts +0 -21
- package/dist/router/index.mjs +0 -107
- package/dist/router/matcher.d.mts +0 -15
- package/dist/router/matcher.mjs +0 -76
- package/dist/router/middleware/cors.d.mts +0 -15
- package/dist/router/middleware/cors.mjs +0 -114
- package/dist/router/safe-request.d.mts +0 -52
- package/dist/router/safe-request.mjs +0 -160
- package/dist/router/types.d.mts +0 -67
- package/dist/router/types.mjs +0 -1
- package/dist/router/variables.d.mts +0 -12
- package/dist/router/variables.mjs +0 -20
- package/dist/storage/memory.mjs +0 -125
- package/dist/storage/storage.d.mts +0 -179
- package/dist/storage/storage.mjs +0 -104
- package/dist/storage/turso.mjs +0 -117
- package/dist/storage/unstorage.mjs +0 -103
- package/dist/subject.d.mts +0 -62
- package/dist/subject.mjs +0 -36
- package/dist/themes/theme.d.mts +0 -209
- package/dist/themes/theme.mjs +0 -120
- package/dist/toolkit/client.d.mts +0 -169
- package/dist/toolkit/client.mjs +0 -209
- package/dist/toolkit/index.d.mts +0 -9
- package/dist/toolkit/index.mjs +0 -9
- package/dist/toolkit/providers/facebook.d.mts +0 -12
- package/dist/toolkit/providers/facebook.mjs +0 -16
- package/dist/toolkit/providers/github.d.mts +0 -12
- package/dist/toolkit/providers/github.mjs +0 -16
- package/dist/toolkit/providers/google.d.mts +0 -12
- package/dist/toolkit/providers/google.mjs +0 -20
- package/dist/toolkit/providers/strategy.d.mts +0 -40
- package/dist/toolkit/providers/strategy.mjs +0 -1
- package/dist/toolkit/storage.mjs +0 -157
- package/dist/toolkit/utils.mjs +0 -30
- package/dist/types.d.mts +0 -94
- package/dist/types.mjs +0 -1
- package/dist/ui/base.d.mts +0 -30
- package/dist/ui/base.mjs +0 -407
- package/dist/ui/code.d.mts +0 -43
- package/dist/ui/code.mjs +0 -173
- package/dist/ui/form.d.mts +0 -32
- package/dist/ui/form.mjs +0 -49
- package/dist/ui/icon.d.mts +0 -58
- package/dist/ui/icon.mjs +0 -247
- package/dist/ui/magiclink.d.mts +0 -41
- package/dist/ui/magiclink.mjs +0 -152
- package/dist/ui/passkey.d.mts +0 -27
- package/dist/ui/passkey.mjs +0 -323
- package/dist/ui/password.d.mts +0 -42
- package/dist/ui/password.mjs +0 -402
- package/dist/ui/select.d.mts +0 -34
- package/dist/ui/select.mjs +0 -98
- package/dist/ui/totp.d.mts +0 -34
- package/dist/ui/totp.mjs +0 -270
- 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
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
//#
|
|
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 {
|
|
2
|
-
import {
|
|
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
|
-
//#
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
34
|
-
}?: {
|
|
35
|
-
driver?: Driver;
|
|
36
|
+
export declare const UnStorage: ({ driver }?: {
|
|
37
|
+
driver?: UnstorageDriver;
|
|
36
38
|
}) => StorageAdapter;
|
|
37
|
-
//#
|
|
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"}
|