sentri 1.0.6 → 1.1.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.
- package/README.md +107 -21
- package/dist/client.d.ts +51 -14
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3 -1
- package/dist/client.js.map +1 -1
- package/dist/errors/AuthError.d.ts +82 -21
- package/dist/errors/AuthError.d.ts.map +1 -1
- package/dist/errors/AuthError.js +87 -17
- package/dist/errors/AuthError.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/libs/token.d.ts +5 -4
- package/dist/libs/token.d.ts.map +1 -1
- package/dist/libs/token.js +3 -2
- package/dist/libs/token.js.map +1 -1
- package/dist/middleware/errorHandler.d.ts +73 -0
- package/dist/middleware/errorHandler.d.ts.map +1 -0
- package/dist/middleware/errorHandler.js +76 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/protect.d.ts +14 -4
- package/dist/middleware/protect.d.ts.map +1 -1
- package/dist/middleware/protect.js +24 -6
- package/dist/middleware/protect.js.map +1 -1
- package/dist/middleware/router.d.ts +5 -2
- package/dist/middleware/router.d.ts.map +1 -1
- package/dist/middleware/router.js +30 -8
- package/dist/middleware/router.js.map +1 -1
- package/dist/services/auth.d.ts +3 -1
- package/dist/services/auth.d.ts.map +1 -1
- package/dist/services/auth.js +7 -3
- package/dist/services/auth.js.map +1 -1
- package/dist/types/auth.d.ts +50 -8
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js.map +1 -1
- package/package.json +5 -2
- package/templates/drizzle/auth.ts +37 -2
- package/templates/prisma/auth.ts +37 -2
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
|
|
|
@@ -99,7 +99,7 @@ npx sentri generate drizzle
|
|
|
99
99
|
import { createAuth } from 'sentri';
|
|
100
100
|
|
|
101
101
|
export const auth = createAuth({
|
|
102
|
-
secret: process.env.JWT_SECRET!, // required — keep in env
|
|
102
|
+
secret: process.env.JWT_SECRET!, // required — keep in env, min 32 chars
|
|
103
103
|
validRoles: ['user', 'admin'] as const, // required — use `as const` for type safety
|
|
104
104
|
adapter: myAdapter, // required — see Adapter Interface
|
|
105
105
|
|
|
@@ -109,6 +109,10 @@ export const auth = createAuth({
|
|
|
109
109
|
algorithm: 'HS256', // default: 'HS256' — also 'HS384' | 'HS512'
|
|
110
110
|
saltRounds: 12, // default: 12 (bcrypt rounds, min 10)
|
|
111
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
|
+
|
|
112
116
|
cookie: { // optional — enables httpOnly cookie for refresh token
|
|
113
117
|
secure: process.env.NODE_ENV === 'production',
|
|
114
118
|
// name: 'refresh_token', // default: 'refresh_token'
|
|
@@ -119,7 +123,7 @@ export const auth = createAuth({
|
|
|
119
123
|
|
|
120
124
|
// router: { // optional — replace built-in service logic per route
|
|
121
125
|
// login: async (input) => { ... },
|
|
122
|
-
//
|
|
126
|
+
// register: async (input) => { ... },
|
|
123
127
|
// refresh: async (refreshToken) => { ... },
|
|
124
128
|
// logout: async (refreshToken) => { ... },
|
|
125
129
|
// logoutAll: async (userId) => { ... },
|
|
@@ -134,6 +138,50 @@ When `cookie` is configured, the refresh token is stored in an httpOnly cookie a
|
|
|
134
138
|
|
|
135
139
|
---
|
|
136
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
|
+
|
|
137
185
|
## Custom Route Handlers
|
|
138
186
|
|
|
139
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.
|
|
@@ -159,9 +207,9 @@ export const auth = createAuth({
|
|
|
159
207
|
return defaultLogin(input);
|
|
160
208
|
},
|
|
161
209
|
|
|
162
|
-
// Send a welcome email after
|
|
163
|
-
|
|
164
|
-
const result = await
|
|
210
|
+
// Send a welcome email after registration
|
|
211
|
+
register: async (input) => {
|
|
212
|
+
const result = await defaultRegister(input);
|
|
165
213
|
if (result.success) {
|
|
166
214
|
await emailService.sendWelcome(input.identifier);
|
|
167
215
|
}
|
|
@@ -184,7 +232,7 @@ export const auth = createAuth({
|
|
|
184
232
|
|
|
185
233
|
| Key | Signature | Must return |
|
|
186
234
|
|---|---|---|
|
|
187
|
-
| `
|
|
235
|
+
| `register` | `(input: SignupInput) => Promise<SignupResult>` | `SignupResult` |
|
|
188
236
|
| `login` | `(input: LoginInput) => Promise<AuthResult>` | `AuthResult` |
|
|
189
237
|
| `refresh` | `(refreshToken: string) => Promise<RefreshResult>` | `RefreshResult` |
|
|
190
238
|
| `logout` | `(refreshToken: string \| undefined) => Promise<void>` | `void` |
|
|
@@ -258,11 +306,12 @@ export const adapter = createAdapter(db);
|
|
|
258
306
|
|
|
259
307
|
### Endpoints
|
|
260
308
|
|
|
261
|
-
#### `POST /
|
|
309
|
+
#### `POST /register`
|
|
262
310
|
|
|
263
|
-
Register a new user. Does **not** issue tokens — call `/login` after
|
|
311
|
+
Register a new user. Does **not** issue tokens — call `/login` after registration.
|
|
264
312
|
|
|
265
313
|
```
|
|
314
|
+
Headers: X-Api-Key: <key> (required when config.apiKey is set)
|
|
266
315
|
Body: { identifier, password, roles?: string[] }
|
|
267
316
|
Returns: { user: { id, identifier, roles } }
|
|
268
317
|
Status: 201
|
|
@@ -310,7 +359,7 @@ Returns: null
|
|
|
310
359
|
Status: 200
|
|
311
360
|
```
|
|
312
361
|
|
|
313
|
-
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.
|
|
314
363
|
|
|
315
364
|
---
|
|
316
365
|
|
|
@@ -324,6 +373,8 @@ Returns: null
|
|
|
324
373
|
Status: 200
|
|
325
374
|
```
|
|
326
375
|
|
|
376
|
+
All access tokens across all devices are immediately rejected by `protect()` after this call.
|
|
377
|
+
|
|
327
378
|
---
|
|
328
379
|
|
|
329
380
|
#### `GET /me`
|
|
@@ -355,7 +406,7 @@ Status: 200
|
|
|
355
406
|
|
|
356
407
|
### `auth.protect()`
|
|
357
408
|
|
|
358
|
-
Verifies the `Authorization: Bearer <token>` header and injects `request.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.
|
|
359
410
|
|
|
360
411
|
```typescript
|
|
361
412
|
router.get('/dashboard', auth.protect(), (request, response) => {
|
|
@@ -363,6 +414,11 @@ router.get('/dashboard', auth.protect(), (request, response) => {
|
|
|
363
414
|
});
|
|
364
415
|
```
|
|
365
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
|
+
|
|
366
422
|
---
|
|
367
423
|
|
|
368
424
|
### `auth.authorize(...roles)`
|
|
@@ -467,11 +523,11 @@ All errors thrown by the library are instances of `AuthError` with a machine-rea
|
|
|
467
523
|
| Code | HTTP | Meaning |
|
|
468
524
|
|---|---|---|
|
|
469
525
|
| `INVALID_CREDENTIALS` | 401 | Wrong identifier or password |
|
|
470
|
-
| `USER_ALREADY_EXISTS` | 409 |
|
|
526
|
+
| `USER_ALREADY_EXISTS` | 409 | Registration with duplicate identifier |
|
|
471
527
|
| `USER_NOT_FOUND` | 404 | Operation on a non-existent user |
|
|
472
528
|
| `TOKEN_EXPIRED` | 401 | JWT `exp` claim is in the past |
|
|
473
529
|
| `TOKEN_INVALID` | 401 | JWT signature invalid or malformed |
|
|
474
|
-
| `UNAUTHORIZED` | 401 | No valid access token
|
|
530
|
+
| `UNAUTHORIZED` | 401 | No valid access token, revoked session, or invalid API key |
|
|
475
531
|
| `FORBIDDEN` | 403 | Authenticated but missing required role |
|
|
476
532
|
| `INVALID_ROLE` | 400 | Role name not in `validRoles` |
|
|
477
533
|
| `VALIDATION_ERROR` | 400 | Missing or invalid input field |
|
|
@@ -482,17 +538,47 @@ The built-in router converts all `AuthError` instances to the standard envelope
|
|
|
482
538
|
```typescript
|
|
483
539
|
import { AuthError } from 'sentri';
|
|
484
540
|
|
|
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
|
+
};
|
|
553
|
+
|
|
485
554
|
app.use((error, _request, response, next) => {
|
|
486
555
|
if (error instanceof AuthError) {
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
:
|
|
490
|
-
|
|
491
|
-
: error.code
|
|
492
|
-
:
|
|
493
|
-
|
|
494
|
-
|
|
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
|
+
});
|
|
495
564
|
}
|
|
496
565
|
next(error);
|
|
497
566
|
});
|
|
498
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,6 +1,7 @@
|
|
|
1
1
|
import type { PermitCheck, PermitOptions } from './middleware/permit.js';
|
|
2
|
+
import type { ErrorHandlerOptions } from './middleware/errorHandler.js';
|
|
2
3
|
import type { AuthConfig, AuthUser } from './types/auth.js';
|
|
3
|
-
import type { RequestHandler, Router } from 'express';
|
|
4
|
+
import type { ErrorRequestHandler, RequestHandler, Router } from 'express';
|
|
4
5
|
/**
|
|
5
6
|
* The bound auth client returned by {@link createAuth}.
|
|
6
7
|
*
|
|
@@ -15,11 +16,12 @@ export interface AuthClient<TRole extends string = string> {
|
|
|
15
16
|
* Express middleware factory that enforces authentication.
|
|
16
17
|
*
|
|
17
18
|
* Reads the `Authorization: Bearer <token>` header, verifies the access token,
|
|
18
|
-
*
|
|
19
|
+
* confirms the session is still active in the database, and injects the decoded
|
|
20
|
+
* payload as `request.user`. Calls `next(AuthError)` on any failure.
|
|
19
21
|
*
|
|
20
22
|
* @example
|
|
21
|
-
* router.get('/me', auth.protect(), (
|
|
22
|
-
*
|
|
23
|
+
* router.get('/me', auth.protect(), (request, response) => {
|
|
24
|
+
* response.json(request.user);
|
|
23
25
|
* });
|
|
24
26
|
*/
|
|
25
27
|
protect(): RequestHandler;
|
|
@@ -47,7 +49,7 @@ export interface AuthClient<TRole extends string = string> {
|
|
|
47
49
|
* // User can only update their own profile
|
|
48
50
|
* router.put('/users/:id',
|
|
49
51
|
* auth.protect(),
|
|
50
|
-
* auth.permit((
|
|
52
|
+
* auth.permit((request) => request.user!.id === request.params['id']),
|
|
51
53
|
* handler,
|
|
52
54
|
* );
|
|
53
55
|
*
|
|
@@ -57,9 +59,9 @@ export interface AuthClient<TRole extends string = string> {
|
|
|
57
59
|
* auth.protect(),
|
|
58
60
|
* auth.permit({
|
|
59
61
|
* roles: ['admin'],
|
|
60
|
-
* check: async (
|
|
61
|
-
* const post = await db.post.findUnique({ where: { id:
|
|
62
|
-
* return post?.authorId ===
|
|
62
|
+
* check: async (request) => {
|
|
63
|
+
* const post = await db.post.findUnique({ where: { id: request.params['id'] } });
|
|
64
|
+
* return post?.authorId === request.user!.id;
|
|
63
65
|
* },
|
|
64
66
|
* }),
|
|
65
67
|
* handler,
|
|
@@ -82,23 +84,58 @@ export interface AuthClient<TRole extends string = string> {
|
|
|
82
84
|
sessionId: string;
|
|
83
85
|
};
|
|
84
86
|
/**
|
|
85
|
-
* Returns a pre-built Express Router with all standard auth endpoints mounted
|
|
87
|
+
* Returns a pre-built Express Router with all standard auth endpoints mounted.
|
|
86
88
|
*
|
|
87
|
-
*
|
|
89
|
+
* Endpoints:
|
|
90
|
+
* - `POST /register` — register a new user. Requires `X-Api-Key` header when `config.apiKey` is set.
|
|
88
91
|
* - `POST /login` — authenticate, sets refresh token cookie, returns `{ accessToken, user }`
|
|
89
|
-
* - `POST /refresh` —
|
|
90
|
-
* - `POST /logout` —
|
|
91
|
-
* - `POST /logout-all` —
|
|
92
|
+
* - `POST /refresh` — rotate refresh token, returns new `{ accessToken }`
|
|
93
|
+
* - `POST /logout` — delete the current session; the bound access token is immediately rejected by `protect()`
|
|
94
|
+
* - `POST /logout-all` — delete all sessions for the user (requires valid access token)
|
|
92
95
|
* - `GET /me` — return the authenticated user
|
|
93
96
|
* - `POST /users/:userId/roles` — assign roles (requires admin)
|
|
94
97
|
*
|
|
95
|
-
* Requires `express.json()`
|
|
98
|
+
* Requires `express.json()` before the router.
|
|
96
99
|
*
|
|
97
100
|
* @example
|
|
98
101
|
* app.use(express.json());
|
|
99
102
|
* app.use('/auth', auth.router());
|
|
100
103
|
*/
|
|
101
104
|
router(): Router;
|
|
105
|
+
/**
|
|
106
|
+
* Returns an Express error-handling middleware that formats every `AuthError`
|
|
107
|
+
* (and any subclass) into the standard sentri response envelope:
|
|
108
|
+
*
|
|
109
|
+
* ```json
|
|
110
|
+
* { "error": true, "statusCode": 401, "code": "UNAUTHORIZED", "message": "...", "data": null }
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* Mount it **after all your routes** so it acts as the global catch-all for
|
|
114
|
+
* both sentri errors and your own `AuthError` subclasses.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* import { AuthError } from 'sentri';
|
|
118
|
+
*
|
|
119
|
+
* // Define app-specific errors by extending AuthError
|
|
120
|
+
* class NotFoundError extends AuthError {
|
|
121
|
+
* constructor(resource: string) {
|
|
122
|
+
* super('NOT_FOUND', `${resource} not found`, 404);
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
*
|
|
126
|
+
* app.use('/auth', auth.router());
|
|
127
|
+
* app.use('/api', apiRouter);
|
|
128
|
+
*
|
|
129
|
+
* // Catches errors from sentri AND your own subclasses
|
|
130
|
+
* app.use(auth.errorHandler());
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* // With optional unhandled-error logger
|
|
134
|
+
* app.use(auth.errorHandler({
|
|
135
|
+
* onUnhandled: (err) => logger.error('Unexpected error', { err }),
|
|
136
|
+
* }));
|
|
137
|
+
*/
|
|
138
|
+
errorHandler(options?: ErrorHandlerOptions): ErrorRequestHandler;
|
|
102
139
|
}
|
|
103
140
|
/**
|
|
104
141
|
* Create a fully configured auth client for your application.
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
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,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM;IACvD;;;;;;;;;;;OAWG;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;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,IAAI,MAAM,CAAC;IAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,YAAY,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,CAAC;CAClE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EACtD,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,GACxB,UAAU,CAAC,KAAK,CAAC,CAiBnB"}
|
package/dist/client.js
CHANGED
|
@@ -5,6 +5,7 @@ import { protect } from './middleware/protect.js';
|
|
|
5
5
|
import { authorize } from './middleware/authorize.js';
|
|
6
6
|
import { permit } from './middleware/permit.js';
|
|
7
7
|
import { createAuthRouter } from './middleware/router.js';
|
|
8
|
+
import { createErrorHandler } from './middleware/errorHandler.js';
|
|
8
9
|
/**
|
|
9
10
|
* Create a fully configured auth client for your application.
|
|
10
11
|
*
|
|
@@ -30,6 +31,7 @@ export function createAuth(config) {
|
|
|
30
31
|
return {
|
|
31
32
|
protect: () => protect(config),
|
|
32
33
|
authorize: (...roles) => authorize(...roles),
|
|
34
|
+
permit: (optionsOrCheck) => permit(optionsOrCheck),
|
|
33
35
|
hashPassword: (plain) => hashPassword(plain, resolved.saltRounds),
|
|
34
36
|
verifyPassword: (plain, hash) => verifyPassword(plain, hash),
|
|
35
37
|
signAccessToken: (payload) => signAccessToken(payload, config),
|
|
@@ -37,7 +39,7 @@ export function createAuth(config) {
|
|
|
37
39
|
verifyAccessToken: (token) => verifyAccessToken(token, config),
|
|
38
40
|
verifyRefreshToken: (token) => verifyRefreshToken(token, config),
|
|
39
41
|
router: () => createAuthRouter(config),
|
|
40
|
-
|
|
42
|
+
errorHandler: (options) => createErrorHandler(options),
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
45
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -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,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;
|
|
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;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAsJlE;;;;;;;;;;;;;;;;;;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,MAAM,EAAE,CAAC,cAAkD,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC;QACtF,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,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC;KACvD,CAAC;AACJ,CAAC"}
|
|
@@ -1,40 +1,101 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Discriminant codes for {@link AuthError}.
|
|
2
|
+
* Discriminant codes for built-in {@link AuthError} instances.
|
|
3
3
|
*
|
|
4
4
|
* - `INVALID_CREDENTIALS` — identifier or password did not match (intentionally vague to prevent user enumeration)
|
|
5
5
|
* - `USER_NOT_FOUND` — an operation required a user that does not exist
|
|
6
|
-
* - `USER_ALREADY_EXISTS` —
|
|
6
|
+
* - `USER_ALREADY_EXISTS` — registration was attempted with an identifier already in the database
|
|
7
7
|
* - `TOKEN_EXPIRED` — the JWT was valid but its `exp` claim is in the past
|
|
8
8
|
* - `TOKEN_INVALID` — the JWT could not be verified (bad signature, malformed, wrong type)
|
|
9
9
|
* - `FORBIDDEN` — the user is authenticated but lacks the required role
|
|
10
|
-
* - `UNAUTHORIZED` — no valid access token was present on the request
|
|
10
|
+
* - `UNAUTHORIZED` — no valid access token was present on the request, or the session was revoked
|
|
11
11
|
* - `INVALID_ROLE` — a role name was used that is not in `validRoles`
|
|
12
12
|
* - `VALIDATION_ERROR` — a required field was missing or had an invalid value
|
|
13
13
|
* - `CONFIGURATION_ERROR` — `createAuth` was called with an invalid configuration
|
|
14
|
+
*
|
|
15
|
+
* When you extend {@link AuthError} for your own error types you can use any
|
|
16
|
+
* string as `code` — it does not need to be one of these built-in values.
|
|
14
17
|
*/
|
|
15
18
|
export type AuthErrorCode = 'INVALID_CREDENTIALS' | 'USER_NOT_FOUND' | 'USER_ALREADY_EXISTS' | 'TOKEN_EXPIRED' | 'TOKEN_INVALID' | 'FORBIDDEN' | 'UNAUTHORIZED' | 'INVALID_ROLE' | 'VALIDATION_ERROR' | 'CONFIGURATION_ERROR';
|
|
16
19
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
20
|
+
* Default HTTP status codes for built-in error codes.
|
|
21
|
+
* Custom codes that are not in this map default to 500.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export declare const AUTH_ERROR_STATUS: Record<string, number>;
|
|
26
|
+
/**
|
|
27
|
+
* Base error class for all authentication and authorization failures.
|
|
28
|
+
*
|
|
29
|
+
* Every error thrown by sentri is an instance of `AuthError`. The `code`
|
|
30
|
+
* property is a machine-readable string that lets you distinguish error
|
|
31
|
+
* types without string-matching on the message. Built-in codes are listed
|
|
32
|
+
* in {@link AuthErrorCode}; custom subclasses may use any string.
|
|
33
|
+
*
|
|
34
|
+
* The `statusCode` property holds the HTTP status that the built-in router
|
|
35
|
+
* and `createErrorHandler()` will use in the response. For built-in codes
|
|
36
|
+
* it is derived automatically. Pass it explicitly when subclassing with a
|
|
37
|
+
* custom code.
|
|
38
|
+
*
|
|
39
|
+
* ---
|
|
40
|
+
*
|
|
41
|
+
* **Extending AuthError**
|
|
42
|
+
*
|
|
43
|
+
* You can create application-specific error classes by extending `AuthError`.
|
|
44
|
+
* Any subclass will be caught automatically by `createErrorHandler()` because
|
|
45
|
+
* `instanceof AuthError` is `true` for all subclasses.
|
|
46
|
+
*
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { AuthError } from 'sentri';
|
|
49
|
+
*
|
|
50
|
+
* // Domain error with a custom code and explicit HTTP status
|
|
51
|
+
* export class PaymentError extends AuthError {
|
|
52
|
+
* constructor(message: string) {
|
|
53
|
+
* super('PAYMENT_FAILED', message, 402);
|
|
33
54
|
* }
|
|
55
|
+
* }
|
|
56
|
+
*
|
|
57
|
+
* // Throw it anywhere in your routes — createErrorHandler() catches it
|
|
58
|
+
* router.post('/checkout', auth.protect(), async (req, res) => {
|
|
59
|
+
* const ok = await chargeCard(req.body.cardToken);
|
|
60
|
+
* if (!ok) throw new PaymentError('Card declined');
|
|
61
|
+
* res.json({ success: true });
|
|
34
62
|
* });
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* ---
|
|
66
|
+
*
|
|
67
|
+
* **Error handling in custom routes**
|
|
68
|
+
*
|
|
69
|
+
* ```typescript
|
|
70
|
+
* import { AuthError, createErrorHandler } from 'sentri';
|
|
71
|
+
*
|
|
72
|
+
* app.use('/auth', auth.router());
|
|
73
|
+
* app.use('/api', apiRouter);
|
|
74
|
+
*
|
|
75
|
+
* // Mount after all routes — catches AuthError from sentri AND your subclasses
|
|
76
|
+
* app.use(createErrorHandler());
|
|
77
|
+
* ```
|
|
35
78
|
*/
|
|
36
79
|
export declare class AuthError extends Error {
|
|
37
|
-
|
|
38
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Machine-readable error code.
|
|
82
|
+
* Built-in codes are defined by {@link AuthErrorCode}.
|
|
83
|
+
* Custom subclasses may use any string.
|
|
84
|
+
*/
|
|
85
|
+
readonly code: string;
|
|
86
|
+
/**
|
|
87
|
+
* HTTP status code associated with this error.
|
|
88
|
+
* Derived automatically for built-in codes; pass it explicitly when
|
|
89
|
+
* subclassing with a custom `code`.
|
|
90
|
+
*/
|
|
91
|
+
readonly statusCode: number;
|
|
92
|
+
/**
|
|
93
|
+
* @param code - Machine-readable error code. Use a built-in {@link AuthErrorCode}
|
|
94
|
+
* or any string for custom subclasses.
|
|
95
|
+
* @param message - Human-readable description of the error.
|
|
96
|
+
* @param statusCode - HTTP status to use in the response. For built-in codes
|
|
97
|
+
* this is derived automatically; for custom codes it defaults to `500`.
|
|
98
|
+
*/
|
|
99
|
+
constructor(code: AuthErrorCode | (string & {}), message: string, statusCode?: number);
|
|
39
100
|
}
|
|
40
101
|
//# sourceMappingURL=AuthError.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthError.d.ts","sourceRoot":"","sources":["../../src/errors/AuthError.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"AuthError.d.ts","sourceRoot":"","sources":["../../src/errors/AuthError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;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;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWpD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC;;;;OAIG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;;;OAIG;IACH,SAAgB,UAAU,EAAE,MAAM,CAAC;IAEnC;;;;;;OAMG;gBAED,IAAI,EAAE,aAAa,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EACnC,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM;CAOtB"}
|
package/dist/errors/AuthError.js
CHANGED
|
@@ -1,29 +1,99 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
* Default HTTP status codes for built-in error codes.
|
|
3
|
+
* Custom codes that are not in this map default to 500.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export const AUTH_ERROR_STATUS = {
|
|
8
|
+
UNAUTHORIZED: 401,
|
|
9
|
+
TOKEN_EXPIRED: 401,
|
|
10
|
+
TOKEN_INVALID: 401,
|
|
11
|
+
INVALID_CREDENTIALS: 401,
|
|
12
|
+
FORBIDDEN: 403,
|
|
13
|
+
USER_NOT_FOUND: 404,
|
|
14
|
+
USER_ALREADY_EXISTS: 409,
|
|
15
|
+
INVALID_ROLE: 400,
|
|
16
|
+
VALIDATION_ERROR: 400,
|
|
17
|
+
CONFIGURATION_ERROR: 500,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Base error class for all authentication and authorization failures.
|
|
21
|
+
*
|
|
22
|
+
* Every error thrown by sentri is an instance of `AuthError`. The `code`
|
|
23
|
+
* property is a machine-readable string that lets you distinguish error
|
|
24
|
+
* types without string-matching on the message. Built-in codes are listed
|
|
25
|
+
* in {@link AuthErrorCode}; custom subclasses may use any string.
|
|
26
|
+
*
|
|
27
|
+
* The `statusCode` property holds the HTTP status that the built-in router
|
|
28
|
+
* and `createErrorHandler()` will use in the response. For built-in codes
|
|
29
|
+
* it is derived automatically. Pass it explicitly when subclassing with a
|
|
30
|
+
* custom code.
|
|
31
|
+
*
|
|
32
|
+
* ---
|
|
33
|
+
*
|
|
34
|
+
* **Extending AuthError**
|
|
35
|
+
*
|
|
36
|
+
* You can create application-specific error classes by extending `AuthError`.
|
|
37
|
+
* Any subclass will be caught automatically by `createErrorHandler()` because
|
|
38
|
+
* `instanceof AuthError` is `true` for all subclasses.
|
|
39
|
+
*
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { AuthError } from 'sentri';
|
|
42
|
+
*
|
|
43
|
+
* // Domain error with a custom code and explicit HTTP status
|
|
44
|
+
* export class PaymentError extends AuthError {
|
|
45
|
+
* constructor(message: string) {
|
|
46
|
+
* super('PAYMENT_FAILED', message, 402);
|
|
18
47
|
* }
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* // Throw it anywhere in your routes — createErrorHandler() catches it
|
|
51
|
+
* router.post('/checkout', auth.protect(), async (req, res) => {
|
|
52
|
+
* const ok = await chargeCard(req.body.cardToken);
|
|
53
|
+
* if (!ok) throw new PaymentError('Card declined');
|
|
54
|
+
* res.json({ success: true });
|
|
19
55
|
* });
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* ---
|
|
59
|
+
*
|
|
60
|
+
* **Error handling in custom routes**
|
|
61
|
+
*
|
|
62
|
+
* ```typescript
|
|
63
|
+
* import { AuthError, createErrorHandler } from 'sentri';
|
|
64
|
+
*
|
|
65
|
+
* app.use('/auth', auth.router());
|
|
66
|
+
* app.use('/api', apiRouter);
|
|
67
|
+
*
|
|
68
|
+
* // Mount after all routes — catches AuthError from sentri AND your subclasses
|
|
69
|
+
* app.use(createErrorHandler());
|
|
70
|
+
* ```
|
|
20
71
|
*/
|
|
21
72
|
export class AuthError extends Error {
|
|
73
|
+
/**
|
|
74
|
+
* Machine-readable error code.
|
|
75
|
+
* Built-in codes are defined by {@link AuthErrorCode}.
|
|
76
|
+
* Custom subclasses may use any string.
|
|
77
|
+
*/
|
|
22
78
|
code;
|
|
23
|
-
|
|
79
|
+
/**
|
|
80
|
+
* HTTP status code associated with this error.
|
|
81
|
+
* Derived automatically for built-in codes; pass it explicitly when
|
|
82
|
+
* subclassing with a custom `code`.
|
|
83
|
+
*/
|
|
84
|
+
statusCode;
|
|
85
|
+
/**
|
|
86
|
+
* @param code - Machine-readable error code. Use a built-in {@link AuthErrorCode}
|
|
87
|
+
* or any string for custom subclasses.
|
|
88
|
+
* @param message - Human-readable description of the error.
|
|
89
|
+
* @param statusCode - HTTP status to use in the response. For built-in codes
|
|
90
|
+
* this is derived automatically; for custom codes it defaults to `500`.
|
|
91
|
+
*/
|
|
92
|
+
constructor(code, message, statusCode) {
|
|
24
93
|
super(message);
|
|
25
94
|
this.name = 'AuthError';
|
|
26
95
|
this.code = code;
|
|
96
|
+
this.statusCode = statusCode ?? AUTH_ERROR_STATUS[code] ?? 500;
|
|
27
97
|
}
|
|
28
98
|
}
|
|
29
99
|
//# sourceMappingURL=AuthError.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthError.js","sourceRoot":"","sources":["../../src/errors/AuthError.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AuthError.js","sourceRoot":"","sources":["../../src/errors/AuthError.ts"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,YAAY,EAAE,GAAG;IACjB,aAAa,EAAE,GAAG;IAClB,aAAa,EAAE,GAAG;IAClB,mBAAmB,EAAE,GAAG;IACxB,SAAS,EAAE,GAAG;IACd,cAAc,EAAE,GAAG;IACnB,mBAAmB,EAAE,GAAG;IACxB,YAAY,EAAE,GAAG;IACjB,gBAAgB,EAAE,GAAG;IACrB,mBAAmB,EAAE,GAAG;CACzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC;;;;OAIG;IACa,IAAI,CAAS;IAE7B;;;;OAIG;IACa,UAAU,CAAS;IAEnC;;;;;;OAMG;IACH,YACE,IAAmC,EACnC,OAAe,EACf,UAAmB;QAEnB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;IACjE,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,9 @@ declare global {
|
|
|
9
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
|
-
export {
|
|
12
|
+
export type { ErrorHandlerOptions } from './middleware/errorHandler.js';
|
|
13
|
+
export { AuthError, AUTH_ERROR_STATUS } from './errors/AuthError.js';
|
|
13
14
|
export { createAuth } from './client.js';
|
|
15
|
+
export { createErrorHandler } from './middleware/errorHandler.js';
|
|
14
16
|
export type { PermitCheck, PermitOptions } from './middleware/permit.js';
|
|
15
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,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;
|
|
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;AAC9C,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
|