nestjs-openapi-parser 0.0.4 → 0.0.5
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/dist/config/types.d.ts +25 -0
- package/dist/config/types.js.map +1 -1
- package/dist/lib.d.ts +2 -2
- package/dist/lib.js.map +1 -1
- package/dist/parser/index.js +47 -0
- package/dist/parser/index.js.map +1 -1
- package/dist/types/openapi.d.ts +10 -0
- package/docs/configuration.md +21 -0
- package/package.json +1 -1
package/dist/config/types.d.ts
CHANGED
|
@@ -111,11 +111,36 @@ export interface ConventionsConfig {
|
|
|
111
111
|
* constructor. Looked up against the project's AST index by `klass.name`.
|
|
112
112
|
*/
|
|
113
113
|
export type ModelConstructor = abstract new (...args: any[]) => unknown;
|
|
114
|
+
export interface PagesConfig {
|
|
115
|
+
/**
|
|
116
|
+
* Markdown files rendered as standalone pages. Each path is relative to the
|
|
117
|
+
* project root or absolute. The page title is the file's first `# heading`
|
|
118
|
+
* line (else the file name); the whole file body is the page content.
|
|
119
|
+
*/
|
|
120
|
+
files: string[];
|
|
121
|
+
/**
|
|
122
|
+
* Sidebar heading for the Markdown pages section, placed first (right under
|
|
123
|
+
* the Introduction). Defaults to `Documentation`.
|
|
124
|
+
*/
|
|
125
|
+
group?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Sidebar heading that groups the API's operation tags. Required because
|
|
128
|
+
* `x-tagGroups` hides any ungrouped tag, so the API tags must be grouped too.
|
|
129
|
+
* Defaults to `API`.
|
|
130
|
+
*/
|
|
131
|
+
apiGroup?: string;
|
|
132
|
+
}
|
|
114
133
|
export interface NestParserConfig {
|
|
115
134
|
openapi: OpenApiConfig;
|
|
116
135
|
project?: ProjectConfig;
|
|
117
136
|
conventions?: ConventionsConfig;
|
|
118
137
|
hooks?: NestParserHooks;
|
|
138
|
+
/**
|
|
139
|
+
* Standalone Markdown pages emitted ahead of the API reference via
|
|
140
|
+
* `x-tagGroups` (rendered by Scalar/Redoc). Omit to emit no pages and no
|
|
141
|
+
* `x-tagGroups` at all.
|
|
142
|
+
*/
|
|
143
|
+
pages?: PagesConfig;
|
|
119
144
|
/**
|
|
120
145
|
* Class references to force-include in `components.schemas`, even when no
|
|
121
146
|
* endpoint reaches them. Pass the class itself (not its name) — we resolve
|
package/dist/config/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":";;AAwLA,oCAEC;AAHD,yEAAyE;AACzE,SAAgB,YAAY,CAAC,MAAwB;IACnD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/lib.d.ts
CHANGED
|
@@ -2,11 +2,11 @@ export { parseNestProject } from './parser';
|
|
|
2
2
|
export type { ParseNestProjectOptions } from './parser';
|
|
3
3
|
export { AstIndex, PathBuilder, SchemaBuilder } from './parser';
|
|
4
4
|
export { defineConfig } from './config/types';
|
|
5
|
-
export type { NestParserConfig, NestParserHooks, OpenApiConfig, ProjectConfig, ConventionsConfig, ResponseSchemaContext, SecurityContext, EndpointSummaryContext, ModelConstructor, } from './config/types';
|
|
5
|
+
export type { NestParserConfig, NestParserHooks, OpenApiConfig, ProjectConfig, ConventionsConfig, PagesConfig, ResponseSchemaContext, SecurityContext, EndpointSummaryContext, ModelConstructor, } from './config/types';
|
|
6
6
|
export { loadConfig } from './config/loader';
|
|
7
7
|
export type { LoadConfigOptions, LoadedConfig } from './config/loader';
|
|
8
8
|
export { validateDocument } from './validate';
|
|
9
9
|
export type { ValidationResult } from './validate';
|
|
10
10
|
export { filterScopedComments, getScopes, getTags, isVisible, parseScopeList } from './parser/tags';
|
|
11
11
|
export type { TagBag } from './parser/tags';
|
|
12
|
-
export type { OpenApiDocument, OpenApiInfo, OpenApiServer, OpenApiSchema, OpenApiSecurityScheme, OpenApiSecurityRequirement, } from './types/openapi';
|
|
12
|
+
export type { OpenApiDocument, OpenApiInfo, OpenApiServer, OpenApiSchema, OpenApiSecurityScheme, OpenApiSecurityRequirement, OpenApiTagGroup, } from './types/openapi';
|
package/dist/lib.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":";;;AAAA,mCAA4C;AAAnC,0GAAA,gBAAgB,OAAA;AAEzB,mCAAgE;AAAvD,kGAAA,QAAQ,OAAA;AAAE,qGAAA,WAAW,OAAA;AAAE,uGAAA,aAAa,OAAA;AAE7C,wCAA8C;AAArC,qGAAA,YAAY,OAAA;
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":";;;AAAA,mCAA4C;AAAnC,0GAAA,gBAAgB,OAAA;AAEzB,mCAAgE;AAAvD,kGAAA,QAAQ,OAAA;AAAE,qGAAA,WAAW,OAAA;AAAE,uGAAA,aAAa,OAAA;AAE7C,wCAA8C;AAArC,qGAAA,YAAY,OAAA;AAcrB,0CAA6C;AAApC,oGAAA,UAAU,OAAA;AAGnB,uCAA8C;AAArC,4GAAA,gBAAgB,OAAA;AAGzB,sCAAoG;AAA3F,4GAAA,oBAAoB,OAAA;AAAE,iGAAA,SAAS,OAAA;AAAE,+FAAA,OAAO,OAAA;AAAE,iGAAA,SAAS,OAAA;AAAE,sGAAA,cAAc,OAAA"}
|
package/dist/parser/index.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.SchemaBuilder = exports.PathBuilder = exports.AstIndex = void 0;
|
|
4
7
|
exports.parseNestProject = parseNestProject;
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
5
10
|
const validate_1 = require("../validate");
|
|
6
11
|
const ast_index_1 = require("./ast-index");
|
|
7
12
|
Object.defineProperty(exports, "AstIndex", { enumerable: true, get: function () { return ast_index_1.AstIndex; } });
|
|
@@ -81,6 +86,7 @@ async function parseNestProject(options) {
|
|
|
81
86
|
if (tags.length > 0) {
|
|
82
87
|
document.tags = tags;
|
|
83
88
|
}
|
|
89
|
+
applyPages(document, projectRoot, config.pages, tags);
|
|
84
90
|
const { valid, errors } = await (0, validate_1.validateDocument)(document);
|
|
85
91
|
if (!valid) {
|
|
86
92
|
throw new Error(`Generated OpenAPI document failed schema validation:\n${errors
|
|
@@ -92,4 +98,45 @@ async function parseNestProject(options) {
|
|
|
92
98
|
function formatScopes(scopes) {
|
|
93
99
|
return scopes.size === 0 ? '{}' : `{${[...scopes].join(', ')}}`;
|
|
94
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Emit the configured Markdown pages as standalone, operation-less tags and wrap
|
|
103
|
+
* the whole document in `x-tagGroups` so Scalar/Redoc renders the pages first
|
|
104
|
+
* (right under the Introduction). Because `x-tagGroups` hides any ungrouped tag,
|
|
105
|
+
* the API's own operation tags are gathered into a second group.
|
|
106
|
+
*/
|
|
107
|
+
function applyPages(document, projectRoot, pages, operationTags) {
|
|
108
|
+
if (!pages || pages.files.length === 0)
|
|
109
|
+
return;
|
|
110
|
+
const pageTags = pages.files.map((file) => {
|
|
111
|
+
const { title, content } = readPage(node_path_1.default.resolve(projectRoot, file));
|
|
112
|
+
return { name: title, description: content };
|
|
113
|
+
});
|
|
114
|
+
// Pages render first; the existing operation tags keep their order after them.
|
|
115
|
+
document.tags = [...pageTags, ...(document.tags ?? [])];
|
|
116
|
+
const tagGroups = [
|
|
117
|
+
{ name: pages.group ?? 'Documentation', tags: pageTags.map((t) => t.name) },
|
|
118
|
+
];
|
|
119
|
+
if (operationTags.length > 0) {
|
|
120
|
+
tagGroups.push({ name: pages.apiGroup ?? 'API', tags: operationTags.map((t) => t.name) });
|
|
121
|
+
}
|
|
122
|
+
document['x-tagGroups'] = tagGroups;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Read a Markdown page: the title is the first line when it's an ATX heading
|
|
126
|
+
* (`# Title`), otherwise the file's base name without extension. The content is
|
|
127
|
+
* the whole file, verbatim.
|
|
128
|
+
*/
|
|
129
|
+
function readPage(filePath) {
|
|
130
|
+
let content;
|
|
131
|
+
try {
|
|
132
|
+
content = node_fs_1.default.readFileSync(filePath, 'utf-8');
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
throw new Error(`pages: Markdown file not found or unreadable: ${filePath}`);
|
|
136
|
+
}
|
|
137
|
+
const firstLine = content.split('\n', 1)[0]?.trim() ?? '';
|
|
138
|
+
const heading = /^#{1,6}\s+(.+?)\s*$/.exec(firstLine);
|
|
139
|
+
const title = heading ? heading[1].trim() : node_path_1.default.basename(filePath).replace(/\.[^.]+$/, '');
|
|
140
|
+
return { title, content };
|
|
141
|
+
}
|
|
95
142
|
//# sourceMappingURL=index.js.map
|
package/dist/parser/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types/openapi.d.ts
CHANGED
|
@@ -25,6 +25,11 @@ export interface OpenApiInfo {
|
|
|
25
25
|
}
|
|
26
26
|
export type OpenApiSecurityScheme = Record<string, unknown>;
|
|
27
27
|
export type OpenApiSecurityRequirement = Record<string, string[]>;
|
|
28
|
+
/** A Redoc/Scalar tag group — top-level navigation grouping a set of tag names. */
|
|
29
|
+
export interface OpenApiTagGroup {
|
|
30
|
+
name: string;
|
|
31
|
+
tags: string[];
|
|
32
|
+
}
|
|
28
33
|
export interface OpenApiDocument {
|
|
29
34
|
openapi: string;
|
|
30
35
|
info: OpenApiInfo;
|
|
@@ -39,4 +44,9 @@ export interface OpenApiDocument {
|
|
|
39
44
|
name: string;
|
|
40
45
|
description?: string;
|
|
41
46
|
}[];
|
|
47
|
+
/**
|
|
48
|
+
* Redoc/Scalar navigation groups. When present, tags not listed in any group
|
|
49
|
+
* are hidden — so the API's own tags must be grouped too, not just doc pages.
|
|
50
|
+
*/
|
|
51
|
+
'x-tagGroups'?: OpenApiTagGroup[];
|
|
42
52
|
}
|
package/docs/configuration.md
CHANGED
|
@@ -34,6 +34,7 @@ export default defineConfig({
|
|
|
34
34
|
|
|
35
35
|
scopes: [], // see "Documentation variants" below
|
|
36
36
|
additionalModels: [], // force-include unreachable models — see docs/parser.md
|
|
37
|
+
pages: { files: ['./docs/getting-started.md'] }, // see "Markdown pages" below
|
|
37
38
|
|
|
38
39
|
hooks: {
|
|
39
40
|
// see "Hooks"
|
|
@@ -41,6 +42,26 @@ export default defineConfig({
|
|
|
41
42
|
});
|
|
42
43
|
```
|
|
43
44
|
|
|
45
|
+
## Markdown pages — `pages`
|
|
46
|
+
|
|
47
|
+
Render standalone Markdown files as documentation pages ahead of the API reference (via `x-tagGroups`, which Scalar and Redoc display in the sidebar, right under the Introduction):
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
defineConfig({
|
|
51
|
+
// ...
|
|
52
|
+
pages: {
|
|
53
|
+
files: ['./docs/getting-started.md', './docs/authentication.md'],
|
|
54
|
+
group: 'Documentation', // sidebar heading for the pages (default)
|
|
55
|
+
apiGroup: 'API', // sidebar heading for the endpoints (default)
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Each path is resolved relative to the project root (or absolute). A missing file fails the build.
|
|
61
|
+
- The page **title** is the file's first line when it's a `#` heading, otherwise the file name (without extension). The **whole file body** becomes the page content.
|
|
62
|
+
- Pages are emitted first, so they appear at the top of the sidebar.
|
|
63
|
+
- Because `x-tagGroups` hides any tag not in a group, the API's own operation tags are automatically gathered into the `apiGroup` section — so endpoints stay visible.
|
|
64
|
+
|
|
44
65
|
## Documentation variants — `@Scope`
|
|
45
66
|
|
|
46
67
|
Tag controllers, methods, models or fields with `@Scope` to make them appear in the spec only when the build is configured for a matching scope. Untagged items are always emitted.
|