exisjs 0.7.11 → 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.
Files changed (150) hide show
  1. package/README.md +195 -39
  2. package/dist/cli/commands/dev.d.ts +4 -0
  3. package/dist/cli/commands/dev.d.ts.map +1 -1
  4. package/dist/cli/commands/dev.js +136 -32
  5. package/dist/cli/commands/dev.js.map +1 -1
  6. package/dist/cli/commands/run.d.ts +7 -0
  7. package/dist/cli/commands/run.d.ts.map +1 -0
  8. package/dist/cli/commands/run.js +99 -0
  9. package/dist/cli/commands/run.js.map +1 -0
  10. package/dist/cli/index.js +29 -13
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/cli/manifest.d.ts.map +1 -1
  13. package/dist/cli/manifest.js +18 -3
  14. package/dist/cli/manifest.js.map +1 -1
  15. package/dist/cli/routes.d.ts +6 -0
  16. package/dist/cli/routes.d.ts.map +1 -1
  17. package/dist/cli/routes.js +224 -135
  18. package/dist/cli/routes.js.map +1 -1
  19. package/dist/config/config.d.ts +2 -1
  20. package/dist/config/config.d.ts.map +1 -1
  21. package/dist/config/config.js.map +1 -1
  22. package/dist/config/types.d.ts +30 -9
  23. package/dist/config/types.d.ts.map +1 -1
  24. package/dist/database/lifecycle.d.ts +6 -1
  25. package/dist/database/lifecycle.d.ts.map +1 -1
  26. package/dist/database/lifecycle.js +15 -4
  27. package/dist/database/lifecycle.js.map +1 -1
  28. package/dist/decorators/params.d.ts +21 -0
  29. package/dist/decorators/params.d.ts.map +1 -1
  30. package/dist/decorators/params.js +21 -1
  31. package/dist/decorators/params.js.map +1 -1
  32. package/dist/di/container.d.ts +15 -6
  33. package/dist/di/container.d.ts.map +1 -1
  34. package/dist/di/container.js +26 -3
  35. package/dist/di/container.js.map +1 -1
  36. package/dist/di/index.d.ts +1 -1
  37. package/dist/di/index.d.ts.map +1 -1
  38. package/dist/di/index.js.map +1 -1
  39. package/dist/di/inject.d.ts +2 -1
  40. package/dist/di/inject.d.ts.map +1 -1
  41. package/dist/di/inject.js +2 -1
  42. package/dist/di/inject.js.map +1 -1
  43. package/dist/docs/BENCHMARKS.md +4 -4
  44. package/dist/docs/content/README.md +43 -44
  45. package/dist/docs/content/boundaries.mdx +141 -48
  46. package/dist/docs/content/cli/commands.mdx +161 -107
  47. package/dist/docs/content/cli/overview.mdx +61 -46
  48. package/dist/docs/content/cli/usage.mdx +107 -30
  49. package/dist/docs/content/config.mdx +145 -147
  50. package/dist/docs/content/controllers.mdx +193 -464
  51. package/dist/docs/content/cron.mdx +183 -69
  52. package/dist/docs/content/decorators.mdx +449 -154
  53. package/dist/docs/content/errors.mdx +202 -305
  54. package/dist/docs/content/exisjs-mcp.mdx +59 -49
  55. package/dist/docs/content/installation.mdx +243 -157
  56. package/dist/docs/content/introduction.mdx +220 -48
  57. package/dist/docs/content/middleware.mdx +171 -497
  58. package/dist/docs/content/modules.mdx +141 -83
  59. package/dist/docs/content/providers.mdx +216 -180
  60. package/dist/docs/content/requests.mdx +168 -488
  61. package/dist/docs/content/responses.mdx +200 -533
  62. package/dist/docs/content/routing.mdx +239 -558
  63. package/dist/docs/content/security.mdx +233 -57
  64. package/dist/docs/content/structure.mdx +151 -240
  65. package/dist/docs/content/swagger.mdx +192 -91
  66. package/dist/docs/content/testing.mdx +205 -74
  67. package/dist/docs/content/validation.mdx +479 -341
  68. package/dist/docs/reference/README.md +34 -2
  69. package/dist/docs/reference/config.mdx +277 -73
  70. package/dist/docs/reference/context.mdx +197 -106
  71. package/dist/docs/reference/cron.mdx +266 -152
  72. package/dist/docs/reference/database.mdx +135 -53
  73. package/dist/docs/reference/decorators.mdx +234 -116
  74. package/dist/docs/reference/di.mdx +146 -112
  75. package/dist/docs/reference/error.mdx +155 -178
  76. package/dist/docs/reference/exis.mdx +141 -70
  77. package/dist/docs/reference/logger.mdx +110 -126
  78. package/dist/docs/reference/middleware.mdx +235 -158
  79. package/dist/docs/reference/plugin.mdx +136 -64
  80. package/dist/docs/reference/router.mdx +277 -251
  81. package/dist/docs/reference/sanitize.mdx +91 -87
  82. package/dist/docs/reference/swagger.mdx +280 -100
  83. package/dist/docs/reference/testing.mdx +223 -89
  84. package/dist/docs/reference/validator.mdx +194 -206
  85. package/dist/lib/inspect-routes.d.ts +2 -0
  86. package/dist/lib/inspect-routes.d.ts.map +1 -0
  87. package/dist/lib/inspect-routes.js +148 -0
  88. package/dist/lib/inspect-routes.js.map +1 -0
  89. package/dist/lib/start-server.js +13 -8
  90. package/dist/lib/start-server.js.map +1 -1
  91. package/dist/module/module.d.ts +6 -3
  92. package/dist/module/module.d.ts.map +1 -1
  93. package/dist/module/module.js +17 -3
  94. package/dist/module/module.js.map +1 -1
  95. package/dist/router/controller-registrar.d.ts.map +1 -1
  96. package/dist/router/controller-registrar.js +26 -4
  97. package/dist/router/controller-registrar.js.map +1 -1
  98. package/dist/router/scanner/cron-mounter.d.ts.map +1 -1
  99. package/dist/router/scanner/cron-mounter.js +9 -2
  100. package/dist/router/scanner/cron-mounter.js.map +1 -1
  101. package/dist/server/app.d.ts +3 -1
  102. package/dist/server/app.d.ts.map +1 -1
  103. package/dist/server/app.js +29 -8
  104. package/dist/server/app.js.map +1 -1
  105. package/dist/server/define.d.ts.map +1 -1
  106. package/dist/server/define.js +5 -0
  107. package/dist/server/define.js.map +1 -1
  108. package/dist/server/request.d.ts +2 -0
  109. package/dist/server/request.d.ts.map +1 -1
  110. package/dist/server/request.js +11 -0
  111. package/dist/server/request.js.map +1 -1
  112. package/dist/swagger/generator.d.ts.map +1 -1
  113. package/dist/swagger/generator.js +130 -10
  114. package/dist/swagger/generator.js.map +1 -1
  115. package/dist/telemetry/index.d.ts +12 -0
  116. package/dist/telemetry/index.d.ts.map +1 -0
  117. package/dist/telemetry/index.js +121 -0
  118. package/dist/telemetry/index.js.map +1 -0
  119. package/dist/testing/client.d.ts +1 -0
  120. package/dist/testing/client.d.ts.map +1 -1
  121. package/dist/testing/client.js +4 -1
  122. package/dist/testing/client.js.map +1 -1
  123. package/dist/testing/index.d.ts.map +1 -1
  124. package/dist/testing/index.js +20 -4
  125. package/dist/testing/index.js.map +1 -1
  126. package/dist/validator/builder.d.ts +26 -1
  127. package/dist/validator/builder.d.ts.map +1 -1
  128. package/dist/validator/builder.js +31 -0
  129. package/dist/validator/builder.js.map +1 -1
  130. package/dist/validator/engine.d.ts +23 -0
  131. package/dist/validator/engine.d.ts.map +1 -1
  132. package/dist/validator/engine.js +228 -31
  133. package/dist/validator/engine.js.map +1 -1
  134. package/dist/validator/index.d.ts +8 -4
  135. package/dist/validator/index.d.ts.map +1 -1
  136. package/dist/validator/index.js +4 -1
  137. package/dist/validator/index.js.map +1 -1
  138. package/dist/validator/tex-types.d.ts +15 -0
  139. package/dist/validator/tex-types.d.ts.map +1 -1
  140. package/dist/validator/tex-types.js +102 -0
  141. package/dist/validator/tex-types.js.map +1 -1
  142. package/dist/validator/tex.d.ts +1 -1
  143. package/dist/validator/tex.d.ts.map +1 -1
  144. package/dist/validator/tex.js +3 -1
  145. package/dist/validator/tex.js.map +1 -1
  146. package/dist/validator/types.d.ts +1 -0
  147. package/dist/validator/types.d.ts.map +1 -1
  148. package/package.json +47 -14
  149. package/dist/docs/content/dataloader.mdx +0 -170
  150. package/dist/docs/reference/dataloader.mdx +0 -91
@@ -1,47 +1,51 @@
1
1
  ---
2
- nextUrl: "/docs/reference/swagger"
3
- nextTitle: "Swagger API Reference"
2
+ title: "OpenAPI and Swagger Documentation"
3
+ description: "Automatically generate OpenAPI 3.1 specifications and host interactive Swagger UI and Scalar documentation in ExisJS."
4
+ nextUrl: "/docs/testing"
5
+ nextTitle: "Testing Framework"
4
6
  ---
5
7
 
6
- # Swagger & OpenAPI 3.1 Documentation
8
+ # OpenAPI & Swagger Documentation
7
9
 
8
- ExisJS comes with a native, built-in **Swagger & OpenAPI 3.1** documentation engine. It automatically discovers all registered routes, introspects **Tex** and **Zod** validation schemas, and serves interactive API documentation at `/docs`.
10
+ ExisJS includes a native **OpenAPI 3.1** documentation engine. It automatically introspects registered routes, parses `tex` and Zod validation schemas, and serves interactive documentation UIs alongside raw JSON specifications.
9
11
 
10
12
  ---
11
13
 
12
- ## Quick Start
14
+ ## Enabling Documentation
13
15
 
14
- Enable Swagger documentation in your `exis.config.ts`:
16
+ Configure documentation in `exis.config.ts` using `defineConfig`:
15
17
 
16
18
  ```typescript filename="exis.config.ts"
17
19
  import { defineConfig } from 'exisjs/config'
18
20
 
19
21
  export default defineConfig({
20
22
  docs: {
21
- enabled: true, // Mounts UI at /docs and spec at /docs/json
23
+ enabled: true, // Mounts interactive UI and spec endpoint
24
+ path: '/docs', // Base path for UI (default: '/docs')
25
+ specPath: '/docs/json', // OpenAPI 3.1 JSON endpoint (default: '/docs/json')
22
26
  title: 'Store API Documentation',
23
27
  version: '1.0.0',
24
- description: 'Auto-generated API documentation with native schema validation',
28
+ description: 'REST API reference with native schema introspection',
25
29
  ui: 'swagger-ui', // 'swagger-ui' | 'scalar'
26
30
  }
27
31
  })
28
32
  ```
29
33
 
30
- Once enabled:
31
- * Visit `http://localhost:3000/docs` to view the interactive documentation UI.
32
- * Visit `http://localhost:3000/docs/json` (or `/docs/openapi.json`) for the raw OpenAPI 3.1 specification.
34
+ When enabled:
35
+ - **Interactive UI**: Navigate to `http://localhost:3000/docs` in your browser.
36
+ - **OpenAPI 3.1 Spec**: Access the JSON schema at `http://localhost:3000/docs/json` (or `/docs/openapi.json`).
33
37
 
34
38
  ---
35
39
 
36
40
  ## Interactive Documentation UIs
37
41
 
38
- ExisJS supports two built-in UI renderers:
42
+ ExisJS supports two documentation renderers:
39
43
 
40
44
  ### 1. Swagger UI (`ui: 'swagger-ui'`, default)
41
- The industry-standard interactive Swagger explorer featuring **Try it out**, live request execution, and parameter inspection.
45
+ The standard interactive OpenAPI explorer featuring live request execution (**Try it out**), parameter testing, and schema validation previews.
42
46
 
43
47
  ### 2. Scalar API Reference (`ui: 'scalar'`)
44
- A modern, high-performance, dark-mode-first API reference documentation viewer with integrated code snippets and fast search.
48
+ A modern, dark-mode-first API reference viewer featuring integrated multi-language code snippets, instant search, and response previews.
45
49
 
46
50
  ```typescript filename="exis.config.ts"
47
51
  import { defineConfig } from 'exisjs/config'
@@ -49,16 +53,16 @@ import { defineConfig } from 'exisjs/config'
49
53
  export default defineConfig({
50
54
  docs: {
51
55
  enabled: true,
52
- ui: 'scalar', // Switches UI to modern Scalar
56
+ ui: 'scalar', // Use Scalar instead of Swagger UI
53
57
  }
54
58
  })
55
59
  ```
56
60
 
57
61
  ---
58
62
 
59
- ## Documenting Functional Routes
63
+ ## 1. Functional Paradigm (`route.*`)
60
64
 
61
- In ExisJS folder-based routing, each endpoint folder contains a `route.ts` file that exports a default `controller({ ... })`. You can add OpenAPI metadata directly to each route definition:
65
+ In functional file-system routing, specify documentation metadata directly inside `route.get()`, `route.post()`, and other method definitions. Schema properties (`query`, `params`, `headers`, `body`) defined using `tex` are automatically converted to OpenAPI 3.1 parameter and request body schemas.
62
66
 
63
67
  ```typescript filename="src/http/users/route.ts"
64
68
  import { controller, route } from 'exisjs/router'
@@ -72,25 +76,30 @@ export default controller({
72
76
  query: tex.pagination({ defaultLimit: 25, maxLimit: 100 }),
73
77
  responses: {
74
78
  200: {
75
- description: 'Paginated user list',
79
+ description: 'Paginated user collection',
76
80
  schema: tex.object({
77
- data: tex.array(tex.object({ id: tex.uuid(), name: tex.string() })),
81
+ data: tex.array(
82
+ tex.object({
83
+ id: tex.uuid(),
84
+ name: tex.string(),
85
+ email: tex.email(),
86
+ })
87
+ ),
78
88
  total: tex.number(),
89
+ skip: tex.number(),
90
+ limit: tex.number(),
79
91
  }),
80
92
  },
81
- 400: { description: 'Invalid query parameters' },
93
+ 400: { description: 'Invalid query pagination parameters' },
82
94
  },
83
95
  async handle({ query }) {
84
96
  const { skip, limit } = getPaginationSkip(query)
85
- return {
86
- data: [
87
- { id: '550e8400-e29b-41d4-a716-446655440000', name: 'Alice' },
88
- { id: '550e8400-e29b-41d4-a716-446655440001', name: 'Bob' },
89
- ],
90
- total: 2,
91
- skip,
92
- limit,
93
- }
97
+ const [data, total] = await Promise.all([
98
+ db.users.findMany({ skip, take: limit }),
99
+ db.users.count(),
100
+ ])
101
+
102
+ return { data, total, skip, limit }
94
103
  },
95
104
  }),
96
105
 
@@ -100,26 +109,29 @@ export default controller({
100
109
  body: tex.object({
101
110
  name: tex.string({ min: 2 }),
102
111
  email: tex.email(),
112
+ role: tex.enum(['admin', 'member', 'guest']).optional(),
103
113
  }),
104
114
  responses: {
105
115
  201: { description: 'User successfully created' },
106
- 400: { description: 'Validation error' },
116
+ 400: { description: 'Validation failure' },
107
117
  },
108
118
  async handle({ body }) {
109
- return { id: '550e8400-e29b-41d4-a716-446655440002', ...body }
119
+ return await db.users.create(body)
110
120
  },
111
121
  }),
112
122
 
113
123
  getById: route.get('/:id', {
114
- summary: 'Get user by UUID',
124
+ summary: 'Get user details by ID',
115
125
  tags: ['Users'],
116
- params: tex.object({ id: tex.uuid() }),
126
+ params: tex.object({
127
+ id: tex.uuid(),
128
+ }),
117
129
  responses: {
118
130
  200: { description: 'User details found' },
119
131
  404: { description: 'User not found' },
120
132
  },
121
133
  async handle({ params }) {
122
- return { id: params.id, name: 'Alice' }
134
+ return await db.users.findById(params.id)
123
135
  },
124
136
  }),
125
137
  })
@@ -127,9 +139,9 @@ export default controller({
127
139
 
128
140
  ---
129
141
 
130
- ## Documenting Class-Based Controllers (OOP)
142
+ ## 2. Class-Based (OOP) Paradigm (`@Api*` Decorators)
131
143
 
132
- For class-based controllers in `route.ts`, use OpenAPI decorators from `exisjs/swagger` alongside standard routing decorators:
144
+ In class-based controllers in `route.ts`, annotate classes and route methods with documentation decorators from `exisjs/swagger`:
133
145
 
134
146
  ```typescript filename="src/http/products/route.ts"
135
147
  import { Controller, Get, Post, Body, Param, Query } from 'exisjs/decorators'
@@ -148,21 +160,22 @@ export default class ProductsController {
148
160
  @Get('/')
149
161
  @ApiOperation({
150
162
  summary: 'List products',
151
- description: 'Fetches paginated list of catalog products',
163
+ description: 'Fetches paginated catalog items',
152
164
  })
153
- @ApiResponse({ status: 200, description: 'List of products' })
165
+ @ApiResponse({ status: 200, description: 'List of catalog products' })
154
166
  async list(@Query('page') page: number = 1) {
155
167
  return [
156
- { id: 1, name: 'Mechanical Keyboard', price: 99 },
157
- { id: 2, name: 'Ergonomic Mouse', price: 49 },
168
+ { id: 'prod_1', name: 'Mechanical Keyboard', price: 99 },
169
+ { id: 'prod_2', name: 'Ergonomic Mouse', price: 49 },
158
170
  ]
159
171
  }
160
172
 
161
173
  @Post('/')
162
174
  @ApiOperation({ summary: 'Create new product' })
163
- @ApiResponse({ status: 201, description: 'Product created' })
175
+ @ApiResponse({ status: 201, description: 'Product created successfully' })
176
+ @ApiResponse({ status: 400, description: 'Invalid product payload' })
164
177
  async create(@Body() dto: { name: string; price: number }) {
165
- return { id: 3, ...dto }
178
+ return { id: 'prod_3', ...dto }
166
179
  }
167
180
 
168
181
  @Get('/:id')
@@ -174,18 +187,30 @@ export default class ProductsController {
174
187
  }
175
188
 
176
189
  @Get('/internal/metrics')
177
- @ApiExclude() // Excluded from Swagger documentation
178
- async metrics() {
190
+ @ApiExclude() // Excluded from generated Swagger documentation
191
+ async getInternalMetrics() {
179
192
  return { uptime: process.uptime() }
180
193
  }
181
194
  }
182
195
  ```
183
196
 
197
+ ### Decorator Reference
198
+
199
+ | Decorator | Target | Description |
200
+ | :--- | :--- | :--- |
201
+ | `@ApiTags(...tags)` | Class / Method | Groups operations under specified tag sections in the documentation UI. |
202
+ | `@ApiOperation(options)` | Method | Specifies `summary`, `description`, `operationId`, and `deprecated` status. |
203
+ | `@ApiResponse(options)` | Method | Documents response status codes, descriptions, and schemas. |
204
+ | `@ApiBearerAuth(name?)` | Class / Method | Applies Bearer JWT authentication requirement to the endpoint. |
205
+ | `@ApiSecurity(name, scopes?)` | Class / Method | Applies a custom security scheme requirement to the endpoint. |
206
+ | `@ApiExclude()` | Class / Method | Excludes the controller or endpoint from generated documentation. |
207
+ | `@ApiProperty(options)` | Class Property | Annotates DTO class properties with description, examples, and enums. |
208
+
184
209
  ---
185
210
 
186
- ## Cascading Boundary Metadata
211
+ ## Boundary Cascading Documentation (`boundary.ts`)
187
212
 
188
- Cascading boundaries (`boundary.ts`) can assign shared tags, descriptions, or security requirements to all nested routes in the directory:
213
+ Boundaries (`boundary.ts`) apply shared tags or security requirements to all nested routes within a directory hierarchy:
189
214
 
190
215
  ```typescript filename="src/http/admin/boundary.ts"
191
216
  import { defineBoundary } from 'exisjs/router'
@@ -198,9 +223,96 @@ export const config = defineBoundary({
198
223
 
199
224
  ---
200
225
 
201
- ## Security Schemes & Authentication
226
+ ## Schema Introspection & Multi-Validator Support
227
+
228
+ The OpenAPI generator inspects route validation schemas and automatically translates them into OpenAPI 3.1 JSON Schemas.
229
+
230
+ ### 1. Native `tex` Schemas
231
+
232
+ All `tex` primitives, options, and metadata methods translate into OpenAPI properties:
233
+
234
+ ```typescript filename="src/http/users/schema.ts"
235
+ import { tex } from 'exisjs/validator'
236
+
237
+ export const UserRegistrationSchema = tex.object({
238
+ username: tex.string({ min: 3, max: 30 })
239
+ .describe('Unique alphanumeric handle')
240
+ .example('alex_dev'),
241
+ email: tex.email()
242
+ .describe('Primary contact email address')
243
+ .example('alex@example.com'),
244
+ age: tex.number({ min: 18 })
245
+ .describe('User age in years')
246
+ .example(25),
247
+ role: tex.enum(['admin', 'member', 'guest'] as const)
248
+ .describe('Assigned account authorization level')
249
+ .example('member'),
250
+ })
251
+ ```
252
+
253
+ #### Discriminated Unions in OpenAPI
254
+
255
+ When using `tex.discriminatedUnion()`, the generator generates an OpenAPI `oneOf` schema along with the `discriminator` mapping:
256
+
257
+ ```typescript filename="src/http/events/schema.ts"
258
+ export const PaymentEvent = tex.discriminatedUnion('method', [
259
+ tex.object({ method: tex.literal('card'), cardNumber: tex.creditCard() }),
260
+ tex.object({ method: tex.literal('crypto'), walletAddress: tex.string() }),
261
+ ])
262
+ ```
263
+
264
+ Translates to OpenAPI 3.1:
265
+
266
+ ```json
267
+ {
268
+ "oneOf": [
269
+ {
270
+ "type": "object",
271
+ "properties": { "method": { "type": "string", "enum": ["card"] }, "cardNumber": { "type": "string" } },
272
+ "required": ["method", "cardNumber"]
273
+ },
274
+ {
275
+ "type": "object",
276
+ "properties": { "method": { "type": "string", "enum": ["crypto"] }, "walletAddress": { "type": "string" } },
277
+ "required": ["method", "walletAddress"]
278
+ }
279
+ ],
280
+ "discriminator": {
281
+ "propertyName": "method"
282
+ }
283
+ }
284
+ ```
285
+
286
+ ### 2. Third-Party Validators (Zod, ArkType, JSON Schema)
287
+
288
+ ExisJS uses multi-validator duck typing to introspect external schemas without requiring adapter packages:
289
+
290
+ ```typescript filename="src/http/orders/route.ts"
291
+ import { controller, route } from 'exisjs/router'
292
+ import { z } from 'zod'
293
+
294
+ const OrderSchema = z.object({
295
+ item: z.string().min(2).describe('Product title'),
296
+ quantity: z.number().int().positive().describe('Item count'),
297
+ coupon: z.string().optional(),
298
+ })
299
+
300
+ export default controller({
301
+ create: route.post('/', {
302
+ summary: 'Place an order',
303
+ body: OrderSchema,
304
+ async handle({ body }) {
305
+ return { success: true, order: body }
306
+ },
307
+ }),
308
+ })
309
+ ```
310
+
311
+ ---
312
+
313
+ ## Security Schemes Configuration
202
314
 
203
- Define reusable security schemes (such as Bearer JWT, API Keys, or OAuth2) in `exis.config.ts`:
315
+ Define authentication mechanisms (e.g. Bearer JWT, API Keys, OAuth2) in `exis.config.ts`:
204
316
 
205
317
  ```typescript filename="exis.config.ts"
206
318
  import { defineConfig } from 'exisjs/config'
@@ -219,8 +331,10 @@ export default defineConfig({
219
331
  type: 'apiKey',
220
332
  in: 'header',
221
333
  name: 'X-API-KEY',
334
+ description: 'Static API Key passed in headers',
222
335
  },
223
336
  },
337
+ // Global default security (can be overridden per route)
224
338
  security: [
225
339
  { bearerAuth: [] },
226
340
  ],
@@ -230,60 +344,47 @@ export default defineConfig({
230
344
 
231
345
  ---
232
346
 
233
- ## Advanced Configuration (`exis.config.ts`)
234
-
235
- For advanced customization, such as modifying the generated OpenAPI spec before serving or injecting custom styling:
236
-
237
- ```typescript filename="exis.config.ts"
238
- import { defineConfig } from 'exisjs/config'
239
-
240
- export default defineConfig({
241
- docs: {
242
- enabled: true,
243
- title: 'Enterprise API Gateway',
244
- version: '2.0.0',
245
- description: 'Internal and external microservices API reference',
246
- ui: 'scalar', // 'swagger-ui' | 'scalar'
247
- servers: [
248
- { url: 'https://api.example.com', description: 'Production Server' },
249
- { url: 'http://localhost:3000', description: 'Local Development' },
250
- ],
251
- transformSpec(spec) {
252
- // Programmatically mutate or enrich OpenAPI specification
253
- spec.info.contact = { name: 'API Support', email: 'support@example.com' }
254
- return spec
255
- },
256
- },
257
- })
258
- ```
347
+ ## Configuration Reference (`SwaggerConfig`)
348
+
349
+ The full set of options supported under `docs` in `exis.config.ts`:
350
+
351
+ | Option | Type | Default | Description |
352
+ | :--- | :--- | :--- | :--- |
353
+ | `enabled` | `boolean` | `false` | Enables documentation mounting and OpenAPI spec generation. |
354
+ | `path` | `string` | `'/docs'` | URL path where the interactive documentation UI is served. |
355
+ | `specPath` | `string` | `'/docs/json'` | URL path where the raw OpenAPI 3.1 JSON specification is served. |
356
+ | `title` | `string` | `'ExisJS API Documentation'` | Title displayed in the documentation header. |
357
+ | `version` | `string` | `'1.0.0'` | API Version displayed in documentation. |
358
+ | `description` | `string` | — | API description markdown shown below the header. |
359
+ | `termsOfService` | `string` | — | URL to terms of service agreement. |
360
+ | `contact` | `object` | — | Contact information (`name`, `url`, `email`). |
361
+ | `license` | `object` | — | License information (`name`, `url`). |
362
+ | `servers` | `OpenApiServer[]` | — | Target environments (e.g., Production, Staging). |
363
+ | `tags` | `OpenApiTag[]` | — | Global list of tag metadata and external documentation links. |
364
+ | `ui` | `'swagger-ui' \| 'scalar'` | `'swagger-ui'` | Interactive documentation UI renderer. |
365
+ | `customCss` | `string` | — | Custom CSS styles injected into the Swagger/Scalar page. |
366
+ | `customFavicon` | `string` | — | Custom favicon URL for the documentation page. |
367
+ | `transformSpec` | `(spec) => spec` | — | Synchronous hook to programmatically mutate the generated OpenAPI spec. |
259
368
 
260
369
  ---
261
370
 
262
- ## Server Lifecycle Hook (`server.ts`)
371
+ ## Programmatic Mount Helper (`swagger()`)
263
372
 
264
- You can also interact with the Swagger subsystem or application instance during server boot in `src/http/server.ts`:
373
+ You can also mount Swagger documentation programmatically inside custom server bootstrapping in `server.ts`:
265
374
 
266
- ### Functional Paradigm
267
375
  ```typescript filename="src/http/server.ts"
268
376
  import { exis } from 'exisjs'
377
+ import { swagger } from 'exisjs/swagger'
269
378
 
270
379
  export default exis({
271
- onStart(app) {
272
- console.log('[API] Swagger documentation ready at /docs')
380
+ async onStart(app) {
381
+ swagger({
382
+ title: 'Custom API Gateway',
383
+ version: '2.0.0',
384
+ path: '/api/docs',
385
+ })(app)
273
386
  },
274
387
  })
275
388
  ```
276
389
 
277
- ### Class-Based (OOP) Paradigm
278
- ```typescript filename="src/http/server.ts"
279
- import { Server } from 'exisjs/decorators'
280
- import type { App } from 'exisjs'
281
-
282
- @Server()
283
- export default class RootServer {
284
- async onStart(app: App) {
285
- console.log('[API] Swagger documentation ready at /docs')
286
- }
287
- }
288
- ```
289
390