exisjs 0.7.12 → 0.7.13
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 +195 -39
- package/dist/config/types.d.ts +2 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/decorators/params.d.ts +21 -0
- package/dist/decorators/params.d.ts.map +1 -1
- package/dist/decorators/params.js +21 -1
- package/dist/decorators/params.js.map +1 -1
- package/dist/di/container.d.ts +15 -6
- package/dist/di/container.d.ts.map +1 -1
- package/dist/di/container.js +26 -3
- package/dist/di/container.js.map +1 -1
- package/dist/di/index.d.ts +1 -1
- package/dist/di/index.d.ts.map +1 -1
- package/dist/di/index.js.map +1 -1
- package/dist/di/inject.d.ts +2 -1
- package/dist/di/inject.d.ts.map +1 -1
- package/dist/di/inject.js +2 -1
- package/dist/di/inject.js.map +1 -1
- package/dist/docs/BENCHMARKS.md +4 -4
- package/dist/docs/content/README.md +43 -44
- package/dist/docs/content/boundaries.mdx +138 -61
- package/dist/docs/content/cli/commands.mdx +151 -128
- package/dist/docs/content/cli/overview.mdx +61 -47
- package/dist/docs/content/cli/usage.mdx +107 -30
- package/dist/docs/content/config.mdx +145 -158
- package/dist/docs/content/controllers.mdx +193 -464
- package/dist/docs/content/cron.mdx +183 -69
- package/dist/docs/content/decorators.mdx +449 -154
- package/dist/docs/content/errors.mdx +202 -305
- package/dist/docs/content/exisjs-mcp.mdx +59 -49
- package/dist/docs/content/installation.mdx +243 -157
- package/dist/docs/content/introduction.mdx +220 -48
- package/dist/docs/content/middleware.mdx +171 -497
- package/dist/docs/content/modules.mdx +141 -83
- package/dist/docs/content/providers.mdx +216 -180
- package/dist/docs/content/requests.mdx +168 -488
- package/dist/docs/content/responses.mdx +200 -533
- package/dist/docs/content/routing.mdx +235 -598
- package/dist/docs/content/security.mdx +233 -57
- package/dist/docs/content/structure.mdx +151 -240
- package/dist/docs/content/swagger.mdx +192 -91
- package/dist/docs/content/testing.mdx +205 -74
- package/dist/docs/content/validation.mdx +479 -341
- package/dist/docs/reference/README.md +34 -2
- package/dist/docs/reference/config.mdx +277 -75
- package/dist/docs/reference/context.mdx +197 -106
- package/dist/docs/reference/cron.mdx +266 -152
- package/dist/docs/reference/database.mdx +135 -53
- package/dist/docs/reference/decorators.mdx +234 -116
- package/dist/docs/reference/di.mdx +146 -112
- package/dist/docs/reference/error.mdx +155 -178
- package/dist/docs/reference/exis.mdx +141 -70
- package/dist/docs/reference/logger.mdx +110 -126
- package/dist/docs/reference/middleware.mdx +235 -158
- package/dist/docs/reference/plugin.mdx +136 -64
- package/dist/docs/reference/router.mdx +275 -293
- package/dist/docs/reference/sanitize.mdx +91 -87
- package/dist/docs/reference/swagger.mdx +280 -100
- package/dist/docs/reference/testing.mdx +223 -89
- package/dist/docs/reference/validator.mdx +194 -206
- package/dist/lib/start-server.js +3 -8
- package/dist/lib/start-server.js.map +1 -1
- package/dist/module/module.d.ts +6 -3
- package/dist/module/module.d.ts.map +1 -1
- package/dist/module/module.js +17 -3
- package/dist/module/module.js.map +1 -1
- package/dist/router/controller-registrar.d.ts.map +1 -1
- package/dist/router/controller-registrar.js +26 -4
- package/dist/router/controller-registrar.js.map +1 -1
- package/dist/server/app.d.ts +3 -1
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +24 -8
- package/dist/server/app.js.map +1 -1
- package/dist/server/request.d.ts +2 -0
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +11 -0
- package/dist/server/request.js.map +1 -1
- package/dist/swagger/generator.d.ts.map +1 -1
- package/dist/swagger/generator.js +130 -10
- package/dist/swagger/generator.js.map +1 -1
- package/dist/telemetry/index.d.ts +12 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +121 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/testing/client.d.ts +1 -0
- package/dist/testing/client.d.ts.map +1 -1
- package/dist/testing/client.js +4 -1
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +11 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/validator/builder.d.ts +26 -1
- package/dist/validator/builder.d.ts.map +1 -1
- package/dist/validator/builder.js +31 -0
- package/dist/validator/builder.js.map +1 -1
- package/dist/validator/engine.d.ts +23 -0
- package/dist/validator/engine.d.ts.map +1 -1
- package/dist/validator/engine.js +228 -31
- package/dist/validator/engine.js.map +1 -1
- package/dist/validator/index.d.ts +8 -4
- package/dist/validator/index.d.ts.map +1 -1
- package/dist/validator/index.js +4 -1
- package/dist/validator/index.js.map +1 -1
- package/dist/validator/tex-types.d.ts +15 -0
- package/dist/validator/tex-types.d.ts.map +1 -1
- package/dist/validator/tex-types.js +102 -0
- package/dist/validator/tex-types.js.map +1 -1
- package/dist/validator/tex.d.ts +1 -1
- package/dist/validator/tex.d.ts.map +1 -1
- package/dist/validator/tex.js +3 -1
- package/dist/validator/tex.js.map +1 -1
- package/dist/validator/types.d.ts +1 -0
- package/dist/validator/types.d.ts.map +1 -1
- package/package.json +46 -14
- package/dist/docs/content/dataloader.mdx +0 -170
- package/dist/docs/reference/dataloader.mdx +0 -91
|
@@ -1,44 +1,43 @@
|
|
|
1
|
-
# ExisJS Documentation
|
|
2
|
-
|
|
3
|
-
This directory contains the
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
* **`adapters.mdx`**: How to run ExisJS inside serverless environments or mount it seamlessly alongside Next.js.
|
|
1
|
+
# ExisJS Documentation Content Directory
|
|
2
|
+
|
|
3
|
+
This directory contains the user guides, conceptual explanations, and how-to manuals for ExisJS.
|
|
4
|
+
|
|
5
|
+
Documentation follows the [Diátaxis Framework](https://diataxis.fr/), separating conceptual overviews, procedural how-to guides, and reference materials.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Content Index
|
|
10
|
+
|
|
11
|
+
### 1. Getting Started & Architecture
|
|
12
|
+
- [`introduction.mdx`](./introduction.mdx): Overview of framework architecture, design decisions, and supported paradigms.
|
|
13
|
+
- [`installation.mdx`](./installation.mdx): Prerequisites, project scaffolding (`npm create exisjs@latest`), and manual setup.
|
|
14
|
+
- [`structure.mdx`](./structure.mdx): Standardized directory layout (`src/http/`, `src/database/`, `src/common/`, `src/config/`, `src/cron/`).
|
|
15
|
+
|
|
16
|
+
### 2. HTTP Routing & Request Pipeline
|
|
17
|
+
- [`routing.mdx`](./routing.mdx): File-system routing conventions (`route.ts`), path parameters, route groups, and handlers.
|
|
18
|
+
- [`controllers.mdx`](./controllers.mdx): Class-based routing, `@Controller` decorators, and parameter mappings.
|
|
19
|
+
- [`decorators.mdx`](./decorators.mdx): Reference guide for all decorators across routing, parameters, pipes, middlewares, security, and lifecycle.
|
|
20
|
+
- [`requests.mdx`](./requests.mdx): Request anatomy (`ExisRequest`), query strings, headers, cookies, and context augmentation.
|
|
21
|
+
- [`responses.mdx`](./responses.mdx): Response helpers, JSON output, HTTP status codes, SSE, and stream handling.
|
|
22
|
+
- [`boundaries.mdx`](./boundaries.mdx): Directory-scoped middleware cascading, hierarchical CORS inheritance, and boundary isolation.
|
|
23
|
+
|
|
24
|
+
### 3. Validation, Dependency Injection & Data
|
|
25
|
+
- [`validation.mdx`](./validation.mdx): Schema validation engine (`tex.*`), parameter coercion, custom validators, and sanitization.
|
|
26
|
+
- [`providers.mdx`](./providers.mdx): Dependency injection, constructor injection, `@Injectable()`, `@Inject()`, and `forwardRef()`.
|
|
27
|
+
- [`modules.mdx`](./modules.mdx): Module encapsulation, `@Module()`, dynamic module registration, and `@Global()` scopes.
|
|
28
|
+
|
|
29
|
+
### 4. Middleware, Security & Operations
|
|
30
|
+
- [`middleware.mdx`](./middleware.mdx): Global, boundary, and route-level middlewares, Express bridge, and execution order.
|
|
31
|
+
- [`security.mdx`](./security.mdx): Security headers (Helmet), CSRF tokens, CIDR IP filtering, parameter pollution, and probe blocking.
|
|
32
|
+
- [`errors.mdx`](./errors.mdx): HTTP exception classes, JSON error payloads, and custom error boundaries.
|
|
33
|
+
- [`cron.mdx`](./cron.mdx): Background task scheduling (`cron()` and `@Cron()`) with drift correction and overlap protection.
|
|
34
|
+
- [`swagger.mdx`](./swagger.mdx): Automatic OpenAPI 3.1 schema extraction, Swagger UI (`/docs`), and JSON documentation endpoints.
|
|
35
|
+
- [`testing.mdx`](./testing.mdx): Test harness (`createTestContext`, `createTestApp`), mocking utilities (`ex`), and CLI test runner.
|
|
36
|
+
- [`config.mdx`](./config.mdx): Global configuration options in `exis.config.ts`, lifecycle phases, clustering, and file watcher settings.
|
|
37
|
+
- [`exisjs-mcp.mdx`](./exisjs-mcp.mdx): Model Context Protocol (MCP) server integration for IDE AI assistants.
|
|
38
|
+
|
|
39
|
+
### 5. CLI Tooling (`cli/`)
|
|
40
|
+
- [`cli/overview.mdx`](./cli/overview.mdx): CLI architecture and runtime execution.
|
|
41
|
+
- [`cli/usage.mdx`](./cli/usage.mdx): Basic usage and script execution.
|
|
42
|
+
- [`cli/commands.mdx`](./cli/commands.mdx): Reference for all CLI commands (`dev`, `build`, `start`, `routes`, `test`, `doctor`, `init`).
|
|
43
|
+
|
|
@@ -1,86 +1,88 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
title: 'Boundaries & Middleware Cascading'
|
|
3
|
+
description: 'Folder-scoped middleware cascading, security guards, CORS inheritance hierarchy, exclusion rules, and error handling with boundary.ts.'
|
|
4
|
+
nextUrl: '/docs/validation'
|
|
5
|
+
nextTitle: 'Validation & Schemas'
|
|
4
6
|
---
|
|
5
7
|
|
|
6
|
-
# Boundaries
|
|
8
|
+
# Boundaries & Middleware Cascading (`boundary.ts`)
|
|
7
9
|
|
|
8
|
-
A `boundary.ts`
|
|
10
|
+
A `boundary.ts` (or `<name>.boundary.ts`) file defines a folder-scoped request pipeline and configuration module in the ExisJS file-system routing hierarchy.
|
|
9
11
|
|
|
10
|
-
Any `boundary.ts` applies to every route
|
|
12
|
+
Any `boundary.ts` automatically applies to every route within its directory and all descendant subdirectories recursively, providing scoped **CORS policies**, **custom headers**, **security guards**, **lifecycle hooks**, **route exclusions**, and **dependency injection scoping**.
|
|
11
13
|
|
|
12
14
|
---
|
|
13
15
|
|
|
14
16
|
## Anatomy of a Boundary
|
|
15
17
|
|
|
16
|
-
A `boundary.ts`
|
|
18
|
+
A `boundary.ts` consists of two distinct components:
|
|
17
19
|
|
|
18
|
-
1. **
|
|
19
|
-
2. **Pipeline
|
|
20
|
+
1. **Configuration**: Pure declarative options declared via `defineBoundary()` (functional) or `@Boundary()` (OOP). It sets CORS, response headers, timeout limits, exclusion patterns, probe blackholing, and DI providers.
|
|
21
|
+
2. **Pipeline Handlers**: Functions and lifecycle hooks that run before, during, or after request execution:
|
|
20
22
|
|
|
21
|
-
|
|
|
22
|
-
|
|
23
|
-
| `(req, res, next)` |
|
|
24
|
-
| `beforeHandle(req, res)` |
|
|
25
|
-
| `afterHandle(req, res, data)` |
|
|
26
|
-
| `(ctx, next)`
|
|
23
|
+
| Handler Type | Signature | Description |
|
|
24
|
+
| :--- | :--- | :--- |
|
|
25
|
+
| **Chain Step** | `(req, res, next)` | Standard middleware step running in declaration order before route handlers |
|
|
26
|
+
| **Guard Hook** | `beforeHandle(req, res)` | Runs immediately before route handler execution; aborts if returning `false` |
|
|
27
|
+
| **Audit Hook** | `afterHandle(req, res, data)` | Runs immediately after route handler returns; can transform response data |
|
|
28
|
+
| **Pipeline Wrapper** | `(ctx, next)` / `handle(ctx, next)` | Onion-style wrapper around all steps and downstream routes in the boundary |
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
30
32
|
## 1. Functional Paradigm
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
Export `config = defineBoundary(...)`, named middleware functions `(req, res, next)`, and optionally a default export `(ctx, next)` as a request wrapper:
|
|
33
35
|
|
|
34
36
|
```typescript filename="src/http/admin/boundary.ts"
|
|
35
37
|
import { defineBoundary } from 'exisjs/router'
|
|
36
38
|
import type { Request, Response, Next, BoundaryContext } from 'exisjs/router'
|
|
37
39
|
import { UnauthorizedError } from 'exisjs/error'
|
|
38
40
|
|
|
39
|
-
// 1.
|
|
41
|
+
// 1. Declarative Boundary Configuration
|
|
40
42
|
export const config = defineBoundary({
|
|
41
43
|
cors: {
|
|
42
|
-
origin: ['https://admin.
|
|
44
|
+
origin: ['https://admin.example.com'],
|
|
43
45
|
credentials: true,
|
|
44
46
|
},
|
|
45
47
|
headers: {
|
|
46
|
-
'X-Admin-
|
|
48
|
+
'X-Admin-Scope': 'active',
|
|
47
49
|
},
|
|
48
50
|
exclude: [
|
|
49
51
|
'/admin/health',
|
|
50
|
-
{ path: '/admin/public/*', method: 'GET' }
|
|
52
|
+
{ path: '/admin/public/*', method: 'GET' },
|
|
51
53
|
],
|
|
52
54
|
|
|
53
|
-
// Pre-handler hook
|
|
55
|
+
// Pre-handler guard hook
|
|
54
56
|
beforeHandle(req, res) {
|
|
55
57
|
if (!req.headers['x-admin-token']) {
|
|
56
58
|
res.status(401).json({ error: 'Missing admin access token' })
|
|
57
|
-
return false
|
|
59
|
+
return false // Aborts downstream execution
|
|
58
60
|
}
|
|
59
61
|
},
|
|
60
62
|
|
|
61
|
-
// Post-handler
|
|
63
|
+
// Post-handler response transformation hook
|
|
62
64
|
afterHandle(req, res, data) {
|
|
63
|
-
res.setHeader('X-Audited',
|
|
64
|
-
return { ...data,
|
|
65
|
+
res.setHeader('X-Audited-At', new Date().toISOString())
|
|
66
|
+
return { ...data, audited: true }
|
|
65
67
|
},
|
|
66
68
|
})
|
|
67
69
|
|
|
68
|
-
// 2. Chain Step
|
|
69
|
-
export function
|
|
70
|
+
// 2. Named Chain Step Middleware
|
|
71
|
+
export function verifyApiKey(req: Request, res: Response, next: Next) {
|
|
70
72
|
if (!req.headers['x-api-key']) {
|
|
71
|
-
throw new UnauthorizedError('Missing API key')
|
|
73
|
+
throw new UnauthorizedError('Missing required API key')
|
|
72
74
|
}
|
|
73
75
|
next()
|
|
74
76
|
}
|
|
75
77
|
|
|
76
|
-
// 3. Wrapper (
|
|
78
|
+
// 3. Pipeline Wrapper (Default Export)
|
|
77
79
|
export default async function (ctx: BoundaryContext, next: Next) {
|
|
78
80
|
const start = Date.now()
|
|
79
81
|
try {
|
|
80
82
|
const result = await next()
|
|
81
83
|
const duration = Date.now() - start
|
|
82
84
|
ctx.res.setHeader('X-Response-Time', `${duration}ms`)
|
|
83
|
-
return
|
|
85
|
+
return result
|
|
84
86
|
} catch (err: any) {
|
|
85
87
|
return {
|
|
86
88
|
success: false,
|
|
@@ -94,7 +96,7 @@ export default async function (ctx: BoundaryContext, next: Next) {
|
|
|
94
96
|
|
|
95
97
|
## 2. Class-Based (OOP) Paradigm
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
Decorate a class with `@Boundary(...)`. Class methods taking `(req, res, next)` become chain steps, `beforeHandle` / `afterHandle` serve as lifecycle hooks, and a method named `handle(ctx, next)` acts as the pipeline wrapper:
|
|
98
100
|
|
|
99
101
|
```typescript filename="src/http/admin/boundary.ts"
|
|
100
102
|
import { Boundary } from 'exisjs/decorators'
|
|
@@ -103,11 +105,11 @@ import { UnauthorizedError } from 'exisjs/error'
|
|
|
103
105
|
|
|
104
106
|
@Boundary({
|
|
105
107
|
cors: {
|
|
106
|
-
origin: ['https://admin.
|
|
108
|
+
origin: ['https://admin.example.com'],
|
|
107
109
|
credentials: true,
|
|
108
110
|
},
|
|
109
111
|
headers: {
|
|
110
|
-
'X-Admin-
|
|
112
|
+
'X-Admin-Scope': 'active',
|
|
111
113
|
},
|
|
112
114
|
exclude: ['/admin/health'],
|
|
113
115
|
})
|
|
@@ -122,19 +124,19 @@ export default class AdminBoundary {
|
|
|
122
124
|
|
|
123
125
|
// Post-handler hook
|
|
124
126
|
afterHandle(req: Request, res: Response, data: any) {
|
|
125
|
-
res.setHeader('X-Audited',
|
|
126
|
-
return { ...data,
|
|
127
|
+
res.setHeader('X-Audited-At', new Date().toISOString())
|
|
128
|
+
return { ...data, audited: true }
|
|
127
129
|
}
|
|
128
130
|
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
+
// Named chain step
|
|
132
|
+
verifyApiKey(req: Request, res: Response, next: Next) {
|
|
131
133
|
if (!req.headers['x-api-key']) {
|
|
132
|
-
throw new UnauthorizedError('Missing API key')
|
|
134
|
+
throw new UnauthorizedError('Missing required API key')
|
|
133
135
|
}
|
|
134
136
|
next()
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
//
|
|
139
|
+
// Pipeline wrapper
|
|
138
140
|
async handle(ctx: BoundaryContext, next: Next) {
|
|
139
141
|
const start = Date.now()
|
|
140
142
|
const result = await next()
|
|
@@ -146,44 +148,110 @@ export default class AdminBoundary {
|
|
|
146
148
|
|
|
147
149
|
---
|
|
148
150
|
|
|
149
|
-
## Cascading &
|
|
151
|
+
## Boundary Cascading & Execution Order
|
|
150
152
|
|
|
151
|
-
Boundaries cascade down the
|
|
153
|
+
Boundaries cascade top-down through the folder structure:
|
|
152
154
|
|
|
153
155
|
```text
|
|
154
156
|
src/http/
|
|
155
|
-
├── boundary.ts
|
|
157
|
+
├── boundary.ts # Root Boundary (applies to all routes)
|
|
156
158
|
└── admin/
|
|
157
|
-
├── boundary.ts
|
|
159
|
+
├── boundary.ts # Admin Boundary (applies to /admin/*)
|
|
158
160
|
└── users/
|
|
159
|
-
└── route.ts
|
|
161
|
+
└── route.ts # Handled by both Root Boundary and Admin Boundary
|
|
160
162
|
```
|
|
161
163
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
### Execution Order
|
|
165
|
+
|
|
166
|
+
1. **Wrappers**: Outer wrappers wrap inner wrappers (onion architecture).
|
|
167
|
+
2. **Chain Steps**: Root chain steps run before nested boundary chain steps.
|
|
168
|
+
3. **Guard Hooks (`beforeHandle`)**: Run immediately before the route handler, evaluated from root boundary down to the innermost boundary.
|
|
169
|
+
4. **Response Hooks (`afterHandle`)**: Run in reverse order (innermost boundary up to root boundary).
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## CORS Inheritance & Precedence
|
|
174
|
+
|
|
175
|
+
CORS configuration follows a 4-tier hierarchy:
|
|
176
|
+
|
|
177
|
+
| Priority | Level | Where Defined | Description |
|
|
178
|
+
| :---: | :--- | :--- | :--- |
|
|
179
|
+
| 1 | **Route Override** | `route.get('/', { cors: ... })` or `@Cors(...)` | Specific to a single endpoint; overrides all boundaries and global configs |
|
|
180
|
+
| 2 | **Innermost Boundary** | `src/http/admin/boundary.ts` | Scoped to subfolder tree; overrides parent boundaries |
|
|
181
|
+
| 3 | **Parent / Root Boundary** | `src/http/boundary.ts` | Scoped to all routes in `src/http/`; overrides global defaults |
|
|
182
|
+
| 4 | **Global Configuration** | `exis.config.ts` (`cors`) | Fallback baseline for endpoints without boundary or route CORS |
|
|
183
|
+
|
|
184
|
+
> [!NOTE]
|
|
185
|
+
> If a sub-boundary omits `cors`, it inherits the CORS settings of the nearest ancestor boundary (or `exis.config.ts`). Setting `cors: false` on a boundary explicitly disables CORS for that entire subtree.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Headers Merging
|
|
170
190
|
|
|
171
|
-
|
|
191
|
+
Response headers defined across boundaries are deep-merged from root to child. If header keys conflict, the innermost boundary value takes precedence:
|
|
172
192
|
|
|
173
|
-
|
|
193
|
+
```typescript
|
|
194
|
+
// src/http/boundary.ts (Root)
|
|
195
|
+
export const config = defineBoundary({
|
|
196
|
+
headers: { 'X-Framework': 'ExisJS', 'X-Environment': 'production' },
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// src/http/v2/boundary.ts (Nested)
|
|
200
|
+
export const config = defineBoundary({
|
|
201
|
+
headers: { 'X-Api-Version': 'v2', 'X-Environment': 'v2-canary' },
|
|
202
|
+
})
|
|
174
203
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
| **Global Config** | `exis.config.ts` (`defineConfig({ cors })`) | **Base** | Fallback baseline for any route not covered by a boundary or route override. |
|
|
204
|
+
// Endpoints under /v2 receive:
|
|
205
|
+
// X-Framework: ExisJS
|
|
206
|
+
// X-Api-Version: v2
|
|
207
|
+
// X-Environment: v2-canary (overwritten by nested boundary)
|
|
208
|
+
```
|
|
181
209
|
|
|
182
210
|
---
|
|
183
211
|
|
|
184
|
-
##
|
|
212
|
+
## Route Exclusion Rules
|
|
213
|
+
|
|
214
|
+
To bypass boundary middleware for specific routes (e.g. public webhooks or health checks), add rules to `exclude`:
|
|
215
|
+
|
|
216
|
+
```typescript filename="src/http/boundary.ts"
|
|
217
|
+
import { defineBoundary } from 'exisjs/router'
|
|
218
|
+
|
|
219
|
+
export const config = defineBoundary({
|
|
220
|
+
exclude: [
|
|
221
|
+
// 1. Exact path string
|
|
222
|
+
'/health',
|
|
185
223
|
|
|
186
|
-
|
|
224
|
+
// 2. Wildcard pattern matching any HTTP method
|
|
225
|
+
'/public/*',
|
|
226
|
+
|
|
227
|
+
// 3. Path with specific HTTP method restriction
|
|
228
|
+
{ path: '/webhooks/stripe', method: 'POST' },
|
|
229
|
+
{ path: '/docs/*', methods: ['GET', 'HEAD'] },
|
|
230
|
+
],
|
|
231
|
+
})
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
When an incoming request matches an exclusion rule, the boundary's chain steps and `beforeHandle` hooks are bypassed.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Noise Suppression & Exploit Probe Blackholing
|
|
239
|
+
|
|
240
|
+
ExisJS can automatically intercept and drop automated vulnerability scanner probes (e.g. `/.env`, `/.git`, `/.DS_Store`, `/wp-admin`) at the boundary level without flooding application logs:
|
|
241
|
+
|
|
242
|
+
```typescript filename="src/http/boundary.ts"
|
|
243
|
+
import { defineBoundary } from 'exisjs/router'
|
|
244
|
+
|
|
245
|
+
export const config = defineBoundary({
|
|
246
|
+
blockSuspiciousProbes: true, // Blackholes malicious probe paths immediately
|
|
247
|
+
})
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Dependency Injection Scoping
|
|
253
|
+
|
|
254
|
+
Boundaries can register scoped providers into the IoC container for all routes within their sub-tree:
|
|
187
255
|
|
|
188
256
|
```typescript filename="src/http/users/boundary.ts"
|
|
189
257
|
import { defineBoundary } from 'exisjs/router'
|
|
@@ -195,3 +263,12 @@ export const config = defineBoundary({
|
|
|
195
263
|
],
|
|
196
264
|
})
|
|
197
265
|
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Next Steps
|
|
270
|
+
|
|
271
|
+
- **[Validation Guide](/docs/validation)**: Building request schemas with `tex`.
|
|
272
|
+
- **[Dependency Injection](/docs/providers)**: IoC containers, tokens, and provider lifecycles.
|
|
273
|
+
- **[Routing](/docs/routing)**: File-system route parameters and handler definitions.
|
|
274
|
+
- **[Controllers](/docs/controllers)**: Class-based routing and parameter decorators.
|