kroxt 1.3.10 → 1.3.11
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/README.md +270 -231
- package/dist/auth/adapters/drizzle.cjs +5 -0
- package/dist/auth/adapters/drizzle.cjs.map +2 -2
- package/dist/auth/adapters/drizzle.d.ts.map +1 -1
- package/dist/auth/adapters/drizzle.js +5 -0
- package/dist/auth/adapters/drizzle.js.map +2 -2
- package/dist/auth/adapters/index.cjs.map +1 -1
- package/dist/auth/adapters/index.d.ts +2 -0
- package/dist/auth/adapters/index.d.ts.map +1 -1
- package/dist/auth/adapters/memory.cjs +9 -0
- package/dist/auth/adapters/memory.cjs.map +2 -2
- package/dist/auth/adapters/memory.d.ts.map +1 -1
- package/dist/auth/adapters/memory.js +9 -0
- package/dist/auth/adapters/memory.js.map +2 -2
- package/dist/auth/adapters/mongoose.cjs +5 -0
- package/dist/auth/adapters/mongoose.cjs.map +2 -2
- package/dist/auth/adapters/mongoose.d.ts.map +1 -1
- package/dist/auth/adapters/mongoose.js +5 -0
- package/dist/auth/adapters/mongoose.js.map +2 -2
- package/dist/auth/adapters/prisma.cjs +8 -0
- package/dist/auth/adapters/prisma.cjs.map +2 -2
- package/dist/auth/adapters/prisma.d.ts.map +1 -1
- package/dist/auth/adapters/prisma.js +8 -0
- package/dist/auth/adapters/prisma.js.map +2 -2
- package/dist/auth/core/index.cjs +32 -5
- package/dist/auth/core/index.cjs.map +2 -2
- package/dist/auth/core/index.d.ts +3 -0
- package/dist/auth/core/index.d.ts.map +1 -1
- package/dist/auth/core/index.js +32 -5
- package/dist/auth/core/index.js.map +2 -2
- package/dist/cli/index.cjs +49 -18
- package/dist/cli/index.cjs.map +3 -3
- package/dist/cli/index.js +49 -18
- package/dist/cli/index.js.map +2 -2
- package/dist/cli/templates.cjs +5 -1
- package/dist/cli/templates.cjs.map +2 -2
- package/dist/cli/templates.d.ts +1 -1
- package/dist/cli/templates.d.ts.map +1 -1
- package/dist/cli/templates.js +5 -1
- package/dist/cli/templates.js.map +2 -2
- package/package.json +107 -107
package/README.md
CHANGED
|
@@ -1,231 +1,270 @@
|
|
|
1
|
-
# Kroxt
|
|
2
|
-
|
|
3
|
-
**The Most Simplified auth library**
|
|
4
|
-
|
|
5
|
-
Kroxt is a premium, framework-agnostic, and security-hardened authentication
|
|
6
|
-
|
|
7
|
-
[](https://www.npmjs.com/package/kroxt)
|
|
8
|
-
[](https://www.npmjs.com/package/kroxt)
|
|
8
|
+
[](https://nextjs.org)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
|
|
11
|
+
The recommended way to start is the **Kroxt CLI**. It detects your framework (Next.js, Express, Fastify) and scaffolds a professional auth structure automatically.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx kroxt init
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🚀 Next.js First-Class Support
|
|
20
|
+
|
|
21
|
+
Kroxt is optimized for the Next.js App Router. Use standard **Route Handlers** for high performance and zero overhead.
|
|
22
|
+
|
|
23
|
+
### 1. Configuration (`lib/kroxt/auth.ts`)
|
|
24
|
+
```typescript
|
|
25
|
+
import { createAuth } from "kroxt";
|
|
26
|
+
import { createMongoAdapter } from "kroxt/adapters/mongoose";
|
|
27
|
+
import { User } from "./models/user.model";
|
|
28
|
+
|
|
29
|
+
export const auth = createAuth({
|
|
30
|
+
adapter: createMongoAdapter(User),
|
|
31
|
+
secret: process.env.JWT_SECRET,
|
|
32
|
+
session: { enforceStrictRevocation: true } // Real-time security
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 2. Login Route (`app/api/auth/login/route.ts`)
|
|
37
|
+
```typescript
|
|
38
|
+
import { auth } from "@/lib/kroxt/auth";
|
|
39
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
40
|
+
|
|
41
|
+
export async function POST(req: NextRequest) {
|
|
42
|
+
try {
|
|
43
|
+
const { email, password } = await req.json();
|
|
44
|
+
const result = await auth.loginWithPassword(email, password, req.ip);
|
|
45
|
+
|
|
46
|
+
return NextResponse.json(result);
|
|
47
|
+
} catch (error: any) {
|
|
48
|
+
return NextResponse.json({ error: error.message }, { status: 401 });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 🏗️ Core Architecture
|
|
54
|
+
|
|
55
|
+
Kroxt is "Headless." It provides the **Brain** (Logic, Hashing, JWTs, Security) while you provide the **Face** (UI/Routes).
|
|
56
|
+
|
|
57
|
+
### 1. The Configuration Matrix
|
|
58
|
+
Every feature in Kroxt is modular. Toggle security layers with a single boolean.
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { createAuth } from "kroxt";
|
|
62
|
+
import { createMongoAdapter } from "kroxt/adapters/mongoose";
|
|
63
|
+
|
|
64
|
+
export const auth = createAuth({
|
|
65
|
+
adapter: createMongoAdapter(UserModel),
|
|
66
|
+
secret: process.env.JWT_SECRET,
|
|
67
|
+
|
|
68
|
+
// Security Layer 1: Sessions
|
|
69
|
+
session: {
|
|
70
|
+
expires: "15m", // Access Token duration
|
|
71
|
+
refreshExpires: "7d", // Refresh Token duration
|
|
72
|
+
enforceStrictRevocation: true, // DB-lookup on EVERY request (Admin-mode)
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// Security Layer 2: Defense
|
|
76
|
+
rateLimit: {
|
|
77
|
+
max: 100, // Requests per window
|
|
78
|
+
windowMs: 60 * 1000 // 1 Minute window
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
// Security Layer 3: Brute Force
|
|
82
|
+
ipBlocking: {
|
|
83
|
+
maxStrikes: 5, // Ban after 5 failures
|
|
84
|
+
blockDurationMs: 15 * 60 * 1000 // 15 Min ban
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
// Security Layer 4: Crypto
|
|
88
|
+
passwordPolicy: {
|
|
89
|
+
minLength: 8,
|
|
90
|
+
requireUppercase: true,
|
|
91
|
+
requireSpecialCharacter: true,
|
|
92
|
+
usePepper: true // Requires JWT_PEPPER env variable
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🔌 Universal Adapters
|
|
100
|
+
|
|
101
|
+
Bring your own schema. Kroxt adapts to you.
|
|
102
|
+
|
|
103
|
+
### Mongoose (MongoDB)
|
|
104
|
+
```typescript
|
|
105
|
+
import { createMongoAdapter } from "kroxt/adapters/mongoose";
|
|
106
|
+
const adapter = createMongoAdapter(User);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Prisma (SQL)
|
|
110
|
+
```typescript
|
|
111
|
+
import { createPrismaAdapter } from "kroxt/adapters/prisma";
|
|
112
|
+
const adapter = createPrismaAdapter(prisma.user);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Drizzle (SQL)
|
|
116
|
+
```typescript
|
|
117
|
+
import { createDrizzleAdapter } from "kroxt/adapters/drizzle";
|
|
118
|
+
import { eq } from "drizzle-orm";
|
|
119
|
+
const adapter = createDrizzleAdapter(db, users, eq);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Memory (Testing)
|
|
123
|
+
```typescript
|
|
124
|
+
import { createMemoryAdapter } from "kroxt";
|
|
125
|
+
const adapter = createMemoryAdapter();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 🧠 API Reference
|
|
131
|
+
|
|
132
|
+
### `auth.signup(userData, password)`
|
|
133
|
+
Registers a new user. User data is strictly typed to your schema.
|
|
134
|
+
```typescript
|
|
135
|
+
const { user, accessToken, refreshToken } = await auth.signup({
|
|
136
|
+
email: "dev@kroxt.io",
|
|
137
|
+
role: "admin"
|
|
138
|
+
}, "secure_password");
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `auth.loginWithPassword(email, password, clientIp?)`
|
|
142
|
+
Authenticates a user and generates tokens. Pass `clientIp` to enable IP-Blocking.
|
|
143
|
+
```typescript
|
|
144
|
+
const result = await auth.loginWithPassword(email, password, req.ip);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### `auth.refreshSession(refreshToken, clientIp?)`
|
|
148
|
+
Rotates the session. If `enforceStrictRevocation` is on, it validates the token against the user's current password hash.
|
|
149
|
+
```typescript
|
|
150
|
+
const { user, accessToken, refreshToken: newRefresh } = await auth.refreshSession(token);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `auth.logout(userId)`
|
|
154
|
+
Terminates all active sessions for a user globally. This increments the `sessionVersion` in the database, invalidating all current tokens instantly.
|
|
155
|
+
```typescript
|
|
156
|
+
await auth.logout(payload.sub);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `auth.changePassword(userId, newPassword)`
|
|
160
|
+
Updates password and **instantly invalidates all other active sessions** globally via Hash-Linked revocation.
|
|
161
|
+
```typescript
|
|
162
|
+
await auth.changePassword(payload.sub, "new_secure_pass");
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 🧩 Middleware Implementation
|
|
168
|
+
|
|
169
|
+
### Express / Fastify
|
|
170
|
+
```typescript
|
|
171
|
+
const protect = async (req, res, next) => {
|
|
172
|
+
const token = req.headers.authorization?.split(" ")[1];
|
|
173
|
+
try {
|
|
174
|
+
const session = await auth.verifyAccessToken(token);
|
|
175
|
+
req.user = session.user;
|
|
176
|
+
next();
|
|
177
|
+
} catch (err) {
|
|
178
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 🚀 Advanced Deployment
|
|
186
|
+
|
|
187
|
+
### Custom JWT Payloads
|
|
188
|
+
Inject metadata into your tokens safely.
|
|
189
|
+
```typescript
|
|
190
|
+
jwt: {
|
|
191
|
+
payload: (user, type) => {
|
|
192
|
+
return type === "access" ? { role: user.role } : {};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Password Peppering
|
|
198
|
+
Kroxt supports server-side peppering to protect against rainbow table attacks even if your database is leaked.
|
|
199
|
+
1. Set `usePepper: true` in config.
|
|
200
|
+
2. Add `JWT_PEPPER` to your `.env`.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 🧠 API Reference (Exhaustive)
|
|
205
|
+
|
|
206
|
+
### `auth.signup()`
|
|
207
|
+
| Argument | Type | Description |
|
|
208
|
+
| --- | --- | --- |
|
|
209
|
+
| `userData` | `Omit<User, "id">` | Your user object without the ID (ID is auto-generated) |
|
|
210
|
+
| `password` | `string` (Optional) | Plain text password. Will be hashed using Argon2 |
|
|
211
|
+
|
|
212
|
+
### `auth.loginWithPassword()`
|
|
213
|
+
| Argument | Type | Description |
|
|
214
|
+
| --- | --- | --- |
|
|
215
|
+
| `email` | `string` | User email |
|
|
216
|
+
| `password` | `string` | User password |
|
|
217
|
+
| `clientIp` | `string` (Optional) | Required for IP-Blocking defense |
|
|
218
|
+
|
|
219
|
+
### `auth.logout()`
|
|
220
|
+
| Argument | Type | Description |
|
|
221
|
+
| --- | --- | --- |
|
|
222
|
+
| `userId` | `string` | The ID of the user whose sessions will be revoked |
|
|
223
|
+
|
|
224
|
+
> [!IMPORTANT]
|
|
225
|
+
> **Global Session Revocation**: Kroxt uses a `sessionVersion` counter. When `logout` is called, this counter increments in the database. Any token presented with an older version will be rejected during verification if `enforceStrictRevocation` is enabled or during session refreshes.
|
|
226
|
+
|
|
227
|
+
### `auth.changePassword()`
|
|
228
|
+
| Argument | Type | Description |
|
|
229
|
+
| --- | --- | --- |
|
|
230
|
+
| `userId` | `string` | The ID of the user to update |
|
|
231
|
+
| `newPassword` | `string` | The new plain text password |
|
|
232
|
+
|
|
233
|
+
> [!TIP]
|
|
234
|
+
> **Hash-Linked Revocation**: When you call `changePassword`, all existing refresh tokens for that user are immediately invalidated because they contain a fragment of the old password hash (`pw_frag`).
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 🚦 Error Handling
|
|
239
|
+
|
|
240
|
+
Kroxt throws descriptive errors that you can catch in your controller.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
try {
|
|
244
|
+
await auth.loginWithPassword(email, password, req.ip);
|
|
245
|
+
} catch (err) {
|
|
246
|
+
if (err.message === "IP is temporarily blocked.") {
|
|
247
|
+
return res.status(403).send("Banned.");
|
|
248
|
+
}
|
|
249
|
+
if (err.message === "Too many requests, please try again later.") {
|
|
250
|
+
return res.status(429).send("Slow down.");
|
|
251
|
+
}
|
|
252
|
+
return res.status(401).send("Invalid Credentials");
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 🔒 Security Best Practices
|
|
259
|
+
|
|
260
|
+
1. **Environmental Pepper**: Always use `JWT_PEPPER`. This adds a server-side secret to every password hash. If your database is stolen, your user passwords are still protected by this environment variable.
|
|
261
|
+
2. **Strict Revocation**: Set `enforceStrictRevocation: true` for high-security areas (like admin panels). This forces a database lookup on every single request to ensure the user hasn't been banned or changed their password in the last few seconds.
|
|
262
|
+
3. **Dual Tokens**: Always use the provided `accessToken` for short-term API access and the `refreshToken` (stored in an `HttpOnly` cookie) for session persistence.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## 🔗 Ecosystem
|
|
267
|
+
- [Kroxt Examples Repository](https://github.com/adepoju-oluwatobi/kroxt-examples)
|
|
268
|
+
|
|
269
|
+
## 📄 License
|
|
270
|
+
MIT © [Adepoju Oluwatobi](https://github.com/adepoju-oluwatobi)
|
|
@@ -45,6 +45,11 @@ function createDrizzleAdapter(db, table, eq, rateLimitTable) {
|
|
|
45
45
|
oauthProvider: provider,
|
|
46
46
|
oauthId: providerId
|
|
47
47
|
}).where(eq(table.id, userId));
|
|
48
|
+
},
|
|
49
|
+
async invalidateSession(userId) {
|
|
50
|
+
await db.update(table).set({
|
|
51
|
+
sessionVersion: (table.sessionVersion || 0) + 1
|
|
52
|
+
}).where(eq(table.id, userId));
|
|
48
53
|
}
|
|
49
54
|
};
|
|
50
55
|
if (rateLimitTable) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/auth/adapters/drizzle.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a Drizzle ORM adapter.\r\n * \r\n * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)\r\n * by using the standard drizzle-orm `db` instance and table definition.\r\n * \r\n * @param db - The Drizzle database instance.\r\n * @param table - The Drizzle table representing users.\r\n * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).\r\n * @param rateLimitTable - Optional Drizzle table for rate limiting tracking.\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createDrizzleAdapter<TUser extends User = User>(\r\n db: any,\r\n table: any,\r\n eq: any,\r\n rateLimitTable?: any\r\n): AuthAdapter<TUser> {\r\n const adapter: AuthAdapter<TUser> = {\r\n async createUser(data: any) {\r\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\r\n const results = await db.insert(table).values(dataToSave).returning();\r\n return results[0] as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const results = await db.select().from(table).where(eq(table.email, email)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const results = await db.select().from(table).where(eq(table.id, id)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async updateUser(id: string, data: Partial<TUser>) {\r\n const results = await db.update(table).set(data).where(eq(table.id, id)).returning();\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await db.update(table)\r\n .set({\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n })\r\n .where(eq(table.id, userId));\r\n },\r\n };\r\n\r\n if (rateLimitTable) {\r\n adapter.incrementRateLimit = async (key: string, windowMs: number) => {\r\n const now = Date.now();\r\n const resetTime = now + windowMs;\r\n \r\n let records = await db.select().from(rateLimitTable).where(eq(rateLimitTable.key, key)).limit(1);\r\n let record = records[0];\r\n \r\n if (!record || now > record.resetTime) {\r\n if (record) {\r\n await db.update(rateLimitTable).set({ count: 1, resetTime }).where(eq(rateLimitTable.key, key));\r\n } else {\r\n await db.insert(rateLimitTable).values({ key, count: 1, resetTime });\r\n }\r\n return { count: 1, resetTime };\r\n } else {\r\n await db.update(rateLimitTable).set({ count: record.count + 1 }).where(eq(rateLimitTable.key, key));\r\n return { count: record.count + 1, resetTime: record.resetTime };\r\n }\r\n };\r\n\r\n adapter.getRateLimit = async (key: string) => {\r\n const now = Date.now();\r\n let records = await db.select().from(rateLimitTable).where(eq(rateLimitTable.key, key)).limit(1);\r\n let record = records[0];\r\n if (!record || now > record.resetTime) return null;\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n }\r\n\r\n return adapter;\r\n}\r\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAcO,SAAS,qBACd,IACA,OACA,IACA,gBACoB;AACpB,QAAM,UAA8B;AAAA,IAClC,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,UAAU,MAAM,GAAG,OAAO,KAAK,EAAE,OAAO,UAAU,EAAE,UAAU;AACpE,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,CAAC;AACnF,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC;AAC7E,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,WAAW,IAAY,MAAsB;AACjD,YAAM,UAAU,MAAM,GAAG,OAAO,KAAK,EAAE,IAAI,IAAI,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC,EAAE,UAAU;AACnF,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,GAAG,OAAO,KAAK,EAClB,IAAI;AAAA,QACH,eAAe;AAAA,QACf,SAAS;AAAA,MACX,CAAC,EACA,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,gBAAgB;AAClB,YAAQ,qBAAqB,OAAO,KAAa,aAAqB;AACpE,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,YAAY,MAAM;AAExB,UAAI,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,GAAG,eAAe,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC;AAC/F,UAAI,SAAS,QAAQ,CAAC;AAEtB,UAAI,CAAC,UAAU,MAAM,OAAO,WAAW;AACnC,YAAI,QAAQ;AACR,gBAAM,GAAG,OAAO,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,KAAK,GAAG,CAAC;AAAA,QAClG,OAAO;AACH,gBAAM,GAAG,OAAO,cAAc,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,UAAU,CAAC;AAAA,QACvE;AACA,eAAO,EAAE,OAAO,GAAG,UAAU;AAAA,MACjC,OAAO;AACH,cAAM,GAAG,OAAO,cAAc,EAAE,IAAI,EAAE,OAAO,OAAO,QAAQ,EAAE,CAAC,EAAE,MAAM,GAAG,eAAe,KAAK,GAAG,CAAC;AAClG,eAAO,EAAE,OAAO,OAAO,QAAQ,GAAG,WAAW,OAAO,UAAU;AAAA,MAClE;AAAA,IACF;AAEA,YAAQ,eAAe,OAAO,QAAgB;AAC5C,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,GAAG,eAAe,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC;AAC/F,UAAI,SAAS,QAAQ,CAAC;AACtB,UAAI,CAAC,UAAU,MAAM,OAAO,UAAW,QAAO;AAC9C,aAAO,EAAE,OAAO,OAAO,OAAO,WAAW,OAAO,UAAU;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
4
|
+
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a Drizzle ORM adapter.\r\n * \r\n * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)\r\n * by using the standard drizzle-orm `db` instance and table definition.\r\n * \r\n * @param db - The Drizzle database instance.\r\n * @param table - The Drizzle table representing users.\r\n * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).\r\n * @param rateLimitTable - Optional Drizzle table for rate limiting tracking.\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createDrizzleAdapter<TUser extends User = User>(\r\n db: any,\r\n table: any,\r\n eq: any,\r\n rateLimitTable?: any\r\n): AuthAdapter<TUser> {\r\n const adapter: AuthAdapter<TUser> = {\r\n async createUser(data: any) {\r\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\r\n const results = await db.insert(table).values(dataToSave).returning();\r\n return results[0] as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const results = await db.select().from(table).where(eq(table.email, email)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const results = await db.select().from(table).where(eq(table.id, id)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async updateUser(id: string, data: Partial<TUser>) {\r\n const results = await db.update(table).set(data).where(eq(table.id, id)).returning();\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await db.update(table)\r\n .set({\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n })\r\n .where(eq(table.id, userId));\r\n },\r\n\r\n async invalidateSession(userId: string) {\r\n await db.update(table)\r\n .set({\r\n sessionVersion: (table.sessionVersion || 0) + 1,\r\n })\r\n .where(eq(table.id, userId));\r\n },\r\n };\r\n\r\n if (rateLimitTable) {\r\n adapter.incrementRateLimit = async (key: string, windowMs: number) => {\r\n const now = Date.now();\r\n const resetTime = now + windowMs;\r\n \r\n let records = await db.select().from(rateLimitTable).where(eq(rateLimitTable.key, key)).limit(1);\r\n let record = records[0];\r\n \r\n if (!record || now > record.resetTime) {\r\n if (record) {\r\n await db.update(rateLimitTable).set({ count: 1, resetTime }).where(eq(rateLimitTable.key, key));\r\n } else {\r\n await db.insert(rateLimitTable).values({ key, count: 1, resetTime });\r\n }\r\n return { count: 1, resetTime };\r\n } else {\r\n await db.update(rateLimitTable).set({ count: record.count + 1 }).where(eq(rateLimitTable.key, key));\r\n return { count: record.count + 1, resetTime: record.resetTime };\r\n }\r\n };\r\n\r\n adapter.getRateLimit = async (key: string) => {\r\n const now = Date.now();\r\n let records = await db.select().from(rateLimitTable).where(eq(rateLimitTable.key, key)).limit(1);\r\n let record = records[0];\r\n if (!record || now > record.resetTime) return null;\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n }\r\n\r\n return adapter;\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle.d.ts","sourceRoot":"","sources":["../../../src/auth/adapters/drizzle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,SAAS,IAAI,GAAG,IAAI,EAC5D,EAAE,EAAE,GAAG,EACP,KAAK,EAAE,GAAG,EACV,EAAE,EAAE,GAAG,EACP,cAAc,CAAC,EAAE,GAAG,GACnB,WAAW,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"drizzle.d.ts","sourceRoot":"","sources":["../../../src/auth/adapters/drizzle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,SAAS,IAAI,GAAG,IAAI,EAC5D,EAAE,EAAE,GAAG,EACP,KAAK,EAAE,GAAG,EACV,EAAE,EAAE,GAAG,EACP,cAAc,CAAC,EAAE,GAAG,GACnB,WAAW,CAAC,KAAK,CAAC,CAwEpB"}
|
|
@@ -22,6 +22,11 @@ function createDrizzleAdapter(db, table, eq, rateLimitTable) {
|
|
|
22
22
|
oauthProvider: provider,
|
|
23
23
|
oauthId: providerId
|
|
24
24
|
}).where(eq(table.id, userId));
|
|
25
|
+
},
|
|
26
|
+
async invalidateSession(userId) {
|
|
27
|
+
await db.update(table).set({
|
|
28
|
+
sessionVersion: (table.sessionVersion || 0) + 1
|
|
29
|
+
}).where(eq(table.id, userId));
|
|
25
30
|
}
|
|
26
31
|
};
|
|
27
32
|
if (rateLimitTable) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/auth/adapters/drizzle.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a Drizzle ORM adapter.\r\n * \r\n * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)\r\n * by using the standard drizzle-orm `db` instance and table definition.\r\n * \r\n * @param db - The Drizzle database instance.\r\n * @param table - The Drizzle table representing users.\r\n * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).\r\n * @param rateLimitTable - Optional Drizzle table for rate limiting tracking.\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createDrizzleAdapter<TUser extends User = User>(\r\n db: any,\r\n table: any,\r\n eq: any,\r\n rateLimitTable?: any\r\n): AuthAdapter<TUser> {\r\n const adapter: AuthAdapter<TUser> = {\r\n async createUser(data: any) {\r\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\r\n const results = await db.insert(table).values(dataToSave).returning();\r\n return results[0] as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const results = await db.select().from(table).where(eq(table.email, email)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const results = await db.select().from(table).where(eq(table.id, id)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async updateUser(id: string, data: Partial<TUser>) {\r\n const results = await db.update(table).set(data).where(eq(table.id, id)).returning();\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await db.update(table)\r\n .set({\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n })\r\n .where(eq(table.id, userId));\r\n },\r\n };\r\n\r\n if (rateLimitTable) {\r\n adapter.incrementRateLimit = async (key: string, windowMs: number) => {\r\n const now = Date.now();\r\n const resetTime = now + windowMs;\r\n \r\n let records = await db.select().from(rateLimitTable).where(eq(rateLimitTable.key, key)).limit(1);\r\n let record = records[0];\r\n \r\n if (!record || now > record.resetTime) {\r\n if (record) {\r\n await db.update(rateLimitTable).set({ count: 1, resetTime }).where(eq(rateLimitTable.key, key));\r\n } else {\r\n await db.insert(rateLimitTable).values({ key, count: 1, resetTime });\r\n }\r\n return { count: 1, resetTime };\r\n } else {\r\n await db.update(rateLimitTable).set({ count: record.count + 1 }).where(eq(rateLimitTable.key, key));\r\n return { count: record.count + 1, resetTime: record.resetTime };\r\n }\r\n };\r\n\r\n adapter.getRateLimit = async (key: string) => {\r\n const now = Date.now();\r\n let records = await db.select().from(rateLimitTable).where(eq(rateLimitTable.key, key)).limit(1);\r\n let record = records[0];\r\n if (!record || now > record.resetTime) return null;\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n }\r\n\r\n return adapter;\r\n}\r\n"],
|
|
5
|
-
"mappings": "AAcO,SAAS,qBACd,IACA,OACA,IACA,gBACoB;AACpB,QAAM,UAA8B;AAAA,IAClC,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,UAAU,MAAM,GAAG,OAAO,KAAK,EAAE,OAAO,UAAU,EAAE,UAAU;AACpE,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,CAAC;AACnF,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC;AAC7E,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,WAAW,IAAY,MAAsB;AACjD,YAAM,UAAU,MAAM,GAAG,OAAO,KAAK,EAAE,IAAI,IAAI,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC,EAAE,UAAU;AACnF,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,GAAG,OAAO,KAAK,EAClB,IAAI;AAAA,QACH,eAAe;AAAA,QACf,SAAS;AAAA,MACX,CAAC,EACA,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,gBAAgB;AAClB,YAAQ,qBAAqB,OAAO,KAAa,aAAqB;AACpE,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,YAAY,MAAM;AAExB,UAAI,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,GAAG,eAAe,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC;AAC/F,UAAI,SAAS,QAAQ,CAAC;AAEtB,UAAI,CAAC,UAAU,MAAM,OAAO,WAAW;AACnC,YAAI,QAAQ;AACR,gBAAM,GAAG,OAAO,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,KAAK,GAAG,CAAC;AAAA,QAClG,OAAO;AACH,gBAAM,GAAG,OAAO,cAAc,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,UAAU,CAAC;AAAA,QACvE;AACA,eAAO,EAAE,OAAO,GAAG,UAAU;AAAA,MACjC,OAAO;AACH,cAAM,GAAG,OAAO,cAAc,EAAE,IAAI,EAAE,OAAO,OAAO,QAAQ,EAAE,CAAC,EAAE,MAAM,GAAG,eAAe,KAAK,GAAG,CAAC;AAClG,eAAO,EAAE,OAAO,OAAO,QAAQ,GAAG,WAAW,OAAO,UAAU;AAAA,MAClE;AAAA,IACF;AAEA,YAAQ,eAAe,OAAO,QAAgB;AAC5C,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,GAAG,eAAe,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC;AAC/F,UAAI,SAAS,QAAQ,CAAC;AACtB,UAAI,CAAC,UAAU,MAAM,OAAO,UAAW,QAAO;AAC9C,aAAO,EAAE,OAAO,OAAO,OAAO,WAAW,OAAO,UAAU;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
4
|
+
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a Drizzle ORM adapter.\r\n * \r\n * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)\r\n * by using the standard drizzle-orm `db` instance and table definition.\r\n * \r\n * @param db - The Drizzle database instance.\r\n * @param table - The Drizzle table representing users.\r\n * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).\r\n * @param rateLimitTable - Optional Drizzle table for rate limiting tracking.\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createDrizzleAdapter<TUser extends User = User>(\r\n db: any,\r\n table: any,\r\n eq: any,\r\n rateLimitTable?: any\r\n): AuthAdapter<TUser> {\r\n const adapter: AuthAdapter<TUser> = {\r\n async createUser(data: any) {\r\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\r\n const results = await db.insert(table).values(dataToSave).returning();\r\n return results[0] as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const results = await db.select().from(table).where(eq(table.email, email)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const results = await db.select().from(table).where(eq(table.id, id)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async updateUser(id: string, data: Partial<TUser>) {\r\n const results = await db.update(table).set(data).where(eq(table.id, id)).returning();\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await db.update(table)\r\n .set({\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n })\r\n .where(eq(table.id, userId));\r\n },\r\n\r\n async invalidateSession(userId: string) {\r\n await db.update(table)\r\n .set({\r\n sessionVersion: (table.sessionVersion || 0) + 1,\r\n })\r\n .where(eq(table.id, userId));\r\n },\r\n };\r\n\r\n if (rateLimitTable) {\r\n adapter.incrementRateLimit = async (key: string, windowMs: number) => {\r\n const now = Date.now();\r\n const resetTime = now + windowMs;\r\n \r\n let records = await db.select().from(rateLimitTable).where(eq(rateLimitTable.key, key)).limit(1);\r\n let record = records[0];\r\n \r\n if (!record || now > record.resetTime) {\r\n if (record) {\r\n await db.update(rateLimitTable).set({ count: 1, resetTime }).where(eq(rateLimitTable.key, key));\r\n } else {\r\n await db.insert(rateLimitTable).values({ key, count: 1, resetTime });\r\n }\r\n return { count: 1, resetTime };\r\n } else {\r\n await db.update(rateLimitTable).set({ count: record.count + 1 }).where(eq(rateLimitTable.key, key));\r\n return { count: record.count + 1, resetTime: record.resetTime };\r\n }\r\n };\r\n\r\n adapter.getRateLimit = async (key: string) => {\r\n const now = Date.now();\r\n let records = await db.select().from(rateLimitTable).where(eq(rateLimitTable.key, key)).limit(1);\r\n let record = records[0];\r\n if (!record || now > record.resetTime) return null;\r\n return { count: record.count, resetTime: record.resetTime };\r\n };\r\n }\r\n\r\n return adapter;\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/auth/adapters/index.ts"],
|
|
4
|
-
"sourcesContent": ["export interface BaseUser {\r\n id: string;\r\n email: string;\r\n passwordHash?: string;\r\n role?: string;\r\n}\r\n\r\n// Allows any extended fields natively (like nin, bvn, maritalStatus, etc.)\r\nexport type User<TExtended = Record<string, any>> = BaseUser & TExtended;\r\n\r\nexport interface AuthAdapter<TUser = User> {\r\n createUser: (data: any) => Promise<TUser>;\r\n findUserByEmail: (email: string) => Promise<TUser | null>;\r\n findUserById: (id: string) => Promise<TUser | null>;\r\n updateUser?: (id: string, data: Partial<TUser>) => Promise<TUser | null>;\r\n linkOAuthAccount: (userId: string, provider: string, providerId: string) => Promise<void>;\r\n incrementRateLimit?: (key: string, windowMs: number) => Promise<{ count: number; resetTime: number }>;\r\n getRateLimit?: (key: string) => Promise<{ count: number; resetTime: number } | null>;\r\n}\r\n"],
|
|
4
|
+
"sourcesContent": ["export interface BaseUser {\r\n id: string;\r\n email: string;\r\n passwordHash?: string;\r\n role?: string;\r\n sessionVersion?: number;\r\n}\r\n\r\n// Allows any extended fields natively (like nin, bvn, maritalStatus, etc.)\r\nexport type User<TExtended = Record<string, any>> = BaseUser & TExtended;\r\n\r\nexport interface AuthAdapter<TUser = User> {\r\n createUser: (data: any) => Promise<TUser>;\r\n findUserByEmail: (email: string) => Promise<TUser | null>;\r\n findUserById: (id: string) => Promise<TUser | null>;\r\n updateUser?: (id: string, data: Partial<TUser>) => Promise<TUser | null>;\r\n linkOAuthAccount: (userId: string, provider: string, providerId: string) => Promise<void>;\r\n incrementRateLimit?: (key: string, windowMs: number) => Promise<{ count: number; resetTime: number }>;\r\n getRateLimit?: (key: string) => Promise<{ count: number; resetTime: number } | null>;\r\n invalidateSession?: (userId: string) => Promise<void>;\r\n}\r\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,6 +3,7 @@ export interface BaseUser {
|
|
|
3
3
|
email: string;
|
|
4
4
|
passwordHash?: string;
|
|
5
5
|
role?: string;
|
|
6
|
+
sessionVersion?: number;
|
|
6
7
|
}
|
|
7
8
|
export type User<TExtended = Record<string, any>> = BaseUser & TExtended;
|
|
8
9
|
export interface AuthAdapter<TUser = User> {
|
|
@@ -19,5 +20,6 @@ export interface AuthAdapter<TUser = User> {
|
|
|
19
20
|
count: number;
|
|
20
21
|
resetTime: number;
|
|
21
22
|
} | null>;
|
|
23
|
+
invalidateSession?: (userId: string) => Promise<void>;
|
|
22
24
|
}
|
|
23
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/adapters/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/adapters/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,QAAQ,GAAG,SAAS,CAAC;AAEzE,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,IAAI;IACvC,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC1D,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACpD,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACzE,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1F,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtG,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACrF,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD"}
|