@igxjs/node-components 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -4
- package/components/http-handlers.js +6 -0
- package/components/jwt.js +89 -45
- package/components/session.js +571 -101
- package/index.d.ts +114 -44
- package/index.js +1 -1
- package/package.json +10 -3
- package/.github/workflows/node.js.yml +0 -31
- package/.github/workflows/npm-publish.yml +0 -33
- package/docs/README.md +0 -54
- package/docs/flex-router.md +0 -167
- package/docs/http-handlers.md +0 -302
- package/docs/jwt-manager.md +0 -124
- package/docs/redis-manager.md +0 -210
- package/docs/session-manager.md +0 -160
- package/tests/http-handlers.test.js +0 -21
- package/tests/jwt.test.js +0 -345
- package/tests/redis.test.js +0 -50
- package/tests/router.test.js +0 -50
- package/tests/session.test.js +0 -116
package/index.d.ts
CHANGED
|
@@ -5,14 +5,26 @@ import { EncryptJWT, JWTDecryptResult, JWTPayload } from 'jose';
|
|
|
5
5
|
import { RedisClientType } from '@redis/client';
|
|
6
6
|
import { Application, RequestHandler, Request, Response, NextFunction, Router } from 'express';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
export { JWTPayload } from 'jose';
|
|
9
|
+
|
|
10
|
+
// Session Mode constants
|
|
11
|
+
export const SessionMode: {
|
|
12
|
+
SESSION: string;
|
|
13
|
+
TOKEN: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Session Configuration - uses strict UPPERCASE naming convention for all property names
|
|
9
17
|
export interface SessionConfig {
|
|
18
|
+
/** Identity Provider */
|
|
10
19
|
SSO_ENDPOINT_URL?: string;
|
|
11
20
|
SSO_CLIENT_ID?: string;
|
|
12
21
|
SSO_CLIENT_SECRET?: string;
|
|
13
22
|
SSO_SUCCESS_URL?: string;
|
|
14
23
|
SSO_FAILURE_URL?: string;
|
|
15
24
|
|
|
25
|
+
/** Authentication mode: 'session' or 'token' (default: 'session') */
|
|
26
|
+
SESSION_MODE?: string;
|
|
27
|
+
|
|
16
28
|
SESSION_AGE?: number;
|
|
17
29
|
SESSION_COOKIE_PATH?: string;
|
|
18
30
|
SESSION_SECRET?: string;
|
|
@@ -20,6 +32,15 @@ export interface SessionConfig {
|
|
|
20
32
|
|
|
21
33
|
REDIS_URL?: string;
|
|
22
34
|
REDIS_CERT_PATH?: string;
|
|
35
|
+
|
|
36
|
+
JWT_ALGORITHM?: string;
|
|
37
|
+
JWT_ENCRYPTION?: string;
|
|
38
|
+
JWT_EXPIRATION_TIME?: string;
|
|
39
|
+
JWT_CLOCK_TOLERANCE?: number;
|
|
40
|
+
JWT_SECRET_HASH_ALGORITHM?: string;
|
|
41
|
+
JWT_ISSUER?: string;
|
|
42
|
+
JWT_AUDIENCE?: string;
|
|
43
|
+
JWT_SUBJECT?: string;
|
|
23
44
|
}
|
|
24
45
|
|
|
25
46
|
export interface SessionUserAttributes {
|
|
@@ -58,7 +79,7 @@ export interface SessionUser {
|
|
|
58
79
|
export class SessionManager {
|
|
59
80
|
/**
|
|
60
81
|
* Constructor
|
|
61
|
-
* @param config - Session configuration
|
|
82
|
+
* @param config - Session configuration (uses strict UPPERCASE property names)
|
|
62
83
|
*/
|
|
63
84
|
constructor(config: SessionConfig);
|
|
64
85
|
|
|
@@ -97,15 +118,35 @@ export class SessionManager {
|
|
|
97
118
|
): Promise<void>;
|
|
98
119
|
|
|
99
120
|
/**
|
|
100
|
-
* Resource protection middleware
|
|
121
|
+
* Resource protection middleware based on configured SESSION_MODE
|
|
122
|
+
* Uses verifySession() for SESSION mode and verifyToken() for TOKEN mode
|
|
101
123
|
* @param isDebugging Debugging flag (default: false)
|
|
102
124
|
* @param redirectUrl Redirect URL (default: '')
|
|
103
125
|
* @returns Returns express Request Handler
|
|
104
126
|
*/
|
|
105
127
|
authenticate(isDebugging?: boolean, redirectUrl?: string): RequestHandler;
|
|
106
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Resource protection by token (explicit token verification)
|
|
131
|
+
* Requires Authorization: Bearer {token} header
|
|
132
|
+
* @param isDebugging Debugging flag (default: false)
|
|
133
|
+
* @param redirectUrl Redirect URL (default: '')
|
|
134
|
+
* @returns Returns express Request Handler
|
|
135
|
+
*/
|
|
136
|
+
verifyToken(isDebugging?: boolean, redirectUrl?: string): RequestHandler;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Resource protection by session (explicit session verification)
|
|
140
|
+
* @param isDebugging Debugging flag (default: false)
|
|
141
|
+
* @param redirectUrl Redirect URL (default: '')
|
|
142
|
+
* @returns Returns express Request Handler
|
|
143
|
+
*/
|
|
144
|
+
verifySession(isDebugging?: boolean, redirectUrl?: string): RequestHandler;
|
|
145
|
+
|
|
107
146
|
/**
|
|
108
147
|
* SSO callback for successful login
|
|
148
|
+
* SESSION mode: Saves session and redirects
|
|
149
|
+
* TOKEN mode: Generates JWT token, returns HTML page with localStorage script
|
|
109
150
|
* @param initUser Initialize user object function
|
|
110
151
|
* @returns Returns express Request Handler
|
|
111
152
|
*/
|
|
@@ -118,17 +159,22 @@ export class SessionManager {
|
|
|
118
159
|
identityProviders(): RequestHandler;
|
|
119
160
|
|
|
120
161
|
/**
|
|
121
|
-
*
|
|
162
|
+
* Refresh user authentication based on configured SESSION_MODE
|
|
163
|
+
* SESSION mode: Refreshes session data
|
|
164
|
+
* TOKEN mode: Generates new token, invalidates old token
|
|
165
|
+
* @param initUser Initialize user object function
|
|
122
166
|
* @returns Returns express Request Handler
|
|
123
167
|
*/
|
|
124
|
-
|
|
168
|
+
refresh(initUser: (user: SessionUser) => SessionUser): RequestHandler;
|
|
125
169
|
|
|
126
170
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
171
|
+
* Application logout based on configured SESSION_MODE (NOT SSO)
|
|
172
|
+
* SESSION mode: Destroys session and clears cookie
|
|
173
|
+
* TOKEN mode: Invalidates current token or all tokens (with ?all=true query param)
|
|
174
|
+
* Query params: redirect=true (redirect to success/failure URL), all=true (logout all tokens - TOKEN mode only)
|
|
129
175
|
* @returns Returns express Request Handler
|
|
130
176
|
*/
|
|
131
|
-
|
|
177
|
+
logout(): RequestHandler;
|
|
132
178
|
}
|
|
133
179
|
|
|
134
180
|
// Custom Error class
|
|
@@ -187,7 +233,7 @@ export class RedisManager {
|
|
|
187
233
|
|
|
188
234
|
/**
|
|
189
235
|
* Determine if the Redis server is connected
|
|
190
|
-
* @returns Returns true if Redis server is connected
|
|
236
|
+
* @returns Returns true if the Redis server is connected
|
|
191
237
|
*/
|
|
192
238
|
isConnected(): Promise<boolean>;
|
|
193
239
|
|
|
@@ -198,57 +244,81 @@ export class RedisManager {
|
|
|
198
244
|
disConnect(): Promise<void>;
|
|
199
245
|
}
|
|
200
246
|
|
|
201
|
-
// JWT Manager Configuration
|
|
247
|
+
// JWT Manager Configuration - uses strict UPPERCASE naming convention with JWT_ prefix for all property names
|
|
202
248
|
export interface JwtManagerOptions {
|
|
203
|
-
/**
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
encryption
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
249
|
+
/** JWE algorithm (default: 'dir') */
|
|
250
|
+
JWT_ALGORITHM?: string;
|
|
251
|
+
|
|
252
|
+
/** JWE encryption method (default: 'A256GCM') */
|
|
253
|
+
JWT_ENCRYPTION?: string;
|
|
254
|
+
|
|
255
|
+
/** Token expiration time (default: '10m') */
|
|
256
|
+
JWT_EXPIRATION_TIME?: string;
|
|
257
|
+
|
|
258
|
+
/** Clock tolerance in seconds for token validation (default: 30) */
|
|
259
|
+
JWT_CLOCK_TOLERANCE?: number;
|
|
260
|
+
|
|
261
|
+
/** Hash algorithm for secret derivation (default: 'SHA-256') */
|
|
262
|
+
JWT_SECRET_HASH_ALGORITHM?: string;
|
|
263
|
+
|
|
264
|
+
/** Optional JWT issuer claim */
|
|
265
|
+
JWT_ISSUER?: string;
|
|
266
|
+
|
|
267
|
+
/** Optional JWT audience claim */
|
|
268
|
+
JWT_AUDIENCE?: string;
|
|
269
|
+
|
|
270
|
+
/** Optional JWT subject claim */
|
|
271
|
+
JWT_SUBJECT?: string;
|
|
219
272
|
}
|
|
220
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Options for encrypt() method - uses camelCase naming convention
|
|
276
|
+
*/
|
|
221
277
|
export interface JwtEncryptOptions {
|
|
222
|
-
/**
|
|
278
|
+
/** Override default algorithm */
|
|
223
279
|
algorithm?: string;
|
|
224
|
-
|
|
280
|
+
|
|
281
|
+
/** Override default encryption method */
|
|
225
282
|
encryption?: string;
|
|
226
|
-
|
|
283
|
+
|
|
284
|
+
/** Override default expiration time */
|
|
227
285
|
expirationTime?: string;
|
|
228
|
-
|
|
286
|
+
|
|
287
|
+
/** Override default hash algorithm */
|
|
229
288
|
secretHashAlgorithm?: string;
|
|
230
|
-
|
|
289
|
+
|
|
290
|
+
/** Override default issuer claim */
|
|
231
291
|
issuer?: string;
|
|
232
|
-
|
|
292
|
+
|
|
293
|
+
/** Override default audience claim */
|
|
233
294
|
audience?: string;
|
|
234
|
-
|
|
295
|
+
|
|
296
|
+
/** Override default subject claim */
|
|
235
297
|
subject?: string;
|
|
236
298
|
}
|
|
237
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Options for decrypt() method - uses camelCase naming convention
|
|
302
|
+
*/
|
|
238
303
|
export interface JwtDecryptOptions {
|
|
239
|
-
/**
|
|
304
|
+
/** Override default clock tolerance */
|
|
240
305
|
clockTolerance?: number;
|
|
241
|
-
|
|
306
|
+
|
|
307
|
+
/** Override default hash algorithm */
|
|
242
308
|
secretHashAlgorithm?: string;
|
|
243
|
-
|
|
309
|
+
|
|
310
|
+
/** Expected issuer claim for validation */
|
|
244
311
|
issuer?: string;
|
|
245
|
-
|
|
312
|
+
|
|
313
|
+
/** Expected audience claim for validation */
|
|
246
314
|
audience?: string;
|
|
247
|
-
|
|
315
|
+
|
|
316
|
+
/** Expected subject claim for validation */
|
|
248
317
|
subject?: string;
|
|
249
318
|
}
|
|
250
319
|
|
|
251
|
-
export type
|
|
320
|
+
export type JwtDecryptResult = JWTDecryptResult<EncryptJWT>;
|
|
321
|
+
|
|
252
322
|
// JwtManager class for JWT encryption and decryption
|
|
253
323
|
export class JwtManager {
|
|
254
324
|
algorithm: string;
|
|
@@ -262,7 +332,7 @@ export class JwtManager {
|
|
|
262
332
|
|
|
263
333
|
/**
|
|
264
334
|
* Create a new JwtManager instance with configurable defaults
|
|
265
|
-
* @param options Configuration options
|
|
335
|
+
* @param options Configuration options (uses strict UPPERCASE with JWT_ prefix property names)
|
|
266
336
|
*/
|
|
267
337
|
constructor(options?: JwtManagerOptions);
|
|
268
338
|
|
|
@@ -270,7 +340,7 @@ export class JwtManager {
|
|
|
270
340
|
* Generate JWT token for user session
|
|
271
341
|
* @param data User data payload
|
|
272
342
|
* @param input Secret key or password for encryption
|
|
273
|
-
* @param options Per-call configuration overrides
|
|
343
|
+
* @param options Per-call configuration overrides (uses strict UPPERCASE with JWT_ prefix property names)
|
|
274
344
|
* @returns Returns encrypted JWT token
|
|
275
345
|
*/
|
|
276
346
|
encrypt(data: JWTPayload, input: string, options?: JwtEncryptOptions): Promise<string>;
|
|
@@ -279,10 +349,10 @@ export class JwtManager {
|
|
|
279
349
|
* Decrypt JWT token for user session
|
|
280
350
|
* @param token JWT token to decrypt
|
|
281
351
|
* @param input Secret key or password for decryption
|
|
282
|
-
* @param options Per-call configuration overrides
|
|
352
|
+
* @param options Per-call configuration overrides (uses strict UPPERCASE with JWT_ prefix property names)
|
|
283
353
|
* @returns Returns decrypted JWT token
|
|
284
354
|
*/
|
|
285
|
-
decrypt(token: string, input: string, options?: JwtDecryptOptions): Promise<
|
|
355
|
+
decrypt(token: string, input: string, options?: JwtDecryptOptions): Promise<JwtDecryptResult>;
|
|
286
356
|
}
|
|
287
357
|
|
|
288
358
|
// HTTP status code keys (exposed for type safety)
|
|
@@ -400,4 +470,4 @@ declare module 'express-session' {
|
|
|
400
470
|
[key: string]: any;
|
|
401
471
|
user?: SessionUser;
|
|
402
472
|
}
|
|
403
|
-
}
|
|
473
|
+
}
|
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { SessionConfig, SessionManager } from './components/session.js';
|
|
1
|
+
export { SessionConfig, SessionManager, SessionMode } from './components/session.js';
|
|
2
2
|
export { httpCodes, httpMessages, httpErrorHandler, httpNotFoundHandler, CustomError, httpHelper, httpError } from './components/http-handlers.js';
|
|
3
3
|
export { RedisManager } from './components/redis.js';
|
|
4
4
|
export { FlexRouter } from './components/router.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@igxjs/node-components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Node components for igxjs",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -26,16 +26,23 @@
|
|
|
26
26
|
"axios": "^1.13.6",
|
|
27
27
|
"connect-redis": "^9.0.0",
|
|
28
28
|
"express-session": "^1.19.0",
|
|
29
|
-
"jose": "^6.
|
|
29
|
+
"jose": "^6.2.0",
|
|
30
30
|
"memorystore": "^1.6.7"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"chai": "^6.2.2",
|
|
34
34
|
"express": "^5.2.1",
|
|
35
|
-
"mocha": "^
|
|
35
|
+
"mocha": "^12.0.0-beta-10",
|
|
36
36
|
"sinon": "^21.0.2",
|
|
37
37
|
"supertest": "^7.0.0"
|
|
38
38
|
},
|
|
39
|
+
"files": [
|
|
40
|
+
"index.js",
|
|
41
|
+
"index.d.ts",
|
|
42
|
+
"components/",
|
|
43
|
+
"LICENSE",
|
|
44
|
+
"README.md"
|
|
45
|
+
],
|
|
39
46
|
"publishConfig": {
|
|
40
47
|
"access": "public"
|
|
41
48
|
},
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
|
2
|
-
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
|
|
3
|
-
|
|
4
|
-
name: Node.js CI
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
push:
|
|
8
|
-
branches: [ "main" ]
|
|
9
|
-
pull_request:
|
|
10
|
-
branches: [ "main" ]
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
build:
|
|
14
|
-
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
|
|
17
|
-
strategy:
|
|
18
|
-
matrix:
|
|
19
|
-
node-version: [18.x, 20.x, 22.x]
|
|
20
|
-
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
21
|
-
|
|
22
|
-
steps:
|
|
23
|
-
- uses: actions/checkout@v4
|
|
24
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
25
|
-
uses: actions/setup-node@v4
|
|
26
|
-
with:
|
|
27
|
-
node-version: ${{ matrix.node-version }}
|
|
28
|
-
cache: 'npm'
|
|
29
|
-
- run: npm ci
|
|
30
|
-
- run: npm run build --if-present
|
|
31
|
-
- run: npm test
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
-
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
|
3
|
-
|
|
4
|
-
name: Node.js Package
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
release:
|
|
8
|
-
types: [created]
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
build:
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v4
|
|
15
|
-
- uses: actions/setup-node@v4
|
|
16
|
-
with:
|
|
17
|
-
node-version: 20
|
|
18
|
-
- run: npm ci
|
|
19
|
-
- run: npm test
|
|
20
|
-
|
|
21
|
-
publish-npm:
|
|
22
|
-
needs: build
|
|
23
|
-
runs-on: ubuntu-latest
|
|
24
|
-
steps:
|
|
25
|
-
- uses: actions/checkout@v4
|
|
26
|
-
- uses: actions/setup-node@v4
|
|
27
|
-
with:
|
|
28
|
-
node-version: 20
|
|
29
|
-
registry-url: https://registry.npmjs.org/
|
|
30
|
-
- run: npm ci
|
|
31
|
-
- run: npm publish
|
|
32
|
-
env:
|
|
33
|
-
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
package/docs/README.md
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# Node Components Documentation
|
|
2
|
-
|
|
3
|
-
Detailed documentation for `@igxjs/node-components` - shared components for Express.js applications.
|
|
4
|
-
|
|
5
|
-
## 📚 Component Documentation
|
|
6
|
-
|
|
7
|
-
### Core Modules
|
|
8
|
-
|
|
9
|
-
- **[SessionManager](./session-manager.md)** - SSO session management with Redis and memory storage
|
|
10
|
-
- Configuration options and singleton pattern
|
|
11
|
-
- Complete setup and usage examples
|
|
12
|
-
- API reference for all methods
|
|
13
|
-
|
|
14
|
-
- **[FlexRouter](./flex-router.md)** - Flexible routing utility for Express.js
|
|
15
|
-
- Context path and middleware management
|
|
16
|
-
- API versioning and route organization
|
|
17
|
-
- Advanced usage patterns
|
|
18
|
-
|
|
19
|
-
- **[RedisManager](./redis-manager.md)** - Redis connection management
|
|
20
|
-
- TLS/SSL support
|
|
21
|
-
- Connection monitoring and error handling
|
|
22
|
-
- Direct Redis operations
|
|
23
|
-
|
|
24
|
-
- **[JWT Manager](./jwt-manager.md)** - JWT encryption and decryption
|
|
25
|
-
- Secure token-based authentication
|
|
26
|
-
- Express.js integration patterns
|
|
27
|
-
- Refresh token implementation
|
|
28
|
-
|
|
29
|
-
- **[HTTP Handlers](./http-handlers.md)** - Standardized error handling
|
|
30
|
-
- Custom error classes and middleware
|
|
31
|
-
- HTTP status codes and messages
|
|
32
|
-
- Axios error handling and validation helpers
|
|
33
|
-
|
|
34
|
-
## 🚀 Quick Links
|
|
35
|
-
|
|
36
|
-
- [Main README](../README.md) - Package overview and installation
|
|
37
|
-
- [GitHub Repository](https://github.com/igxjs/node-components)
|
|
38
|
-
|
|
39
|
-
## 💡 Getting Help
|
|
40
|
-
|
|
41
|
-
If you need help:
|
|
42
|
-
1. Check the relevant component documentation above
|
|
43
|
-
2. Review the examples in each guide
|
|
44
|
-
3. Look at the type definitions in `index.d.ts`
|
|
45
|
-
4. Open an issue on GitHub
|
|
46
|
-
|
|
47
|
-
## 📖 Documentation Structure
|
|
48
|
-
|
|
49
|
-
Each component documentation includes:
|
|
50
|
-
- Overview of features
|
|
51
|
-
- Configuration options
|
|
52
|
-
- Basic and advanced usage examples
|
|
53
|
-
- Complete API reference
|
|
54
|
-
- Related documentation links
|
package/docs/flex-router.md
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
# FlexRouter
|
|
2
|
-
|
|
3
|
-
A flexible routing utility for Express.js that allows mounting routers with custom context paths and middleware handlers.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
FlexRouter provides a convenient way to organize and mount Express routers with predefined context paths and optional middleware. This is particularly useful for:
|
|
8
|
-
- API versioning (e.g., `/api/v1`, `/api/v2`)
|
|
9
|
-
- Separating public and protected routes
|
|
10
|
-
- Applying middleware to specific route groups
|
|
11
|
-
- Managing complex routing hierarchies
|
|
12
|
-
|
|
13
|
-
## Usage Example
|
|
14
|
-
|
|
15
|
-
```javascript
|
|
16
|
-
import { Router } from 'express';
|
|
17
|
-
import { FlexRouter } from '@igxjs/node-components';
|
|
18
|
-
// Assuming you have an authenticate middleware
|
|
19
|
-
// import { authenticate } from './middlewares/auth.js';
|
|
20
|
-
|
|
21
|
-
// Create routers
|
|
22
|
-
const publicRouter = Router();
|
|
23
|
-
const privateRouter = Router();
|
|
24
|
-
|
|
25
|
-
publicRouter.get('/health', (req, res) => {
|
|
26
|
-
res.send('OK');
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
privateRouter.get('/users', (req, res) => {
|
|
30
|
-
res.json({ users: [] });
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
// Define flex routers with context paths and optional middleware
|
|
34
|
-
export const routers = [
|
|
35
|
-
new FlexRouter('/api/v1/public', publicRouter),
|
|
36
|
-
new FlexRouter('/api/v1/protected', privateRouter, [authenticate]), // with middleware
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
// Mount all routers to your Express app
|
|
40
|
-
const app = express();
|
|
41
|
-
const basePath = '';
|
|
42
|
-
|
|
43
|
-
routers.forEach(router => {
|
|
44
|
-
router.mount(app, basePath);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// Routes will be available at:
|
|
48
|
-
// - /api/v1/public/health
|
|
49
|
-
// - /api/v1/protected/users (with authenticate middleware)
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Advanced Usage
|
|
53
|
-
|
|
54
|
-
### Multiple Middleware
|
|
55
|
-
|
|
56
|
-
You can apply multiple middleware functions to a FlexRouter:
|
|
57
|
-
|
|
58
|
-
```javascript
|
|
59
|
-
import { rateLimiter } from './middlewares/rate-limiter.js';
|
|
60
|
-
import { logger } from './middlewares/logger.js';
|
|
61
|
-
import { authenticate } from './middlewares/auth.js';
|
|
62
|
-
|
|
63
|
-
const apiRouter = Router();
|
|
64
|
-
|
|
65
|
-
apiRouter.get('/data', (req, res) => {
|
|
66
|
-
res.json({ [] });
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Apply multiple middleware in order
|
|
70
|
-
const protectedApi = new FlexRouter(
|
|
71
|
-
'/api/v1',
|
|
72
|
-
apiRouter,
|
|
73
|
-
[logger, rateLimiter, authenticate] // Applied in this order
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
protectedApi.mount(app, '');
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Using Base Paths
|
|
80
|
-
|
|
81
|
-
You can add a base path when mounting routers, useful for multi-tenant applications:
|
|
82
|
-
|
|
83
|
-
```javascript
|
|
84
|
-
const tenantRouter = Router();
|
|
85
|
-
|
|
86
|
-
tenantRouter.get('/dashboard', (req, res) => {
|
|
87
|
-
res.json({ tenant: req.params.tenantId });
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const flexRouter = new FlexRouter('/api', tenantRouter);
|
|
91
|
-
|
|
92
|
-
// Mount with tenant-specific base path
|
|
93
|
-
flexRouter.mount(app, '/tenant/:tenantId');
|
|
94
|
-
|
|
95
|
-
// Route will be available at: /tenant/:tenantId/api/dashboard
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Organizing Routes by Feature
|
|
99
|
-
|
|
100
|
-
```javascript
|
|
101
|
-
// features/users/routes.js
|
|
102
|
-
const usersRouter = Router();
|
|
103
|
-
usersRouter.get('/', getAllUsers);
|
|
104
|
-
usersRouter.post('/', createUser);
|
|
105
|
-
export const usersFlexRouter = new FlexRouter('/users', usersRouter);
|
|
106
|
-
|
|
107
|
-
// features/products/routes.js
|
|
108
|
-
const productsRouter = Router();
|
|
109
|
-
productsRouter.get('/', getAllProducts);
|
|
110
|
-
export const productsFlexRouter = new FlexRouter('/products', productsRouter);
|
|
111
|
-
|
|
112
|
-
// app.js
|
|
113
|
-
import { usersFlexRouter } from './features/users/routes.js';
|
|
114
|
-
import { productsFlexRouter } from './features/products/routes.js';
|
|
115
|
-
|
|
116
|
-
const apiRouters = [usersFlexRouter, productsFlexRouter];
|
|
117
|
-
|
|
118
|
-
apiRouters.forEach(router => router.mount(app, '/api/v1'));
|
|
119
|
-
|
|
120
|
-
// Routes available:
|
|
121
|
-
// - /api/v1/users
|
|
122
|
-
// - /api/v1/products
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## API
|
|
126
|
-
|
|
127
|
-
### Constructor
|
|
128
|
-
|
|
129
|
-
**`new FlexRouter(context, router, handlers?)`**
|
|
130
|
-
|
|
131
|
-
Creates a new FlexRouter instance.
|
|
132
|
-
|
|
133
|
-
**Parameters:**
|
|
134
|
-
- `context` (string) - The context path for the router (e.g., `/api/v1`)
|
|
135
|
-
- `router` (Router) - Express Router instance containing your route definitions
|
|
136
|
-
- `handlers` (Array, optional) - Array of middleware handler functions to apply to all routes in this router
|
|
137
|
-
|
|
138
|
-
**Returns:** FlexRouter instance
|
|
139
|
-
|
|
140
|
-
### Methods
|
|
141
|
-
|
|
142
|
-
**`mount(app, basePath)`**
|
|
143
|
-
|
|
144
|
-
Mounts the router to an Express application with the specified base path.
|
|
145
|
-
|
|
146
|
-
**Parameters:**
|
|
147
|
-
- `app` (Express) - Express application instance
|
|
148
|
-
- `basePath` (string) - Base path to prepend to the context path
|
|
149
|
-
|
|
150
|
-
**Example:**
|
|
151
|
-
```javascript
|
|
152
|
-
const flexRouter = new FlexRouter('/api', router);
|
|
153
|
-
flexRouter.mount(app, '/v1'); // Mounts at /v1/api
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## Best Practices
|
|
157
|
-
|
|
158
|
-
1. **Group Related Routes**: Use FlexRouter to group related routes together
|
|
159
|
-
2. **Apply Middleware Strategically**: Apply middleware at the FlexRouter level for route groups that share the same requirements
|
|
160
|
-
3. **Consistent Naming**: Use consistent naming conventions for context paths (e.g., all lowercase, kebab-case)
|
|
161
|
-
4. **Version Your APIs**: Use FlexRouter to manage different API versions easily
|
|
162
|
-
5. **Keep Routers Focused**: Each router should handle a specific feature or resource type
|
|
163
|
-
|
|
164
|
-
## Related Documentation
|
|
165
|
-
|
|
166
|
-
- [SessionManager](./session-manager.md) - For authentication middleware usage
|
|
167
|
-
- [Back to main documentation](../README.md)
|