sentri 1.0.5 → 1.1.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 (48) hide show
  1. package/README.md +182 -46
  2. package/dist/client.d.ts +43 -82
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +0 -7
  5. package/dist/client.js.map +1 -1
  6. package/dist/errors/AuthError.d.ts +9 -8
  7. package/dist/errors/AuthError.d.ts.map +1 -1
  8. package/dist/errors/AuthError.js +9 -8
  9. package/dist/errors/AuthError.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/libs/config.d.ts +45 -1
  14. package/dist/libs/config.d.ts.map +1 -1
  15. package/dist/libs/config.js +40 -2
  16. package/dist/libs/config.js.map +1 -1
  17. package/dist/libs/hash.d.ts +14 -0
  18. package/dist/libs/hash.d.ts.map +1 -1
  19. package/dist/libs/hash.js +14 -0
  20. package/dist/libs/hash.js.map +1 -1
  21. package/dist/libs/token.d.ts +40 -2
  22. package/dist/libs/token.d.ts.map +1 -1
  23. package/dist/libs/token.js +64 -0
  24. package/dist/libs/token.js.map +1 -1
  25. package/dist/middleware/authorize.d.ts +15 -0
  26. package/dist/middleware/authorize.d.ts.map +1 -1
  27. package/dist/middleware/authorize.js +15 -0
  28. package/dist/middleware/authorize.js.map +1 -1
  29. package/dist/middleware/protect.d.ts +27 -0
  30. package/dist/middleware/protect.d.ts.map +1 -1
  31. package/dist/middleware/protect.js +37 -2
  32. package/dist/middleware/protect.js.map +1 -1
  33. package/dist/middleware/router.d.ts +13 -6
  34. package/dist/middleware/router.d.ts.map +1 -1
  35. package/dist/middleware/router.js +49 -15
  36. package/dist/middleware/router.js.map +1 -1
  37. package/dist/services/auth.d.ts +77 -0
  38. package/dist/services/auth.d.ts.map +1 -1
  39. package/dist/services/auth.js +81 -2
  40. package/dist/services/auth.js.map +1 -1
  41. package/dist/types/auth.d.ts +189 -3
  42. package/dist/types/auth.d.ts.map +1 -1
  43. package/dist/types/auth.js.map +1 -1
  44. package/package.json +15 -4
  45. package/templates/drizzle/adapter.ts +3 -9
  46. package/templates/drizzle/auth.ts +20 -0
  47. package/templates/prisma/adapter.ts +3 -9
  48. package/templates/prisma/auth.ts +20 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # sentri
2
2
 
3
- Auth and authorization library for Express + PostgreSQL. Provides JWT-based authentication with refresh token rotation, role-based access control, fine-grained permission checks, and a pre-built Express router — all behind a single typed client.
3
+ Auth and authorization library for Express + PostgreSQL. Provides JWT-based authentication with session-bound access tokens, refresh token rotation, role-based access control, fine-grained permission checks, and a pre-built Express router — all behind a single typed client.
4
4
 
5
5
  ---
6
6
 
@@ -10,6 +10,7 @@ Auth and authorization library for Express + PostgreSQL. Provides JWT-based auth
10
10
  - [Quick Start](#quick-start)
11
11
  - [CLI](#cli)
12
12
  - [Configuration](#configuration)
13
+ - [Custom Route Handlers](#custom-route-handlers)
13
14
  - [Adapter Interface](#adapter-interface)
14
15
  - [Pre-built Router](#pre-built-router)
15
16
  - [Middleware](#middleware)
@@ -98,7 +99,7 @@ npx sentri generate drizzle
98
99
  import { createAuth } from 'sentri';
99
100
 
100
101
  export const auth = createAuth({
101
- secret: process.env.JWT_SECRET!, // required — keep in env
102
+ secret: process.env.JWT_SECRET!, // required — keep in env, min 32 chars
102
103
  validRoles: ['user', 'admin'] as const, // required — use `as const` for type safety
103
104
  adapter: myAdapter, // required — see Adapter Interface
104
105
 
@@ -108,6 +109,10 @@ export const auth = createAuth({
108
109
  algorithm: 'HS256', // default: 'HS256' — also 'HS384' | 'HS512'
109
110
  saltRounds: 12, // default: 12 (bcrypt rounds, min 10)
110
111
 
112
+ // Restrict POST /register to callers that supply X-Api-Key header.
113
+ // When set, only requests with this exact key can create new accounts.
114
+ apiKey: process.env.REGISTER_API_KEY, // optional
115
+
111
116
  cookie: { // optional — enables httpOnly cookie for refresh token
112
117
  secure: process.env.NODE_ENV === 'production',
113
118
  // name: 'refresh_token', // default: 'refresh_token'
@@ -115,6 +120,15 @@ export const auth = createAuth({
115
120
  // sameSite: 'strict', // default: 'strict'
116
121
  // path: '/', // default: '/'
117
122
  },
123
+
124
+ // router: { // optional — replace built-in service logic per route
125
+ // login: async (input) => { ... },
126
+ // register: async (input) => { ... },
127
+ // refresh: async (refreshToken) => { ... },
128
+ // logout: async (refreshToken) => { ... },
129
+ // logoutAll: async (userId) => { ... },
130
+ // assignRoles: async (userId, roles) => { ... },
131
+ // },
118
132
  });
119
133
  ```
120
134
 
@@ -124,6 +138,111 @@ When `cookie` is configured, the refresh token is stored in an httpOnly cookie a
124
138
 
125
139
  ---
126
140
 
141
+ ## apiKey — Restricting Registration
142
+
143
+ By default `POST /register` is open to the public. This can be a security risk when your application allows role selection at registration time — any caller could register themselves as `admin`.
144
+
145
+ Set `apiKey` in your config to lock the endpoint:
146
+
147
+ ```typescript
148
+ export const auth = createAuth({
149
+ // ...
150
+ apiKey: process.env.REGISTER_API_KEY!,
151
+ });
152
+ ```
153
+
154
+ Requests to `POST /register` must then include the header:
155
+
156
+ ```
157
+ X-Api-Key: <value of REGISTER_API_KEY>
158
+ ```
159
+
160
+ Requests without the header, or with the wrong value, receive HTTP 401 `UNAUTHORIZED`. Keep the API key in an environment variable and share it only with trusted services (your back-office panel, CI scripts, etc.).
161
+
162
+ ---
163
+
164
+ ## Session-Bound Access Tokens
165
+
166
+ Since version 1.1.0, access tokens embed the `sessionId` of the session that was created at login. The `protect()` middleware validates this session against the database on every request.
167
+
168
+ **What this means in practice:**
169
+
170
+ - `POST /logout` deletes the session. Any access token issued during that login is immediately rejected — even if it has not expired yet.
171
+ - `POST /logout-all` deletes **all** sessions for the user. Every access token across all devices is immediately rejected.
172
+ - Tokens issued before 1.1.0 (without the `sessionId` claim) are still accepted but bypass session validation — plan a rolling upgrade if you need strict enforcement for existing tokens.
173
+
174
+ ```
175
+ Login → session created → access token embeds sessionId
176
+ Request → protect() verifies JWT → checks session exists → ✓ allowed
177
+ Logout → session deleted
178
+ Request → protect() verifies JWT → session not found → ✗ 401 UNAUTHORIZED
179
+ ```
180
+
181
+ > **Trade-off:** `protect()` now performs one additional database read per request. For most applications this is negligible. If you need to avoid any per-request DB access, keep `accessExpiresIn` short (e.g. `'5m'`) and rely on token expiry instead — but note that tokens will remain valid for up to `accessExpiresIn` after logout.
182
+
183
+ ---
184
+
185
+ ## Custom Route Handlers
186
+
187
+ The `router` field in config lets you replace the built-in service logic for individual routes while the router still handles request parsing, input validation, and response formatting.
188
+
189
+ Each key is optional — only override what you need. Any key you omit falls back to the built-in behaviour.
190
+
191
+ ```typescript
192
+ import { createAuth, AuthError } from 'sentri';
193
+ import type { AuthResult } from 'sentri';
194
+
195
+ export const auth = createAuth({
196
+ secret: process.env.JWT_SECRET!,
197
+ validRoles: ['user', 'admin'] as const,
198
+ adapter: myAdapter,
199
+
200
+ router: {
201
+ // Add an OTP check before issuing tokens
202
+ login: async (input): Promise<AuthResult> => {
203
+ const otpVerified = await redis.get(`otp:${input.identifier}`);
204
+ if (!otpVerified) {
205
+ return { success: false, error: new AuthError('INVALID_CREDENTIALS', 'OTP required') };
206
+ }
207
+ return defaultLogin(input);
208
+ },
209
+
210
+ // Send a welcome email after registration
211
+ register: async (input) => {
212
+ const result = await defaultRegister(input);
213
+ if (result.success) {
214
+ await emailService.sendWelcome(input.identifier);
215
+ }
216
+ return result;
217
+ },
218
+
219
+ // Audit-log every token rotation
220
+ refresh: async (refreshToken) => {
221
+ const result = await defaultRefresh(refreshToken);
222
+ if (result.success) {
223
+ await auditLog.record('token_rotated', result.user.id);
224
+ }
225
+ return result;
226
+ },
227
+ },
228
+ });
229
+ ```
230
+
231
+ ### Available handler signatures
232
+
233
+ | Key | Signature | Must return |
234
+ |---|---|---|
235
+ | `register` | `(input: SignupInput) => Promise<SignupResult>` | `SignupResult` |
236
+ | `login` | `(input: LoginInput) => Promise<AuthResult>` | `AuthResult` |
237
+ | `refresh` | `(refreshToken: string) => Promise<RefreshResult>` | `RefreshResult` |
238
+ | `logout` | `(refreshToken: string \| undefined) => Promise<void>` | `void` |
239
+ | `logoutAll` | `(userId: string) => Promise<void>` | `void` |
240
+ | `assignRoles` | `(userId: string, roles: string[]) => Promise<AssignRolesResult>` | `AssignRolesResult` |
241
+
242
+ The router always validates the request body and URL parameters before calling any handler. Your function receives the already-validated, trimmed input.
243
+
244
+ ---
245
+
127
246
  ## Adapter Interface
128
247
 
129
248
  The adapter connects sentri to your database. Implement `AuthAdapter` for any ORM or data layer.
@@ -168,7 +287,7 @@ import { createAdapter } from './adapter.js';
168
287
  export const adapter = createAdapter(db);
169
288
  ```
170
289
 
171
- `createAdapter` throws an `AdapterConfigError` at runtime if called without a `db` argument.
290
+ `createAdapter` throws `AuthError` with code `CONFIGURATION_ERROR` at runtime if called without a `db` argument.
172
291
 
173
292
  ---
174
293
 
@@ -187,11 +306,12 @@ export const adapter = createAdapter(db);
187
306
 
188
307
  ### Endpoints
189
308
 
190
- #### `POST /signup`
309
+ #### `POST /register`
191
310
 
192
- Register a new user. Does **not** issue tokens — call `/login` after signup.
311
+ Register a new user. Does **not** issue tokens — call `/login` after registration.
193
312
 
194
313
  ```
314
+ Headers: X-Api-Key: <key> (required when config.apiKey is set)
195
315
  Body: { identifier, password, roles?: string[] }
196
316
  Returns: { user: { id, identifier, roles } }
197
317
  Status: 201
@@ -239,7 +359,7 @@ Returns: null
239
359
  Status: 200
240
360
  ```
241
361
 
242
- Safe to call even if the cookie is missing or the token is already expired.
362
+ After logout, any access token bound to this session is immediately rejected by `protect()`. Safe to call even if the cookie is missing or the token is already expired.
243
363
 
244
364
  ---
245
365
 
@@ -253,6 +373,8 @@ Returns: null
253
373
  Status: 200
254
374
  ```
255
375
 
376
+ All access tokens across all devices are immediately rejected by `protect()` after this call.
377
+
256
378
  ---
257
379
 
258
380
  #### `GET /me`
@@ -284,14 +406,19 @@ Status: 200
284
406
 
285
407
  ### `auth.protect()`
286
408
 
287
- Verifies the `Authorization: Bearer <token>` header and injects `req.user` into the request.
409
+ Verifies the `Authorization: Bearer <token>` header, confirms the session is still active in the database, and injects `request.user` into the request.
288
410
 
289
411
  ```typescript
290
- router.get('/dashboard', auth.protect(), (req, res) => {
291
- res.json(req.user); // { id, identifier, roles }
412
+ router.get('/dashboard', auth.protect(), (request, response) => {
413
+ response.json(request.user); // { id, identifier, roles }
292
414
  });
293
415
  ```
294
416
 
417
+ Returns HTTP 401 if:
418
+ - The `Authorization` header is missing or malformed
419
+ - The token signature is invalid or the token is expired
420
+ - The session embedded in the token has been revoked (logout)
421
+
295
422
  ---
296
423
 
297
424
  ### `auth.authorize(...roles)`
@@ -341,43 +468,21 @@ router.delete(
341
468
 
342
469
  ## Programmatic API
343
470
 
344
- All methods are available on the auth client for use outside the built-in router.
471
+ Token and password utilities are available on the auth client for use outside the built-in router.
345
472
 
346
473
  ```typescript
347
- // Auth
348
- const result = await auth.signup({ identifier: 'user@example.com', password: 'secret123' });
349
- const result = await auth.login({ identifier: 'user@example.com', password: 'secret123' });
350
- const result = await auth.refresh(refreshToken);
351
- await auth.logout(refreshToken);
352
- await auth.logoutAll(userId);
353
-
354
- // Roles
355
- const result = await auth.assignRoles(userId, ['admin']);
356
- // Merges with existing roles — result.user.roles has the full updated list
357
-
358
474
  // Token utilities
359
475
  const accessToken = auth.signAccessToken({ id, identifier, roles });
360
476
  const user = auth.verifyAccessToken(accessToken); // throws AuthError if invalid
361
477
  const { sessionId } = auth.verifyRefreshToken(token); // throws AuthError if invalid
478
+ const refreshToken = auth.signRefreshToken(sessionId);
362
479
 
363
480
  // Password utilities
364
481
  const hash = await auth.hashPassword('secret123');
365
482
  const valid = await auth.verifyPassword('secret123', hash);
366
483
  ```
367
484
 
368
- All auth methods return a discriminated union check `result.success` before accessing data:
369
-
370
- ```typescript
371
- const result = await auth.login({ identifier, password });
372
-
373
- if (!result.success) {
374
- console.error(result.error.code); // 'INVALID_CREDENTIALS'
375
- console.error(result.error.message);
376
- return;
377
- }
378
-
379
- const { accessToken, refreshToken, user } = result;
380
- ```
485
+ `verifyAccessToken` and `verifyRefreshToken` throw `AuthError` with code `TOKEN_EXPIRED` or `TOKEN_INVALID` wrap them in a try/catch or use the router which handles this automatically.
381
486
 
382
487
  ---
383
488
 
@@ -396,6 +501,7 @@ import type {
396
501
  ApiResponse,
397
502
  SignupInput,
398
503
  LoginInput,
504
+ RouterHandlers,
399
505
  UserRecord,
400
506
  SessionRecord,
401
507
  CreateUserData,
@@ -417,11 +523,11 @@ All errors thrown by the library are instances of `AuthError` with a machine-rea
417
523
  | Code | HTTP | Meaning |
418
524
  |---|---|---|
419
525
  | `INVALID_CREDENTIALS` | 401 | Wrong identifier or password |
420
- | `USER_ALREADY_EXISTS` | 409 | Signup with duplicate identifier |
526
+ | `USER_ALREADY_EXISTS` | 409 | Registration with duplicate identifier |
421
527
  | `USER_NOT_FOUND` | 404 | Operation on a non-existent user |
422
528
  | `TOKEN_EXPIRED` | 401 | JWT `exp` claim is in the past |
423
529
  | `TOKEN_INVALID` | 401 | JWT signature invalid or malformed |
424
- | `UNAUTHORIZED` | 401 | No valid access token on the request |
530
+ | `UNAUTHORIZED` | 401 | No valid access token, revoked session, or invalid API key |
425
531
  | `FORBIDDEN` | 403 | Authenticated but missing required role |
426
532
  | `INVALID_ROLE` | 400 | Role name not in `validRoles` |
427
533
  | `VALIDATION_ERROR` | 400 | Missing or invalid input field |
@@ -432,17 +538,47 @@ The built-in router converts all `AuthError` instances to the standard envelope
432
538
  ```typescript
433
539
  import { AuthError } from 'sentri';
434
540
 
435
- app.use((err, req, res, next) => {
436
- if (err instanceof AuthError) {
437
- const status =
438
- err.code === 'UNAUTHORIZED' || err.code === 'TOKEN_EXPIRED' || err.code === 'TOKEN_INVALID' || err.code === 'INVALID_CREDENTIALS' ? 401
439
- : err.code === 'FORBIDDEN' ? 403
440
- : err.code === 'USER_NOT_FOUND' ? 404
441
- : err.code === 'USER_ALREADY_EXISTS' ? 409
442
- : 400;
541
+ const AUTH_ERROR_STATUS: Record<string, number> = {
542
+ UNAUTHORIZED: 401,
543
+ TOKEN_EXPIRED: 401,
544
+ TOKEN_INVALID: 401,
545
+ INVALID_CREDENTIALS: 401,
546
+ FORBIDDEN: 403,
547
+ USER_NOT_FOUND: 404,
548
+ USER_ALREADY_EXISTS: 409,
549
+ INVALID_ROLE: 400,
550
+ VALIDATION_ERROR: 400,
551
+ CONFIGURATION_ERROR: 500,
552
+ };
443
553
 
444
- return res.status(status).json({ error: true, statusCode: status, message: err.message, data: null });
554
+ app.use((error, _request, response, next) => {
555
+ if (error instanceof AuthError) {
556
+ const statusCode = AUTH_ERROR_STATUS[error.code] ?? 500;
557
+ return response.status(statusCode).json({
558
+ error: true,
559
+ statusCode,
560
+ code: error.code,
561
+ message: error.message,
562
+ data: null,
563
+ });
445
564
  }
446
- next(err);
565
+ next(error);
447
566
  });
448
567
  ```
568
+
569
+ ---
570
+
571
+ ## Migration from 1.0.x
572
+
573
+ ### Breaking changes
574
+
575
+ | What changed | Action required |
576
+ |---|---|
577
+ | `POST /signup` renamed to `POST /register` | Update all client-side calls |
578
+ | `RouterHandlers.signup` renamed to `RouterHandlers.register` | Update config if you used a custom signup handler |
579
+ | `protect()` now performs one DB read per request | Ensure your adapter's `session.findById` is indexed on session ID |
580
+
581
+ ### New features
582
+
583
+ - **Session-bound tokens** — access tokens are immediately invalidated after logout without waiting for expiry.
584
+ - **`apiKey` config** — lock `POST /register` to trusted callers via `X-Api-Key` header.
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { PermitCheck, PermitOptions } from './middleware/permit.js';
2
- import type { AssignRolesResult, AuthConfig, AuthResult, AuthUser, LoginInput, RefreshResult, SignupInput, SignupResult } from './types/auth.js';
2
+ import type { AuthConfig, AuthUser } from './types/auth.js';
3
3
  import type { RequestHandler, Router } from 'express';
4
4
  /**
5
5
  * The bound auth client returned by {@link createAuth}.
@@ -8,61 +8,18 @@ import type { RequestHandler, Router } from 'express';
8
8
  * you never need to pass config around yourself.
9
9
  *
10
10
  * `TRole` is inferred from `validRoles` and narrows role strings to your
11
- * application's exact union type everywhere (signup, authorize, req.user, etc.).
11
+ * application's exact union type everywhere (authorize, req.user, etc.).
12
12
  */
13
13
  export interface AuthClient<TRole extends string = string> {
14
- /**
15
- * Register a new user.
16
- *
17
- * Validates that every requested role is in `validRoles`, rejects duplicate
18
- * identifiers, hashes the password, creates the user record, and returns the
19
- * created user. No tokens are issued — call `login` after signup.
20
- */
21
- signup(input: SignupInput<TRole>): Promise<SignupResult<TRole>>;
22
- /**
23
- * Authenticate an existing user by email and password.
24
- *
25
- * On success, creates a new session and returns an access + refresh token pair.
26
- * Returns `{ success: false, error }` with code `INVALID_CREDENTIALS` on any
27
- * mismatch (intentionally vague to prevent user enumeration).
28
- */
29
- login(input: LoginInput): Promise<AuthResult<TRole>>;
30
- /**
31
- * Exchange a valid refresh token for a new access + refresh token pair.
32
- *
33
- * Verifies the JWT, looks up the session in the database, checks expiry,
34
- * then **rotates** the session: the old session is deleted and a new one is
35
- * created. Old refresh tokens are immediately invalidated.
36
- */
37
- refresh(refreshToken: string): Promise<RefreshResult<TRole>>;
38
- /**
39
- * Invalidate a single session identified by the refresh token.
40
- *
41
- * Safe to call even if the token is already expired — it will simply
42
- * attempt a DB delete and resolve.
43
- */
44
- logout(refreshToken: string): Promise<void>;
45
- /**
46
- * Delete all sessions for a user, effectively logging them out of every device.
47
- *
48
- * @param userId - The user's primary key as stored in the database.
49
- */
50
- logoutAll(userId: string): Promise<void>;
51
- /**
52
- * Add roles to another user. Merges the given roles with the user's existing
53
- * roles (no duplicates). The built-in router exposes this as
54
- * `POST /users/:userId/roles` and restricts it to users with the `admin` role.
55
- */
56
- assignRoles(userId: string, roles: string[]): Promise<AssignRolesResult<TRole>>;
57
14
  /**
58
15
  * Express middleware factory that enforces authentication.
59
16
  *
60
17
  * Reads the `Authorization: Bearer <token>` header, verifies the access token,
61
- * and injects the decoded payload as `req.user`. Calls `next(AuthError)` on failure.
18
+ * and injects the decoded payload as `request.user`. Calls `next(AuthError)` on failure.
62
19
  *
63
20
  * @example
64
- * router.get('/me', auth.protect(), (req, res) => {
65
- * res.json(req.user);
21
+ * router.get('/me', auth.protect(), (request, response) => {
22
+ * response.json(request.user);
66
23
  * });
67
24
  */
68
25
  protect(): RequestHandler;
@@ -77,36 +34,6 @@ export interface AuthClient<TRole extends string = string> {
77
34
  * router.delete('/posts/:id', auth.protect(), auth.authorize('admin'), handler);
78
35
  */
79
36
  authorize(...roles: TRole[]): RequestHandler;
80
- /** Hash a plain-text password using the configured `saltRounds`. */
81
- hashPassword(plain: string): Promise<string>;
82
- /** Compare a plain-text password against a stored bcrypt hash. */
83
- verifyPassword(plain: string, hash: string): Promise<boolean>;
84
- /** Sign an access token for the given user payload. */
85
- signAccessToken(payload: AuthUser<TRole>): string;
86
- /** Sign a refresh token bound to a session ID. */
87
- signRefreshToken(sessionId: string): string;
88
- /** Verify and decode an access token. Throws `AuthError` if invalid or expired. */
89
- verifyAccessToken(token: string): AuthUser<TRole>;
90
- /** Verify and decode a refresh token. Throws `AuthError` if invalid or expired. */
91
- verifyRefreshToken(token: string): {
92
- sessionId: string;
93
- };
94
- /**
95
- * Returns a pre-built Express Router with all standard auth endpoints mounted:
96
- *
97
- * - `POST /signup` — register, returns `{ user }`
98
- * - `POST /login` — authenticate, sets refresh token cookie, returns `{ accessToken, user }`
99
- * - `POST /refresh` — reads refresh token from cookie, returns `{ accessToken }`
100
- * - `POST /logout` — invalidate current session
101
- * - `POST /logout-all` — invalidate all sessions (requires valid access token)
102
- *
103
- * Requires `express.json()` to be applied before the router.
104
- *
105
- * @example
106
- * app.use(express.json());
107
- * app.use('/auth', auth.router());
108
- */
109
- router(): Router;
110
37
  /**
111
38
  * Express middleware factory for resource-level permission checks.
112
39
  *
@@ -120,7 +47,7 @@ export interface AuthClient<TRole extends string = string> {
120
47
  * // User can only update their own profile
121
48
  * router.put('/users/:id',
122
49
  * auth.protect(),
123
- * auth.permit((req) => req.user!.id === req.params['id']),
50
+ * auth.permit((request) => request.user!.id === request.params['id']),
124
51
  * handler,
125
52
  * );
126
53
  *
@@ -130,9 +57,9 @@ export interface AuthClient<TRole extends string = string> {
130
57
  * auth.protect(),
131
58
  * auth.permit({
132
59
  * roles: ['admin'],
133
- * check: async (req) => {
134
- * const post = await db.post.findUnique({ where: { id: req.params['id'] } });
135
- * return post?.authorId === req.user!.id;
60
+ * check: async (request) => {
61
+ * const post = await db.post.findUnique({ where: { id: request.params['id'] } });
62
+ * return post?.authorId === request.user!.id;
136
63
  * },
137
64
  * }),
138
65
  * handler,
@@ -140,6 +67,40 @@ export interface AuthClient<TRole extends string = string> {
140
67
  */
141
68
  permit(check: PermitCheck): RequestHandler;
142
69
  permit(options: PermitOptions<TRole>): RequestHandler;
70
+ /** Hash a plain-text password using the configured `saltRounds`. */
71
+ hashPassword(plain: string): Promise<string>;
72
+ /** Compare a plain-text password against a stored bcrypt hash. */
73
+ verifyPassword(plain: string, hash: string): Promise<boolean>;
74
+ /** Sign an access token for the given user payload. */
75
+ signAccessToken(payload: AuthUser<TRole>): string;
76
+ /** Sign a refresh token bound to a session ID. */
77
+ signRefreshToken(sessionId: string): string;
78
+ /** Verify and decode an access token. Throws `AuthError` if invalid or expired. */
79
+ verifyAccessToken(token: string): AuthUser<TRole>;
80
+ /** Verify and decode a refresh token. Throws `AuthError` if invalid or expired. */
81
+ verifyRefreshToken(token: string): {
82
+ sessionId: string;
83
+ };
84
+ /**
85
+ * Returns a pre-built Express Router with all standard auth endpoints mounted:
86
+ *
87
+ * - `POST /register` — register a new user, returns `{ user }`.
88
+ * Requires `X-Api-Key` header when `config.apiKey` is set.
89
+ * - `POST /login` — authenticate, sets refresh token cookie, returns `{ accessToken, user }`
90
+ * - `POST /refresh` — reads refresh token from cookie, returns `{ accessToken }`
91
+ * - `POST /logout` — invalidate the current session; any access token bound to
92
+ * this session is immediately rejected by `protect()`.
93
+ * - `POST /logout-all` — invalidate all sessions for the user (requires valid access token)
94
+ * - `GET /me` — return the authenticated user
95
+ * - `POST /users/:userId/roles` — assign roles (requires admin)
96
+ *
97
+ * Requires `express.json()` to be applied before the router.
98
+ *
99
+ * @example
100
+ * app.use(express.json());
101
+ * app.use('/auth', auth.router());
102
+ */
103
+ router(): Router;
143
104
  }
144
105
  /**
145
106
  * Create a fully configured auth client for your application.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACb,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM;IACvD;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IAEhE;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAErD;;;;;;OAMG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IAE7D;;;;;OAKG;IACH,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5C;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC;;;;OAIG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IAEhF;;;;;;;;;;OAUG;IACH,OAAO,IAAI,cAAc,CAAC;IAE1B;;;;;;;;;OASG;IACH,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC;IAE7C,oEAAoE;IACpE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7C,kEAAkE;IAClE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9D,uDAAuD;IACvD,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;IAElD,kDAAkD;IAClD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5C,mFAAmF;IACnF,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElD,mFAAmF;IACnF,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAEzD;;;;;;;;;;;;;;OAcG;IACH,MAAM,IAAI,MAAM,CAAC;IAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,CAAC;IAC3C,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC;CACvD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EACtD,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,GACxB,UAAU,CAAC,KAAK,CAAC,CAsBnB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM;IACvD;;;;;;;;;;OAUG;IACH,OAAO,IAAI,cAAc,CAAC;IAE1B;;;;;;;;;OASG;IACH,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC;IAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,CAAC;IAC3C,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC;IAEtD,oEAAoE;IACpE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7C,kEAAkE;IAClE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9D,uDAAuD;IACvD,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;IAElD,kDAAkD;IAClD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5C,mFAAmF;IACnF,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElD,mFAAmF;IACnF,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAEzD;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,IAAI,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EACtD,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,GACxB,UAAU,CAAC,KAAK,CAAC,CAgBnB"}
package/dist/client.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { hashPassword, verifyPassword } from './libs/hash.js';
2
2
  import { signAccessToken, signRefreshToken, verifyAccessToken, verifyRefreshToken } from './libs/token.js';
3
3
  import { resolveConfig, validateConfig } from './libs/config.js';
4
- import { signup, login, refresh, logout, logoutAll, assignRoles } from './services/auth.js';
5
4
  import { protect } from './middleware/protect.js';
6
5
  import { authorize } from './middleware/authorize.js';
7
6
  import { permit } from './middleware/permit.js';
@@ -29,12 +28,6 @@ export function createAuth(config) {
29
28
  validateConfig(config);
30
29
  const resolved = resolveConfig(config);
31
30
  return {
32
- signup: (input) => signup(input, config),
33
- login: (input) => login(input, config),
34
- refresh: (refreshToken) => refresh(refreshToken, config),
35
- logout: (refreshToken) => logout(refreshToken, config),
36
- logoutAll: (userId) => logoutAll(userId, config),
37
- assignRoles: (userId, roles) => assignRoles(userId, roles, config),
38
31
  protect: () => protect(config),
39
32
  authorize: (...roles) => authorize(...roles),
40
33
  hashPassword: (plain) => hashPassword(plain, resolved.saltRounds),
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAwK1D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,UAAU,CACxB,MAAyB;IAEzB,cAAc,CAAC,MAAoB,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAoB,CAAC,CAAC;IAErD,OAAO;QACL,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAoB,EAAE,MAAoB,CAAiC;QACrG,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,MAAoB,CAA+B;QAClF,OAAO,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,MAAoB,CAAkC;QACvG,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,MAAoB,CAAC;QACpE,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAoB,CAAC;QAC9D,WAAW,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,MAAoB,CAAsC;QACrH,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAoB,CAAC;QAC5C,SAAS,EAAE,CAAC,GAAG,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;QAC5C,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC;QACjE,cAAc,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC;QAC5D,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,OAAmB,EAAE,MAAoB,CAAC;QACxF,gBAAgB,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAoB,CAAC;QAClF,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAoB,CAAoB;QAC/F,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAoB,CAAC;QAC9E,MAAM,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;QACtC,MAAM,EAAE,CAAC,cAAkD,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC;KACvF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAkH1D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,UAAU,CACxB,MAAyB;IAEzB,cAAc,CAAC,MAAoB,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAoB,CAAC,CAAC;IAErD,OAAO;QACL,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAoB,CAAC;QAC5C,SAAS,EAAE,CAAC,GAAG,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;QAC5C,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC;QACjE,cAAc,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC;QAC5D,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,OAAmB,EAAE,MAAoB,CAAC;QACxF,gBAAgB,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAoB,CAAC;QAClF,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAoB,CAAoB;QAC/F,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAoB,CAAC;QAC9E,MAAM,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;QACtC,MAAM,EAAE,CAAC,cAAkD,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC;KACvF,CAAC;AACJ,CAAC"}
@@ -17,19 +17,20 @@ export type AuthErrorCode = 'INVALID_CREDENTIALS' | 'USER_NOT_FOUND' | 'USER_ALR
17
17
  * Error class thrown by the library for all authentication and authorization failures.
18
18
  *
19
19
  * Carries a machine-readable `code` that lets you distinguish error types without
20
- * string-matching on the message:
20
+ * string-matching on the message.
21
21
  *
22
22
  * @example
23
- * import { AuthError } from 'rizzzdev-auth';
23
+ * import { AuthError } from 'sentri';
24
24
  *
25
- * app.use((err, req, res, next) => {
26
- * if (err instanceof AuthError) {
27
- * const status = err.code === 'UNAUTHORIZED' ? 401
28
- * : err.code === 'FORBIDDEN' ? 403
25
+ * app.use((error, _request, response, next) => {
26
+ * if (error instanceof AuthError) {
27
+ * const status =
28
+ * error.code === 'UNAUTHORIZED' ? 401
29
+ * : error.code === 'FORBIDDEN' ? 403
29
30
  * : 400;
30
- * res.status(status).json({ error: err.code, message: err.message });
31
+ * response.status(status).json({ error: error.code, message: error.message });
31
32
  * } else {
32
- * next(err);
33
+ * next(error);
33
34
  * }
34
35
  * });
35
36
  */
@@ -1 +1 @@
1
- {"version":3,"file":"AuthError.d.ts","sourceRoot":"","sources":["../../src/errors/AuthError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,aAAa,GACrB,qBAAqB,GACrB,gBAAgB,GAChB,qBAAqB,GACrB,eAAe,GACf,eAAe,GACf,WAAW,GACX,cAAc,GACd,cAAc,GACd,kBAAkB,GAClB,qBAAqB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,SAAgB,IAAI,EAAE,aAAa,CAAC;gBAExB,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM;CAKjD"}
1
+ {"version":3,"file":"AuthError.d.ts","sourceRoot":"","sources":["../../src/errors/AuthError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,aAAa,GACrB,qBAAqB,GACrB,gBAAgB,GAChB,qBAAqB,GACrB,eAAe,GACf,eAAe,GACf,WAAW,GACX,cAAc,GACd,cAAc,GACd,kBAAkB,GAClB,qBAAqB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,SAAgB,IAAI,EAAE,aAAa,CAAC;gBAExB,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM;CAKjD"}
@@ -2,19 +2,20 @@
2
2
  * Error class thrown by the library for all authentication and authorization failures.
3
3
  *
4
4
  * Carries a machine-readable `code` that lets you distinguish error types without
5
- * string-matching on the message:
5
+ * string-matching on the message.
6
6
  *
7
7
  * @example
8
- * import { AuthError } from 'rizzzdev-auth';
8
+ * import { AuthError } from 'sentri';
9
9
  *
10
- * app.use((err, req, res, next) => {
11
- * if (err instanceof AuthError) {
12
- * const status = err.code === 'UNAUTHORIZED' ? 401
13
- * : err.code === 'FORBIDDEN' ? 403
10
+ * app.use((error, _request, response, next) => {
11
+ * if (error instanceof AuthError) {
12
+ * const status =
13
+ * error.code === 'UNAUTHORIZED' ? 401
14
+ * : error.code === 'FORBIDDEN' ? 403
14
15
  * : 400;
15
- * res.status(status).json({ error: err.code, message: err.message });
16
+ * response.status(status).json({ error: error.code, message: error.message });
16
17
  * } else {
17
- * next(err);
18
+ * next(error);
18
19
  * }
19
20
  * });
20
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"AuthError.js","sourceRoot":"","sources":["../../src/errors/AuthError.ts"],"names":[],"mappings":"AA0BA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClB,IAAI,CAAgB;IAEpC,YAAY,IAAmB,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
1
+ {"version":3,"file":"AuthError.js","sourceRoot":"","sources":["../../src/errors/AuthError.ts"],"names":[],"mappings":"AA0BA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClB,IAAI,CAAgB;IAEpC,YAAY,IAAmB,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ declare global {
6
6
  }
7
7
  }
8
8
  }
9
- export type { AuthConfig, CookieConfig, AuthUser, AuthResult, SignupResult, AssignRolesResult, RefreshResult, ApiResponse, SignupInput, LoginInput, AuthAdapter, UserRecord, SessionRecord, CreateUserData, } from './types/auth.js';
9
+ export type { AuthConfig, CookieConfig, AuthUser, ApiResponse, AuthAdapter, UserRecord, SessionRecord, CreateUserData, RouterHandlers, SignupInput, LoginInput, SignupResult, AuthResult, RefreshResult, AssignRolesResult, } from './types/auth.js';
10
10
  export type { AuthErrorCode } from './errors/AuthError.js';
11
11
  export type { AuthClient } from './client.js';
12
12
  export { AuthError } from './errors/AuthError.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,QAAQ,CAAC;SACjB;KACF;CACF;AAED,YAAY,EACV,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,EACX,UAAU,EACV,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,QAAQ,CAAC;SACjB;KACF;CACF;AAED,YAAY,EACV,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,cAAc,EACd,cAAc,EACd,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}