sentri 1.1.2 → 2.0.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.
- package/README.md +325 -181
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +10 -103
- package/dist/index.d.ts +1046 -11
- package/dist/index.js +1 -5
- package/package.json +13 -6
- package/templates/drizzle/auth.ts +47 -4
- package/templates/prisma/auth.ts +47 -4
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/client.d.ts +0 -160
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -45
- package/dist/client.js.map +0 -1
- package/dist/errors/AuthError.d.ts +0 -99
- package/dist/errors/AuthError.d.ts.map +0 -1
- package/dist/errors/AuthError.js +0 -97
- package/dist/errors/AuthError.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/libs/config.d.ts +0 -62
- package/dist/libs/config.d.ts.map +0 -1
- package/dist/libs/config.js +0 -97
- package/dist/libs/config.js.map +0 -1
- package/dist/libs/hash.d.ts +0 -17
- package/dist/libs/hash.d.ts.map +0 -1
- package/dist/libs/hash.js +0 -22
- package/dist/libs/hash.js.map +0 -1
- package/dist/libs/token.d.ts +0 -46
- package/dist/libs/token.d.ts.map +0 -1
- package/dist/libs/token.js +0 -118
- package/dist/libs/token.js.map +0 -1
- package/dist/middleware/authorize.d.ts +0 -18
- package/dist/middleware/authorize.d.ts.map +0 -1
- package/dist/middleware/authorize.js +0 -30
- package/dist/middleware/authorize.js.map +0 -1
- package/dist/middleware/errorHandler.d.ts +0 -71
- package/dist/middleware/errorHandler.d.ts.map +0 -1
- package/dist/middleware/errorHandler.js +0 -74
- package/dist/middleware/errorHandler.js.map +0 -1
- package/dist/middleware/permit.d.ts +0 -62
- package/dist/middleware/permit.d.ts.map +0 -1
- package/dist/middleware/permit.js +0 -61
- package/dist/middleware/permit.js.map +0 -1
- package/dist/middleware/protect.d.ts +0 -31
- package/dist/middleware/protect.d.ts.map +0 -1
- package/dist/middleware/protect.js +0 -54
- package/dist/middleware/protect.js.map +0 -1
- package/dist/middleware/router.d.ts +0 -34
- package/dist/middleware/router.d.ts.map +0 -1
- package/dist/middleware/router.js +0 -264
- package/dist/middleware/router.js.map +0 -1
- package/dist/services/auth.d.ts +0 -85
- package/dist/services/auth.d.ts.map +0 -1
- package/dist/services/auth.js +0 -173
- package/dist/services/auth.js.map +0 -1
- package/dist/types/auth.d.ts +0 -450
- package/dist/types/auth.d.ts.map +0 -1
- package/dist/types/auth.js +0 -21
- package/dist/types/auth.js.map +0 -1
package/dist/errors/AuthError.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
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 in sentri.
|
|
21
|
-
*
|
|
22
|
-
* Every error thrown by sentri is an instance of `SentriError`. 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 SentriErrorCode}; custom subclasses may use any string.
|
|
26
|
-
*
|
|
27
|
-
* The `statusCode` property holds the HTTP status that the built-in router
|
|
28
|
-
* and `auth.errorHandler()` 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 SentriError**
|
|
35
|
-
*
|
|
36
|
-
* You can create application-specific error classes by extending `SentriError`.
|
|
37
|
-
* Any subclass will be caught automatically by `auth.errorHandler()` because
|
|
38
|
-
* `instanceof SentriError` is `true` for all subclasses.
|
|
39
|
-
*
|
|
40
|
-
* ```typescript
|
|
41
|
-
* import { SentriError } from 'sentri';
|
|
42
|
-
*
|
|
43
|
-
* // Domain error with a custom code and explicit HTTP status
|
|
44
|
-
* export class PaymentError extends SentriError {
|
|
45
|
-
* constructor(message: string) {
|
|
46
|
-
* super('PAYMENT_FAILED', message, 402);
|
|
47
|
-
* }
|
|
48
|
-
* }
|
|
49
|
-
*
|
|
50
|
-
* // Throw it anywhere in your routes — auth.errorHandler() 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 });
|
|
55
|
-
* });
|
|
56
|
-
* ```
|
|
57
|
-
*
|
|
58
|
-
* ---
|
|
59
|
-
*
|
|
60
|
-
* **Error handling in custom routes**
|
|
61
|
-
*
|
|
62
|
-
* ```typescript
|
|
63
|
-
* app.use('/auth', auth.router());
|
|
64
|
-
* app.use('/api', apiRouter);
|
|
65
|
-
*
|
|
66
|
-
* // Mount after all routes — catches SentriError from sentri AND your subclasses
|
|
67
|
-
* app.use(auth.errorHandler());
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
export class SentriError extends Error {
|
|
71
|
-
/**
|
|
72
|
-
* Machine-readable error code.
|
|
73
|
-
* Built-in codes are defined by {@link SentriErrorCode}.
|
|
74
|
-
* Custom subclasses may use any string.
|
|
75
|
-
*/
|
|
76
|
-
code;
|
|
77
|
-
/**
|
|
78
|
-
* HTTP status code associated with this error.
|
|
79
|
-
* Derived automatically for built-in codes; pass it explicitly when
|
|
80
|
-
* subclassing with a custom `code`.
|
|
81
|
-
*/
|
|
82
|
-
statusCode;
|
|
83
|
-
/**
|
|
84
|
-
* @param code - Machine-readable error code. Use a built-in {@link SentriErrorCode}
|
|
85
|
-
* or any string for custom subclasses.
|
|
86
|
-
* @param message - Human-readable description of the error.
|
|
87
|
-
* @param statusCode - HTTP status to use in the response. For built-in codes
|
|
88
|
-
* this is derived automatically; for custom codes it defaults to `500`.
|
|
89
|
-
*/
|
|
90
|
-
constructor(code, message, statusCode) {
|
|
91
|
-
super(message);
|
|
92
|
-
this.name = 'SentriError';
|
|
93
|
-
this.code = code;
|
|
94
|
-
this.statusCode = statusCode ?? AUTH_ERROR_STATUS[code] ?? 500;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
//# sourceMappingURL=AuthError.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC;;;;OAIG;IACa,IAAI,CAAS;IAE7B;;;;OAIG;IACa,UAAU,CAAS;IAEnC;;;;;;OAMG;IACH,YACE,IAAqC,EACrC,OAAe,EACf,UAAmB;QAEnB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,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.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGhD,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,aAAa,EACb,UAAU,EACV,cAAc,EACd,UAAU,EACV,aAAa,EACb,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/libs/config.d.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { AuthAdapter, AuthConfig } from '../types/auth.js';
|
|
2
|
-
/**
|
|
3
|
-
* Fully-resolved configuration with all optional fields filled in by
|
|
4
|
-
* their defaults. Produced by {@link resolveConfig} and used internally
|
|
5
|
-
* wherever the library needs guaranteed values.
|
|
6
|
-
*/
|
|
7
|
-
export interface ResolvedConfig {
|
|
8
|
-
secret: string;
|
|
9
|
-
accessExpiresIn: string | number;
|
|
10
|
-
refreshExpiresIn: string | number;
|
|
11
|
-
algorithm: 'HS256' | 'HS384' | 'HS512';
|
|
12
|
-
saltRounds: number;
|
|
13
|
-
validRoles: readonly string[];
|
|
14
|
-
adapter: AuthAdapter;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Validate configuration at startup so misconfiguration is caught immediately,
|
|
18
|
-
* not at the first login attempt.
|
|
19
|
-
*
|
|
20
|
-
* Throws {@link SentriError} with code `CONFIGURATION_ERROR` for any of:
|
|
21
|
-
* - `secret` missing or shorter than 32 characters
|
|
22
|
-
* - `saltRounds` outside the range 10–31
|
|
23
|
-
* - `validRoles` is empty or missing
|
|
24
|
-
* - `adapter` is missing
|
|
25
|
-
*
|
|
26
|
-
* @param config - The raw config passed to {@link createAuth}.
|
|
27
|
-
* @throws {SentriError} With code `CONFIGURATION_ERROR` on any invalid field.
|
|
28
|
-
*/
|
|
29
|
-
export declare function validateConfig(config: AuthConfig): void;
|
|
30
|
-
/**
|
|
31
|
-
* Merge a partial {@link AuthConfig} with library defaults and return a
|
|
32
|
-
* fully-resolved configuration object.
|
|
33
|
-
*
|
|
34
|
-
* Does **not** validate the config — call {@link validateConfig} first.
|
|
35
|
-
*
|
|
36
|
-
* Defaults applied:
|
|
37
|
-
* - `accessExpiresIn` → `'15m'`
|
|
38
|
-
* - `refreshExpiresIn` → `'7d'`
|
|
39
|
-
* - `algorithm` → `'HS256'`
|
|
40
|
-
* - `saltRounds` → `12`
|
|
41
|
-
*
|
|
42
|
-
* @param partial - The raw config passed to {@link createAuth}.
|
|
43
|
-
* @returns A {@link ResolvedConfig} with every field guaranteed to be present.
|
|
44
|
-
*/
|
|
45
|
-
export declare function resolveConfig(partial: AuthConfig): ResolvedConfig;
|
|
46
|
-
/**
|
|
47
|
-
* Convert a duration string or a number of seconds into milliseconds.
|
|
48
|
-
*
|
|
49
|
-
* Supported unit suffixes: `s` (seconds), `m` (minutes), `h` (hours),
|
|
50
|
-
* `d` (days), `w` (weeks). Numeric inputs are treated as seconds.
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* parseExpiry('15m') // 900_000
|
|
54
|
-
* parseExpiry('7d') // 604_800_000
|
|
55
|
-
* parseExpiry(60) // 60_000
|
|
56
|
-
*
|
|
57
|
-
* @param expiresIn - A duration string (e.g. `'15m'`, `'7d'`) or a number of seconds.
|
|
58
|
-
* @returns The equivalent duration in milliseconds.
|
|
59
|
-
* @throws {Error} If the string format is unrecognised.
|
|
60
|
-
*/
|
|
61
|
-
export declare function parseExpiry(expiresIn: string | number): number;
|
|
62
|
-
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/libs/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEhE;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,WAAW,CAAC;CACtB;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CA0BvD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,cAAc,CAUjE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAkB9D"}
|
package/dist/libs/config.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { SentriError } from '../errors/AuthError.js';
|
|
2
|
-
const MIN_SECRET_LENGTH = 32;
|
|
3
|
-
const MIN_SALT_ROUNDS = 10;
|
|
4
|
-
const MAX_SALT_ROUNDS = 31;
|
|
5
|
-
/**
|
|
6
|
-
* Validate configuration at startup so misconfiguration is caught immediately,
|
|
7
|
-
* not at the first login attempt.
|
|
8
|
-
*
|
|
9
|
-
* Throws {@link SentriError} with code `CONFIGURATION_ERROR` for any of:
|
|
10
|
-
* - `secret` missing or shorter than 32 characters
|
|
11
|
-
* - `saltRounds` outside the range 10–31
|
|
12
|
-
* - `validRoles` is empty or missing
|
|
13
|
-
* - `adapter` is missing
|
|
14
|
-
*
|
|
15
|
-
* @param config - The raw config passed to {@link createAuth}.
|
|
16
|
-
* @throws {SentriError} With code `CONFIGURATION_ERROR` on any invalid field.
|
|
17
|
-
*/
|
|
18
|
-
export function validateConfig(config) {
|
|
19
|
-
if (!config.secret || config.secret.trim().length === 0) {
|
|
20
|
-
throw new SentriError('CONFIGURATION_ERROR', 'secret must not be empty');
|
|
21
|
-
}
|
|
22
|
-
if (config.secret.length < MIN_SECRET_LENGTH) {
|
|
23
|
-
throw new SentriError('CONFIGURATION_ERROR', `secret must be at least ${MIN_SECRET_LENGTH} characters to be cryptographically safe`);
|
|
24
|
-
}
|
|
25
|
-
const saltRounds = config.saltRounds ?? 12;
|
|
26
|
-
if (!Number.isInteger(saltRounds) || saltRounds < MIN_SALT_ROUNDS || saltRounds > MAX_SALT_ROUNDS) {
|
|
27
|
-
throw new SentriError('CONFIGURATION_ERROR', `saltRounds must be an integer between ${MIN_SALT_ROUNDS} and ${MAX_SALT_ROUNDS}`);
|
|
28
|
-
}
|
|
29
|
-
if (!config.validRoles || config.validRoles.length === 0) {
|
|
30
|
-
throw new SentriError('CONFIGURATION_ERROR', 'validRoles must contain at least one role');
|
|
31
|
-
}
|
|
32
|
-
if (!config.adapter) {
|
|
33
|
-
throw new SentriError('CONFIGURATION_ERROR', 'adapter is required');
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Merge a partial {@link AuthConfig} with library defaults and return a
|
|
38
|
-
* fully-resolved configuration object.
|
|
39
|
-
*
|
|
40
|
-
* Does **not** validate the config — call {@link validateConfig} first.
|
|
41
|
-
*
|
|
42
|
-
* Defaults applied:
|
|
43
|
-
* - `accessExpiresIn` → `'15m'`
|
|
44
|
-
* - `refreshExpiresIn` → `'7d'`
|
|
45
|
-
* - `algorithm` → `'HS256'`
|
|
46
|
-
* - `saltRounds` → `12`
|
|
47
|
-
*
|
|
48
|
-
* @param partial - The raw config passed to {@link createAuth}.
|
|
49
|
-
* @returns A {@link ResolvedConfig} with every field guaranteed to be present.
|
|
50
|
-
*/
|
|
51
|
-
export function resolveConfig(partial) {
|
|
52
|
-
return {
|
|
53
|
-
secret: partial.secret,
|
|
54
|
-
accessExpiresIn: partial.accessExpiresIn ?? '15m',
|
|
55
|
-
refreshExpiresIn: partial.refreshExpiresIn ?? '7d',
|
|
56
|
-
algorithm: partial.algorithm ?? 'HS256',
|
|
57
|
-
saltRounds: partial.saltRounds ?? 12,
|
|
58
|
-
validRoles: partial.validRoles,
|
|
59
|
-
adapter: partial.adapter,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Convert a duration string or a number of seconds into milliseconds.
|
|
64
|
-
*
|
|
65
|
-
* Supported unit suffixes: `s` (seconds), `m` (minutes), `h` (hours),
|
|
66
|
-
* `d` (days), `w` (weeks). Numeric inputs are treated as seconds.
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* parseExpiry('15m') // 900_000
|
|
70
|
-
* parseExpiry('7d') // 604_800_000
|
|
71
|
-
* parseExpiry(60) // 60_000
|
|
72
|
-
*
|
|
73
|
-
* @param expiresIn - A duration string (e.g. `'15m'`, `'7d'`) or a number of seconds.
|
|
74
|
-
* @returns The equivalent duration in milliseconds.
|
|
75
|
-
* @throws {Error} If the string format is unrecognised.
|
|
76
|
-
*/
|
|
77
|
-
export function parseExpiry(expiresIn) {
|
|
78
|
-
if (typeof expiresIn === 'number')
|
|
79
|
-
return expiresIn * 1000;
|
|
80
|
-
const multipliers = {
|
|
81
|
-
s: 1_000,
|
|
82
|
-
m: 60_000,
|
|
83
|
-
h: 3_600_000,
|
|
84
|
-
d: 86_400_000,
|
|
85
|
-
w: 604_800_000,
|
|
86
|
-
};
|
|
87
|
-
const match = /^(\d+)([smhdw])$/.exec(expiresIn);
|
|
88
|
-
if (!match?.[1] || !match?.[2]) {
|
|
89
|
-
throw new Error(`Invalid expiresIn: "${expiresIn}". Use e.g. "15m", "7d", "1h".`);
|
|
90
|
-
}
|
|
91
|
-
const unit = multipliers[match[2]];
|
|
92
|
-
if (unit === undefined) {
|
|
93
|
-
throw new Error(`Invalid expiresIn: "${expiresIn}". Use e.g. "15m", "7d", "1h".`);
|
|
94
|
-
}
|
|
95
|
-
return parseInt(match[1], 10) * unit;
|
|
96
|
-
}
|
|
97
|
-
//# sourceMappingURL=config.js.map
|
package/dist/libs/config.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/libs/config.ts"],"names":[],"mappings":"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"}
|
package/dist/libs/hash.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hash a plain-text password using bcrypt.
|
|
3
|
-
*
|
|
4
|
-
* @param plain - The raw password string supplied by the user.
|
|
5
|
-
* @param saltRounds - bcrypt cost factor; higher values increase security at the cost of speed.
|
|
6
|
-
* @returns The bcrypt hash string to persist in the database.
|
|
7
|
-
*/
|
|
8
|
-
export declare function hashPassword(plain: string, saltRounds?: number): Promise<string>;
|
|
9
|
-
/**
|
|
10
|
-
* Compare a plain-text password against a stored bcrypt hash.
|
|
11
|
-
*
|
|
12
|
-
* @param plain - The raw password string to verify.
|
|
13
|
-
* @param hash - The stored bcrypt hash from the database.
|
|
14
|
-
* @returns `true` if the password matches the hash, `false` otherwise.
|
|
15
|
-
*/
|
|
16
|
-
export declare function verifyPassword(plain: string, hash: string): Promise<boolean>;
|
|
17
|
-
//# sourceMappingURL=hash.d.ts.map
|
package/dist/libs/hash.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/libs/hash.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAElF;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAElF"}
|
package/dist/libs/hash.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import bcrypt from 'bcrypt';
|
|
2
|
-
/**
|
|
3
|
-
* Hash a plain-text password using bcrypt.
|
|
4
|
-
*
|
|
5
|
-
* @param plain - The raw password string supplied by the user.
|
|
6
|
-
* @param saltRounds - bcrypt cost factor; higher values increase security at the cost of speed.
|
|
7
|
-
* @returns The bcrypt hash string to persist in the database.
|
|
8
|
-
*/
|
|
9
|
-
export async function hashPassword(plain, saltRounds = 12) {
|
|
10
|
-
return bcrypt.hash(plain, saltRounds);
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Compare a plain-text password against a stored bcrypt hash.
|
|
14
|
-
*
|
|
15
|
-
* @param plain - The raw password string to verify.
|
|
16
|
-
* @param hash - The stored bcrypt hash from the database.
|
|
17
|
-
* @returns `true` if the password matches the hash, `false` otherwise.
|
|
18
|
-
*/
|
|
19
|
-
export async function verifyPassword(plain, hash) {
|
|
20
|
-
return bcrypt.compare(plain, hash);
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=hash.js.map
|
package/dist/libs/hash.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/libs/hash.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,UAAU,GAAG,EAAE;IAC/D,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa,EAAE,IAAY;IAC9D,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/libs/token.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { AccessTokenPayload, AuthConfig, AuthUser } from '../types/auth.js';
|
|
2
|
-
/**
|
|
3
|
-
* Sign a short-lived access token containing the user's identity, roles, and
|
|
4
|
-
* the session ID that `protect()` uses to verify the session is still active.
|
|
5
|
-
*
|
|
6
|
-
* Uses the access-specific secret derived from config and the configured
|
|
7
|
-
* `accessExpiresIn` duration and HMAC algorithm.
|
|
8
|
-
*
|
|
9
|
-
* @param payload - The {@link AccessTokenPayload} to embed (id, identifier, roles, sessionId).
|
|
10
|
-
* @param config - Auth configuration used to derive the secret and options.
|
|
11
|
-
* @returns Compact JWT string.
|
|
12
|
-
*/
|
|
13
|
-
export declare function signAccessToken(payload: AuthUser | AccessTokenPayload, config: AuthConfig): string;
|
|
14
|
-
/**
|
|
15
|
-
* Sign a long-lived refresh token bound to a specific session ID.
|
|
16
|
-
*
|
|
17
|
-
* Uses the refresh-specific secret derived from config and the configured
|
|
18
|
-
* `refreshExpiresIn` duration. The session ID is embedded as the sole claim
|
|
19
|
-
* so the token can be used to look up and rotate the session.
|
|
20
|
-
*
|
|
21
|
-
* @param sessionId - The database session ID to bind to this token.
|
|
22
|
-
* @param config - Auth configuration used to derive the secret and options.
|
|
23
|
-
* @returns Compact JWT string.
|
|
24
|
-
*/
|
|
25
|
-
export declare function signRefreshToken(sessionId: string, config: AuthConfig): string;
|
|
26
|
-
/**
|
|
27
|
-
* Verify an access token and return its decoded {@link AuthUser} payload.
|
|
28
|
-
*
|
|
29
|
-
* @param token - Compact JWT access token string.
|
|
30
|
-
* @param config - Auth configuration used to derive the secret and algorithm.
|
|
31
|
-
* @returns Decoded `AuthUser` payload (id, identifier, roles).
|
|
32
|
-
* @throws {SentriError} With `TOKEN_EXPIRED` if expired, `TOKEN_INVALID` otherwise.
|
|
33
|
-
*/
|
|
34
|
-
export declare function verifyAccessToken(token: string, config: AuthConfig): AuthUser;
|
|
35
|
-
/**
|
|
36
|
-
* Verify a refresh token and return the embedded session ID.
|
|
37
|
-
*
|
|
38
|
-
* @param token - Compact JWT refresh token string.
|
|
39
|
-
* @param config - Auth configuration used to derive the secret and algorithm.
|
|
40
|
-
* @returns Object with `sessionId` matching the one passed to {@link signRefreshToken}.
|
|
41
|
-
* @throws {SentriError} With `TOKEN_EXPIRED` if expired, `TOKEN_INVALID` otherwise.
|
|
42
|
-
*/
|
|
43
|
-
export declare function verifyRefreshToken(token: string, config: AuthConfig): {
|
|
44
|
-
sessionId: string;
|
|
45
|
-
};
|
|
46
|
-
//# sourceMappingURL=token.d.ts.map
|
package/dist/libs/token.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/libs/token.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAqEjF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,kBAAkB,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAIlG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAI9E;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,QAAQ,CAI7E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAI3F"}
|
package/dist/libs/token.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import jwt, {} from 'jsonwebtoken';
|
|
2
|
-
import { SentriError } from '../errors/AuthError.js';
|
|
3
|
-
import { resolveConfig } from './config.js';
|
|
4
|
-
/**
|
|
5
|
-
* Derive separate HMAC secrets for access and refresh tokens from a single
|
|
6
|
-
* root secret by appending a domain suffix.
|
|
7
|
-
*
|
|
8
|
-
* Using distinct secrets prevents a refresh token from being accepted as an
|
|
9
|
-
* access token and vice versa.
|
|
10
|
-
*/
|
|
11
|
-
function deriveSecrets(secret) {
|
|
12
|
-
return {
|
|
13
|
-
access: `${secret}:access`,
|
|
14
|
-
refresh: `${secret}:refresh`,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Sign a JWT payload with the given secret and options.
|
|
19
|
-
*
|
|
20
|
-
* @param payload - Claims to embed in the token.
|
|
21
|
-
* @param secret - HMAC signing key.
|
|
22
|
-
* @param expiresIn - Expiry duration string (e.g. `'15m'`) or seconds.
|
|
23
|
-
* @param algorithm - HMAC algorithm variant.
|
|
24
|
-
* @returns Compact JWT string.
|
|
25
|
-
*/
|
|
26
|
-
function sign(payload, secret, expiresIn, algorithm) {
|
|
27
|
-
const options = {
|
|
28
|
-
expiresIn: expiresIn,
|
|
29
|
-
algorithm,
|
|
30
|
-
};
|
|
31
|
-
return jwt.sign(payload, secret, options);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Verify and decode a JWT, mapping jsonwebtoken errors to typed {@link SentriError}s.
|
|
35
|
-
*
|
|
36
|
-
* @param token - Compact JWT string to verify.
|
|
37
|
-
* @param secret - HMAC key used to sign the token.
|
|
38
|
-
* @param algorithm - Expected signing algorithm.
|
|
39
|
-
* @returns Decoded payload cast to `T`.
|
|
40
|
-
* @throws {SentriError} With `TOKEN_EXPIRED` if the token's `exp` claim is in the past.
|
|
41
|
-
* @throws {SentriError} With `TOKEN_INVALID` for any other verification failure.
|
|
42
|
-
*/
|
|
43
|
-
function verify(token, secret, algorithm) {
|
|
44
|
-
try {
|
|
45
|
-
const decoded = jwt.verify(token, secret, { algorithms: [algorithm] });
|
|
46
|
-
if (typeof decoded === 'string' || decoded === null) {
|
|
47
|
-
throw new SentriError('TOKEN_INVALID', 'Token payload is not an object');
|
|
48
|
-
}
|
|
49
|
-
return decoded;
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
if (err instanceof SentriError)
|
|
53
|
-
throw err;
|
|
54
|
-
if (err instanceof jwt.TokenExpiredError) {
|
|
55
|
-
throw new SentriError('TOKEN_EXPIRED', 'Token has expired');
|
|
56
|
-
}
|
|
57
|
-
throw new SentriError('TOKEN_INVALID', 'Token is invalid or malformed');
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Sign a short-lived access token containing the user's identity, roles, and
|
|
62
|
-
* the session ID that `protect()` uses to verify the session is still active.
|
|
63
|
-
*
|
|
64
|
-
* Uses the access-specific secret derived from config and the configured
|
|
65
|
-
* `accessExpiresIn` duration and HMAC algorithm.
|
|
66
|
-
*
|
|
67
|
-
* @param payload - The {@link AccessTokenPayload} to embed (id, identifier, roles, sessionId).
|
|
68
|
-
* @param config - Auth configuration used to derive the secret and options.
|
|
69
|
-
* @returns Compact JWT string.
|
|
70
|
-
*/
|
|
71
|
-
export function signAccessToken(payload, config) {
|
|
72
|
-
const resolved = resolveConfig(config);
|
|
73
|
-
const { access } = deriveSecrets(resolved.secret);
|
|
74
|
-
return sign(payload, access, resolved.accessExpiresIn, resolved.algorithm);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Sign a long-lived refresh token bound to a specific session ID.
|
|
78
|
-
*
|
|
79
|
-
* Uses the refresh-specific secret derived from config and the configured
|
|
80
|
-
* `refreshExpiresIn` duration. The session ID is embedded as the sole claim
|
|
81
|
-
* so the token can be used to look up and rotate the session.
|
|
82
|
-
*
|
|
83
|
-
* @param sessionId - The database session ID to bind to this token.
|
|
84
|
-
* @param config - Auth configuration used to derive the secret and options.
|
|
85
|
-
* @returns Compact JWT string.
|
|
86
|
-
*/
|
|
87
|
-
export function signRefreshToken(sessionId, config) {
|
|
88
|
-
const resolved = resolveConfig(config);
|
|
89
|
-
const { refresh } = deriveSecrets(resolved.secret);
|
|
90
|
-
return sign({ sessionId }, refresh, resolved.refreshExpiresIn, resolved.algorithm);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Verify an access token and return its decoded {@link AuthUser} payload.
|
|
94
|
-
*
|
|
95
|
-
* @param token - Compact JWT access token string.
|
|
96
|
-
* @param config - Auth configuration used to derive the secret and algorithm.
|
|
97
|
-
* @returns Decoded `AuthUser` payload (id, identifier, roles).
|
|
98
|
-
* @throws {SentriError} With `TOKEN_EXPIRED` if expired, `TOKEN_INVALID` otherwise.
|
|
99
|
-
*/
|
|
100
|
-
export function verifyAccessToken(token, config) {
|
|
101
|
-
const resolved = resolveConfig(config);
|
|
102
|
-
const { access } = deriveSecrets(resolved.secret);
|
|
103
|
-
return verify(token, access, resolved.algorithm);
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Verify a refresh token and return the embedded session ID.
|
|
107
|
-
*
|
|
108
|
-
* @param token - Compact JWT refresh token string.
|
|
109
|
-
* @param config - Auth configuration used to derive the secret and algorithm.
|
|
110
|
-
* @returns Object with `sessionId` matching the one passed to {@link signRefreshToken}.
|
|
111
|
-
* @throws {SentriError} With `TOKEN_EXPIRED` if expired, `TOKEN_INVALID` otherwise.
|
|
112
|
-
*/
|
|
113
|
-
export function verifyRefreshToken(token, config) {
|
|
114
|
-
const resolved = resolveConfig(config);
|
|
115
|
-
const { refresh } = deriveSecrets(resolved.secret);
|
|
116
|
-
return verify(token, refresh, resolved.algorithm);
|
|
117
|
-
}
|
|
118
|
-
//# sourceMappingURL=token.js.map
|
package/dist/libs/token.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/libs/token.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { RequestHandler } from 'express';
|
|
2
|
-
/**
|
|
3
|
-
* Express middleware factory for role-based access control (RBAC).
|
|
4
|
-
*
|
|
5
|
-
* Passes if the authenticated user (set by `protect()`) has **at least one**
|
|
6
|
-
* of the specified `allowedRoles`. Calls `next(SentriError)` with code `FORBIDDEN`
|
|
7
|
-
* if no roles match, or `UNAUTHORIZED` if `req.user` is absent.
|
|
8
|
-
*
|
|
9
|
-
* Must be used **after** `protect()`.
|
|
10
|
-
*
|
|
11
|
-
* @param allowedRoles - One or more role strings. The user needs at least one of them.
|
|
12
|
-
* @returns An Express `RequestHandler` that enforces the role check.
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* router.delete('/posts/:id', protect(config), authorize('admin', 'moderator'), handler);
|
|
16
|
-
*/
|
|
17
|
-
export declare function authorize<TRole extends string>(...allowedRoles: TRole[]): RequestHandler;
|
|
18
|
-
//# sourceMappingURL=authorize.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/middleware/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,KAAK,SAAS,MAAM,EAAE,GAAG,YAAY,EAAE,KAAK,EAAE,GAAG,cAAc,CAcxF"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { SentriError } from '../errors/AuthError.js';
|
|
2
|
-
/**
|
|
3
|
-
* Express middleware factory for role-based access control (RBAC).
|
|
4
|
-
*
|
|
5
|
-
* Passes if the authenticated user (set by `protect()`) has **at least one**
|
|
6
|
-
* of the specified `allowedRoles`. Calls `next(SentriError)` with code `FORBIDDEN`
|
|
7
|
-
* if no roles match, or `UNAUTHORIZED` if `req.user` is absent.
|
|
8
|
-
*
|
|
9
|
-
* Must be used **after** `protect()`.
|
|
10
|
-
*
|
|
11
|
-
* @param allowedRoles - One or more role strings. The user needs at least one of them.
|
|
12
|
-
* @returns An Express `RequestHandler` that enforces the role check.
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* router.delete('/posts/:id', protect(config), authorize('admin', 'moderator'), handler);
|
|
16
|
-
*/
|
|
17
|
-
export function authorize(...allowedRoles) {
|
|
18
|
-
return (request, _response, next) => {
|
|
19
|
-
if (!request.user) {
|
|
20
|
-
return next(new SentriError('UNAUTHORIZED', 'Not authenticated'));
|
|
21
|
-
}
|
|
22
|
-
const userRoles = request.user.roles;
|
|
23
|
-
const hasRole = allowedRoles.some((role) => userRoles.includes(role));
|
|
24
|
-
if (!hasRole) {
|
|
25
|
-
return next(new SentriError('FORBIDDEN', `Requires one of roles: ${allowedRoles.join(', ')}`));
|
|
26
|
-
}
|
|
27
|
-
next();
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=authorize.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/middleware/authorize.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,SAAS,CAAuB,GAAG,YAAqB;IACtE,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,IAAI,WAAW,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,SAAS,GAAsB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QACxD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CACT,IAAI,WAAW,CAAC,WAAW,EAAE,0BAA0B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAClF,CAAC;QACJ,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type { ErrorRequestHandler } from 'express';
|
|
2
|
-
/**
|
|
3
|
-
* Options for {@link createErrorHandler}.
|
|
4
|
-
*/
|
|
5
|
-
export interface ErrorHandlerOptions {
|
|
6
|
-
/**
|
|
7
|
-
* Called for errors that are **not** a `SentriError` instance (or subclass).
|
|
8
|
-
*
|
|
9
|
-
* Use this to log unexpected server errors before the generic 500 response
|
|
10
|
-
* is sent. The error is passed as-is and may be any unknown value.
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* app.use(auth.errorHandler({
|
|
14
|
-
* onUnhandled: (err) => logger.error('Unhandled error', { err }),
|
|
15
|
-
* }));
|
|
16
|
-
*/
|
|
17
|
-
onUnhandled?: (error: unknown) => void;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Creates an Express error-handling middleware that formats every `SentriError`
|
|
21
|
-
* (including subclasses) into the standard sentri response envelope:
|
|
22
|
-
*
|
|
23
|
-
* ```json
|
|
24
|
-
* { "error": true, "statusCode": 401, "code": "UNAUTHORIZED", "message": "...", "data": null }
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* Prefer using `auth.errorHandler()` instead of calling this directly:
|
|
28
|
-
*
|
|
29
|
-
* ```typescript
|
|
30
|
-
* app.use('/auth', auth.router());
|
|
31
|
-
* app.use('/api', apiRouter);
|
|
32
|
-
*
|
|
33
|
-
* // Must come after all route/middleware registrations
|
|
34
|
-
* app.use(auth.errorHandler());
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* ---
|
|
38
|
-
*
|
|
39
|
-
* **Works with built-in sentri errors and your own subclasses**
|
|
40
|
-
*
|
|
41
|
-
* Because `instanceof SentriError` matches any subclass, you can define
|
|
42
|
-
* application-specific error types and have them automatically formatted
|
|
43
|
-
* by this handler:
|
|
44
|
-
*
|
|
45
|
-
* ```typescript
|
|
46
|
-
* import { SentriError } from 'sentri';
|
|
47
|
-
*
|
|
48
|
-
* // Extend SentriError for domain-specific failures
|
|
49
|
-
* export class NotFoundError extends SentriError {
|
|
50
|
-
* constructor(resource: string) {
|
|
51
|
-
* super('NOT_FOUND', `${resource} not found`, 404);
|
|
52
|
-
* }
|
|
53
|
-
* }
|
|
54
|
-
*
|
|
55
|
-
* export class PaymentError extends SentriError {
|
|
56
|
-
* constructor(message: string) {
|
|
57
|
-
* super('PAYMENT_FAILED', message, 402);
|
|
58
|
-
* }
|
|
59
|
-
* }
|
|
60
|
-
*
|
|
61
|
-
* // All of the above are caught and formatted by one handler
|
|
62
|
-
* app.use(auth.errorHandler({
|
|
63
|
-
* onUnhandled: (err) => console.error('Unexpected error:', err),
|
|
64
|
-
* }));
|
|
65
|
-
* ```
|
|
66
|
-
*
|
|
67
|
-
* @param options - Optional configuration (see {@link ErrorHandlerOptions}).
|
|
68
|
-
* @returns An Express `ErrorRequestHandler` (4-argument middleware).
|
|
69
|
-
*/
|
|
70
|
-
export declare function createErrorHandler(options?: ErrorHandlerOptions): ErrorRequestHandler;
|
|
71
|
-
//# sourceMappingURL=errorHandler.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGnD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,CAsBrF"}
|