@rudderjs/auth 0.2.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 (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -0
  3. package/boost/guidelines.md +137 -0
  4. package/dist/auth-manager.d.ts +40 -0
  5. package/dist/auth-manager.d.ts.map +1 -0
  6. package/dist/auth-manager.js +85 -0
  7. package/dist/auth-manager.js.map +1 -0
  8. package/dist/contracts.d.ts +27 -0
  9. package/dist/contracts.d.ts.map +1 -0
  10. package/dist/contracts.js +3 -0
  11. package/dist/contracts.js.map +1 -0
  12. package/dist/gate.d.ts +49 -0
  13. package/dist/gate.d.ts.map +1 -0
  14. package/dist/gate.js +181 -0
  15. package/dist/gate.js.map +1 -0
  16. package/dist/index.d.ts +41 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +123 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/password-reset.d.ts +56 -0
  21. package/dist/password-reset.d.ts.map +1 -0
  22. package/dist/password-reset.js +101 -0
  23. package/dist/password-reset.js.map +1 -0
  24. package/dist/providers.d.ts +20 -0
  25. package/dist/providers.d.ts.map +1 -0
  26. package/dist/providers.js +41 -0
  27. package/dist/providers.js.map +1 -0
  28. package/dist/session-guard.d.ts +21 -0
  29. package/dist/session-guard.d.ts.map +1 -0
  30. package/dist/session-guard.js +52 -0
  31. package/dist/session-guard.js.map +1 -0
  32. package/dist/verification.d.ts +58 -0
  33. package/dist/verification.d.ts.map +1 -0
  34. package/dist/verification.js +93 -0
  35. package/dist/verification.js.map +1 -0
  36. package/package.json +57 -0
  37. package/pages/react/forgot-password/+Page.tsx +64 -0
  38. package/pages/react/login/+Page.tsx +70 -0
  39. package/pages/react/login/+guard.ts +15 -0
  40. package/pages/react/register/+Page.tsx +78 -0
  41. package/pages/react/register/+guard.ts +15 -0
  42. package/pages/react/reset-password/+Page.tsx +118 -0
  43. package/pages/solid/forgot-password/+Page.tsx +62 -0
  44. package/pages/solid/login/+Page.tsx +66 -0
  45. package/pages/solid/login/+guard.ts +15 -0
  46. package/pages/solid/register/+Page.tsx +72 -0
  47. package/pages/solid/register/+guard.ts +15 -0
  48. package/pages/solid/reset-password/+Page.tsx +94 -0
  49. package/pages/vue/forgot-password/+Page.vue +60 -0
  50. package/pages/vue/login/+Page.vue +63 -0
  51. package/pages/vue/login/+guard.ts +15 -0
  52. package/pages/vue/register/+Page.vue +68 -0
  53. package/pages/vue/register/+guard.ts +15 -0
  54. package/pages/vue/reset-password/+Page.vue +93 -0
  55. package/schema/auth.drizzle.mysql.ts +48 -0
  56. package/schema/auth.drizzle.pg.ts +48 -0
  57. package/schema/auth.drizzle.sqlite.ts +48 -0
  58. package/schema/auth.prisma +50 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Suleiman Shahbari
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # @rudderjs/auth
2
+
3
+ Native authentication for RudderJS. Laravel-style guards, user providers, and Auth facade.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @rudderjs/auth @rudderjs/hash @rudderjs/session
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ ```ts
14
+ // config/auth.ts
15
+ import { User } from '../app/Models/User.js'
16
+
17
+ export default {
18
+ defaults: {
19
+ guard: 'web',
20
+ },
21
+ guards: {
22
+ web: { driver: 'session', provider: 'users' },
23
+ },
24
+ providers: {
25
+ users: { driver: 'eloquent', model: User },
26
+ },
27
+ }
28
+
29
+ // bootstrap/providers.ts
30
+ import { session } from '@rudderjs/session'
31
+ import { hash } from '@rudderjs/hash'
32
+ import { auth } from '@rudderjs/auth'
33
+
34
+ export default [
35
+ session(configs.session),
36
+ hash(configs.hash),
37
+ auth(configs.auth),
38
+ ]
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ ### Auth Facade
44
+
45
+ ```ts
46
+ import { Auth } from '@rudderjs/auth'
47
+
48
+ // Attempt login
49
+ const success = await Auth.attempt({ email, password })
50
+
51
+ // Manual login/logout
52
+ Auth.login(user)
53
+ Auth.logout()
54
+
55
+ // Current user
56
+ const user = await Auth.user() // Authenticatable | null
57
+ const id = await Auth.id() // string | null
58
+ const ok = await Auth.check() // boolean
59
+ const no = await Auth.guest() // boolean
60
+
61
+ // Switch guard
62
+ Auth.guard('api').user()
63
+ ```
64
+
65
+ ### Middleware
66
+
67
+ ```ts
68
+ import { AuthMiddleware, RequireAuth } from '@rudderjs/auth'
69
+
70
+ // Attach user to request (non-blocking)
71
+ Route.get('/profile', handler, [AuthMiddleware()])
72
+
73
+ // Require authentication (returns 401 if not logged in)
74
+ Route.post('/posts', handler, [RequireAuth()])
75
+ ```
76
+
77
+ ### Authenticatable Contract
78
+
79
+ Your User model must implement:
80
+
81
+ ```ts
82
+ interface Authenticatable {
83
+ getAuthIdentifier(): string
84
+ getAuthPassword(): string
85
+ getRememberToken(): string | null
86
+ setRememberToken(token: string): void
87
+ }
88
+ ```
89
+
90
+ The `EloquentUserProvider` auto-wraps ORM model records with these methods (mapping `id`, `password`, `rememberToken` fields).
91
+
92
+ ## Architecture
93
+
94
+ - **Guards** determine *how* users are authenticated (session cookies, API tokens)
95
+ - **User Providers** determine *where* users are retrieved from (Eloquent model, raw DB)
96
+ - **Auth facade** delegates to the current guard via `AsyncLocalStorage`
97
+ - **AuthManager** creates guards + providers from config, one per request
98
+
99
+ ### Built-in Guards
100
+
101
+ | Guard | Driver | Description |
102
+ |-------|--------|-------------|
103
+ | Session | `session` | Cookie-based auth via `@rudderjs/session` |
104
+
105
+ ### Built-in Providers
106
+
107
+ | Provider | Driver | Description |
108
+ |----------|--------|-------------|
109
+ | Eloquent | `eloquent` | Uses `@rudderjs/orm` Model class |
@@ -0,0 +1,137 @@
1
+ # @rudderjs/auth
2
+
3
+ ## Overview
4
+
5
+ Full-featured authentication and authorization package for RudderJS. Provides session-based guards, an Eloquent user provider, password reset broker, email verification, and a Laravel-style Gate/Policy authorization system. Uses `AsyncLocalStorage` for request-scoped auth context, integrates with `@rudderjs/hash` for password checking and `@rudderjs/session` for cookie-based sessions.
6
+
7
+ ## Key Patterns
8
+
9
+ ### Authentication Guards
10
+
11
+ Guards implement the `Guard` contract (`user()`, `check()`, `attempt()`, `login()`, `logout()`). The `SessionGuard` is the built-in driver that stores `auth_user_id` in the session.
12
+
13
+ ```ts
14
+ // config/auth.ts
15
+ export default {
16
+ defaults: { guard: 'web' },
17
+ guards: {
18
+ web: { driver: 'session', provider: 'users' },
19
+ },
20
+ providers: {
21
+ users: { driver: 'eloquent', model: User },
22
+ },
23
+ } satisfies AuthConfig
24
+ ```
25
+
26
+ Use `AuthMiddleware()` to populate `req.user` without blocking, or `RequireAuth()` to return 401 for unauthenticated requests:
27
+
28
+ ```ts
29
+ router.get('/profile', RequireAuth(), async (req, res) => {
30
+ res.json(req.user) // AuthUser — id, name, email + extra fields
31
+ })
32
+ ```
33
+
34
+ Use the `Auth` facade inside route handlers (request-scoped via AsyncLocalStorage):
35
+
36
+ ```ts
37
+ const success = await Auth.attempt({ email, password })
38
+ await Auth.login(user)
39
+ await Auth.logout()
40
+ const user = await Auth.user()
41
+ ```
42
+
43
+ ### Password Hashing
44
+
45
+ Auth delegates hashing to `@rudderjs/hash`. The hash provider **must** be registered before auth in the provider array:
46
+
47
+ ```ts
48
+ // bootstrap/providers.ts
49
+ export default [hash(configs.hash), auth(configs.auth), ...]
50
+ ```
51
+
52
+ The `EloquentUserProvider` calls `hashCheck(plain, hashed)` internally during `validateCredentials()`.
53
+
54
+ ### Email Verification
55
+
56
+ Implement `MustVerifyEmail` on your User model:
57
+
58
+ ```ts
59
+ class User extends Model implements Authenticatable, MustVerifyEmail {
60
+ hasVerifiedEmail() { return this.emailVerifiedAt !== null }
61
+ markEmailAsVerified() { this.emailVerifiedAt = new Date().toISOString(); return Promise.resolve() }
62
+ getEmailForVerification() { return this.email }
63
+ }
64
+ ```
65
+
66
+ Use the middleware and helpers:
67
+
68
+ ```ts
69
+ router.get('/dashboard', RequireAuth(), EnsureEmailIsVerified(), handler)
70
+
71
+ // Generate a signed verification URL (requires @rudderjs/router)
72
+ const url = verificationUrl(user)
73
+
74
+ // Handle verification in the route
75
+ await handleEmailVerification(req.params.id, req.params.hash, (id) => User.find(id))
76
+ ```
77
+
78
+ ### Authorization (Gates/Policies)
79
+
80
+ Define abilities and policies, then check them anywhere:
81
+
82
+ ```ts
83
+ // In a provider's boot()
84
+ Gate.define('edit-post', (user, post) => user.id === post.authorId)
85
+ Gate.policy(Post, PostPolicy)
86
+ Gate.before((user) => user.isAdmin ? true : undefined)
87
+
88
+ // In a handler
89
+ await Gate.authorize('edit-post', post) // throws AuthorizationError (403)
90
+ if (await Gate.allows('edit-post', post)) { ... }
91
+
92
+ // Scoped to a specific user
93
+ await Gate.forUser(user).allows('edit-post', post)
94
+ ```
95
+
96
+ Policies are classes with method names matching ability names:
97
+
98
+ ```ts
99
+ class PostPolicy extends Policy {
100
+ before(user: Authenticatable) { return user.isAdmin ? true : undefined }
101
+ update(user: Authenticatable, post: Post) { return user.id === post.authorId }
102
+ delete(user: Authenticatable, post: Post) { return user.id === post.authorId }
103
+ }
104
+ ```
105
+
106
+ ## Common Pitfalls
107
+
108
+ - **Provider order matters**: `hash()` must come before `auth()` in the providers array, or boot throws.
109
+ - **Missing session**: `@rudderjs/session` is a required peer dep. The session middleware must run before `AuthMiddleware`.
110
+ - **Auth outside middleware context**: `Auth.user()` / `Gate.allows()` only work inside the `AuthMiddleware` scope (AsyncLocalStorage). Outside that scope you get "No auth context" errors.
111
+ - **Password stripped from AuthUser**: The `userToPlain()` helper removes `password` from `req.user` automatically.
112
+ - **Gate.reset()**: Only for testing. Gate state is static/global.
113
+
114
+ ## Key Imports
115
+
116
+ ```ts
117
+ // Provider factory
118
+ import { auth } from '@rudderjs/auth'
119
+
120
+ // Middleware
121
+ import { AuthMiddleware, RequireAuth, EnsureEmailIsVerified } from '@rudderjs/auth'
122
+
123
+ // Facades & managers
124
+ import { Auth, Gate, Policy, AuthorizationError } from '@rudderjs/auth'
125
+
126
+ // Password reset
127
+ import { PasswordBroker, MemoryTokenRepository } from '@rudderjs/auth'
128
+
129
+ // Email verification
130
+ import { verificationUrl, handleEmailVerification, mustVerifyEmail } from '@rudderjs/auth'
131
+
132
+ // User provider
133
+ import { EloquentUserProvider, toAuthenticatable } from '@rudderjs/auth'
134
+
135
+ // Types
136
+ import type { Authenticatable, AuthUser, Guard, UserProvider, AuthConfig, MustVerifyEmail } from '@rudderjs/auth'
137
+ ```
@@ -0,0 +1,40 @@
1
+ import type { Authenticatable, Guard } from './contracts.js';
2
+ import { type SessionStore } from './session-guard.js';
3
+ export interface AuthGuardConfig {
4
+ driver: 'session';
5
+ provider: string;
6
+ }
7
+ export interface AuthProviderConfig {
8
+ driver: 'eloquent';
9
+ model: unknown;
10
+ }
11
+ export interface AuthConfig {
12
+ defaults: {
13
+ guard: string;
14
+ };
15
+ guards: Record<string, AuthGuardConfig>;
16
+ providers: Record<string, AuthProviderConfig>;
17
+ }
18
+ export declare class AuthManager {
19
+ private readonly config;
20
+ private readonly hashCheck;
21
+ private readonly getSession;
22
+ private readonly _guards;
23
+ constructor(config: AuthConfig, hashCheck: (plain: string, hashed: string) => Promise<boolean>, getSession: () => SessionStore);
24
+ guard(name?: string): Guard;
25
+ private createProvider;
26
+ }
27
+ export declare function runWithAuth<T>(manager: AuthManager, fn: () => T): T;
28
+ export declare function currentAuth(): AuthManager;
29
+ export declare class Auth {
30
+ private static g;
31
+ static guard(name: string): Guard;
32
+ static attempt(credentials: Record<string, unknown>, remember?: boolean): Promise<boolean>;
33
+ static login(user: Authenticatable, remember?: boolean): Promise<void>;
34
+ static logout(): Promise<void>;
35
+ static user(): Promise<Authenticatable | null>;
36
+ static id(): Promise<string | null>;
37
+ static check(): Promise<boolean>;
38
+ static guest(): Promise<boolean>;
39
+ }
40
+ //# sourceMappingURL=auth-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-manager.d.ts","sourceRoot":"","sources":["../src/auth-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAgB,MAAM,gBAAgB,CAAA;AAC1E,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAKpE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,UAAU,CAAA;IAClB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;IACD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACvC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;CAC9C;AAID,qBAAa,WAAW;IAIpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAL7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;gBAGhC,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAC9D,UAAU,EAAE,MAAM,YAAY;IAGjD,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK;IAqB3B,OAAO,CAAC,cAAc;CAavB;AAMD,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEnE;AAED,wBAAgB,WAAW,IAAI,WAAW,CAIzC;AAID,qBAAa,IAAI;IACf,OAAO,CAAC,MAAM,CAAC,CAAC;IAIhB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IAIjC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1F,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAI9C,MAAM,CAAC,EAAE,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAInC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;CAGjC"}
@@ -0,0 +1,85 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { SessionGuard } from './session-guard.js';
3
+ import { EloquentUserProvider } from './providers.js';
4
+ // ─── Auth Manager ─────────────────────────────────────────
5
+ export class AuthManager {
6
+ config;
7
+ hashCheck;
8
+ getSession;
9
+ _guards = new Map();
10
+ constructor(config, hashCheck, getSession) {
11
+ this.config = config;
12
+ this.hashCheck = hashCheck;
13
+ this.getSession = getSession;
14
+ }
15
+ guard(name) {
16
+ const guardName = name ?? this.config.defaults.guard;
17
+ const existing = this._guards.get(guardName);
18
+ if (existing)
19
+ return existing;
20
+ const guardConfig = this.config.guards[guardName];
21
+ if (!guardConfig)
22
+ throw new Error(`[RudderJS Auth] Guard "${guardName}" is not defined.`);
23
+ const provider = this.createProvider(guardConfig.provider);
24
+ let guard;
25
+ if (guardConfig.driver === 'session') {
26
+ guard = new SessionGuard(provider, this.getSession());
27
+ }
28
+ else {
29
+ throw new Error(`[RudderJS Auth] Guard driver "${guardConfig.driver}" is not supported.`);
30
+ }
31
+ this._guards.set(guardName, guard);
32
+ return guard;
33
+ }
34
+ createProvider(name) {
35
+ const providerConfig = this.config.providers[name];
36
+ if (!providerConfig)
37
+ throw new Error(`[RudderJS Auth] User provider "${name}" is not defined.`);
38
+ if (providerConfig.driver === 'eloquent') {
39
+ return new EloquentUserProvider(providerConfig.model, this.hashCheck);
40
+ }
41
+ throw new Error(`[RudderJS Auth] Provider driver "${providerConfig.driver}" is not supported.`);
42
+ }
43
+ }
44
+ // ─── Request-scoped Auth (AsyncLocalStorage) ──────────────
45
+ const _als = new AsyncLocalStorage();
46
+ export function runWithAuth(manager, fn) {
47
+ return _als.run(manager, fn);
48
+ }
49
+ export function currentAuth() {
50
+ const m = _als.getStore();
51
+ if (!m)
52
+ throw new Error('[RudderJS Auth] No auth context. Use AuthMiddleware.');
53
+ return m;
54
+ }
55
+ // ─── Auth Facade ──────────────────────────────────────────
56
+ export class Auth {
57
+ static g(name) {
58
+ return currentAuth().guard(name);
59
+ }
60
+ static guard(name) {
61
+ return currentAuth().guard(name);
62
+ }
63
+ static attempt(credentials, remember) {
64
+ return this.g().attempt(credentials, remember);
65
+ }
66
+ static login(user, remember) {
67
+ return this.g().login(user, remember);
68
+ }
69
+ static logout() {
70
+ return this.g().logout();
71
+ }
72
+ static user() {
73
+ return this.g().user();
74
+ }
75
+ static id() {
76
+ return this.g().id();
77
+ }
78
+ static check() {
79
+ return this.g().check();
80
+ }
81
+ static guest() {
82
+ return this.g().guest();
83
+ }
84
+ }
85
+ //# sourceMappingURL=auth-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-manager.js","sourceRoot":"","sources":["../src/auth-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface Authenticatable {
2
+ getAuthIdentifier(): string;
3
+ getAuthPassword(): string;
4
+ getRememberToken(): string | null;
5
+ setRememberToken(token: string): void;
6
+ }
7
+ export interface AuthUser {
8
+ id: string;
9
+ name: string;
10
+ email: string;
11
+ [key: string]: unknown;
12
+ }
13
+ export interface UserProvider {
14
+ retrieveById(id: string): Promise<Authenticatable | null>;
15
+ retrieveByCredentials(credentials: Record<string, unknown>): Promise<Authenticatable | null>;
16
+ validateCredentials(user: Authenticatable, credentials: Record<string, unknown>): Promise<boolean>;
17
+ }
18
+ export interface Guard {
19
+ user(): Promise<Authenticatable | null>;
20
+ id(): Promise<string | null>;
21
+ check(): Promise<boolean>;
22
+ guest(): Promise<boolean>;
23
+ attempt(credentials: Record<string, unknown>, remember?: boolean): Promise<boolean>;
24
+ login(user: Authenticatable, remember?: boolean): Promise<void>;
25
+ logout(): Promise<void>;
26
+ }
27
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,iBAAiB,IAAI,MAAM,CAAA;IAC3B,eAAe,IAAI,MAAM,CAAA;IACzB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAAA;IACjC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACtC;AAID,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAID,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IACzD,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IAC5F,mBAAmB,CAAC,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACnG;AAID,MAAM,WAAW,KAAK;IACpB,IAAI,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IACvC,EAAE,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC5B,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACzB,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACzB,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACnF,KAAK,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB"}
@@ -0,0 +1,3 @@
1
+ // ─── Authenticatable Contract ─────────────────────────────
2
+ export {};
3
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,6DAA6D"}
package/dist/gate.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ import type { Authenticatable } from './contracts.js';
2
+ type AbilityCallback = (user: Authenticatable, ...args: unknown[]) => boolean | Promise<boolean>;
3
+ type BeforeCallback = (user: Authenticatable, ability: string) => boolean | null | undefined | Promise<boolean | null | undefined>;
4
+ export declare abstract class Policy {
5
+ /**
6
+ * Run before any other check. Return true/false to short-circuit,
7
+ * or null/undefined to fall through to the specific method.
8
+ */
9
+ before?(_user: Authenticatable): boolean | null | undefined | Promise<boolean | null | undefined>;
10
+ }
11
+ type PolicyClass = new () => Policy;
12
+ type ModelClass = abstract new (...args: any[]) => unknown;
13
+ export declare class Gate {
14
+ private static _abilities;
15
+ private static _policies;
16
+ private static _beforeCallbacks;
17
+ static define(ability: string, callback: AbilityCallback): void;
18
+ static before(callback: BeforeCallback): void;
19
+ static policy(model: ModelClass, policy: PolicyClass): void;
20
+ static allows(ability: string, ...args: unknown[]): Promise<boolean>;
21
+ static denies(ability: string, ...args: unknown[]): Promise<boolean>;
22
+ /**
23
+ * Check ability — throw 403 if denied.
24
+ */
25
+ static authorize(ability: string, ...args: unknown[]): Promise<void>;
26
+ static forUser(user: Authenticatable): GateForUser;
27
+ private static resolveUser;
28
+ private static _check;
29
+ private static findPolicy;
30
+ private static callPolicy;
31
+ /** @internal — reset all definitions. Used for testing. */
32
+ static reset(): void;
33
+ }
34
+ declare class GateForUser {
35
+ private readonly user;
36
+ private readonly abilities;
37
+ private readonly policies;
38
+ private readonly beforeCallbacks;
39
+ constructor(user: Authenticatable, abilities: Map<string, AbilityCallback>, policies: Map<ModelClass, PolicyClass>, beforeCallbacks: BeforeCallback[]);
40
+ allows(ability: string, ...args: unknown[]): Promise<boolean>;
41
+ denies(ability: string, ...args: unknown[]): Promise<boolean>;
42
+ authorize(ability: string, ...args: unknown[]): Promise<void>;
43
+ }
44
+ export declare class AuthorizationError extends Error {
45
+ readonly status = 403;
46
+ constructor(message?: string);
47
+ }
48
+ export {};
49
+ //# sourceMappingURL=gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAKrD,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAChG,KAAK,cAAc,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;AAIlI,8BAAsB,MAAM;IAC1B;;;OAGG;IACH,MAAM,CAAC,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;CAClG;AAED,KAAK,WAAW,GAAG,UAAU,MAAM,CAAA;AAEnC,KAAK,UAAU,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAA;AAI1D,qBAAa,IAAI;IACf,OAAO,CAAC,MAAM,CAAC,UAAU,CAAqC;IAC9D,OAAO,CAAC,MAAM,CAAC,SAAS,CAAqC;IAC7D,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAuB;IAItD,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAI/D,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAI7C,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI;WAM9C,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;WAM7D,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1E;;OAEG;WACU,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1E,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,WAAW;mBAM7B,WAAW;mBASX,MAAM;IAuB3B,OAAO,CAAC,MAAM,CAAC,UAAU;mBAiBJ,UAAU;IAqB/B,2DAA2D;IAC3D,MAAM,CAAC,KAAK,IAAI,IAAI;CAKrB;AAID,cAAM,WAAW;IAEb,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,eAAe;gBAHf,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACvC,QAAQ,EAAE,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,EACtC,eAAe,EAAE,cAAc,EAAE;IAG9C,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAkC7D,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAKpE;AAID,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,OAAM;gBAET,OAAO,SAAiC;CAIrD"}