@rudderjs/auth 0.2.0 → 0.2.1

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 (45) hide show
  1. package/README.md +63 -21
  2. package/boost/skills/auth-setup/SKILL.md +273 -0
  3. package/dist/auth-manager.d.ts +31 -1
  4. package/dist/auth-manager.d.ts.map +1 -1
  5. package/dist/auth-manager.js +53 -12
  6. package/dist/auth-manager.js.map +1 -1
  7. package/dist/gate-observers.d.ts +37 -0
  8. package/dist/gate-observers.d.ts.map +1 -0
  9. package/dist/gate-observers.js +38 -0
  10. package/dist/gate-observers.js.map +1 -0
  11. package/dist/gate.d.ts +3 -0
  12. package/dist/gate.d.ts.map +1 -1
  13. package/dist/gate.js +72 -15
  14. package/dist/gate.js.map +1 -1
  15. package/dist/index.d.ts +13 -7
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +53 -39
  18. package/dist/index.js.map +1 -1
  19. package/dist/require-guest.d.ts +10 -0
  20. package/dist/require-guest.d.ts.map +1 -0
  21. package/dist/require-guest.js +25 -0
  22. package/dist/require-guest.js.map +1 -0
  23. package/dist/routes.d.ts +43 -0
  24. package/dist/routes.d.ts.map +1 -0
  25. package/dist/routes.js +43 -0
  26. package/dist/routes.js.map +1 -0
  27. package/package.json +38 -8
  28. package/{pages/react/forgot-password/+Page.tsx → views/react/ForgotPassword.tsx} +17 -4
  29. package/{pages/react/login/+Page.tsx → views/react/Login.tsx} +25 -7
  30. package/{pages/react/register/+Page.tsx → views/react/Register.tsx} +17 -4
  31. package/{pages/react/reset-password/+Page.tsx → views/react/ResetPassword.tsx} +20 -5
  32. package/pages/react/login/+guard.ts +0 -15
  33. package/pages/react/register/+guard.ts +0 -15
  34. package/pages/solid/forgot-password/+Page.tsx +0 -62
  35. package/pages/solid/login/+Page.tsx +0 -66
  36. package/pages/solid/login/+guard.ts +0 -15
  37. package/pages/solid/register/+Page.tsx +0 -72
  38. package/pages/solid/register/+guard.ts +0 -15
  39. package/pages/solid/reset-password/+Page.tsx +0 -94
  40. package/pages/vue/forgot-password/+Page.vue +0 -60
  41. package/pages/vue/login/+Page.vue +0 -63
  42. package/pages/vue/login/+guard.ts +0 -15
  43. package/pages/vue/register/+Page.vue +0 -68
  44. package/pages/vue/register/+guard.ts +0 -15
  45. package/pages/vue/reset-password/+Page.vue +0 -93
package/README.md CHANGED
@@ -29,51 +29,93 @@ export default {
29
29
  // bootstrap/providers.ts
30
30
  import { session } from '@rudderjs/session'
31
31
  import { hash } from '@rudderjs/hash'
32
- import { auth } from '@rudderjs/auth'
32
+ import { authProvider } from '@rudderjs/auth'
33
33
 
34
34
  export default [
35
35
  session(configs.session),
36
36
  hash(configs.hash),
37
- auth(configs.auth),
37
+ authProvider(configs.auth),
38
38
  ]
39
39
  ```
40
40
 
41
+ > `authProvider()` is the service-provider factory.
42
+ > `auth()` (lowercase) is the per-request helper — see below.
43
+
41
44
  ## Usage
42
45
 
43
- ### Auth Facade
46
+ ### Reading the current user
47
+
48
+ Three equivalent shapes, pick whichever reads best at the call site:
44
49
 
45
50
  ```ts
46
- import { Auth } from '@rudderjs/auth'
51
+ import { auth, Auth } from '@rudderjs/auth'
52
+
53
+ // 1. `auth()` helper — Laravel's `auth()->user()`
54
+ const user = await auth().user()
55
+ const ok = await auth().check()
56
+ const user = await auth().guard('api').user() // non-default guard
57
+
58
+ // 2. `Auth` facade — same thing, static methods
59
+ const user = await Auth.user()
60
+ const ok = await Auth.check()
61
+
62
+ // 3. `req.user` — populated on every request, zero await
63
+ Route.get('/profile', async (req) => {
64
+ return { user: req.user ?? null }
65
+ })
66
+ ```
67
+
68
+ None of these require attaching any middleware per-route. The `authProvider()`
69
+ service provider installs `AuthMiddleware` as a global router middleware at
70
+ boot, so every request has the auth context ready before your handler runs.
71
+
72
+ ### Login / logout
47
73
 
48
- // Attempt login
74
+ ```ts
75
+ // Attempt with credentials
49
76
  const success = await Auth.attempt({ email, password })
50
77
 
51
- // Manual login/logout
52
- Auth.login(user)
53
- Auth.logout()
78
+ // Manual login (after a sign-up flow, social login, etc.)
79
+ await Auth.login(user)
54
80
 
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
81
+ // Logout
82
+ await Auth.logout()
83
+ ```
60
84
 
61
- // Switch guard
62
- Auth.guard('api').user()
85
+ ### Route protection
86
+
87
+ ```ts
88
+ import { RequireAuth, RequireGuest } from '@rudderjs/auth'
89
+
90
+ // 401 if not logged in
91
+ Route.post('/posts', handler, [RequireAuth()])
92
+
93
+ // Bounce already-logged-in users away (e.g. /login, /register)
94
+ Route.get('/login', showLoginPage, [RequireGuest('/')])
63
95
  ```
64
96
 
65
- ### Middleware
97
+ ### `AuthMiddleware` — advanced only
66
98
 
67
99
  ```ts
68
- import { AuthMiddleware, RequireAuth } from '@rudderjs/auth'
100
+ import { AuthMiddleware } from '@rudderjs/auth'
101
+ ```
69
102
 
70
- // Attach user to request (non-blocking)
71
- Route.get('/profile', handler, [AuthMiddleware()])
103
+ **You don't normally attach this.** The `authProvider()` service provider
104
+ already installs `AuthMiddleware()` globally, so `req.user` and `auth()` work
105
+ on every route without wiring. The only time to reach for it manually is to
106
+ run a **non-default guard** on a specific route — the RudderJS equivalent of
107
+ Laravel's `->middleware('auth:api')`:
72
108
 
73
- // Require authentication (returns 401 if not logged in)
74
- Route.post('/posts', handler, [RequireAuth()])
109
+ ```ts
110
+ Route.get('/api/admin/stats', handler, [
111
+ AuthMiddleware('api'), // populate req.user using the 'api' guard
112
+ RequireAuth('api'), // 401 if not authenticated against 'api'
113
+ ])
75
114
  ```
76
115
 
116
+ In normal app code you can forget `AuthMiddleware` exists — use `auth()`,
117
+ `Auth`, or `req.user` directly.
118
+
77
119
  ### Authenticatable Contract
78
120
 
79
121
  Your User model must implement:
@@ -0,0 +1,273 @@
1
+ ---
2
+ name: auth-setup
3
+ description: Setting up authentication with guards, sessions, registration, password reset, gates/policies, and vendor views in RudderJS
4
+ ---
5
+
6
+ # Auth Setup
7
+
8
+ ## When to use this skill
9
+
10
+ Load this skill when you need to set up authentication, configure guards, add login/register views, implement authorization gates/policies, or work with password reset and email verification.
11
+
12
+ ## Key concepts
13
+
14
+ - **AuthManager**: Process-wide DI singleton that creates fresh `SessionGuard` instances per call (never cached -- prevents ghost user leaks across requests).
15
+ - **Guard contract**: `user()`, `check()`, `guest()`, `attempt()`, `login()`, `logout()` -- all async.
16
+ - **`auth()` helper**: Returns the current request's `AuthManager` via AsyncLocalStorage. Mirrors Laravel's `auth()->user()`.
17
+ - **Auth facade**: `Auth.user()`, `Auth.check()` etc. -- static class that proxies to `currentAuth()`.
18
+ - **AuthMiddleware**: Sets up the auth ALS context and populates `req.user` for every request.
19
+ - **RequireAuth**: Returns 401 if not authenticated.
20
+ - **RequireGuest**: Redirects authenticated users away from guest-only pages (login, register).
21
+ - **Gate/Policy**: Authorization system for checking abilities and model-level policies.
22
+
23
+ ## Step-by-step
24
+
25
+ ### 1. Install dependencies
26
+
27
+ Auth requires `@rudderjs/session` and `@rudderjs/hash` as peer dependencies:
28
+
29
+ ```bash
30
+ pnpm add @rudderjs/auth @rudderjs/session @rudderjs/hash
31
+ ```
32
+
33
+ ### 2. Configure auth (config/auth.ts)
34
+
35
+ ```ts
36
+ import { User } from '../app/Models/User.js'
37
+ import type { AuthConfig } from '@rudderjs/auth'
38
+
39
+ export default {
40
+ defaults: {
41
+ guard: 'web',
42
+ },
43
+ guards: {
44
+ web: {
45
+ driver: 'session',
46
+ provider: 'users',
47
+ },
48
+ },
49
+ providers: {
50
+ users: {
51
+ driver: 'eloquent',
52
+ model: User,
53
+ },
54
+ },
55
+ } satisfies AuthConfig
56
+ ```
57
+
58
+ ### 3. Register the provider (bootstrap/providers.ts)
59
+
60
+ ```ts
61
+ import { defaultProviders } from '@rudderjs/core'
62
+ // AuthProvider is auto-discovered via defaultProviders() if @rudderjs/auth is installed.
63
+ // It requires HashProvider and SessionProvider to boot before it.
64
+ export default [
65
+ ...(await defaultProviders()),
66
+ // ... your app providers
67
+ ]
68
+ ```
69
+
70
+ ### 4. Make the User model authenticatable
71
+
72
+ ```ts
73
+ import { Model, Hidden } from '@rudderjs/orm'
74
+ import type { Authenticatable } from '@rudderjs/auth'
75
+
76
+ export class User extends Model implements Authenticatable {
77
+ static fillable = ['name', 'email', 'password']
78
+
79
+ @Hidden password = ''
80
+
81
+ getAuthIdentifier(): string { return String(this.id) }
82
+ getAuthPassword(): string { return this.password }
83
+ getRememberToken(): string | null { return null }
84
+ setRememberToken(_token: string): void {}
85
+ }
86
+ ```
87
+
88
+ ### 5. Use auth in route handlers
89
+
90
+ ```ts
91
+ import { auth, Auth, RequireAuth } from '@rudderjs/auth'
92
+
93
+ // Using the auth() helper (Laravel-style)
94
+ router.get('/api/me', async (req, res) => {
95
+ const user = await auth().user()
96
+ if (!user) return res.status(401).json({ message: 'Unauthorized' })
97
+ res.json({ user })
98
+ })
99
+
100
+ // Using the Auth facade
101
+ router.get('/api/profile', async (req, res) => {
102
+ if (await Auth.guest()) return res.status(401).json({ message: 'Unauthorized' })
103
+ const user = await Auth.user()
104
+ res.json({ user })
105
+ })
106
+
107
+ // Using RequireAuth middleware
108
+ router.get('/api/dashboard', RequireAuth(), async (req, res) => {
109
+ // req.user is guaranteed to exist here
110
+ res.json({ user: req.user })
111
+ })
112
+ ```
113
+
114
+ ### 6. Login / logout endpoints
115
+
116
+ ```ts
117
+ router.post('/api/auth/login', async (req, res) => {
118
+ const { email, password } = req.body
119
+ const success = await auth().attempt({ email, password })
120
+ if (!success) {
121
+ return res.status(422).json({ message: 'Invalid credentials.' })
122
+ }
123
+ const user = await auth().user()
124
+ res.json({ user })
125
+ })
126
+
127
+ router.post('/api/auth/register', async (req, res) => {
128
+ const user = await User.create({
129
+ name: req.body.name,
130
+ email: req.body.email,
131
+ password: req.body.password, // hashed by Attribute mutator
132
+ })
133
+ await auth().login(user)
134
+ res.json({ user })
135
+ })
136
+
137
+ router.post('/api/auth/logout', RequireAuth(), async (req, res) => {
138
+ await auth().logout()
139
+ res.json({ message: 'Logged out.' })
140
+ })
141
+ ```
142
+
143
+ ### 7. Set up auth views (login/register pages)
144
+
145
+ Vendor the view files into your app:
146
+
147
+ ```bash
148
+ pnpm rudder vendor:publish --tag=auth-views
149
+ ```
150
+
151
+ This copies `@rudderjs/auth/views/react/` into `app/Views/Auth/`. Then register routes:
152
+
153
+ ```ts
154
+ // routes/web.ts
155
+ import { Route } from '@rudderjs/router'
156
+ import { registerAuthRoutes } from '@rudderjs/auth/routes'
157
+
158
+ registerAuthRoutes(Route)
159
+ // Registers: GET /login, GET /register, GET /forgot-password, GET /reset-password
160
+ ```
161
+
162
+ Customize paths and view ids:
163
+
164
+ ```ts
165
+ registerAuthRoutes(Route, {
166
+ paths: {
167
+ login: '/sign-in',
168
+ register: '/sign-up',
169
+ },
170
+ views: {
171
+ login: 'auth.sign-in', // maps to app/Views/Auth/SignIn.tsx
172
+ register: 'auth.sign-up',
173
+ },
174
+ homeUrl: '/dashboard', // redirect destination for authenticated users
175
+ })
176
+ ```
177
+
178
+ ### 8. Authorization with Gates
179
+
180
+ ```ts
181
+ import { Gate, Policy, AuthorizationError } from '@rudderjs/auth'
182
+
183
+ // Define abilities
184
+ Gate.define('manage-settings', (user) => user.role === 'admin')
185
+ Gate.define('edit-post', (user, post) => post.authorId === user.getAuthIdentifier())
186
+
187
+ // Check in handlers
188
+ if (await Gate.allows('manage-settings')) { /* ... */ }
189
+ if (await Gate.denies('edit-post', post)) { /* ... */ }
190
+
191
+ // Throw 403 if denied
192
+ await Gate.authorize('edit-post', post)
193
+
194
+ // Before callback -- runs before all checks
195
+ Gate.before((user, ability) => {
196
+ if (user.role === 'super-admin') return true // allow everything
197
+ return null // fall through to normal checks
198
+ })
199
+ ```
200
+
201
+ ### 9. Model policies
202
+
203
+ ```ts
204
+ import { Policy } from '@rudderjs/auth'
205
+ import type { Authenticatable } from '@rudderjs/auth'
206
+
207
+ class PostPolicy extends Policy {
208
+ before(user: Authenticatable) {
209
+ if ((user as any).role === 'admin') return true
210
+ return null // fall through
211
+ }
212
+
213
+ view(user: Authenticatable, post: Post) {
214
+ return post.isPublished || post.authorId === user.getAuthIdentifier()
215
+ }
216
+
217
+ update(user: Authenticatable, post: Post) {
218
+ return post.authorId === user.getAuthIdentifier()
219
+ }
220
+
221
+ delete(user: Authenticatable, post: Post) {
222
+ return post.authorId === user.getAuthIdentifier()
223
+ }
224
+ }
225
+
226
+ // Register the policy
227
+ Gate.policy(Post, PostPolicy)
228
+
229
+ // Use it
230
+ await Gate.authorize('update', post) // auto-finds PostPolicy.update()
231
+ ```
232
+
233
+ ### 10. Email verification
234
+
235
+ ```ts
236
+ import { EnsureEmailIsVerified, verificationUrl, handleEmailVerification } from '@rudderjs/auth'
237
+ import type { MustVerifyEmail } from '@rudderjs/auth'
238
+
239
+ // Make user implement MustVerifyEmail
240
+ class User extends Model implements Authenticatable, MustVerifyEmail {
241
+ hasVerifiedEmail() { return this.emailVerifiedAt !== null }
242
+ async markEmailAsVerified() { await User.update(this.id, { emailVerifiedAt: new Date() }) }
243
+ getEmailForVerification() { return this.email }
244
+ }
245
+
246
+ // Protect routes
247
+ router.get('/dashboard', RequireAuth(), EnsureEmailIsVerified(), handler)
248
+
249
+ // Generate verification URL (for sending in emails)
250
+ const url = verificationUrl(user)
251
+ ```
252
+
253
+ ### 11. Password reset
254
+
255
+ ```ts
256
+ import { PasswordBroker, MemoryTokenRepository } from '@rudderjs/auth'
257
+
258
+ const broker = new PasswordBroker(new MemoryTokenRepository())
259
+ // In production, implement TokenRepository backed by your database
260
+ ```
261
+
262
+ ## Examples
263
+
264
+ See `playground/config/auth.ts` for configuration, `playground/app/Models/User.ts` for the model, `playground/routes/web.ts` for route registration, and `playground/app/Views/Auth/` for vendored view files.
265
+
266
+ ## Common pitfalls
267
+
268
+ - **Ghost signed-in user**: `AuthManager` must NOT cache `SessionGuard` instances. The manager is a DI singleton; cached guards leak `_user` across requests.
269
+ - **Provider boot order**: `HashProvider` and `SessionProvider` must boot before `AuthProvider`. With `defaultProviders()`, this is handled automatically.
270
+ - **Session middleware required**: Auth views require session middleware. Ensure `@rudderjs/session` is installed and its provider is registered.
271
+ - **View route override**: Auth view files need `export const route = '/login'` etc. so SPA navigation works correctly (URL must match Vike's route table).
272
+ - **POST handlers not included**: `registerAuthRoutes()` only registers GET routes for the UI pages. POST endpoints for login/register/logout are your responsibility in `routes/api.ts`.
273
+ - **Guard driver**: Currently only `'session'` is supported as a guard driver. API token guards are planned.
@@ -19,13 +19,43 @@ export declare class AuthManager {
19
19
  private readonly config;
20
20
  private readonly hashCheck;
21
21
  private readonly getSession;
22
- private readonly _guards;
23
22
  constructor(config: AuthConfig, hashCheck: (plain: string, hashed: string) => Promise<boolean>, getSession: () => SessionStore);
23
+ /**
24
+ * Build a fresh Guard each call. We deliberately do NOT cache guards on
25
+ * the manager: AuthManager is a process-wide DI singleton, and a cached
26
+ * SessionGuard would keep `_user` populated across requests — once any
27
+ * request signs in, every subsequent request would see that user as
28
+ * "still logged in" even with an empty session. A new instance per call
29
+ * scopes `_user` to the local that the handler stores, which is the
30
+ * request-natural lifetime.
31
+ */
24
32
  guard(name?: string): Guard;
33
+ attempt(credentials: Record<string, unknown>, remember?: boolean): Promise<boolean>;
34
+ login(user: Authenticatable, remember?: boolean): Promise<void>;
35
+ logout(): Promise<void>;
36
+ user(): Promise<Authenticatable | null>;
37
+ id(): Promise<string | null>;
38
+ check(): Promise<boolean>;
39
+ guest(): Promise<boolean>;
25
40
  private createProvider;
26
41
  }
27
42
  export declare function runWithAuth<T>(manager: AuthManager, fn: () => T): T;
28
43
  export declare function currentAuth(): AuthManager;
44
+ /**
45
+ * Laravel-style helper — returns the current request's AuthManager.
46
+ *
47
+ * Mirrors Laravel's `auth()->user()`, `auth()->check()`, `auth()->guard('api')`.
48
+ * Inside an HTTP handler (after AuthMiddleware has run) you can call:
49
+ *
50
+ * await auth().user()
51
+ * await auth().check()
52
+ * await auth().guard('api').user()
53
+ *
54
+ * In non-HTTP contexts (CLI, queue, scheduler) you must still wrap the call
55
+ * in `runWithAuth(manager, …)` yourself — there is no request pipeline to
56
+ * populate the ALS context for you.
57
+ */
58
+ export declare function auth(): AuthManager;
29
59
  export declare class Auth {
30
60
  private static g;
31
61
  static guard(name: string): Guard;
@@ -1 +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"}
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;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAFV,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;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK;IAkB3B,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAInF,KAAK,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,IAAI,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAIvC,EAAE,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI5B,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzB,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzB,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;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,IAAI,IAAI,WAAW,CAElC;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"}
@@ -6,30 +6,54 @@ export class AuthManager {
6
6
  config;
7
7
  hashCheck;
8
8
  getSession;
9
- _guards = new Map();
10
9
  constructor(config, hashCheck, getSession) {
11
10
  this.config = config;
12
11
  this.hashCheck = hashCheck;
13
12
  this.getSession = getSession;
14
13
  }
14
+ /**
15
+ * Build a fresh Guard each call. We deliberately do NOT cache guards on
16
+ * the manager: AuthManager is a process-wide DI singleton, and a cached
17
+ * SessionGuard would keep `_user` populated across requests — once any
18
+ * request signs in, every subsequent request would see that user as
19
+ * "still logged in" even with an empty session. A new instance per call
20
+ * scopes `_user` to the local that the handler stores, which is the
21
+ * request-natural lifetime.
22
+ */
15
23
  guard(name) {
16
24
  const guardName = name ?? this.config.defaults.guard;
17
- const existing = this._guards.get(guardName);
18
- if (existing)
19
- return existing;
20
25
  const guardConfig = this.config.guards[guardName];
21
26
  if (!guardConfig)
22
27
  throw new Error(`[RudderJS Auth] Guard "${guardName}" is not defined.`);
23
- const provider = this.createProvider(guardConfig.provider);
24
- let guard;
25
28
  if (guardConfig.driver === 'session') {
26
- guard = new SessionGuard(provider, this.getSession());
29
+ const provider = this.createProvider(guardConfig.provider);
30
+ return new SessionGuard(provider, this.getSession());
27
31
  }
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;
32
+ throw new Error(`[RudderJS Auth] Guard driver "${guardConfig.driver}" is not supported.`);
33
+ }
34
+ // Default-guard convenience methods — match Laravel's AuthManager, which
35
+ // proxies these through to the default guard so `auth()->user()` works
36
+ // without an explicit `->guard()` call.
37
+ attempt(credentials, remember) {
38
+ return this.guard().attempt(credentials, remember);
39
+ }
40
+ login(user, remember) {
41
+ return this.guard().login(user, remember);
42
+ }
43
+ logout() {
44
+ return this.guard().logout();
45
+ }
46
+ user() {
47
+ return this.guard().user();
48
+ }
49
+ id() {
50
+ return this.guard().id();
51
+ }
52
+ check() {
53
+ return this.guard().check();
54
+ }
55
+ guest() {
56
+ return this.guard().guest();
33
57
  }
34
58
  createProvider(name) {
35
59
  const providerConfig = this.config.providers[name];
@@ -52,6 +76,23 @@ export function currentAuth() {
52
76
  throw new Error('[RudderJS Auth] No auth context. Use AuthMiddleware.');
53
77
  return m;
54
78
  }
79
+ /**
80
+ * Laravel-style helper — returns the current request's AuthManager.
81
+ *
82
+ * Mirrors Laravel's `auth()->user()`, `auth()->check()`, `auth()->guard('api')`.
83
+ * Inside an HTTP handler (after AuthMiddleware has run) you can call:
84
+ *
85
+ * await auth().user()
86
+ * await auth().check()
87
+ * await auth().guard('api').user()
88
+ *
89
+ * In non-HTTP contexts (CLI, queue, scheduler) you must still wrap the call
90
+ * in `runWithAuth(manager, …)` yourself — there is no request pipeline to
91
+ * populate the ALS context for you.
92
+ */
93
+ export function auth() {
94
+ return currentAuth();
95
+ }
55
96
  // ─── Auth Facade ──────────────────────────────────────────
56
97
  export class Auth {
57
98
  static g(name) {
@@ -1 +1 @@
1
- {"version":3,"file":"auth-manager.js","sourceRoot":"","sources":["../src/auth-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-manager.js","sourceRoot":"","sources":["../src/auth-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Gate event observers — process-wide pub/sub for authorization
3
+ * decisions made through `Gate.allows()`, `Gate.denies()`, and
4
+ * `Gate.authorize()`.
5
+ *
6
+ * Used today by `@rudderjs/telescope`'s GateCollector to record
7
+ * authorization checks into the dashboard.
8
+ */
9
+ export interface GateEvent {
10
+ ability: string;
11
+ userId: string | null;
12
+ allowed: boolean;
13
+ /** What resolved the decision */
14
+ resolvedVia: 'ability' | 'policy' | 'before' | 'default';
15
+ /** Policy class name (if resolved via policy) */
16
+ policy?: string | undefined;
17
+ /** Model class name (if a model was passed) */
18
+ model?: string | undefined;
19
+ /** Duration of the check in ms */
20
+ duration: number;
21
+ }
22
+ export type GateObserver = (event: GateEvent) => void;
23
+ export declare class GateObserverRegistry {
24
+ private observers;
25
+ /** Subscribe; returns an unsubscribe function. */
26
+ subscribe(fn: GateObserver): () => void;
27
+ /**
28
+ * Called by `Gate.allows()` after each authorization check.
29
+ * Errors thrown by observers are swallowed — observability must never
30
+ * break authorization.
31
+ */
32
+ emit(event: GateEvent): void;
33
+ /** @internal — used in tests */
34
+ reset(): void;
35
+ }
36
+ export declare const gateObservers: GateObserverRegistry;
37
+ //# sourceMappingURL=gate-observers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-observers.d.ts","sourceRoot":"","sources":["../src/gate-observers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAM,MAAM,CAAA;IACnB,MAAM,EAAO,MAAM,GAAG,IAAI,CAAA;IAC1B,OAAO,EAAM,OAAO,CAAA;IACpB,iCAAiC;IACjC,WAAW,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;IACxD,iDAAiD;IACjD,MAAM,CAAC,EAAM,MAAM,GAAG,SAAS,CAAA;IAC/B,+CAA+C;IAC/C,KAAK,CAAC,EAAO,MAAM,GAAG,SAAS,CAAA;IAC/B,kCAAkC;IAClC,QAAQ,EAAK,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAA;AAErD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,SAAS,CAAqB;IAEtC,kDAAkD;IAClD,SAAS,CAAC,EAAE,EAAE,YAAY,GAAG,MAAM,IAAI;IAKvC;;;;OAIG;IACH,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAM5B,gCAAgC;IAChC,KAAK,IAAI,IAAI;CACd;AAQD,eAAO,MAAM,aAAa,EAAwC,oBAAoB,CAAA"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Gate event observers — process-wide pub/sub for authorization
3
+ * decisions made through `Gate.allows()`, `Gate.denies()`, and
4
+ * `Gate.authorize()`.
5
+ *
6
+ * Used today by `@rudderjs/telescope`'s GateCollector to record
7
+ * authorization checks into the dashboard.
8
+ */
9
+ export class GateObserverRegistry {
10
+ observers = [];
11
+ /** Subscribe; returns an unsubscribe function. */
12
+ subscribe(fn) {
13
+ this.observers.push(fn);
14
+ return () => { this.observers = this.observers.filter(o => o !== fn); };
15
+ }
16
+ /**
17
+ * Called by `Gate.allows()` after each authorization check.
18
+ * Errors thrown by observers are swallowed — observability must never
19
+ * break authorization.
20
+ */
21
+ emit(event) {
22
+ for (const o of this.observers) {
23
+ try {
24
+ o(event);
25
+ }
26
+ catch { /* observer errors must not break auth */ }
27
+ }
28
+ }
29
+ /** @internal — used in tests */
30
+ reset() { this.observers = []; }
31
+ }
32
+ // Process-wide singleton, like `broadcastObservers` in `@rudderjs/broadcast`.
33
+ const _g = globalThis;
34
+ if (!_g['__rudderjs_gate_observers__']) {
35
+ _g['__rudderjs_gate_observers__'] = new GateObserverRegistry();
36
+ }
37
+ export const gateObservers = _g['__rudderjs_gate_observers__'];
38
+ //# sourceMappingURL=gate-observers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-observers.js","sourceRoot":"","sources":["../src/gate-observers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,MAAM,OAAO,oBAAoB;IACvB,SAAS,GAAmB,EAAE,CAAA;IAEtC,kDAAkD;IAClD,SAAS,CAAC,EAAgB;QACxB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACvB,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAA,CAAC,CAAC,CAAA;IACxE,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,KAAgB;QACnB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC;gBAAC,CAAC,CAAC,KAAK,CAAC,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,yCAAyC,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,KAAK,KAAW,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA,CAAC,CAAC;CACtC;AAED,8EAA8E;AAC9E,MAAM,EAAE,GAAG,UAAqC,CAAA;AAChD,IAAI,CAAC,EAAE,CAAC,6BAA6B,CAAC,EAAE,CAAC;IACvC,EAAE,CAAC,6BAA6B,CAAC,GAAG,IAAI,oBAAoB,EAAE,CAAA;AAChE,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC,6BAA6B,CAAyB,CAAA"}
package/dist/gate.d.ts CHANGED
@@ -28,6 +28,8 @@ export declare class Gate {
28
28
  private static _check;
29
29
  private static findPolicy;
30
30
  private static callPolicy;
31
+ /** Emit an observation event to the gate observer registry (if present). */
32
+ private static _emitObservation;
31
33
  /** @internal — reset all definitions. Used for testing. */
32
34
  static reset(): void;
33
35
  }
@@ -38,6 +40,7 @@ declare class GateForUser {
38
40
  private readonly beforeCallbacks;
39
41
  constructor(user: Authenticatable, abilities: Map<string, AbilityCallback>, policies: Map<ModelClass, PolicyClass>, beforeCallbacks: BeforeCallback[]);
40
42
  allows(ability: string, ...args: unknown[]): Promise<boolean>;
43
+ private _check;
41
44
  denies(ability: string, ...args: unknown[]): Promise<boolean>;
42
45
  authorize(ability: string, ...args: unknown[]): Promise<void>;
43
46
  }
@@ -1 +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"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAerD,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;AAWlI,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;WAa7D,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;IAwB3B,OAAO,CAAC,MAAM,CAAC,UAAU;mBAiBJ,UAAU;IAqB/B,4EAA4E;IAC5E,OAAO,CAAC,MAAM,CAAC,gBAAgB;IA0B/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;YAwBrD,MAAM;IAmCd,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"}