@edium/halifax 2.1.0 → 2.2.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 (83) hide show
  1. package/CHANGELOG.md +64 -1
  2. package/README.md +102 -17
  3. package/README_AUTH.md +38 -0
  4. package/README_AUTOCRUD.md +5 -5
  5. package/README_CLASSES.md +322 -0
  6. package/README_HOOKS.md +275 -0
  7. package/README_INTERFACES.md +601 -0
  8. package/README_OPENAPI.md +471 -0
  9. package/README_REPO_ADAPTERS.md +77 -0
  10. package/README_TYPES.md +114 -0
  11. package/dist/adapters/orm/drizzle/DrizzleAdapter.d.ts +128 -0
  12. package/dist/adapters/orm/drizzle/DrizzleAdapter.js +255 -0
  13. package/dist/adapters/orm/drizzle/astToDrizzle.d.ts +21 -0
  14. package/dist/adapters/orm/drizzle/astToDrizzle.js +121 -0
  15. package/dist/adapters/orm/drizzle/index.d.ts +4 -0
  16. package/dist/adapters/orm/drizzle/index.js +2 -0
  17. package/dist/adapters/orm/prisma/PrismaAdapter.d.ts +1 -1
  18. package/dist/adapters/orm/prisma/PrismaAdapter.js +24 -1
  19. package/dist/adapters/orm/prisma/astToPrisma.d.ts +1 -2
  20. package/dist/adapters/orm/prisma/astToPrisma.js +1 -3
  21. package/dist/adapters/orm/prisma/helpers.js +1 -1
  22. package/dist/adapters/orm/prisma/types.d.ts +11 -11
  23. package/dist/auth/AuthStrategy.d.ts +6 -189
  24. package/dist/auth/AuthStrategy.js +4 -220
  25. package/dist/auth/strategies/AllowAllAuthStrategy.d.ts +6 -0
  26. package/dist/auth/strategies/AllowAllAuthStrategy.js +6 -0
  27. package/dist/auth/strategies/ApiKeyAuthStrategy.d.ts +25 -0
  28. package/dist/auth/strategies/ApiKeyAuthStrategy.js +39 -0
  29. package/dist/auth/strategies/JwtClaimsAuthStrategy.d.ts +32 -0
  30. package/dist/auth/strategies/JwtClaimsAuthStrategy.js +52 -0
  31. package/dist/auth/strategies/PassportStrategies.d.ts +94 -0
  32. package/dist/auth/strategies/PassportStrategies.js +142 -0
  33. package/dist/auth/strategies/types.d.ts +70 -0
  34. package/dist/core/crudRouter.d.ts +11 -18
  35. package/dist/core/crudRouter.js +95 -390
  36. package/dist/core/fields.d.ts +8 -0
  37. package/dist/core/fields.js +14 -0
  38. package/dist/core/handlerUtils.d.ts +70 -0
  39. package/dist/core/handlerUtils.js +193 -0
  40. package/dist/core/handlers/create.d.ts +3 -0
  41. package/dist/core/handlers/create.js +26 -0
  42. package/dist/core/handlers/deleteMany.d.ts +3 -0
  43. package/dist/core/handlers/deleteMany.js +24 -0
  44. package/dist/core/handlers/deleteOne.d.ts +3 -0
  45. package/dist/core/handlers/deleteOne.js +19 -0
  46. package/dist/core/handlers/query.d.ts +3 -0
  47. package/dist/core/handlers/query.js +23 -0
  48. package/dist/core/handlers/readMany.d.ts +3 -0
  49. package/dist/core/handlers/readMany.js +18 -0
  50. package/dist/core/handlers/readOne.d.ts +3 -0
  51. package/dist/core/handlers/readOne.js +23 -0
  52. package/dist/core/handlers/updateMany.d.ts +3 -0
  53. package/dist/core/handlers/updateMany.js +34 -0
  54. package/dist/core/handlers/updateOne.d.ts +3 -0
  55. package/dist/core/handlers/updateOne.js +20 -0
  56. package/dist/core/handlers/upsertOne.d.ts +3 -0
  57. package/dist/core/handlers/upsertOne.js +20 -0
  58. package/dist/core/hooks.d.ts +217 -0
  59. package/dist/core/queryString.js +1 -1
  60. package/dist/core/types.d.ts +38 -29
  61. package/dist/core/validation.d.ts +1 -2
  62. package/dist/core/validation.js +1 -3
  63. package/dist/index.d.ts +3 -6
  64. package/dist/index.js +3 -6
  65. package/dist/openapi/generateDocsHtml.d.ts +1 -0
  66. package/dist/openapi/generateDocsHtml.js +47 -0
  67. package/dist/openapi/index.d.ts +3 -0
  68. package/dist/openapi/index.js +2 -0
  69. package/dist/openapi/specGenerator.d.ts +149 -0
  70. package/dist/openapi/specGenerator.js +770 -0
  71. package/package.json +38 -22
  72. package/dist/enums/SqlComparison.d.ts +0 -28
  73. package/dist/enums/SqlComparison.js +0 -29
  74. package/dist/enums/SqlOperator.d.ts +0 -5
  75. package/dist/enums/SqlOperator.js +0 -6
  76. package/dist/enums/SqlOrder.d.ts +0 -5
  77. package/dist/enums/SqlOrder.js +0 -6
  78. package/dist/interfaces/IQueryFilter.d.ts +0 -17
  79. package/dist/interfaces/IQueryOptions.d.ts +0 -20
  80. package/dist/interfaces/ISort.d.ts +0 -8
  81. package/dist/interfaces/ISort.js +0 -1
  82. /package/dist/{interfaces/IQueryFilter.js → auth/strategies/types.js} +0 -0
  83. /package/dist/{interfaces/IQueryOptions.js → core/hooks.js} +0 -0
@@ -1,189 +1,6 @@
1
- import type { CrudAction, ResourceDefinition } from '../core/types.js';
2
- import type { HttpRequest } from '../core/types.js';
3
- /** Resolved user identity and access information returned by {@link AuthStrategy.authenticate}. */
4
- export interface AuthContext {
5
- /** Unique identifier for the authenticated user. */
6
- userId?: string;
7
- /** Roles granted to the user (checked against `requiredPermissions`). */
8
- roles?: string[];
9
- /** Explicit permission strings granted to the user. */
10
- permissions?: string[];
11
- /** Raw claims from the token or session payload. */
12
- claims?: Record<string, unknown>;
13
- /** Always `true` for a successfully authenticated context. */
14
- isAuthenticated: boolean;
15
- }
16
- /** Parameters passed to {@link AuthStrategy.authorize}. */
17
- export interface AuthorizeParams {
18
- /** The resolved authentication context for the current request. */
19
- auth: AuthContext;
20
- /** The CRUD action being performed. */
21
- action: CrudAction;
22
- /** The resource being accessed. */
23
- resource: ResourceDefinition;
24
- /** Permissions required for this action on this resource. */
25
- requiredPermissions: string[];
26
- /** The incoming request. */
27
- req: HttpRequest;
28
- }
29
- /** Contract for pluggable authentication and authorisation strategies. */
30
- export interface AuthStrategy {
31
- /**
32
- * Authenticate the request and return the caller's identity.
33
- * @param req - The incoming HTTP request.
34
- * @returns The resolved {@link AuthContext}, or a promise that resolves to one.
35
- * @throws {@link AuthenticationError} when the request cannot be authenticated.
36
- */
37
- authenticate(req: HttpRequest): Promise<AuthContext> | AuthContext;
38
- /**
39
- * Determine whether the authenticated caller may perform `action`.
40
- * @param params - Authorization context including the auth, action, resource, and required permissions.
41
- * @returns `true` to allow, `false` to deny.
42
- */
43
- authorize?(params: AuthorizeParams): Promise<boolean> | boolean;
44
- }
45
- /** Passes every request through without any authentication checks. Useful for public APIs or testing. */
46
- export declare class AllowAllAuthStrategy implements AuthStrategy {
47
- /**
48
- * Always returns an authenticated context with no user details.
49
- * @returns An {@link AuthContext} with `isAuthenticated: true`.
50
- */
51
- authenticate(): AuthContext;
52
- }
53
- /** Validates a static API key carried in a request header. */
54
- export declare class ApiKeyAuthStrategy implements AuthStrategy {
55
- private readonly expectedApiKey;
56
- private readonly headerName;
57
- /**
58
- * @param expectedApiKey - The secret key that callers must supply.
59
- * @param headerName - Header to read the key from (default: `x-api-key`).
60
- */
61
- constructor(expectedApiKey: string, headerName?: string);
62
- /**
63
- * Checks the API key header and returns an authenticated context.
64
- * @param req - The incoming HTTP request.
65
- * @returns An {@link AuthContext} with `isAuthenticated: true`.
66
- * @throws {@link AuthenticationError} when the key is absent (401).
67
- * @throws {@link AuthorizationError} when the key is present but incorrect (403).
68
- */
69
- authenticate(req: HttpRequest): AuthContext;
70
- }
71
- /** Authenticates via a Bearer JWT and authorises using roles/permissions embedded in its claims. */
72
- export declare class JwtClaimsAuthStrategy implements AuthStrategy {
73
- private readonly verifyToken;
74
- /**
75
- * @param verifyToken - Callback that verifies the JWT string and resolves to an {@link AuthContext}.
76
- * Throw to signal an invalid token.
77
- */
78
- constructor(verifyToken: (token: string, req: HttpRequest) => Promise<AuthContext> | AuthContext);
79
- /**
80
- * Extracts and verifies the Bearer token from the `Authorization` header.
81
- * @param req - The incoming HTTP request.
82
- * @returns The resolved {@link AuthContext} from the token verifier.
83
- * @throws {@link AuthenticationError} when the token is missing or invalid.
84
- */
85
- authenticate(req: HttpRequest): Promise<AuthContext>;
86
- /**
87
- * Returns `true` when the auth context satisfies all required permissions.
88
- * Checks both `permissions` and `roles` arrays against each required permission string.
89
- * @param params - Authorization context including required permissions and the resolved auth.
90
- * @returns `true` when all required permissions are satisfied, `false` otherwise.
91
- */
92
- authorize(params: AuthorizeParams): boolean;
93
- }
94
- /** Delegates authentication to a caller-provided Passport authenticate wrapper. */
95
- export declare class PassportAuthStrategy implements AuthStrategy {
96
- private readonly authenticateWithPassport;
97
- /**
98
- * @param authenticateWithPassport - Function that calls your Passport strategy
99
- * and resolves to an {@link AuthContext}.
100
- */
101
- constructor(authenticateWithPassport: (req: HttpRequest) => Promise<AuthContext> | AuthContext);
102
- /**
103
- * Delegates to the provided Passport authenticate wrapper.
104
- * @param req - The incoming HTTP request.
105
- * @returns The {@link AuthContext} resolved by the wrapper.
106
- */
107
- authenticate(req: HttpRequest): Promise<AuthContext>;
108
- }
109
- /** Minimal structural interface for a Passport.js instance (avoids a hard dependency on `passport`). */
110
- export interface PassportLike {
111
- /**
112
- * Authenticates a request using the named strategy.
113
- * @param strategy - Name of the registered Passport strategy.
114
- * @param options - Authentication options (e.g. `{ session: false }`).
115
- * @param callback - Called with the error or authenticated user on completion.
116
- * @returns An Express-style middleware function that drives the authentication flow.
117
- */
118
- authenticate(strategy: string, options: {
119
- session: boolean;
120
- }, callback: (err: unknown, user: unknown) => void): (req: unknown, res: unknown, next: (err?: unknown) => void) => void;
121
- }
122
- /** Options for {@link PassportJwtStrategy}. */
123
- export interface PassportJwtStrategyOptions {
124
- /** A Passport instance with a JWT strategy registered. */
125
- passport: PassportLike;
126
- /** Name of the Passport strategy to invoke (default: `'jwt'`). */
127
- strategy?: string;
128
- /** Maps the raw Passport user payload to an {@link AuthContext}. Defaults to reading `sub`/`id`, `roles`, and `permissions`. */
129
- mapUser?: (user: unknown) => AuthContext;
130
- }
131
- /** Authenticates via Passport's JWT strategy, invoking it programmatically without Express middleware. */
132
- export declare class PassportJwtStrategy implements AuthStrategy {
133
- private readonly passport;
134
- private readonly strategy;
135
- private readonly mapUser;
136
- /** @param options - Passport instance, optional strategy name, and optional user mapper. */
137
- constructor(options: PassportJwtStrategyOptions);
138
- /**
139
- * Runs the Passport JWT authenticate handler and resolves to an {@link AuthContext}.
140
- * @param req - The incoming HTTP request (must carry a `raw` property for Passport to read).
141
- * @returns The resolved {@link AuthContext}.
142
- * @throws {@link AuthenticationError} when Passport rejects the token or returns no user.
143
- */
144
- authenticate(req: HttpRequest): Promise<AuthContext>;
145
- /**
146
- * Returns `true` when the auth context satisfies all required permissions.
147
- * @param params - Authorization context including required permissions and the resolved auth.
148
- * @returns `true` when all required permissions are satisfied, `false` otherwise.
149
- */
150
- authorize(params: AuthorizeParams): boolean;
151
- }
152
- /** Authenticates via Auth0-issued JWTs. Alias of {@link JwtClaimsAuthStrategy}. */
153
- export declare class Auth0JwtStrategy extends JwtClaimsAuthStrategy {
154
- }
155
- /** Authenticates via Firebase ID tokens. Alias of {@link JwtClaimsAuthStrategy}. */
156
- export declare class FirebaseJwtStrategy extends JwtClaimsAuthStrategy {
157
- }
158
- /**
159
- * Authenticates using Passport session cookies.
160
- *
161
- * Passport's session middleware must run before Halifax and populate `req.user`
162
- * automatically — this strategy simply reads that value and maps it to an
163
- * {@link AuthContext}. No passport instance is needed here.
164
- *
165
- * Prerequisites (add to your Express app before mounting Halifax):
166
- * ```ts
167
- * app.use(session({ ... }))
168
- * app.use(passport.initialize())
169
- * app.use(passport.session())
170
- * ```
171
- */
172
- export declare class PassportSessionStrategy implements AuthStrategy {
173
- private readonly mapUser;
174
- /** @param mapUser - Optional function to convert the raw session user to an {@link AuthContext}. */
175
- constructor(mapUser?: (user: unknown) => AuthContext);
176
- /**
177
- * Reads `req.raw.user` (set by Passport session middleware) and maps it to an {@link AuthContext}.
178
- * @param req - The incoming HTTP request whose `raw.user` property holds the session user.
179
- * @returns The mapped {@link AuthContext}.
180
- * @throws {@link AuthenticationError} when `req.raw.user` is absent (not authenticated).
181
- */
182
- authenticate(req: HttpRequest): AuthContext;
183
- /**
184
- * Returns `true` when the auth context satisfies all required permissions.
185
- * @param params - Authorization context including required permissions and the resolved auth.
186
- * @returns `true` when all required permissions are satisfied, `false` otherwise.
187
- */
188
- authorize(params: AuthorizeParams): boolean;
189
- }
1
+ export type { AuthContext, AuthorizeParams, SecurityScheme, AuthStrategy } from './strategies/types.js';
2
+ export { AllowAllAuthStrategy } from './strategies/AllowAllAuthStrategy.js';
3
+ export { ApiKeyAuthStrategy } from './strategies/ApiKeyAuthStrategy.js';
4
+ export { JwtClaimsAuthStrategy, Auth0JwtStrategy, FirebaseJwtStrategy } from './strategies/JwtClaimsAuthStrategy.js';
5
+ export type { PassportLike, PassportJwtStrategyOptions } from './strategies/PassportStrategies.js';
6
+ export { PassportAuthStrategy, PassportJwtStrategy, PassportSessionStrategy } from './strategies/PassportStrategies.js';
@@ -1,220 +1,4 @@
1
- import { AuthenticationError } from '../errors/AuthenticationError.js';
2
- import { AuthorizationError } from '../errors/AuthorizationError.js';
3
- /** Passes every request through without any authentication checks. Useful for public APIs or testing. */
4
- export class AllowAllAuthStrategy {
5
- /**
6
- * Always returns an authenticated context with no user details.
7
- * @returns An {@link AuthContext} with `isAuthenticated: true`.
8
- */
9
- authenticate() {
10
- return { isAuthenticated: true };
11
- }
12
- }
13
- /** Validates a static API key carried in a request header. */
14
- export class ApiKeyAuthStrategy {
15
- expectedApiKey;
16
- headerName;
17
- /**
18
- * @param expectedApiKey - The secret key that callers must supply.
19
- * @param headerName - Header to read the key from (default: `x-api-key`).
20
- */
21
- constructor(expectedApiKey, headerName = 'x-api-key') {
22
- this.expectedApiKey = expectedApiKey;
23
- this.headerName = headerName;
24
- }
25
- /**
26
- * Checks the API key header and returns an authenticated context.
27
- * @param req - The incoming HTTP request.
28
- * @returns An {@link AuthContext} with `isAuthenticated: true`.
29
- * @throws {@link AuthenticationError} when the key is absent (401).
30
- * @throws {@link AuthorizationError} when the key is present but incorrect (403).
31
- */
32
- authenticate(req) {
33
- const header = req.headers[this.headerName.toLowerCase()] ?? req.headers[this.headerName];
34
- const apiKey = Array.isArray(header) ? header[0] : header;
35
- if (!apiKey)
36
- throw new AuthenticationError('Missing API key');
37
- if (apiKey !== this.expectedApiKey)
38
- throw new AuthorizationError('Invalid API key');
39
- return { isAuthenticated: true };
40
- }
41
- }
42
- /** Authenticates via a Bearer JWT and authorises using roles/permissions embedded in its claims. */
43
- export class JwtClaimsAuthStrategy {
44
- verifyToken;
45
- /**
46
- * @param verifyToken - Callback that verifies the JWT string and resolves to an {@link AuthContext}.
47
- * Throw to signal an invalid token.
48
- */
49
- constructor(verifyToken) {
50
- this.verifyToken = verifyToken;
51
- }
52
- /**
53
- * Extracts and verifies the Bearer token from the `Authorization` header.
54
- * @param req - The incoming HTTP request.
55
- * @returns The resolved {@link AuthContext} from the token verifier.
56
- * @throws {@link AuthenticationError} when the token is missing or invalid.
57
- */
58
- async authenticate(req) {
59
- const header = req.headers.authorization ?? req.headers.Authorization;
60
- const value = Array.isArray(header) ? header[0] : header;
61
- const match = typeof value === 'string' ? value.match(/^Bearer\s+(.+)$/i) : null;
62
- if (!match) {
63
- throw new AuthenticationError('Missing bearer token');
64
- }
65
- return await this.verifyToken(match[1], req);
66
- }
67
- /**
68
- * Returns `true` when the auth context satisfies all required permissions.
69
- * Checks both `permissions` and `roles` arrays against each required permission string.
70
- * @param params - Authorization context including required permissions and the resolved auth.
71
- * @returns `true` when all required permissions are satisfied, `false` otherwise.
72
- */
73
- authorize(params) {
74
- if (!params.requiredPermissions.length) {
75
- return true;
76
- }
77
- const permissions = new Set(params.auth.permissions ?? []);
78
- const roles = new Set(params.auth.roles ?? []);
79
- return params.requiredPermissions.every((permission) => {
80
- return permissions.has(permission) || roles.has(permission);
81
- });
82
- }
83
- }
84
- /** Delegates authentication to a caller-provided Passport authenticate wrapper. */
85
- export class PassportAuthStrategy {
86
- authenticateWithPassport;
87
- /**
88
- * @param authenticateWithPassport - Function that calls your Passport strategy
89
- * and resolves to an {@link AuthContext}.
90
- */
91
- constructor(authenticateWithPassport) {
92
- this.authenticateWithPassport = authenticateWithPassport;
93
- }
94
- /**
95
- * Delegates to the provided Passport authenticate wrapper.
96
- * @param req - The incoming HTTP request.
97
- * @returns The {@link AuthContext} resolved by the wrapper.
98
- */
99
- async authenticate(req) {
100
- return await this.authenticateWithPassport(req);
101
- }
102
- }
103
- /**
104
- * Extracts `userId`, `roles`, `permissions`, and `claims` from a raw Passport user payload.
105
- * @param user - The raw user object returned by Passport (typically a decoded JWT payload).
106
- * @returns A fully populated {@link AuthContext}.
107
- */
108
- function defaultMapUser(user) {
109
- const p = (user ?? {});
110
- const userId = typeof p.sub === 'string' ? p.sub : typeof p.id === 'string' ? p.id : undefined;
111
- const ctx = {
112
- isAuthenticated: true,
113
- roles: Array.isArray(p.roles) ? p.roles : [],
114
- permissions: Array.isArray(p.permissions) ? p.permissions : [],
115
- claims: p
116
- };
117
- if (userId !== undefined)
118
- ctx.userId = userId;
119
- return ctx;
120
- }
121
- /** Authenticates via Passport's JWT strategy, invoking it programmatically without Express middleware. */
122
- export class PassportJwtStrategy {
123
- passport;
124
- strategy;
125
- mapUser;
126
- /** @param options - Passport instance, optional strategy name, and optional user mapper. */
127
- constructor(options) {
128
- this.passport = options.passport;
129
- this.strategy = options.strategy ?? 'jwt';
130
- this.mapUser = options.mapUser ?? defaultMapUser;
131
- }
132
- /**
133
- * Runs the Passport JWT authenticate handler and resolves to an {@link AuthContext}.
134
- * @param req - The incoming HTTP request (must carry a `raw` property for Passport to read).
135
- * @returns The resolved {@link AuthContext}.
136
- * @throws {@link AuthenticationError} when Passport rejects the token or returns no user.
137
- */
138
- async authenticate(req) {
139
- return new Promise((resolve, reject) => {
140
- const handler = this.passport.authenticate(this.strategy, { session: false }, (err, user) => {
141
- if (err) {
142
- reject(err instanceof Error ? err : new AuthenticationError(String(err)));
143
- return;
144
- }
145
- if (!user) {
146
- reject(new AuthenticationError('Unauthorized'));
147
- return;
148
- }
149
- resolve(this.mapUser(user));
150
- });
151
- handler(req.raw, {}, (err) => {
152
- if (err)
153
- reject(err instanceof Error ? err : new AuthenticationError(String(err)));
154
- });
155
- });
156
- }
157
- /**
158
- * Returns `true` when the auth context satisfies all required permissions.
159
- * @param params - Authorization context including required permissions and the resolved auth.
160
- * @returns `true` when all required permissions are satisfied, `false` otherwise.
161
- */
162
- authorize(params) {
163
- if (!params.requiredPermissions.length)
164
- return true;
165
- const permissions = new Set(params.auth.permissions ?? []);
166
- const roles = new Set(params.auth.roles ?? []);
167
- return params.requiredPermissions.every((p) => permissions.has(p) || roles.has(p));
168
- }
169
- }
170
- /** Authenticates via Auth0-issued JWTs. Alias of {@link JwtClaimsAuthStrategy}. */
171
- export class Auth0JwtStrategy extends JwtClaimsAuthStrategy {
172
- }
173
- /** Authenticates via Firebase ID tokens. Alias of {@link JwtClaimsAuthStrategy}. */
174
- export class FirebaseJwtStrategy extends JwtClaimsAuthStrategy {
175
- }
176
- /**
177
- * Authenticates using Passport session cookies.
178
- *
179
- * Passport's session middleware must run before Halifax and populate `req.user`
180
- * automatically — this strategy simply reads that value and maps it to an
181
- * {@link AuthContext}. No passport instance is needed here.
182
- *
183
- * Prerequisites (add to your Express app before mounting Halifax):
184
- * ```ts
185
- * app.use(session({ ... }))
186
- * app.use(passport.initialize())
187
- * app.use(passport.session())
188
- * ```
189
- */
190
- export class PassportSessionStrategy {
191
- mapUser;
192
- /** @param mapUser - Optional function to convert the raw session user to an {@link AuthContext}. */
193
- constructor(mapUser) {
194
- this.mapUser = mapUser ?? defaultMapUser;
195
- }
196
- /**
197
- * Reads `req.raw.user` (set by Passport session middleware) and maps it to an {@link AuthContext}.
198
- * @param req - The incoming HTTP request whose `raw.user` property holds the session user.
199
- * @returns The mapped {@link AuthContext}.
200
- * @throws {@link AuthenticationError} when `req.raw.user` is absent (not authenticated).
201
- */
202
- authenticate(req) {
203
- const user = req.raw != null ? req.raw['user'] : undefined;
204
- if (!user)
205
- throw new AuthenticationError('Not authenticated');
206
- return this.mapUser(user);
207
- }
208
- /**
209
- * Returns `true` when the auth context satisfies all required permissions.
210
- * @param params - Authorization context including required permissions and the resolved auth.
211
- * @returns `true` when all required permissions are satisfied, `false` otherwise.
212
- */
213
- authorize(params) {
214
- if (!params.requiredPermissions.length)
215
- return true;
216
- const permissions = new Set(params.auth.permissions ?? []);
217
- const roles = new Set(params.auth.roles ?? []);
218
- return params.requiredPermissions.every((p) => permissions.has(p) || roles.has(p));
219
- }
220
- }
1
+ export { AllowAllAuthStrategy } from './strategies/AllowAllAuthStrategy.js';
2
+ export { ApiKeyAuthStrategy } from './strategies/ApiKeyAuthStrategy.js';
3
+ export { JwtClaimsAuthStrategy, Auth0JwtStrategy, FirebaseJwtStrategy } from './strategies/JwtClaimsAuthStrategy.js';
4
+ export { PassportAuthStrategy, PassportJwtStrategy, PassportSessionStrategy } from './strategies/PassportStrategies.js';
@@ -0,0 +1,6 @@
1
+ import type { HttpRequest } from '../../core/types.js';
2
+ import type { AuthContext, AuthStrategy } from './types.js';
3
+ /** Passes every request through without any authentication checks. Useful for public APIs or testing. */
4
+ export declare class AllowAllAuthStrategy implements AuthStrategy {
5
+ authenticate(_req: HttpRequest): AuthContext;
6
+ }
@@ -0,0 +1,6 @@
1
+ /** Passes every request through without any authentication checks. Useful for public APIs or testing. */
2
+ export class AllowAllAuthStrategy {
3
+ authenticate(_req) {
4
+ return { isAuthenticated: true };
5
+ }
6
+ }
@@ -0,0 +1,25 @@
1
+ import type { HttpRequest } from '../../core/types.js';
2
+ import type { AuthContext, AuthStrategy, SecurityScheme } from './types.js';
3
+ /** Validates a static API key carried in a request header. */
4
+ export declare class ApiKeyAuthStrategy implements AuthStrategy {
5
+ private readonly expectedApiKey;
6
+ private readonly headerName;
7
+ private readonly roles;
8
+ /**
9
+ * @param expectedApiKey - The secret key that callers must supply.
10
+ * @param headerName - Header to read the key from (default: `x-api-key`).
11
+ * @param roles - Roles to attach to every successfully authenticated context.
12
+ * Use this when resources define per-field `readRoles`/`writeRoles` and
13
+ * all valid API key holders should carry a known set of roles.
14
+ */
15
+ constructor(expectedApiKey: string, headerName?: string, roles?: string[]);
16
+ /**
17
+ * Checks the API key header and returns an authenticated context.
18
+ * @param req - The incoming HTTP request.
19
+ * @returns An {@link AuthContext} with `isAuthenticated: true`.
20
+ * @throws {@link AuthenticationError} when the key is absent (401).
21
+ * @throws {@link AuthorizationError} when the key is present but incorrect (403).
22
+ */
23
+ authenticate(req: HttpRequest): AuthContext;
24
+ openApiScheme(): SecurityScheme;
25
+ }
@@ -0,0 +1,39 @@
1
+ import { AuthenticationError } from '../../errors/AuthenticationError.js';
2
+ import { AuthorizationError } from '../../errors/AuthorizationError.js';
3
+ /** Validates a static API key carried in a request header. */
4
+ export class ApiKeyAuthStrategy {
5
+ expectedApiKey;
6
+ headerName;
7
+ roles;
8
+ /**
9
+ * @param expectedApiKey - The secret key that callers must supply.
10
+ * @param headerName - Header to read the key from (default: `x-api-key`).
11
+ * @param roles - Roles to attach to every successfully authenticated context.
12
+ * Use this when resources define per-field `readRoles`/`writeRoles` and
13
+ * all valid API key holders should carry a known set of roles.
14
+ */
15
+ constructor(expectedApiKey, headerName = 'x-api-key', roles = []) {
16
+ this.expectedApiKey = expectedApiKey;
17
+ this.headerName = headerName;
18
+ this.roles = roles;
19
+ }
20
+ /**
21
+ * Checks the API key header and returns an authenticated context.
22
+ * @param req - The incoming HTTP request.
23
+ * @returns An {@link AuthContext} with `isAuthenticated: true`.
24
+ * @throws {@link AuthenticationError} when the key is absent (401).
25
+ * @throws {@link AuthorizationError} when the key is present but incorrect (403).
26
+ */
27
+ authenticate(req) {
28
+ const header = req.headers[this.headerName.toLowerCase()] ?? req.headers[this.headerName];
29
+ const apiKey = Array.isArray(header) ? header[0] : header;
30
+ if (!apiKey)
31
+ throw new AuthenticationError('Missing API key');
32
+ if (apiKey !== this.expectedApiKey)
33
+ throw new AuthorizationError('Invalid API key');
34
+ return { isAuthenticated: true, roles: this.roles };
35
+ }
36
+ openApiScheme() {
37
+ return { type: 'apiKey', in: 'header', name: this.headerName };
38
+ }
39
+ }
@@ -0,0 +1,32 @@
1
+ import type { HttpRequest } from '../../core/types.js';
2
+ import type { AuthContext, AuthorizeParams, AuthStrategy, SecurityScheme } from './types.js';
3
+ /** Authenticates via a Bearer JWT and authorises using roles/permissions embedded in its claims. */
4
+ export declare class JwtClaimsAuthStrategy implements AuthStrategy {
5
+ private readonly verifyToken;
6
+ /**
7
+ * @param verifyToken - Callback that verifies the JWT string and resolves to an {@link AuthContext}.
8
+ * Throw to signal an invalid token.
9
+ */
10
+ constructor(verifyToken: (token: string, req: HttpRequest) => Promise<AuthContext> | AuthContext);
11
+ /**
12
+ * Extracts and verifies the Bearer token from the `Authorization` header.
13
+ * @param req - The incoming HTTP request.
14
+ * @returns The resolved {@link AuthContext} from the token verifier.
15
+ * @throws {@link AuthenticationError} when the token is missing or invalid.
16
+ */
17
+ authenticate(req: HttpRequest): Promise<AuthContext>;
18
+ /**
19
+ * Returns `true` when the auth context satisfies all required permissions.
20
+ * Checks both `permissions` and `roles` arrays against each required permission string.
21
+ * @param params - Authorization context including required permissions and the resolved auth.
22
+ * @returns `true` when all required permissions are satisfied, `false` otherwise.
23
+ */
24
+ authorize(params: AuthorizeParams): boolean;
25
+ openApiScheme(): SecurityScheme;
26
+ }
27
+ /** Authenticates via Auth0-issued JWTs. Alias of {@link JwtClaimsAuthStrategy}. */
28
+ export declare class Auth0JwtStrategy extends JwtClaimsAuthStrategy {
29
+ }
30
+ /** Authenticates via Firebase ID tokens. Alias of {@link JwtClaimsAuthStrategy}. */
31
+ export declare class FirebaseJwtStrategy extends JwtClaimsAuthStrategy {
32
+ }
@@ -0,0 +1,52 @@
1
+ import { AuthenticationError } from '../../errors/AuthenticationError.js';
2
+ /** Authenticates via a Bearer JWT and authorises using roles/permissions embedded in its claims. */
3
+ export class JwtClaimsAuthStrategy {
4
+ verifyToken;
5
+ /**
6
+ * @param verifyToken - Callback that verifies the JWT string and resolves to an {@link AuthContext}.
7
+ * Throw to signal an invalid token.
8
+ */
9
+ constructor(verifyToken) {
10
+ this.verifyToken = verifyToken;
11
+ }
12
+ /**
13
+ * Extracts and verifies the Bearer token from the `Authorization` header.
14
+ * @param req - The incoming HTTP request.
15
+ * @returns The resolved {@link AuthContext} from the token verifier.
16
+ * @throws {@link AuthenticationError} when the token is missing or invalid.
17
+ */
18
+ async authenticate(req) {
19
+ const header = req.headers.authorization ?? req.headers.Authorization;
20
+ const value = Array.isArray(header) ? header[0] : header;
21
+ const match = typeof value === 'string' ? value.match(/^Bearer\s+(.+)$/i) : null;
22
+ if (!match) {
23
+ throw new AuthenticationError('Missing bearer token');
24
+ }
25
+ return await this.verifyToken(match[1], req);
26
+ }
27
+ /**
28
+ * Returns `true` when the auth context satisfies all required permissions.
29
+ * Checks both `permissions` and `roles` arrays against each required permission string.
30
+ * @param params - Authorization context including required permissions and the resolved auth.
31
+ * @returns `true` when all required permissions are satisfied, `false` otherwise.
32
+ */
33
+ authorize(params) {
34
+ if (!params.requiredPermissions.length) {
35
+ return true;
36
+ }
37
+ const permissions = new Set(params.auth.permissions ?? []);
38
+ const roles = new Set(params.auth.roles ?? []);
39
+ return params.requiredPermissions.every((permission) => {
40
+ return permissions.has(permission) || roles.has(permission);
41
+ });
42
+ }
43
+ openApiScheme() {
44
+ return { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' };
45
+ }
46
+ }
47
+ /** Authenticates via Auth0-issued JWTs. Alias of {@link JwtClaimsAuthStrategy}. */
48
+ export class Auth0JwtStrategy extends JwtClaimsAuthStrategy {
49
+ }
50
+ /** Authenticates via Firebase ID tokens. Alias of {@link JwtClaimsAuthStrategy}. */
51
+ export class FirebaseJwtStrategy extends JwtClaimsAuthStrategy {
52
+ }