@prauga/flexdoc-backend 2.9.9 → 3.1.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 (49) hide show
  1. package/README.md +36 -179
  2. package/dist/auth.js.map +1 -1
  3. package/dist/contract-validation.d.ts +43 -0
  4. package/dist/contract-validation.js +120 -0
  5. package/dist/contract-validation.js.map +1 -0
  6. package/dist/contract-validation.test.d.ts +1 -0
  7. package/dist/contract-validation.test.js +112 -0
  8. package/dist/contract-validation.test.js.map +1 -0
  9. package/dist/flexdoc.module.js.map +1 -1
  10. package/dist/flexdoc.service.js.map +1 -1
  11. package/dist/framework-adapters.d.ts +2 -0
  12. package/dist/framework-adapters.js +21 -0
  13. package/dist/framework-adapters.js.map +1 -1
  14. package/dist/framework-adapters.test.js +32 -0
  15. package/dist/framework-adapters.test.js.map +1 -1
  16. package/dist/hono-adapter.d.ts +4 -0
  17. package/dist/hono-adapter.js +22 -0
  18. package/dist/hono-adapter.js.map +1 -1
  19. package/dist/hono-adapter.test.js +30 -6
  20. package/dist/hono-adapter.test.js.map +1 -1
  21. package/dist/host-execution-route.d.ts +9 -6
  22. package/dist/host-execution-route.js.map +1 -1
  23. package/dist/host-execution.d.ts +38 -42
  24. package/dist/host-execution.js +1 -1
  25. package/dist/host-execution.js.map +1 -1
  26. package/dist/index.d.ts +5 -1
  27. package/dist/index.js +11 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/interfaces.d.ts +105 -105
  30. package/dist/page-cache.js.map +1 -1
  31. package/dist/renderer/flexdoc.standalone.css +1 -1
  32. package/dist/renderer/flexdoc.standalone.js +82 -72
  33. package/dist/renderer-assets.js.map +1 -1
  34. package/dist/runtime-intelligence-setup.test.d.ts +1 -0
  35. package/dist/runtime-intelligence-setup.test.js +51 -0
  36. package/dist/runtime-intelligence-setup.test.js.map +1 -0
  37. package/dist/runtime-intelligence.d.ts +66 -0
  38. package/dist/runtime-intelligence.js +270 -0
  39. package/dist/runtime-intelligence.js.map +1 -0
  40. package/dist/runtime-intelligence.test.d.ts +1 -0
  41. package/dist/runtime-intelligence.test.js +143 -0
  42. package/dist/runtime-intelligence.test.js.map +1 -0
  43. package/dist/setup.js +26 -0
  44. package/dist/setup.js.map +1 -1
  45. package/dist/template.d.ts +1 -0
  46. package/dist/template.js +3 -1
  47. package/dist/template.js.map +1 -1
  48. package/dist/tsconfig.tsbuildinfo +1 -1
  49. package/package.json +1 -1
package/README.md CHANGED
@@ -1,27 +1,9 @@
1
1
  # FlexDoc Backend
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@prauga/flexdoc-backend.svg)](https://www.npmjs.com/package/@prauga/flexdoc-backend)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
4
+ [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
5
5
 
6
- The backend package for FlexDoc, a modern, customizable OpenAPI documentation generator that creates beautiful API documentation.
7
-
8
- ## Screenshots
9
-
10
- ### Light Mode
11
-
12
- ![FlexDoc Light Mode](./images/flexdoc-light.png)
13
-
14
- ### Dark Mode
15
-
16
- ![FlexDoc Dark Mode](./images/flexdoc-dark.png)
17
-
18
- ## Features
19
-
20
- - **Modern UI**: Clean, responsive interface with dark mode support
21
- - **Customizable**: Easily customize colors, typography, and layout
22
- - **Interactive**: Test API endpoints directly from the documentation
23
- - **Framework Agnostic**: Works with any JavaScript framework
24
- - **OpenAPI Compatible**: Supports OpenAPI 3.0 specifications
6
+ Thin self-hosted integrations that mount the FlexDoc renderer, optional API-host execution routes, and runtime intelligence endpoints on Express, Fastify, NestJS, or Hono.
25
7
 
26
8
  ## Installation
27
9
 
@@ -31,197 +13,72 @@ npm install @prauga/flexdoc-backend
31
13
 
32
14
  ## Usage
33
15
 
34
- ### Basic Usage
16
+ ### Express
35
17
 
36
- ```typescript
37
- import { FlexDoc } from '@prauga/flexdoc-backend';
38
- import { OpenAPIObject } from '@nestjs/swagger';
39
-
40
- // Create a new FlexDoc instance with your OpenAPI spec
41
- const flexdoc = new FlexDoc({
42
- spec: yourOpenAPISpec as OpenAPIObject,
43
- title: 'My API Documentation',
44
- description: 'Documentation for my awesome API',
45
- });
46
-
47
- // Generate HTML documentation
48
- const html = flexdoc.generateHTML();
49
-
50
- // Serve the documentation
51
- app.get('/api/docs', (req, res) => {
52
- res.send(html);
53
- });
54
- ```
18
+ ```javascript
19
+ const express = require('express');
20
+ const { setupExpressFlexDoc } = require('@prauga/flexdoc-backend');
21
+ const spec = require('./openapi.json');
55
22
 
56
- ### Configuration Options
57
-
58
- FlexDoc is highly customizable through the `FlexDocOptions` interface:
59
-
60
- ```typescript
61
- import { FlexDoc, FlexDocOptions } from '@prauga/flexdoc-backend';
62
-
63
- const options: FlexDocOptions = {
64
- // Required
65
- spec: yourOpenAPISpec,
66
-
67
- // Basic metadata
68
- title: 'My API Documentation',
69
- description: 'Documentation for my awesome API',
70
-
71
- // Theme configuration
72
- themeConfig: {
73
- colors: {
74
- primary: {
75
- main: '#3b82f6',
76
- light: '#eff6ff',
77
- dark: '#2563eb',
78
- },
79
- // Additional color options...
80
- },
81
- typography: {
82
- fontFamily: 'Inter, system-ui, sans-serif',
83
- fontSize: '16px',
84
- // Additional typography options...
85
- },
86
- },
23
+ const app = express();
87
24
 
88
- // Footer customization
89
- footer: {
90
- copyright: '© 2025 My Company',
91
- links: [
92
- {
93
- text: 'Terms',
94
- url: '/terms',
95
- icon: 'file-text', // Optional Lucide icon name
96
- },
97
- {
98
- text: 'Privacy',
99
- url: '/privacy',
100
- },
101
- ],
25
+ setupExpressFlexDoc(app, '/docs', {
26
+ spec,
27
+ options: {
28
+ title: 'My API Documentation',
29
+ tryIt: { enabled: true },
30
+ runtimeIntelligence: true,
102
31
  },
32
+ });
103
33
 
104
- // Additional options...
105
- };
106
-
107
- const flexdoc = new FlexDoc(options);
34
+ app.listen(3000);
108
35
  ```
109
36
 
110
- ### Framework Integration Examples
111
-
112
- #### NestJS
37
+ ### NestJS
113
38
 
114
39
  ```typescript
115
40
  import { NestFactory } from '@nestjs/core';
116
- import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
117
- import { FlexDoc } from '@prauga/flexdoc-backend';
41
+ import { DocumentBuilder } from '@nestjs/swagger';
42
+ import { setupNestFlexDoc } from '@prauga/flexdoc-backend';
118
43
  import { AppModule } from './app.module';
119
44
 
120
45
  async function bootstrap() {
121
46
  const app = await NestFactory.create(AppModule);
122
47
 
123
- // Create OpenAPI spec with Swagger
124
- const config = new DocumentBuilder()
48
+ const openApiConfig = new DocumentBuilder()
125
49
  .setTitle('My API')
126
- .setDescription('My API description')
127
- .setVersion('1.0')
50
+ .setVersion('1.0.0')
128
51
  .build();
129
- const document = SwaggerModule.createDocument(app, config);
130
52
 
131
- // Create FlexDoc instance
132
- const flexdoc = new FlexDoc({
133
- spec: document,
134
- title: 'My API Documentation',
135
- description: 'Documentation for my awesome API',
136
- footer: {
137
- copyright: '© 2025 My Company',
53
+ setupNestFlexDoc(app, '/docs', openApiConfig, {
54
+ options: {
55
+ title: 'My API Documentation',
56
+ tryIt: { enabled: true, hostExecution: true },
57
+ runtimeIntelligence: true,
138
58
  },
139
59
  });
140
60
 
141
- // Serve FlexDoc at /api/docs
142
- app.use('/api/docs', (req, res) => {
143
- res.send(flexdoc.generateHTML());
144
- });
145
-
146
61
  await app.listen(3000);
147
62
  }
148
63
  bootstrap();
149
64
  ```
150
65
 
151
- #### Express
66
+ ### Fastify and Hono
152
67
 
153
- ```typescript
154
- import express from 'express';
155
- import { FlexDoc } from '@prauga/flexdoc-backend';
156
- import swaggerJsdoc from 'swagger-jsdoc';
68
+ - `setupFastifyFlexDoc(app, path, options)` — static OpenAPI document
69
+ - `setupFastifySwaggerFlexDoc(app, path, options)` — document from `@fastify/swagger`
70
+ - `setupHonoFlexDoc(app, path, options)` Hono without adding Hono as a dependency
157
71
 
158
- const app = express();
72
+ Use `setupFlexDoc(app, path, options)` directly when you already have an Express-compatible `app.use` surface.
159
73
 
160
- // Generate OpenAPI spec
161
- const options = {
162
- definition: {
163
- openapi: '3.0.0',
164
- info: {
165
- title: 'My API',
166
- version: '1.0.0',
167
- },
168
- },
169
- apis: ['./src/routes/*.js'],
170
- };
171
- const openapiSpec = swaggerJsdoc(options);
172
-
173
- // Create FlexDoc instance
174
- const flexdoc = new FlexDoc({
175
- spec: openapiSpec,
176
- title: 'My API Documentation',
177
- });
178
-
179
- // Serve FlexDoc
180
- app.get('/api/docs', (req, res) => {
181
- res.send(flexdoc.generateHTML());
182
- });
183
-
184
- app.listen(3000);
185
- ```
74
+ ## Configuration
186
75
 
187
- ## API Reference
76
+ `FlexDocModuleOptions` requires a mount `path` and either an inline `spec` or a remote `specUrl`. Renderer behavior is configured through `options`, which mirrors the client `FlexDocRendererOptions` contract (theme, Try It, code samples, footer, optional docs-route auth, host execution, and runtime intelligence).
188
77
 
189
- ### `FlexDoc` Class
78
+ ## NestJS module
190
79
 
191
- The main class for generating API documentation.
192
-
193
- #### Constructor
194
-
195
- ```typescript
196
- constructor(options: FlexDocOptions)
197
- ```
198
-
199
- #### Methods
200
-
201
- - `generateHTML()`: Generates the HTML documentation
202
- - `getOpenAPISpec()`: Returns the processed OpenAPI specification
203
-
204
- ### `FlexDocOptions` Interface
205
-
206
- Configuration options for FlexDoc:
207
-
208
- | Property | Type | Description |
209
- | -------------- | ------------------------------- | -------------------------------- |
210
- | `spec` | `OpenAPIObject` | The OpenAPI specification object |
211
- | `title` | `string` | Documentation title |
212
- | `description` | `string` | Documentation description |
213
- | `themeConfig` | `ThemeConfig` | Theme configuration |
214
- | `footer` | `FooterConfig` | Footer configuration |
215
- | `favicon` | `string` | URL to favicon |
216
- | `customCss` | `string` | Custom CSS to inject |
217
- | `customJs` | `string` | Custom JavaScript to inject |
218
- | `defaultTheme` | `'light' \| 'dark' \| 'system'` | Default theme mode |
219
-
220
- ## Contributing
221
-
222
- Contributions are welcome! Please feel free to submit a Pull Request.
80
+ `FlexDocModule.forRoot` / `forRootAsync` registers the same routes through Nest's HTTP adapter. `FlexDocService.generateHTML` is available for programmatic HTML generation.
223
81
 
224
82
  ## License
225
83
 
226
- This project is licensed under the MIT License - see the LICENSE file for details.
227
-
84
+ AGPL-3.0-or-later
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ export type FlexDocContractValidationSeverity = 'error' | 'warning' | 'info';
2
+ export type FlexDocContractValidationCode = 'runtime.operation-undocumented' | 'runtime.operation-unobserved' | 'runtime.method-mismatch' | 'runtime.duplicate-operation';
3
+ export interface FlexDocContractRoute {
4
+ method: string;
5
+ path: string;
6
+ }
7
+ export interface FlexDocContractDuplicateRuntimeRoute extends FlexDocContractRoute {
8
+ count: number;
9
+ }
10
+ export interface FlexDocContractValidationLocation {
11
+ kind: 'operation';
12
+ path: string;
13
+ method?: string;
14
+ }
15
+ export interface FlexDocContractValidationFinding {
16
+ id: string;
17
+ code: FlexDocContractValidationCode;
18
+ severity: FlexDocContractValidationSeverity;
19
+ location: FlexDocContractValidationLocation;
20
+ message: string;
21
+ expected?: string | string[];
22
+ observed?: string | string[];
23
+ }
24
+ export interface FlexDocContractValidationSummary {
25
+ total: number;
26
+ errors: number;
27
+ warnings: number;
28
+ info: number;
29
+ }
30
+ export type FlexDocContractValidationStatus = 'pass' | 'warn' | 'fail' | 'partial';
31
+ export interface FlexDocContractValidationResult {
32
+ status: FlexDocContractValidationStatus;
33
+ complete: boolean;
34
+ findings: FlexDocContractValidationFinding[];
35
+ summary: FlexDocContractValidationSummary;
36
+ }
37
+ export interface ValidateRuntimeContractOptions {
38
+ documentedRoutes: FlexDocContractRoute[];
39
+ runtimeRoutes: FlexDocContractRoute[];
40
+ duplicateRuntimeRoutes?: FlexDocContractDuplicateRuntimeRoute[];
41
+ discoveryComplete: boolean;
42
+ }
43
+ export declare function validateRuntimeContract(options: ValidateRuntimeContractOptions): FlexDocContractValidationResult;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateRuntimeContract = validateRuntimeContract;
4
+ function routeShape(path) {
5
+ return path.replace(/\{[^/{}]+\}/g, '{}');
6
+ }
7
+ function exactShapeKey(route) {
8
+ return `${route.method.toUpperCase()} ${routeShape(route.path)}`;
9
+ }
10
+ function findingId(code, path, method) {
11
+ return `${code}:${method ? `${method}:` : ''}${routeShape(path)}`;
12
+ }
13
+ function groupedMethods(routes) {
14
+ const grouped = new Map();
15
+ for (const route of routes) {
16
+ const shape = routeShape(route.path);
17
+ const methods = grouped.get(shape) || new Set();
18
+ methods.add(route.method.toUpperCase());
19
+ grouped.set(shape, methods);
20
+ }
21
+ return new Map([...grouped.entries()].map(([shape, methods]) => [shape, [...methods].sort()]));
22
+ }
23
+ function representativePath(routes, shape) {
24
+ return routes.find((route) => routeShape(route.path) === shape)?.path || shape;
25
+ }
26
+ function validateRuntimeContract(options) {
27
+ const documentedKeys = new Set(options.documentedRoutes.map(exactShapeKey));
28
+ const runtimeKeys = new Set(options.runtimeRoutes.map(exactShapeKey));
29
+ const findings = [];
30
+ for (const duplicate of options.duplicateRuntimeRoutes || []) {
31
+ const method = duplicate.method.toUpperCase();
32
+ findings.push({
33
+ id: findingId('runtime.duplicate-operation', duplicate.path, method),
34
+ code: 'runtime.duplicate-operation',
35
+ severity: 'warning',
36
+ location: { kind: 'operation', method, path: duplicate.path },
37
+ message: `Runtime registers ${method} ${duplicate.path} ${duplicate.count} times. Multiple host registrations can shadow or chain handlers behind one documented operation.`,
38
+ expected: 'One runtime registration for this HTTP operation',
39
+ observed: `${duplicate.count} runtime registrations`,
40
+ });
41
+ }
42
+ const documentedMethods = groupedMethods(options.documentedRoutes);
43
+ const runtimeMethods = groupedMethods(options.runtimeRoutes);
44
+ const methodMismatchShapes = new Set();
45
+ for (const [shape, expectedMethods] of documentedMethods) {
46
+ const observedMethods = runtimeMethods.get(shape);
47
+ if (!observedMethods)
48
+ continue;
49
+ const hasExact = expectedMethods.some((method) => observedMethods.includes(method));
50
+ if (hasExact)
51
+ continue;
52
+ methodMismatchShapes.add(shape);
53
+ const path = representativePath(options.documentedRoutes, shape);
54
+ findings.push({
55
+ id: findingId('runtime.method-mismatch', path),
56
+ code: 'runtime.method-mismatch',
57
+ severity: options.discoveryComplete ? 'error' : 'warning',
58
+ location: { kind: 'operation', method: expectedMethods[0], path },
59
+ message: `Runtime route ${path} is registered for different HTTP methods than OpenAPI documents.`,
60
+ expected: expectedMethods,
61
+ observed: observedMethods,
62
+ });
63
+ }
64
+ for (const route of options.runtimeRoutes) {
65
+ const shape = routeShape(route.path);
66
+ if (methodMismatchShapes.has(shape))
67
+ continue;
68
+ if (documentedKeys.has(exactShapeKey(route)))
69
+ continue;
70
+ findings.push({
71
+ id: findingId('runtime.operation-undocumented', route.path, route.method),
72
+ code: 'runtime.operation-undocumented',
73
+ severity: 'warning',
74
+ location: { kind: 'operation', method: route.method.toUpperCase(), path: route.path },
75
+ message: `Runtime implements ${route.method.toUpperCase()} ${route.path}, but OpenAPI does not document that operation.`,
76
+ expected: 'Operation is represented in OpenAPI',
77
+ observed: 'Operation exists only in the running backend',
78
+ });
79
+ }
80
+ for (const route of options.documentedRoutes) {
81
+ const shape = routeShape(route.path);
82
+ if (methodMismatchShapes.has(shape))
83
+ continue;
84
+ if (runtimeKeys.has(exactShapeKey(route)))
85
+ continue;
86
+ findings.push({
87
+ id: findingId('runtime.operation-unobserved', route.path, route.method),
88
+ code: 'runtime.operation-unobserved',
89
+ severity: options.discoveryComplete ? 'error' : 'info',
90
+ location: { kind: 'operation', method: route.method.toUpperCase(), path: route.path },
91
+ message: options.discoveryComplete
92
+ ? `OpenAPI documents ${route.method.toUpperCase()} ${route.path}, but the running backend does not expose that operation.`
93
+ : `OpenAPI documents ${route.method.toUpperCase()} ${route.path}, but it was not observed during partial runtime discovery.`,
94
+ expected: 'Operation is exposed by the running backend',
95
+ observed: options.discoveryComplete ? 'No matching runtime operation exists' : 'No matching operation was observed during partial discovery',
96
+ });
97
+ }
98
+ const ordered = findings.sort((left, right) => {
99
+ const rank = { error: 0, warning: 1, info: 2 };
100
+ return rank[left.severity] - rank[right.severity]
101
+ || left.location.path.localeCompare(right.location.path)
102
+ || (left.location.method || '').localeCompare(right.location.method || '')
103
+ || left.code.localeCompare(right.code);
104
+ });
105
+ const summary = {
106
+ total: ordered.length,
107
+ errors: ordered.filter((finding) => finding.severity === 'error').length,
108
+ warnings: ordered.filter((finding) => finding.severity === 'warning').length,
109
+ info: ordered.filter((finding) => finding.severity === 'info').length,
110
+ };
111
+ const status = summary.errors > 0
112
+ ? 'fail'
113
+ : summary.warnings > 0
114
+ ? 'warn'
115
+ : !options.discoveryComplete
116
+ ? 'partial'
117
+ : 'pass';
118
+ return { status, complete: options.discoveryComplete, findings: ordered, summary };
119
+ }
120
+ //# sourceMappingURL=contract-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-validation.js","sourceRoot":"","sources":["../src/contract-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const contract_validation_1 = require("./contract-validation");
4
+ describe('runtime contract validation', () => {
5
+ it('passes when runtime and OpenAPI expose the same operations', () => {
6
+ expect((0, contract_validation_1.validateRuntimeContract)({
7
+ documentedRoutes: [
8
+ { method: 'GET', path: '/pets' },
9
+ { method: 'GET', path: '/pets/{petId}' },
10
+ ],
11
+ runtimeRoutes: [
12
+ { method: 'GET', path: '/pets' },
13
+ { method: 'GET', path: '/pets/{id}' },
14
+ ],
15
+ discoveryComplete: true,
16
+ })).toEqual({
17
+ status: 'pass',
18
+ complete: true,
19
+ findings: [],
20
+ summary: { total: 0, errors: 0, warnings: 0, info: 0 },
21
+ });
22
+ });
23
+ it('reports one navigable method mismatch instead of duplicate presence findings', () => {
24
+ const result = (0, contract_validation_1.validateRuntimeContract)({
25
+ documentedRoutes: [{ method: 'POST', path: '/pets/{petId}' }],
26
+ runtimeRoutes: [{ method: 'GET', path: '/pets/{id}' }],
27
+ discoveryComplete: true,
28
+ });
29
+ expect(result.status).toBe('fail');
30
+ expect(result.summary).toEqual({ total: 1, errors: 1, warnings: 0, info: 0 });
31
+ expect(result.findings).toEqual([expect.objectContaining({
32
+ code: 'runtime.method-mismatch',
33
+ severity: 'error',
34
+ location: { kind: 'operation', method: 'POST', path: '/pets/{petId}' },
35
+ expected: ['POST'],
36
+ observed: ['GET'],
37
+ })]);
38
+ });
39
+ it('uses a deterministic expected method when a path documents multiple methods', () => {
40
+ const result = (0, contract_validation_1.validateRuntimeContract)({
41
+ documentedRoutes: [
42
+ { method: 'POST', path: '/pets/{petId}' },
43
+ { method: 'GET', path: '/pets/{petId}' },
44
+ ],
45
+ runtimeRoutes: [{ method: 'DELETE', path: '/pets/{id}' }],
46
+ discoveryComplete: true,
47
+ });
48
+ expect(result.findings[0]).toEqual(expect.objectContaining({
49
+ code: 'runtime.method-mismatch',
50
+ location: { kind: 'operation', method: 'GET', path: '/pets/{petId}' },
51
+ expected: ['GET', 'POST'],
52
+ observed: ['DELETE'],
53
+ }));
54
+ });
55
+ it('reports undocumented runtime operations as warnings', () => {
56
+ const result = (0, contract_validation_1.validateRuntimeContract)({
57
+ documentedRoutes: [{ method: 'GET', path: '/pets' }],
58
+ runtimeRoutes: [
59
+ { method: 'GET', path: '/pets' },
60
+ { method: 'POST', path: '/internal/reindex' },
61
+ ],
62
+ discoveryComplete: true,
63
+ });
64
+ expect(result.status).toBe('warn');
65
+ expect(result.findings).toEqual([expect.objectContaining({
66
+ code: 'runtime.operation-undocumented',
67
+ severity: 'warning',
68
+ location: { kind: 'operation', method: 'POST', path: '/internal/reindex' },
69
+ })]);
70
+ });
71
+ it('reports duplicate host registrations that standalone OpenAPI tooling cannot observe', () => {
72
+ const result = (0, contract_validation_1.validateRuntimeContract)({
73
+ documentedRoutes: [{ method: 'GET', path: '/pets/{petId}' }],
74
+ runtimeRoutes: [{ method: 'GET', path: '/pets/{id}' }],
75
+ duplicateRuntimeRoutes: [{ method: 'GET', path: '/pets/{id}', count: 2 }],
76
+ discoveryComplete: true,
77
+ });
78
+ expect(result.status).toBe('warn');
79
+ expect(result.summary).toEqual({ total: 1, errors: 0, warnings: 1, info: 0 });
80
+ expect(result.findings[0]).toEqual(expect.objectContaining({
81
+ code: 'runtime.duplicate-operation',
82
+ severity: 'warning',
83
+ location: { kind: 'operation', method: 'GET', path: '/pets/{id}' },
84
+ expected: 'One runtime registration for this HTTP operation',
85
+ observed: '2 runtime registrations',
86
+ }));
87
+ });
88
+ it('treats documented absence as an error only when discovery is complete', () => {
89
+ const complete = (0, contract_validation_1.validateRuntimeContract)({
90
+ documentedRoutes: [{ method: 'GET', path: '/pets/{petId}' }],
91
+ runtimeRoutes: [],
92
+ discoveryComplete: true,
93
+ });
94
+ expect(complete.status).toBe('fail');
95
+ expect(complete.findings[0]).toEqual(expect.objectContaining({
96
+ code: 'runtime.operation-unobserved',
97
+ severity: 'error',
98
+ }));
99
+ const partial = (0, contract_validation_1.validateRuntimeContract)({
100
+ documentedRoutes: [{ method: 'GET', path: '/pets/{petId}' }],
101
+ runtimeRoutes: [],
102
+ discoveryComplete: false,
103
+ });
104
+ expect(partial.status).toBe('partial');
105
+ expect(partial.complete).toBe(false);
106
+ expect(partial.findings[0]).toEqual(expect.objectContaining({
107
+ code: 'runtime.operation-unobserved',
108
+ severity: 'info',
109
+ }));
110
+ });
111
+ });
112
+ //# sourceMappingURL=contract-validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-validation.test.js","sourceRoot":"","sources":["../src/contract-validation.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"flexdoc.module.js","sourceRoot":"","sources":["../src/flexdoc.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAMwB;AACxB,uCAA+C;AAC/C,mCAAuC;AACvC,uDAAmD;AAI5C,IAAM,aAAa,qBAAnB,MAAM,aAAa;IACxB,YAC8C,OAA6B,EACxD,eAAiC;QADN,YAAO,GAAP,OAAO,CAAsB;QACxD,oBAAe,GAAf,eAAe,CAAkB;IACjD,CAAC;IAEJ,YAAY;QACV,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CACV,uEAAuE,CACxE,CAAC;YACF,OAAO;QACT,CAAC;QAGD,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;QACrD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CACV,oEAAoE,CACrE,CAAC;YACF,OAAO;QACT,CAAC;QAGD,MAAM,GAAG,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;QAGtC,IAAA,oBAAY,EAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YACnC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC7B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;SAC9B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,OAA6B;QAC1C,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE;gBACT,gCAAc;gBACd;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,QAAQ,EAAE,OAAO;iBAClB;aACF;YACD,OAAO,EAAE,CAAC,gCAAc,CAAC;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,OAKnB;QACC,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE;gBACT,gCAAc;gBACd;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;oBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;iBAC7B;aACF;YACD,OAAO,EAAE,CAAC,gCAAc,CAAC;SAC1B,CAAC;IACJ,CAAC;CACF,CAAA;AAnEY,sCAAa;wBAAb,aAAa;IADzB,IAAA,eAAM,EAAC,EAAE,CAAC;IAGN,WAAA,IAAA,eAAM,EAAC,iBAAiB,CAAC,CAAA;6CACS,sBAAe;GAHzC,aAAa,CAmEzB"}
1
+ {"version":3,"file":"flexdoc.module.js","sourceRoot":"","sources":["../src/flexdoc.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAMwB;AACxB,uCAA+C;AAC/C,mCAAuC;AACvC,uDAAmD;AAK5C,IAAM,aAAa,qBAAnB,MAAM,aAAa;IAMxB,YAC8C,OAA6B,EACxD,eAAiC;QADN,YAAO,GAAP,OAAO,CAAsB;QACxD,oBAAe,GAAf,eAAe,CAAkB;IACjD,CAAC;IAGJ,YAAY;QACV,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CACV,uEAAuE,CACxE,CAAC;YACF,OAAO;QACT,CAAC;QAGD,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;QACrD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CACV,oEAAoE,CACrE,CAAC;YACF,OAAO;QACT,CAAC;QAGD,MAAM,GAAG,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;QAGtC,IAAA,oBAAY,EAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YACnC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC7B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;SAC9B,CAAC,CAAC;IACL,CAAC;IAOD,MAAM,CAAC,OAAO,CAAC,OAA6B;QAC1C,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE;gBACT,gCAAc;gBACd;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,QAAQ,EAAE,OAAO;iBAClB;aACF;YACD,OAAO,EAAE,CAAC,gCAAc,CAAC;SAC1B,CAAC;IACJ,CAAC;IAOD,MAAM,CAAC,YAAY,CAAC,OAOnB;QACC,OAAO;YACL,MAAM,EAAE,eAAa;YACrB,SAAS,EAAE;gBACT,gCAAc;gBACd;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;oBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;iBAC7B;aACF;YACD,OAAO,EAAE,CAAC,gCAAc,CAAC;SAC1B,CAAC;IACJ,CAAC;CACF,CAAA;AArFY,sCAAa;wBAAb,aAAa;IADzB,IAAA,eAAM,EAAC,EAAE,CAAC;IAQN,WAAA,IAAA,eAAM,EAAC,iBAAiB,CAAC,CAAA;6CACS,sBAAe;GARzC,aAAa,CAqFzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"flexdoc.service.js","sourceRoot":"","sources":["../src/flexdoc.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAE5C,yCAAiD;AAG1C,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAAY,CAAC,IAAY,EAAE,UAA0B,EAAE;QACrD,OAAO,IAAA,8BAAmB,EAAC,IAA+B,EAAE,OAAO,CAAC,CAAC;IACvE,CAAC;IAED,mBAAmB,CAAC,OAAe,EAAE,UAA0B,EAAE;QAC/D,OAAO,IAAA,8BAAmB,EAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5D,CAAC;CACF,CAAA;AARY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;GACA,cAAc,CAQ1B"}
1
+ {"version":3,"file":"flexdoc.service.js","sourceRoot":"","sources":["../src/flexdoc.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAE5C,yCAAiD;AAI1C,IAAM,cAAc,GAApB,MAAM,cAAc;IAOzB,YAAY,CAAC,IAAY,EAAE,UAA0B,EAAE;QACrD,OAAO,IAAA,8BAAmB,EAAC,IAA+B,EAAE,OAAO,CAAC,CAAC;IACvE,CAAC;IAQD,mBAAmB,CAAC,OAAe,EAAE,UAA0B,EAAE;QAC/D,OAAO,IAAA,8BAAmB,EAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5D,CAAC;CACF,CAAA;AApBY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;GACA,cAAc,CAoB1B"}
@@ -28,6 +28,8 @@ export interface FastifyLikeApplication {
28
28
  hasContentTypeParser?: (contentType: string) => boolean;
29
29
  ready?: () => Promise<unknown>;
30
30
  swagger?: () => Record<string, unknown>;
31
+ printRoutes?: (options?: Record<string, unknown>) => string;
32
+ version?: string;
31
33
  }
32
34
  export interface NestLikeApplication {
33
35
  getHttpAdapter(): {
@@ -45,6 +45,7 @@ const template_1 = require("./template");
45
45
  const host_execution_1 = require("./host-execution");
46
46
  const host_execution_route_1 = require("./host-execution-route");
47
47
  const page_cache_1 = require("./page-cache");
48
+ const runtime_intelligence_1 = require("./runtime-intelligence");
48
49
  function setupExpressFlexDoc(app, path, options) {
49
50
  (0, setup_1.setupFlexDoc)(app, path, options);
50
51
  }
@@ -108,6 +109,8 @@ function setupFastifyFlexDocInternal(app, path, options, specProvider) {
108
109
  const auth = options.options?.auth;
109
110
  const hostExecutionState = (0, host_execution_1.createHostExecutionState)(options.options?.tryIt?.hostExecution);
110
111
  const hostRouteAvailable = hostExecutionState.enabled && typeof app.post === 'function';
112
+ const runtimeEnabled = (0, runtime_intelligence_1.runtimeIntelligenceEnabled)(options.options?.runtimeIntelligence);
113
+ const runtimeEndpoint = `${rendererBasePath}/runtime`;
111
114
  let remoteSpecPromise = null;
112
115
  let generatedSpecPromise = null;
113
116
  const routeOptions = auth ? {
@@ -145,6 +148,7 @@ function setupFastifyFlexDocInternal(app, path, options, specProvider) {
145
148
  rendererBasePath,
146
149
  rendererVersion: assets.version,
147
150
  hostExecutionPublic: hostRouteAvailable ? (0, host_execution_1.publicHostExecutionOptions)(hostExecutionState, rendererBasePath) : undefined,
151
+ runtimeIntelligencePublic: runtimeEnabled ? { available: true, endpoint: runtimeEndpoint, framework: 'fastify' } : undefined,
148
152
  });
149
153
  });
150
154
  const sendHostResult = (reply, result) => {
@@ -153,6 +157,23 @@ function setupFastifyFlexDocInternal(app, path, options, specProvider) {
153
157
  target = target.header(name, value);
154
158
  return target.send(result.body);
155
159
  };
160
+ if (runtimeEnabled) {
161
+ app.get(runtimeEndpoint, routeOptions, async (request, reply) => {
162
+ const serverOrigin = (0, host_execution_route_1.hostExecutionRequestOrigin)({
163
+ headers: request.headers,
164
+ protocol: request.protocol || (request.raw?.socket?.encrypted ? 'https' : 'http'),
165
+ });
166
+ const snapshot = (0, runtime_intelligence_1.buildRuntimeIntelligenceSnapshot)({
167
+ spec: await resolvedSpec(),
168
+ discovery: await (0, runtime_intelligence_1.discoverFastifyRoutes)(app, normalizedPath),
169
+ serverOrigin,
170
+ });
171
+ return reply
172
+ .type('application/json; charset=utf-8')
173
+ .header('Cache-Control', 'no-store')
174
+ .send(JSON.stringify(snapshot));
175
+ });
176
+ }
156
177
  if (hostRouteAvailable) {
157
178
  if (app.addContentTypeParser && !app.hasContentTypeParser?.('multipart/form-data')) {
158
179
  app.addContentTypeParser('multipart/form-data', { parseAs: 'buffer' }, (_request, body, done) => done(null, body));