@visulima/jsdoc-open-api 1.3.6 → 1.3.8
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/CHANGELOG.md +14 -0
- package/README.md +80 -68
- package/dist/{chunk-AGKRTLON.mjs → chunk-4BGSTSHH.mjs} +9 -10
- package/dist/chunk-4BGSTSHH.mjs.map +1 -0
- package/dist/chunk-5U2PT3WZ.js +34 -0
- package/dist/chunk-5U2PT3WZ.js.map +1 -0
- package/dist/{chunk-NQ3ULO4M.js → chunk-6BASRGSS.js} +11 -13
- package/dist/chunk-6BASRGSS.js.map +1 -0
- package/dist/chunk-SXATCZ56.mjs +20 -0
- package/dist/chunk-SXATCZ56.mjs.map +1 -0
- package/dist/cli/commander/index.js +3 -3
- package/dist/cli/commander/index.mjs +2 -2
- package/dist/cli/index.js +4 -4
- package/dist/cli/index.mjs +2 -2
- package/dist/index.js +7 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -8
- package/dist/chunk-AGKRTLON.mjs.map +0 -1
- package/dist/chunk-HCLKS7N6.mjs +0 -18
- package/dist/chunk-HCLKS7N6.mjs.map +0 -1
- package/dist/chunk-NQ3ULO4M.js.map +0 -1
- package/dist/chunk-THSPLI4X.js +0 -31
- package/dist/chunk-THSPLI4X.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## @visulima/jsdoc-open-api [1.3.8](https://github.com/visulima/visulima/compare/@visulima/jsdoc-open-api@1.3.7...@visulima/jsdoc-open-api@1.3.8) (2023-06-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* wrong import of the new validator ([73a3e89](https://github.com/visulima/visulima/commit/73a3e8944590b8a158db7afcb5cc0baa0632775b))
|
|
7
|
+
|
|
8
|
+
## @visulima/jsdoc-open-api [1.3.7](https://github.com/visulima/visulima/compare/@visulima/jsdoc-open-api@1.3.6...@visulima/jsdoc-open-api@1.3.7) (2023-05-31)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* switched the oas validator to @stoplight/spectral-core to support OpenAPI v2 & v3.x and AsyncAPI validation ([4d416ff](https://github.com/visulima/visulima/commit/4d416ff425eeb0c68a9e389982cbd4be4b3eaaee))
|
|
14
|
+
|
|
1
15
|
## @visulima/jsdoc-open-api [1.3.6](https://github.com/visulima/visulima/compare/@visulima/jsdoc-open-api@1.3.5...@visulima/jsdoc-open-api@1.3.6) (2023-05-29)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<h3>Visulima jsdoc-open-api</h3>
|
|
3
3
|
<p>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Visulima jsdoc-open-api parser and generator is a forked version of [openapi-comment-parser](https://github.com/bee-travels/openapi-comment-parser) and [swagger-jsdoc](https://github.com/Surnet/swagger-jsdoc) its built on top of [swagger](https://swagger.io/) and [JSDoc](https://jsdoc.app/), for speed and minimal runtime overhead.
|
|
6
6
|
|
|
7
7
|
</p>
|
|
8
8
|
</div>
|
|
@@ -51,7 +51,6 @@ Choose the syntax you want to use for your OpenAPI definitions:
|
|
|
51
51
|
|
|
52
52
|
#### To use the CLI, you need to install this missing packages:
|
|
53
53
|
|
|
54
|
-
|
|
55
54
|
```sh
|
|
56
55
|
npm install cli-progress commander
|
|
57
56
|
```
|
|
@@ -77,8 +76,8 @@ jsdoc-open-api generate src/
|
|
|
77
76
|
### As Next.js webpack plugin:
|
|
78
77
|
|
|
79
78
|
#### with-open-api.js
|
|
80
|
-
```js
|
|
81
79
|
|
|
80
|
+
```js
|
|
82
81
|
const path = require("node:path");
|
|
83
82
|
const fs = require("node:fs");
|
|
84
83
|
const { SwaggerCompilerPlugin } = require("@visulima/jsdoc-open-api");
|
|
@@ -91,52 +90,60 @@ const { SwaggerCompilerPlugin } = require("@visulima/jsdoc-open-api");
|
|
|
91
90
|
*
|
|
92
91
|
* @returns {function(*): *&{webpack: function(Configuration, *): (Configuration)}}
|
|
93
92
|
*/
|
|
94
|
-
const withOpenApi =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
const withOpenApi =
|
|
94
|
+
({ definition, sources, verbose, output = "swagger/swagger.json" }) =>
|
|
95
|
+
(nextConfig) => {
|
|
96
|
+
return {
|
|
97
|
+
...nextConfig,
|
|
98
|
+
webpack: (config, options) => {
|
|
99
|
+
if (!options.isServer) {
|
|
100
|
+
return config;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (output.startsWith("/")) {
|
|
104
|
+
output = output.slice(1);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!output.endsWith(".json")) {
|
|
108
|
+
throw new Error("The output path must end with .json");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// eslint-disable-next-line no-param-reassign
|
|
112
|
+
config = {
|
|
113
|
+
...config,
|
|
114
|
+
plugins: [
|
|
115
|
+
// @ts-ignore
|
|
116
|
+
...config.plugins,
|
|
117
|
+
new SwaggerCompilerPlugin(
|
|
118
|
+
`${options.dir}/${output}`,
|
|
119
|
+
sources.map((source) => {
|
|
120
|
+
const combinedPath = path.join(options.dir, source.replace("./", ""));
|
|
121
|
+
|
|
122
|
+
// Check if the path is a directory
|
|
123
|
+
fs.lstatSync(combinedPath).isDirectory();
|
|
124
|
+
|
|
125
|
+
return combinedPath;
|
|
126
|
+
}),
|
|
127
|
+
definition,
|
|
128
|
+
{ verbose },
|
|
129
|
+
),
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
if (typeof nextConfig.webpack === "function") {
|
|
134
|
+
return nextConfig.webpack(config, options);
|
|
135
|
+
}
|
|
136
|
+
|
|
99
137
|
return config;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (output.startsWith("/")) {
|
|
103
|
-
output = output.slice(1);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (!output.endsWith(".json")) {
|
|
107
|
-
throw new Error("The output path must end with .json");
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// eslint-disable-next-line no-param-reassign
|
|
111
|
-
config = {
|
|
112
|
-
...config,
|
|
113
|
-
plugins: [
|
|
114
|
-
// @ts-ignore
|
|
115
|
-
...config.plugins,
|
|
116
|
-
new SwaggerCompilerPlugin(`${options.dir}/${output}`, sources.map((source) => {
|
|
117
|
-
const combinedPath = path.join(options.dir, source.replace("./", ""));
|
|
118
|
-
|
|
119
|
-
// Check if the path is a directory
|
|
120
|
-
fs.lstatSync(combinedPath).isDirectory();
|
|
121
|
-
|
|
122
|
-
return combinedPath;
|
|
123
|
-
}), definition, { verbose }),
|
|
124
|
-
],
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
if (typeof nextConfig.webpack === "function") {
|
|
128
|
-
return nextConfig.webpack(config, options);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return config;
|
|
132
|
-
},
|
|
138
|
+
},
|
|
139
|
+
};
|
|
133
140
|
};
|
|
134
|
-
};
|
|
135
141
|
|
|
136
142
|
module.exports = withOpenApi;
|
|
137
143
|
```
|
|
138
144
|
|
|
139
145
|
#### Next.config.js
|
|
146
|
+
|
|
140
147
|
```js
|
|
141
148
|
const withOpenApi = require("./with-open-api");
|
|
142
149
|
|
|
@@ -146,7 +153,7 @@ const nextConfig = {
|
|
|
146
153
|
swcMinify: true,
|
|
147
154
|
env: {
|
|
148
155
|
NEXT_PUBLIC_APP_ORIGIN: process.env.VERCEL_URL || "http://localhost:3001",
|
|
149
|
-
}
|
|
156
|
+
},
|
|
150
157
|
};
|
|
151
158
|
|
|
152
159
|
module.exports = withOpenApi({
|
|
@@ -157,9 +164,7 @@ module.exports = withOpenApi({
|
|
|
157
164
|
version: "1.0.0",
|
|
158
165
|
},
|
|
159
166
|
},
|
|
160
|
-
sources: [
|
|
161
|
-
"pages/api",
|
|
162
|
-
],
|
|
167
|
+
sources: ["pages/api"],
|
|
163
168
|
verbose: false, // default is false
|
|
164
169
|
})(nextConfig);
|
|
165
170
|
```
|
|
@@ -178,12 +183,12 @@ The library will take the contents of @openapi (or @swagger):
|
|
|
178
183
|
* 200:
|
|
179
184
|
* description: Returns a mysterious string.
|
|
180
185
|
*/
|
|
181
|
-
|
|
182
186
|
```
|
|
183
187
|
|
|
184
188
|
## OpenApi short syntax
|
|
185
189
|
|
|
186
190
|
### Basic structure
|
|
191
|
+
|
|
187
192
|
You can write OpenAPI definitions in JSDoc comments or YAML files.
|
|
188
193
|
In this guide, we use only JSDoc comments examples. However, YAML files work equally as well.
|
|
189
194
|
|
|
@@ -201,6 +206,7 @@ For example, `GET /users` can be described as:
|
|
|
201
206
|
```
|
|
202
207
|
|
|
203
208
|
#### Parameters
|
|
209
|
+
|
|
204
210
|
Operations can have parameters passed via URL path (`/users/{userId}`), query string (`/users?role=admin`),
|
|
205
211
|
headers (`X-CustomHeader: Value`) or cookies (`Cookie: debug=0`).
|
|
206
212
|
You can define the parameter data types, format, whether they are required or optional, and other details:
|
|
@@ -217,6 +223,7 @@ You can define the parameter data types, format, whether they are required or op
|
|
|
217
223
|
For more information, see [Describing Parameters](/docs/short/describing-parameters.md).
|
|
218
224
|
|
|
219
225
|
#### Request body
|
|
226
|
+
|
|
220
227
|
If an operation sends a request body, use the `bodyContent` keyword to describe the body content and media type.
|
|
221
228
|
Use `bodyRequired` to indicate that a request body is required.
|
|
222
229
|
|
|
@@ -233,6 +240,7 @@ Use `bodyRequired` to indicate that a request body is required.
|
|
|
233
240
|
For more information, see [Describing Request Body](/docs/short/describing-request-body.md).
|
|
234
241
|
|
|
235
242
|
#### Responses
|
|
243
|
+
|
|
236
244
|
For each operation, you can define possible status codes, such as 200 OK or 404 Not Found, and the response body content.
|
|
237
245
|
You can also provide example responses for different content types:
|
|
238
246
|
|
|
@@ -252,14 +260,15 @@ You can also provide example responses for different content types:
|
|
|
252
260
|
For more information, see [Describing Responses](/docs/short/describing-responses.md).
|
|
253
261
|
|
|
254
262
|
#### Input and output models
|
|
263
|
+
|
|
255
264
|
You can create global `components/schemas` section lets you define common data structures used in your API.
|
|
256
265
|
They can be referenced by name whenever a schema is required – in parameters, request bodies, and response bodies.
|
|
257
266
|
For example, this JSON object:
|
|
258
267
|
|
|
259
268
|
```json
|
|
260
269
|
{
|
|
261
|
-
|
|
262
|
-
|
|
270
|
+
"id": 4,
|
|
271
|
+
"name": "Arthur Dent"
|
|
263
272
|
}
|
|
264
273
|
```
|
|
265
274
|
|
|
@@ -267,17 +276,17 @@ Can be represented as:
|
|
|
267
276
|
|
|
268
277
|
```yaml
|
|
269
278
|
components:
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
279
|
+
schemas:
|
|
280
|
+
User:
|
|
281
|
+
properties:
|
|
282
|
+
id:
|
|
283
|
+
type: integer
|
|
284
|
+
name:
|
|
285
|
+
type: string
|
|
286
|
+
# Both properties are required
|
|
287
|
+
required:
|
|
288
|
+
- id
|
|
289
|
+
- name
|
|
281
290
|
```
|
|
282
291
|
|
|
283
292
|
And then referenced in the request body schema and response body schema as follows:
|
|
@@ -301,13 +310,15 @@ And then referenced in the request body schema and response body schema as follo
|
|
|
301
310
|
```
|
|
302
311
|
|
|
303
312
|
#### Authentication
|
|
313
|
+
|
|
304
314
|
The `securitySchemes` and `security` keywords are used to describe the authentication methods used in your API.
|
|
315
|
+
|
|
305
316
|
```yaml
|
|
306
317
|
components:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
318
|
+
securitySchemes:
|
|
319
|
+
BasicAuth:
|
|
320
|
+
type: http
|
|
321
|
+
scheme: basic
|
|
311
322
|
```
|
|
312
323
|
|
|
313
324
|
```js
|
|
@@ -318,10 +329,11 @@ components:
|
|
|
318
329
|
```
|
|
319
330
|
|
|
320
331
|
Supported authentication methods are:
|
|
321
|
-
|
|
322
|
-
-
|
|
323
|
-
-
|
|
324
|
-
-
|
|
332
|
+
|
|
333
|
+
- HTTP authentication: Basic, Bearer, and so on.
|
|
334
|
+
- API key as a header or query parameter or in cookies
|
|
335
|
+
- OAuth 2
|
|
336
|
+
- OpenID Connect Discovery
|
|
325
337
|
|
|
326
338
|
For more information, see [Authentication](/docs/short/authentication.md).
|
|
327
339
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a, c, d, e, f } from './chunk-SXATCZ56.mjs';
|
|
2
2
|
import { existsSync, realpathSync, writeFileSync, lstatSync, mkdirSync } from 'fs';
|
|
3
|
-
import
|
|
4
|
-
import S from '@apidevtools/swagger-parser';
|
|
3
|
+
import v from 'read-pkg-up';
|
|
5
4
|
import { collect } from '@visulima/readdir';
|
|
6
|
-
import
|
|
5
|
+
import y from 'cli-progress';
|
|
7
6
|
import { normalize, dirname } from 'path';
|
|
8
7
|
import { pathToFileURL } from 'url';
|
|
9
8
|
|
|
10
|
-
var
|
|
9
|
+
var S=(r,l=process.cwd())=>{if(existsSync(r))throw new Error("Config file already exists");let e=v.sync({cwd:realpathSync(l)}),o="module.exports =";if(e){let{packageJson:n,path:t}=e;console.info(`Found package.json at "${t}"`),n.type==="module"&&(console.info("Found package.json with type: module, using ES6 as export for the config file"),o="export default");}else console.info("No package.json found");writeFileSync(r,`${o} {
|
|
11
10
|
exclude: [
|
|
12
11
|
'coverage/**',
|
|
13
12
|
'.github/**',
|
|
@@ -41,11 +40,11 @@ var v=(r,l=process.cwd())=>{if(existsSync(r))throw new Error("Config file alread
|
|
|
41
40
|
},
|
|
42
41
|
},
|
|
43
42
|
};
|
|
44
|
-
`),console.log(`Created "${r}"`);},E=
|
|
45
|
-
`)}let n=new
|
|
46
|
-
Found ${
|
|
47
|
-
Swagger specification is ready, check the "${
|
|
43
|
+
`),console.log(`Created "${r}"`);},E=S;var _=async(r,l,e$1)=>{let o={exclude:[],swaggerDefinition:{}};try{let s=await import(pathToFileURL(normalize(e$1.config??r)).href);s?.default&&(s=s.default),o=s;}catch{throw new Error(`No config file found, on: ${e$1.config??".openapirc.js"}
|
|
44
|
+
`)}let n=new y.MultiBar({clearOnComplete:!1,hideCursor:!0,format:"{value}/{total} | {bar} | {filename}"},y.Presets.shades_grey),t=new a(o.swaggerDefinition);for await(let s of l){lstatSync(s).isDirectory();let a=await collect(s,{skip:[...o.exclude,"node_modules/**"],extensions:o.extensions??[".js",".cjs",".mjs",".ts",".tsx",".jsx",".yaml",".yml"],followSymlinks:o.followSymlinks??!1,match:o.include,minimatchOptions:{match:{debug:e$1.verbose,matchBase:!0},skip:{debug:e$1.verbose,matchBase:!0}}});(e$1.verbose??e$1.veryVerbose)&&console.log(`
|
|
45
|
+
Found ${a.length} files in ${s}`),e$1.veryVerbose&&console.log(a);let w=n.create(a.length,0);a.forEach(c$1=>{e$1.verbose&&console.log(`Parsing file ${c$1}`),w.increment(1,{filename:s});let j=c(c$1,d,e$1.verbose);t.addData(j.map(m=>m.spec));let k=c(c$1,e,e$1.verbose);t.addData(k.map(m=>m.spec));});}e$1.verbose&&console.log("Validating swagger spec"),e$1.veryVerbose&&console.log(JSON.stringify(t,null,2)),await f(JSON.parse(JSON.stringify(t)));let i=e$1.output??"swagger.json";n.stop(),e$1.verbose&&console.log(`Written swagger spec to "${i}" file`),mkdirSync(dirname(i),{recursive:!0}),writeFileSync(i,JSON.stringify(t,null,2)),console.log(`
|
|
46
|
+
Swagger specification is ready, check the "${i}" file.`);},G=_;
|
|
48
47
|
|
|
49
48
|
export { E as a, G as b };
|
|
50
49
|
//# sourceMappingURL=out.js.map
|
|
51
|
-
//# sourceMappingURL=chunk-
|
|
50
|
+
//# sourceMappingURL=chunk-4BGSTSHH.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/command/init-command.ts","../src/cli/command/generate-command.ts"],"names":["existsSync","realpathSync","writeFileSync","readPkgUp","initCommand","configName","packageJsonPath","foundPackageJson","exportTemplate","package_","packagePath","init_command_default","collect","cliProgress","lstatSync","mkdirSync","dirname","normalize","pathToFileURL","generateCommand","paths","options","openapiConfig","config","multibar","spec","spec_builder_default","dir","files","bar","file","parsedJsDocumentFile","parse_file_default","comments_to_open_api_default","item","parsedSwaggerJsDocumentFile","validate_default","output","generate_command_default"],"mappings":"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","sourcesContent":["import { existsSync, realpathSync, writeFileSync } from \"node:fs\";\nimport readPkgUp from \"read-pkg-up\";\n\nconst initCommand = (configName: string, packageJsonPath = process.cwd()): void => {\n if (existsSync(configName)) {\n throw new Error(\"Config file already exists\");\n }\n\n const foundPackageJson = readPkgUp.sync({\n // eslint-disable-next-line no-undef\n cwd: realpathSync(packageJsonPath),\n });\n\n let exportTemplate = \"module.exports =\";\n\n if (foundPackageJson) {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const { packageJson: package_, path: packagePath } = foundPackageJson;\n\n // eslint-disable-next-line no-console\n console.info(`Found package.json at \"${packagePath}\"`);\n\n if (package_[\"type\"] === \"module\") {\n // eslint-disable-next-line no-console\n console.info(\"Found package.json with type: module, using ES6 as export for the config file\");\n\n exportTemplate = \"export default\";\n }\n } else {\n // eslint-disable-next-line no-console\n console.info(\"No package.json found\");\n }\n\n writeFileSync(\n configName,\n `${exportTemplate} {\n exclude: [\n 'coverage/**',\n '.github/**',\n 'packages/*/test{,s}/**',\n '**/*.d.ts',\n 'test{,s}/**',\n 'test{,-*}.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}',\n '**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}',\n '**/__tests__/**',\n '**/{ava,babel,nyc}.config.{js,cjs,mjs}',\n '**/jest.config.{js,cjs,mjs,ts}',\n '**/{karma,rollup,webpack}.config.js',\n '**/.{eslint,mocha}rc.{js,cjs}',\n '**/.{travis,yarnrc}.yml',\n '**/{docker-compose,docker}.yml',\n '**/.yamllint.{yaml,yml}',\n '**/node_modules/**',\n '**/pnpm-lock.yaml',\n '**/pnpm-workspace.yaml',\n '**/{package,package-lock}.json',\n '**/yarn.lock',\n '**/package.json5',\n '**/.next/**',\n ],\n followSymlinks: false,\n swaggerDefinition: {\n openapi: '3.0.0',\n info: {\n title: 'API',\n version: '1.0.0',\n },\n },\n};\n`,\n );\n\n // eslint-disable-next-line no-console\n console.log(`Created \"${configName}\"`);\n};\n\nexport default initCommand;\n","import { collect } from \"@visulima/readdir\";\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport cliProgress from \"cli-progress\";\nimport { lstatSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, normalize } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport type { BaseDefinition } from \"../../exported.d\";\nimport jsDocumentCommentsToOpenApi from \"../../jsdoc/comments-to-open-api\";\nimport parseFile from \"../../parse-file\";\nimport SpecBuilder from \"../../spec-builder\";\nimport swaggerJsDocumentCommentsToOpenApi from \"../../swagger-jsdoc/comments-to-open-api\";\nimport validate from \"../../validate\";\n\nconst generateCommand = async (\n configName: string,\n paths: string[],\n options: {\n config?: string;\n output?: string;\n verbose?: boolean;\n veryVerbose?: boolean;\n },\n // eslint-disable-next-line sonarjs/cognitive-complexity\n): Promise<void> => {\n let openapiConfig: {\n exclude: string[];\n followSymlinks?: boolean;\n swaggerDefinition: BaseDefinition;\n extensions?: string[];\n include?: string | readonly string[];\n } = {\n exclude: [],\n swaggerDefinition: {} as BaseDefinition,\n };\n\n try {\n // eslint-disable-next-line unicorn/prefer-module,import/no-dynamic-require\n let config = await import(pathToFileURL(normalize(options.config ?? configName)).href);\n\n if (config?.default) {\n config = config.default;\n }\n\n openapiConfig = config;\n } catch {\n throw new Error(`No config file found, on: ${options.config ?? \".openapirc.js\"}\\n`);\n }\n\n const multibar = new cliProgress.MultiBar(\n {\n clearOnComplete: false,\n hideCursor: true,\n format: \"{value}/{total} | {bar} | {filename}\",\n },\n cliProgress.Presets.shades_grey,\n );\n const spec = new SpecBuilder(openapiConfig.swaggerDefinition);\n\n // eslint-disable-next-line no-restricted-syntax,unicorn/prevent-abbreviations\n for await (const dir of paths) {\n // Check if the path is a directory\n lstatSync(dir).isDirectory();\n\n const files = await collect(dir, {\n // eslint-disable-next-line @rushstack/security/no-unsafe-regexp\n skip: [...openapiConfig.exclude, \"node_modules/**\"],\n extensions: openapiConfig.extensions ?? [\".js\", \".cjs\", \".mjs\", \".ts\", \".tsx\", \".jsx\", \".yaml\", \".yml\"],\n followSymlinks: openapiConfig.followSymlinks ?? false,\n match: openapiConfig.include,\n minimatchOptions: {\n match: {\n debug: options.verbose,\n matchBase: true,\n },\n skip: {\n debug: options.verbose,\n matchBase: true,\n },\n },\n });\n\n if (options.verbose ?? options.veryVerbose) {\n // eslint-disable-next-line no-console\n console.log(`\\nFound ${files.length} files in ${dir}`);\n }\n\n if (options.veryVerbose) {\n // eslint-disable-next-line no-console\n console.log(files);\n }\n\n const bar = multibar.create(files.length, 0);\n\n files.forEach((file) => {\n if (options.verbose) {\n // eslint-disable-next-line no-console\n console.log(`Parsing file ${file}`);\n }\n\n bar.increment(1, { filename: dir });\n\n const parsedJsDocumentFile = parseFile(file, jsDocumentCommentsToOpenApi, options.verbose);\n\n spec.addData(parsedJsDocumentFile.map((item) => item.spec));\n\n const parsedSwaggerJsDocumentFile = parseFile(file, swaggerJsDocumentCommentsToOpenApi, options.verbose);\n\n spec.addData(parsedSwaggerJsDocumentFile.map((item) => item.spec));\n });\n }\n\n if (options.verbose) {\n // eslint-disable-next-line no-console\n console.log(\"Validating swagger spec\");\n }\n\n if (options.veryVerbose) {\n // eslint-disable-next-line no-console\n console.log(JSON.stringify(spec, null, 2));\n }\n\n await validate(JSON.parse(JSON.stringify(spec)));\n\n const output = options.output ?? \"swagger.json\";\n\n multibar.stop();\n\n if (options.verbose) {\n // eslint-disable-next-line no-console\n console.log(`Written swagger spec to \"${output}\" file`);\n }\n\n // eslint-disable-next-line consistent-return\n mkdirSync(dirname(output), { recursive: true });\n writeFileSync(output, JSON.stringify(spec, null, 2));\n\n // eslint-disable-next-line no-console\n console.log(`\\nSwagger specification is ready, check the \"${output}\" file.`);\n};\n\nexport default generateCommand;\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var v = require('path');
|
|
5
|
+
var w = require('yaml');
|
|
6
|
+
var commentParser = require('comment-parser');
|
|
7
|
+
var D = require('lodash.mergewith');
|
|
8
|
+
var H = require('@stoplight/spectral-core');
|
|
9
|
+
var spectralRulesets = require('@stoplight/spectral-rulesets');
|
|
10
|
+
|
|
11
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
|
|
13
|
+
var v__default = /*#__PURE__*/_interopDefault(v);
|
|
14
|
+
var w__default = /*#__PURE__*/_interopDefault(w);
|
|
15
|
+
var D__default = /*#__PURE__*/_interopDefault(D);
|
|
16
|
+
var H__default = /*#__PURE__*/_interopDefault(H);
|
|
17
|
+
|
|
18
|
+
var E=(t,s)=>{Object.keys(s).forEach(r=>{t[r]===void 0?t[r]={...s[r]}:Object.keys(s[r]).forEach(e=>{t[r][e]={...t[r][e],...s[r][e]};});});},y=E;var u=class{constructor(s){this.openapi=s.openapi,this.info=s.info,this.servers=s.servers,this.paths=s.paths??{},this.components=s.components,this.security=s.security,this.tags=s.tags,this.externalDocs=s.externalDocs;}addData(s){s.forEach(r=>{let{paths:e,components:i,...n}=r;y(this,{paths:e??{},components:i??{}}),Object.entries(n).forEach(([o,a])=>{this[o]=a;});});}},Z=u;function A(t){return t.split(/\r\n|\r|\n/).filter(e=>/^\s*(#\s*.*)?$/.test(e)?!1:e.trim().length>0).length}var g=A;var h=new Set(["openapi","info","servers","security","tags","externalDocs","components","paths"]),l=class extends Error{},$=(t,s,r)=>{let e=fs.readFileSync(t,{encoding:"utf8"}),i=v__default.default.extname(t);if(i===".yaml"||i===".yml"){let n=w__default.default.parse(e),o=Object.keys(n).filter(a=>!h.has(a));if(o.length>0){let a=new l(`Unexpected keys: ${o.join(", ")}`);throw a.filePath=t,a}if(Object.keys(n).some(a=>h.has(a))){let a=g(e);return [{spec:n,loc:a}]}return []}try{return s(e,r)}catch(n){throw n.filePath=t,n}},ie=$;var k=(t,s)=>{if(Array.isArray(t))return [...t,...s]},m=k;function C(t){t.security&&(t.security=Object.keys(t.security).map(s=>({[s]:t.security[s]})));}var I=new Set(["integer","number","string","boolean","object","array"]),b={int32:"integer",int64:"integer",float:"number",double:"number",date:"string","date-time":"string",password:"string",byte:"string",binary:"string"};function q(t){let s=t.type,r=s.endsWith("[]"),e=s.replace(/\[]$/,""),i=I.has(e),n=Object.keys(b).includes(e),o;if(t.default)switch(e){case"integer":case"int32":case"int64":{o=Number.parseInt(t.default,10);break}case"number":case"double":case"float":{o=Number.parseFloat(t.default);break}default:{o=t.default;break}}let a;i?a={type:e,default:o}:n?a={type:b[e],format:e,default:o}:a={$ref:`#/components/schemas/${e}`};let c=r?{type:"array",items:{...a}}:{...a};e===""&&(c=void 0);let p=t.description.trim().replace(/^- /,"");return p===""&&(p=void 0),{name:t.name,description:p,required:!t.optional,schema:c,rawType:s}}function L(t,s){return t.map(r=>{let e=q(r),i="";switch(e.name&&(i+=e.name),e.description&&(i+=` ${e.description.trim()}`),r.tag){case"operationId":case"summary":case"description":return {[r.tag]:i};case"deprecated":return {deprecated:!0};case"externalDocs":return {externalDocs:{url:e.name,description:e.description}};case"server":return {servers:[{url:e.name,description:e.description}]};case"tag":return {tags:[i]};case"cookieParam":case"headerParam":case"queryParam":case"pathParam":return {parameters:[{name:e.name,in:r.tag.replace(/Param$/,""),description:e.description,required:e.required,schema:e.schema}]};case"bodyContent":return {requestBody:{content:{[e.name.replace("*\\/*","*/*")]:{schema:e.schema}}}};case"bodyExample":{let[n,o]=e.name.split(".");return {requestBody:{content:{[n]:{examples:{[o]:{$ref:`#/components/examples/${e.rawType}`}}}}}}}case"bodyDescription":return {requestBody:{description:i}};case"bodyRequired":return {requestBody:{required:!0}};case"response":return {responses:{[e.name]:{description:e.description}}};case"callback":return {callbacks:{[e.name]:{$ref:`#/components/callbacks/${e.rawType}`}}};case"responseContent":{let[n,o]=e.name.split(".");return {responses:{[n]:{content:{[o]:{schema:e.schema}}}}}}case"responseHeaderComponent":{let[n,o]=e.name.split(".");return {responses:{[n]:{headers:{[o]:{$ref:`#/components/headers/${e.rawType}`}}}}}}case"responseHeader":{let[n,o]=e.name.split(".");return {responses:{[n]:{headers:{[o]:{description:e.description,schema:e.schema}}}}}}case"responseExample":{let[n,o,a]=e.name.split(".");return {responses:{[n]:{content:{[o]:{examples:{[a]:{$ref:`#/components/examples/${e.rawType}`}}}}}}}}case"responseLink":{let[n,o]=e.name.split(".");return {responses:{[n]:{links:{[o]:{$ref:`#/components/links/${e.rawType}`}}}}}}case"bodyComponent":return {requestBody:{$ref:`#/components/requestBodies/${e.rawType}`}};case"responseComponent":return {responses:{[e.name]:{$ref:`#/components/responses/${e.rawType}`}}};case"paramComponent":return {parameters:[{$ref:`#/components/parameters/${e.rawType}`}]};case"security":{let[n,o]=e.name.split("."),a=[];return o&&(a=[o]),{security:{[n]:a}}}default:return {}}})}var R=(t,s)=>{let r=/^(GET|PUT|POST|DELETE|OPTIONS|HEAD|PATCH|TRACE) \/.*$/;return commentParser.parse(t,{spacing:"preserve"}).filter(i=>r.test(i.description.trim())).map(i=>{let n=i.tags.length+1,o=D__default.default({},...L(i.tags),m);C(o);let[a,c]=i.description.split(" "),p={[c.trim()]:{[a.toLowerCase().trim()]:{...o}}};return {spec:JSON.parse(JSON.stringify({paths:p})),loc:n}})},le=R;var d=(t,s)=>D__default.default({},t,s,(r,e)=>e===null?r:void 0),O=t=>Object.keys(t).map(s=>t[s]).every(s=>typeof s=="object"&&Object.keys(s).every(r=>!(r in s))),f=(t,s)=>s.some(r=>t.name===r.name),j=t=>{switch(t.tag){case"openapi":return "v3";case"asyncapi":return "v4";case"swagger":return "v2";default:return "v2"}};var N=(t,s,r)=>{if(r==="x-webhooks"&&(t[r]=s[r]),r.startsWith("x-"))return;if(["components","consumes","produces","paths","schemas","securityDefinitions","responses","parameters","definitions","channels"].includes(r))Object.keys(s[r]).forEach(i=>{t[r][i]=d(t[r][i],s[r][i]);});else if(r==="tags"){let{tags:i}=s;Array.isArray(i)?i.forEach(n=>{f(n,t.tags)||t.tags.push(n);}):f(i,t.tags)||t.tags.push(i);}else if(r==="security"){let{security:i}=s;t.security=i;}else r.startsWith("/")&&(t.paths[r]=d(t.paths[r],s[r]));},x=N;var z={v2:["paths","definitions","responses","parameters","securityDefinitions"],v3:["paths","definitions","responses","parameters","securityDefinitions","components"],v4:["components","channels"]},F=(t,s)=>t.map(r=>{if((r.tag==="openapi"||r.tag==="swagger"||r.tag==="asyncapi")&&r.description!==""){let e=w__default.default.parseDocument(r.description);if(e.errors.length>0){e.errors.map(a=>{let c=a;return c.annotation=r.description,c});let o="Error parsing YAML in @openapi spec:";throw o+=s?e.errors.map(a=>`${a.toString()}
|
|
19
|
+
Imbedded within:
|
|
20
|
+
\`\`\`
|
|
21
|
+
${a.annotation?.replace(/\n/g,`
|
|
22
|
+
`)}
|
|
23
|
+
\`\`\``).join(`
|
|
24
|
+
`):e.errors.map(a=>a.toString()).join(`
|
|
25
|
+
`),new Error(o)}let i=e.toJSON(),n={tags:[]};return z[j(r)].forEach(o=>{n[o]=n[o]||{};}),Object.keys(i).forEach(o=>{x(n,i,o);}),n}return {}}),J=(t,s)=>commentParser.parse(t,{spacing:"preserve"}).map(e=>{let i=e.tags.length+1,n=D__default.default({},...F(e.tags,s),m);return ["definitions","responses","parameters","securityDefinitions","components","tags"].forEach(a=>{n[a]!==void 0&&O(n[a])&&delete n[a];}),{spec:JSON.parse(JSON.stringify(n)),loc:i}}),Ae=J;var{Spectral:G}=H__default.default,S=new G;S.setRuleset({extends:[spectralRulesets.oas,spectralRulesets.asyncapi]});var _=async t=>{let s="";return typeof t=="object"?s=t.info.title:typeof t=="string"&&(s=t),S.run(t).then(r=>(r.forEach(e=>{if(e.code==="unrecognized-format")throw new Error(`Could not validate OpenAPI Specification '${s}'. ${e.message}`);if(e.severity<1)throw new Error(`Invalid OpenAPI Specification '${s}'. [${e.path.join(".")}] ${e.message}`)}),r)).catch(r=>{throw new Error(`Could not validate OpenAPI Specification '${s}'. ${r.message}`)})},$e=_;
|
|
26
|
+
|
|
27
|
+
exports.a = Z;
|
|
28
|
+
exports.b = g;
|
|
29
|
+
exports.c = ie;
|
|
30
|
+
exports.d = le;
|
|
31
|
+
exports.e = Ae;
|
|
32
|
+
exports.f = $e;
|
|
33
|
+
//# sourceMappingURL=out.js.map
|
|
34
|
+
//# sourceMappingURL=chunk-5U2PT3WZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/util/object-merge.ts","../src/spec-builder.ts","../src/util/yaml-loc.ts","../src/parse-file.ts","../src/jsdoc/comments-to-open-api.ts","../src/util/customizer.ts","../src/swagger-jsdoc/comments-to-open-api.ts","../src/swagger-jsdoc/utils.ts","../src/swagger-jsdoc/organize-swagger-object.ts","../src/validate.ts"],"names":["objectMerge","a","b","key","subKey","object_merge_default","SpecBuilder","baseDefinition","parsedFile","file","paths","components","rest","value","spec_builder_default","yamlLoc","string","line","yaml_loc_default","readFileSync","path","yaml","ALLOWED_KEYS","ParseError","parseFile","commentsToOpenApi","verbose","fileContent","extension","spec","invalidKeys","error","loc","parse_file_default","parseComments","mergeWith","customizer","objectValue","sourceValue","customizer_default","fixSecurityObject","thing","primitiveTypes","formatMap","parseDescription","tag","rawType","isArray","parsedType","isPrimitive","isFormat","defaultValue","rootType","schema","description","tagsToObjects","tags","parsedResponse","nameAndDescription","contentType","example","status","header","link","security","scopeItem","scope","fileContents","openAPIRegex","comment","result","method","pathsObject","comments_to_open_api_default","mergeDeep","first","second","hasEmptyProperty","object","keyObject","isTagPresentInTags","targetTag","getSwaggerVersionFromSpec","organizeSwaggerObject","swaggerObject","annotation","property","definition","organize_swagger_object_default","specificationTemplate","specs","parsed","newError","errorString","parsedDocument","specification","spectralCore","asyncapi","oas","OASValidator","validator","validate","title","results","validate_default"],"mappings":"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","sourcesContent":["const objectMerge = <T>(a: T, b: T): void => {\n Object.keys(b as object).forEach((key) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (a[key as keyof typeof b] === undefined) {\n // eslint-disable-next-line no-param-reassign\n a[key as keyof typeof b] = {\n ...b[key as keyof typeof b],\n };\n } else {\n Object.keys(b[key as keyof typeof b] as object).forEach((subKey) => {\n // eslint-disable-next-line no-param-reassign\n (a[key as keyof typeof b] as { [key: string]: object })[subKey] = {\n ...(a[key as keyof typeof b] as { [key: string]: object })[subKey],\n ...(b[key as keyof typeof b] as { [key: string]: object })[subKey],\n };\n });\n }\n });\n};\n\nexport default objectMerge;\n","import type {\n BaseDefinition,\n ComponentsObject,\n ExternalDocumentationObject,\n InfoObject,\n OpenApiObject,\n PathsObject,\n SecurityRequirementObject,\n ServerObject,\n TagObject,\n} from \"./exported.d\";\nimport objectMerge from \"./util/object-merge\";\n\nclass SpecBuilder implements OpenApiObject {\n public openapi: string;\n\n public info: InfoObject;\n\n public servers?: ServerObject[];\n\n public paths: PathsObject;\n\n public components?: ComponentsObject;\n\n public security?: SecurityRequirementObject[];\n\n public tags?: TagObject[];\n\n public externalDocs?: ExternalDocumentationObject;\n\n public constructor(baseDefinition: BaseDefinition) {\n this.openapi = baseDefinition.openapi;\n this.info = baseDefinition.info;\n this.servers = baseDefinition.servers;\n this.paths = baseDefinition.paths ?? {};\n this.components = baseDefinition.components;\n this.security = baseDefinition.security;\n this.tags = baseDefinition.tags;\n this.externalDocs = baseDefinition.externalDocs;\n }\n\n public addData(parsedFile: OpenApiObject[]): void {\n parsedFile.forEach((file) => {\n const { paths, components, ...rest } = file;\n\n // only merge paths and components\n objectMerge(this, {\n paths: paths ?? {},\n components: components ?? {},\n } as OpenApiObject);\n\n // overwrite everything else:\n Object.entries(rest).forEach(([key, value]) => {\n // @ts-expect-error\n this[key as keyof OpenApiObject] = value;\n });\n });\n }\n}\n\nexport default SpecBuilder;\n","function yamlLoc(string: string): number {\n // Break string into lines.\n const split = string.split(/\\r\\n|\\r|\\n/);\n\n const filtered = split.filter((line) => {\n // Remove comments.\n if (/^\\s*(#\\s*.*)?$/.test(line)) {\n return false;\n }\n // Remove empty lines.\n return line.trim().length > 0;\n });\n\n return filtered.length;\n}\n\nexport default yamlLoc;\n","import { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"yaml\";\n\nimport type { OpenApiObject } from \"./exported.d\";\nimport yamlLoc from \"./util/yaml-loc\";\n\nconst ALLOWED_KEYS = new Set([\"openapi\", \"info\", \"servers\", \"security\", \"tags\", \"externalDocs\", \"components\", \"paths\"]);\n\nclass ParseError extends Error {\n public filePath?: string;\n}\n\nconst parseFile = (\n file: string,\n commentsToOpenApi: (fileContent: string, verbose?: boolean) => { spec: OpenApiObject; loc: number }[],\n verbose?: boolean,\n): { spec: OpenApiObject; loc: number }[] => {\n const fileContent = readFileSync(file, { encoding: \"utf8\" });\n const extension = path.extname(file);\n\n if (extension === \".yaml\" || extension === \".yml\") {\n const spec = yaml.parse(fileContent);\n const invalidKeys = Object.keys(spec).filter((key) => !ALLOWED_KEYS.has(key));\n\n if (invalidKeys.length > 0) {\n const error = new ParseError(`Unexpected keys: ${invalidKeys.join(\", \")}`);\n\n error.filePath = file;\n\n throw error;\n }\n\n if (Object.keys(spec).some((key) => ALLOWED_KEYS.has(key))) {\n const loc = yamlLoc(fileContent);\n\n return [{ spec, loc }];\n }\n\n return [];\n }\n\n try {\n return commentsToOpenApi(fileContent, verbose);\n } catch (error: any) {\n error.filePath = file;\n\n throw error;\n }\n};\n\nexport default parseFile;\n","import type { Spec } from \"comment-parser\";\nimport { parse as parseComments } from \"comment-parser\";\nimport mergeWith from \"lodash.mergewith\";\n\nimport type { OpenApiObject, PathsObject } from \"../exported.d\";\nimport customizer from \"../util/customizer\";\n\n// The security object has a bizare setup...\nfunction fixSecurityObject(thing: any) {\n if (thing.security) {\n // eslint-disable-next-line no-param-reassign\n thing.security = Object.keys(thing.security).map((s) => {\n return {\n [s]: thing.security[s],\n };\n });\n }\n}\n\nconst primitiveTypes = new Set([\"integer\", \"number\", \"string\", \"boolean\", \"object\", \"array\"]);\n\nconst formatMap: { [key: string]: string } = {\n int32: \"integer\",\n int64: \"integer\",\n float: \"number\",\n double: \"number\",\n date: \"string\",\n \"date-time\": \"string\",\n password: \"string\",\n byte: \"string\",\n binary: \"string\",\n};\n\nfunction parseDescription(tag: Spec): { name: string; description: string | undefined; required: boolean; schema: object | undefined; rawType: string } {\n const rawType = tag.type;\n const isArray = rawType.endsWith(\"[]\");\n const parsedType = rawType.replace(/\\[]$/, \"\");\n\n const isPrimitive = primitiveTypes.has(parsedType);\n const isFormat = Object.keys(formatMap).includes(parsedType);\n\n let defaultValue;\n\n if (tag.default) {\n switch (parsedType) {\n case \"integer\":\n case \"int32\":\n case \"int64\": {\n defaultValue = Number.parseInt(tag.default, 10);\n break;\n }\n case \"number\":\n case \"double\":\n case \"float\": {\n defaultValue = Number.parseFloat(tag.default);\n break;\n }\n default: {\n defaultValue = tag.default;\n break;\n }\n }\n }\n\n let rootType;\n\n if (isPrimitive) {\n rootType = { type: parsedType, default: defaultValue };\n } else if (isFormat) {\n rootType = {\n type: formatMap[parsedType],\n format: parsedType,\n default: defaultValue,\n };\n } else {\n rootType = { $ref: `#/components/schemas/${parsedType}` };\n }\n\n let schema: object | undefined = isArray\n ? {\n type: \"array\",\n items: {\n ...rootType,\n },\n }\n : {\n ...rootType,\n };\n\n if (parsedType === \"\") {\n schema = undefined;\n }\n\n // remove the optional dash from the description.\n let description: string | undefined = tag.description.trim().replace(/^- /, \"\");\n\n if (description === \"\") {\n description = undefined;\n }\n\n return {\n name: tag.name,\n description,\n required: !tag.optional,\n schema,\n rawType,\n };\n}\n\n// @ts-expect-error\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction tagsToObjects(tags: Spec[], verbose?: boolean) {\n return tags.map((tag) => {\n const parsedResponse = parseDescription(tag);\n\n // Some ops only have a `description`, merge `name` and `description`\n // for these.\n let nameAndDescription = \"\";\n\n if (parsedResponse.name) {\n nameAndDescription += parsedResponse.name;\n }\n\n if (parsedResponse.description) {\n nameAndDescription += ` ${parsedResponse.description.trim()}`;\n }\n\n switch (tag.tag) {\n case \"operationId\":\n case \"summary\":\n case \"description\": {\n return { [tag.tag]: nameAndDescription };\n }\n\n case \"deprecated\": {\n return { deprecated: true };\n }\n\n case \"externalDocs\": {\n return {\n externalDocs: {\n url: parsedResponse.name,\n description: parsedResponse.description,\n },\n };\n }\n\n case \"server\": {\n return {\n servers: [\n {\n url: parsedResponse.name,\n description: parsedResponse.description,\n },\n ],\n };\n }\n\n case \"tag\": {\n return { tags: [nameAndDescription] };\n }\n\n case \"cookieParam\":\n case \"headerParam\":\n case \"queryParam\":\n case \"pathParam\": {\n return {\n parameters: [\n {\n name: parsedResponse.name,\n in: tag.tag.replace(/Param$/, \"\"),\n description: parsedResponse.description,\n required: parsedResponse.required,\n schema: parsedResponse.schema,\n },\n ],\n };\n }\n\n case \"bodyContent\": {\n return {\n requestBody: {\n content: {\n [parsedResponse.name.replace(\"*\\\\/*\", \"*/*\")]: {\n schema: parsedResponse.schema,\n },\n },\n },\n };\n }\n\n case \"bodyExample\": {\n const [contentType, example] = parsedResponse.name.split(\".\");\n\n return {\n requestBody: {\n content: {\n [contentType as string]: {\n examples: {\n [example as string]: {\n $ref: `#/components/examples/${parsedResponse.rawType}`,\n },\n },\n },\n },\n },\n };\n }\n\n case \"bodyDescription\": {\n return { requestBody: { description: nameAndDescription } };\n }\n\n case \"bodyRequired\": {\n return { requestBody: { required: true } };\n }\n\n case \"response\": {\n return {\n responses: {\n [parsedResponse.name]: {\n description: parsedResponse.description,\n },\n },\n };\n }\n\n case \"callback\": {\n return {\n callbacks: {\n [parsedResponse.name]: {\n $ref: `#/components/callbacks/${parsedResponse.rawType}`,\n },\n },\n };\n }\n\n case \"responseContent\": {\n const [status, contentType] = parsedResponse.name.split(\".\");\n\n return {\n responses: {\n [status as string]: {\n content: {\n [contentType as string]: {\n schema: parsedResponse.schema,\n },\n },\n },\n },\n };\n }\n\n case \"responseHeaderComponent\": {\n const [status, header] = parsedResponse.name.split(\".\");\n\n return {\n responses: {\n [status as string]: {\n headers: {\n [header as string]: {\n $ref: `#/components/headers/${parsedResponse.rawType}`,\n },\n },\n },\n },\n };\n }\n\n case \"responseHeader\": {\n const [status, header] = parsedResponse.name.split(\".\");\n\n return {\n responses: {\n [status as string]: {\n headers: {\n [header as string]: {\n description: parsedResponse.description,\n schema: parsedResponse.schema,\n },\n },\n },\n },\n };\n }\n\n case \"responseExample\": {\n const [status, contentType, example] = parsedResponse.name.split(\".\");\n\n return {\n responses: {\n [status as string]: {\n content: {\n [contentType as string]: {\n examples: {\n [example as string]: {\n $ref: `#/components/examples/${parsedResponse.rawType}`,\n },\n },\n },\n },\n },\n },\n };\n }\n\n case \"responseLink\": {\n const [status, link] = parsedResponse.name.split(\".\");\n\n return {\n responses: {\n [status as string]: {\n links: {\n [link as string]: {\n $ref: `#/components/links/${parsedResponse.rawType}`,\n },\n },\n },\n },\n };\n }\n\n case \"bodyComponent\": {\n return {\n requestBody: {\n $ref: `#/components/requestBodies/${parsedResponse.rawType}`,\n },\n };\n }\n\n case \"responseComponent\": {\n return {\n responses: {\n [parsedResponse.name]: {\n $ref: `#/components/responses/${parsedResponse.rawType}`,\n },\n },\n };\n }\n\n case \"paramComponent\": {\n return {\n parameters: [{ $ref: `#/components/parameters/${parsedResponse.rawType}` }],\n };\n }\n\n case \"security\": {\n const [security, scopeItem] = parsedResponse.name.split(\".\");\n\n let scope: string[] = [];\n\n if (scopeItem) {\n scope = [scopeItem];\n }\n\n return {\n security: { [security as string]: scope },\n };\n }\n\n default: {\n return {};\n }\n }\n });\n}\n\nconst commentsToOpenApi = (fileContents: string, verbose?: boolean): { spec: OpenApiObject; loc: number }[] => {\n const openAPIRegex = /^(GET|PUT|POST|DELETE|OPTIONS|HEAD|PATCH|TRACE) \\/.*$/;\n\n const jsDocumentComments = parseComments(fileContents, { spacing: \"preserve\" });\n\n return jsDocumentComments\n .filter((comment) => openAPIRegex.test(comment.description.trim()))\n .map((comment) => {\n // Line count, number of tags + 1 for description.\n // - Don't count line-breaking due to long descriptions\n // - Don't count empty lines\n const loc = comment.tags.length + 1;\n\n const result = mergeWith({}, ...tagsToObjects(comment.tags, verbose), customizer);\n\n fixSecurityObject(result);\n\n const [method, path]: string[] = comment.description.split(\" \");\n\n const pathsObject: PathsObject = {\n [(path as string).trim()]: {\n [(method as string).toLowerCase().trim()]: {\n ...result,\n },\n },\n };\n\n // Purge all undefined objects/arrays.\n const spec = JSON.parse(JSON.stringify({ paths: pathsObject }));\n\n return {\n spec,\n loc,\n };\n });\n};\n\nexport default commentsToOpenApi;\n","const customizer = (objectValue: unknown, sourceValue: Array<unknown>): unknown[] | undefined => {\n if (Array.isArray(objectValue)) {\n return [...objectValue, ...sourceValue];\n }\n // eslint-disable-next-line unicorn/no-useless-undefined\n return undefined;\n};\n\nexport default customizer;\n","import type { Spec } from \"comment-parser\";\nimport { parse as parseComments } from \"comment-parser\";\nimport mergeWith from \"lodash.mergewith\";\nimport type { YAMLError } from \"yaml\";\nimport yaml from \"yaml\";\n\nimport type { OpenApiObject } from \"../exported.d\";\nimport customizer from \"../util/customizer\";\nimport organizeSwaggerObject from \"./organize-swagger-object\";\nimport { getSwaggerVersionFromSpec, hasEmptyProperty } from \"./utils\";\n\nconst specificationTemplate = {\n v2: [\"paths\", \"definitions\", \"responses\", \"parameters\", \"securityDefinitions\"],\n v3: [\"paths\", \"definitions\", \"responses\", \"parameters\", \"securityDefinitions\", \"components\"],\n v4: [\"components\", \"channels\"],\n};\n\ntype ExtendedYAMLError = YAMLError & { annotation?: string };\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst tagsToObjects = (specs: Spec[], verbose?: boolean) => specs.map((spec: Spec) => {\n if ((spec.tag === \"openapi\" || spec.tag === \"swagger\" || spec.tag === \"asyncapi\") && spec.description !== \"\") {\n const parsed = yaml.parseDocument(spec.description);\n\n if (parsed.errors.length > 0) {\n // eslint-disable-next-line sonarjs/no-ignored-return\n parsed.errors.map<ExtendedYAMLError>((error) => {\n const newError: ExtendedYAMLError = error;\n\n newError.annotation = spec.description;\n\n return newError;\n });\n\n let errorString = \"Error parsing YAML in @openapi spec:\";\n\n errorString += verbose\n ? (parsed.errors as ExtendedYAMLError[])\n .map((error) => `${error.toString()}\\nImbedded within:\\n\\`\\`\\`\\n ${error.annotation?.replace(/\\n/g, \"\\n \")}\\n\\`\\`\\``)\n .join(\"\\n\")\n : parsed.errors.map((error) => error.toString()).join(\"\\n\");\n\n throw new Error(errorString);\n }\n\n const parsedDocument = parsed.toJSON();\n const specification: Record<string, any> = {\n tags: [],\n };\n\n specificationTemplate[getSwaggerVersionFromSpec(spec)].forEach((property) => {\n specification[property] = specification[property] || {};\n });\n\n Object.keys(parsedDocument).forEach((property) => {\n organizeSwaggerObject(specification, parsedDocument, property);\n });\n\n return specification;\n }\n\n return {};\n});\n\nconst commentsToOpenApi = (fileContents: string, verbose?: boolean): { spec: OpenApiObject; loc: number }[] => {\n const jsDocumentComments = parseComments(fileContents, { spacing: \"preserve\" });\n\n return jsDocumentComments.map((comment) => {\n // Line count, number of tags + 1 for description.\n // - Don't count line-breaking due to long descriptions\n // - Don't count empty lines\n const loc = comment.tags.length + 1;\n const result = mergeWith({}, ...tagsToObjects(comment.tags, verbose), customizer);\n\n [\"definitions\", \"responses\", \"parameters\", \"securityDefinitions\", \"components\", \"tags\"].forEach((property) => {\n if (result[property] !== undefined && hasEmptyProperty(result[property])) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete result[property];\n }\n });\n\n // Purge all undefined objects/arrays.\n const spec = JSON.parse(JSON.stringify(result));\n\n return {\n spec,\n loc,\n };\n });\n};\n\nexport default commentsToOpenApi;\n","import type { Spec } from \"comment-parser\";\nimport mergeWith from \"lodash.mergewith\";\n\n/**\n * A recursive deep-merge that ignores null values when merging.\n * This returns the merged object and does not mutate.\n * @param {object} first the first object to get merged\n * @param {object} second the second object to get merged\n */\nexport const mergeDeep = (first?: object, second?: object): object => mergeWith({}, first, second, (a, b) => (b === null ? a : undefined));\n\n/**\n * Checks if there is any properties of the input object which are an empty object\n * @param {object} object - the object to check\n * @returns boolean\n */\nexport const hasEmptyProperty = (object: Record<string, any>): boolean => Object.keys(object)\n .map((key) => object[key])\n .every((keyObject) => typeof keyObject === \"object\" && Object.keys(keyObject).every((key) => !(key in keyObject)));\n\n/**\n * @param {object} tag\n * @param {array} tags\n * @returns boolean\n */\nexport const isTagPresentInTags = (tag: Spec, tags: Spec[]): boolean => tags.some((targetTag) => tag.name === targetTag.name);\n\nexport const getSwaggerVersionFromSpec = (tag: Spec): \"v2\" | \"v3\" | \"v4\" => {\n switch (tag.tag) {\n case \"openapi\": {\n return \"v3\";\n }\n case \"asyncapi\": {\n return \"v4\";\n }\n case \"swagger\": {\n return \"v2\";\n }\n default: {\n return \"v2\";\n }\n }\n};\n","import { isTagPresentInTags, mergeDeep } from \"./utils\";\n\n/**\n * @param {object} swaggerObject\n * @param {object} annotation\n * @param {string} property\n */\n// eslint-disable-next-line sonarjs/no-duplicate-string\nconst organizeSwaggerObject = (swaggerObject: Record<string, any>, annotation: Record<string, any>, property: string): void => {\n // Root property on purpose.\n // eslint-disable-next-line no-secrets/no-secrets\n // @see https://github.com/OAI/OpenAPI-Specification/blob/master/proposals/002_Webhooks.md#proposed-solution\n if (property === \"x-webhooks\") {\n // eslint-disable-next-line no-param-reassign\n swaggerObject[property] = annotation[property];\n }\n\n // Other extensions can be in varying places depending on different vendors and opinions.\n // The following return makes it so that they are not put in `paths` in the last case.\n // New specific extensions will need to be handled on case-by-case if to be included in `paths`.\n if (property.startsWith(\"x-\")) {\n return;\n }\n\n const commonProperties = [\n \"components\",\n \"consumes\",\n \"produces\",\n \"paths\",\n \"schemas\",\n \"securityDefinitions\",\n \"responses\",\n \"parameters\",\n \"definitions\",\n \"channels\",\n ];\n\n if (commonProperties.includes(property)) {\n Object.keys(annotation[property]).forEach((definition) => {\n // eslint-disable-next-line no-param-reassign\n swaggerObject[property][definition] = mergeDeep(swaggerObject[property][definition], annotation[property][definition]);\n });\n } else if (property === \"tags\") {\n const { tags } = annotation;\n\n if (Array.isArray(tags)) {\n tags.forEach((tag) => {\n if (!isTagPresentInTags(tag, swaggerObject[\"tags\"])) {\n swaggerObject[\"tags\"].push(tag);\n }\n });\n } else if (!isTagPresentInTags(tags, swaggerObject[\"tags\"])) {\n swaggerObject[\"tags\"].push(tags);\n }\n } else if (property === \"security\") {\n const { security } = annotation;\n\n // eslint-disable-next-line no-param-reassign\n swaggerObject[\"security\"] = security;\n } else if (property.startsWith(\"/\")) {\n // Paths which are not defined as \"paths\" property, starting with a slash \"/\"\n // eslint-disable-next-line no-param-reassign\n swaggerObject[\"paths\"][property] = mergeDeep(swaggerObject[\"paths\"][property], annotation[property]);\n }\n};\n\nexport default organizeSwaggerObject;\n","import type { ISpectralDiagnostic } from \"@stoplight/spectral-core\";\nimport spectralCore from \"@stoplight/spectral-core\";\nimport type { IDocument, IParsedResult } from \"@stoplight/spectral-core/dist/document\";\nimport { asyncapi, oas } from \"@stoplight/spectral-rulesets\";\n\nconst { Spectral: OASValidator } = spectralCore;\nconst validator = new OASValidator();\n\nvalidator.setRuleset({\n // @ts-expect-error: TS2322\n extends: [oas, asyncapi],\n});\n\nconst validate = async (spec: IDocument | IParsedResult | Record<string, unknown> | string): Promise<ISpectralDiagnostic[]> => {\n let title = \"\";\n\n if (typeof spec === \"object\") {\n title = (spec as { info: { title: string } }).info.title;\n } else if (typeof spec === \"string\") {\n title = spec;\n }\n\n return validator\n .run(spec)\n .then((results) => {\n results.forEach((result) => {\n // Ensure there are no errors about no format being matched\n if (result.code === \"unrecognized-format\") {\n throw new Error(`Could not validate OpenAPI Specification '${title}'. ${result.message}`);\n }\n\n if (result.severity < 1) {\n throw new Error(`Invalid OpenAPI Specification '${title}'. [${result.path.join(\".\")}] ${result.message}`);\n }\n });\n\n return results;\n })\n .catch((error) => {\n throw new Error(`Could not validate OpenAPI Specification '${title}'. ${error.message}`);\n });\n};\n\nexport default validate;\n"]}
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk5U2PT3WZ_js = require('./chunk-5U2PT3WZ.js');
|
|
4
4
|
var fs = require('fs');
|
|
5
|
-
var
|
|
6
|
-
var S = require('@apidevtools/swagger-parser');
|
|
5
|
+
var v = require('read-pkg-up');
|
|
7
6
|
var readdir = require('@visulima/readdir');
|
|
8
|
-
var
|
|
7
|
+
var y = require('cli-progress');
|
|
9
8
|
var path = require('path');
|
|
10
9
|
var url = require('url');
|
|
11
10
|
|
|
12
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
12
|
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
var u__default = /*#__PURE__*/_interopDefault(u);
|
|
13
|
+
var v__default = /*#__PURE__*/_interopDefault(v);
|
|
14
|
+
var y__default = /*#__PURE__*/_interopDefault(y);
|
|
17
15
|
|
|
18
|
-
var
|
|
16
|
+
var S=(r,l=process.cwd())=>{if(fs.existsSync(r))throw new Error("Config file already exists");let e=v__default.default.sync({cwd:fs.realpathSync(l)}),o="module.exports =";if(e){let{packageJson:n,path:t}=e;console.info(`Found package.json at "${t}"`),n.type==="module"&&(console.info("Found package.json with type: module, using ES6 as export for the config file"),o="export default");}else console.info("No package.json found");fs.writeFileSync(r,`${o} {
|
|
19
17
|
exclude: [
|
|
20
18
|
'coverage/**',
|
|
21
19
|
'.github/**',
|
|
@@ -49,12 +47,12 @@ var v=(r,l=process.cwd())=>{if(fs.existsSync(r))throw new Error("Config file alr
|
|
|
49
47
|
},
|
|
50
48
|
},
|
|
51
49
|
};
|
|
52
|
-
`),console.log(`Created "${r}"`);},E=
|
|
53
|
-
`)}let n=new
|
|
54
|
-
Found ${
|
|
55
|
-
Swagger specification is ready, check the "${
|
|
50
|
+
`),console.log(`Created "${r}"`);},E=S;var _=async(r,l,e)=>{let o={exclude:[],swaggerDefinition:{}};try{let s=await import(url.pathToFileURL(path.normalize(e.config??r)).href);s?.default&&(s=s.default),o=s;}catch{throw new Error(`No config file found, on: ${e.config??".openapirc.js"}
|
|
51
|
+
`)}let n=new y__default.default.MultiBar({clearOnComplete:!1,hideCursor:!0,format:"{value}/{total} | {bar} | {filename}"},y__default.default.Presets.shades_grey),t=new chunk5U2PT3WZ_js.a(o.swaggerDefinition);for await(let s of l){fs.lstatSync(s).isDirectory();let a=await readdir.collect(s,{skip:[...o.exclude,"node_modules/**"],extensions:o.extensions??[".js",".cjs",".mjs",".ts",".tsx",".jsx",".yaml",".yml"],followSymlinks:o.followSymlinks??!1,match:o.include,minimatchOptions:{match:{debug:e.verbose,matchBase:!0},skip:{debug:e.verbose,matchBase:!0}}});(e.verbose??e.veryVerbose)&&console.log(`
|
|
52
|
+
Found ${a.length} files in ${s}`),e.veryVerbose&&console.log(a);let w=n.create(a.length,0);a.forEach(c=>{e.verbose&&console.log(`Parsing file ${c}`),w.increment(1,{filename:s});let j=chunk5U2PT3WZ_js.c(c,chunk5U2PT3WZ_js.d,e.verbose);t.addData(j.map(m=>m.spec));let k=chunk5U2PT3WZ_js.c(c,chunk5U2PT3WZ_js.e,e.verbose);t.addData(k.map(m=>m.spec));});}e.verbose&&console.log("Validating swagger spec"),e.veryVerbose&&console.log(JSON.stringify(t,null,2)),await chunk5U2PT3WZ_js.f(JSON.parse(JSON.stringify(t)));let i=e.output??"swagger.json";n.stop(),e.verbose&&console.log(`Written swagger spec to "${i}" file`),fs.mkdirSync(path.dirname(i),{recursive:!0}),fs.writeFileSync(i,JSON.stringify(t,null,2)),console.log(`
|
|
53
|
+
Swagger specification is ready, check the "${i}" file.`);},G=_;
|
|
56
54
|
|
|
57
55
|
exports.a = E;
|
|
58
56
|
exports.b = G;
|
|
59
57
|
//# sourceMappingURL=out.js.map
|
|
60
|
-
//# sourceMappingURL=chunk-
|
|
58
|
+
//# sourceMappingURL=chunk-6BASRGSS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/command/init-command.ts","../src/cli/command/generate-command.ts"],"names":["existsSync","realpathSync","writeFileSync","readPkgUp","initCommand","configName","packageJsonPath","foundPackageJson","exportTemplate","package_","packagePath","init_command_default","collect","cliProgress","lstatSync","mkdirSync","dirname","normalize","pathToFileURL","generateCommand","paths","options","openapiConfig","config","multibar","spec","spec_builder_default","dir","files","bar","file","parsedJsDocumentFile","parse_file_default","comments_to_open_api_default","item","parsedSwaggerJsDocumentFile","validate_default","output","generate_command_default"],"mappings":"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","sourcesContent":["import { existsSync, realpathSync, writeFileSync } from \"node:fs\";\nimport readPkgUp from \"read-pkg-up\";\n\nconst initCommand = (configName: string, packageJsonPath = process.cwd()): void => {\n if (existsSync(configName)) {\n throw new Error(\"Config file already exists\");\n }\n\n const foundPackageJson = readPkgUp.sync({\n // eslint-disable-next-line no-undef\n cwd: realpathSync(packageJsonPath),\n });\n\n let exportTemplate = \"module.exports =\";\n\n if (foundPackageJson) {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const { packageJson: package_, path: packagePath } = foundPackageJson;\n\n // eslint-disable-next-line no-console\n console.info(`Found package.json at \"${packagePath}\"`);\n\n if (package_[\"type\"] === \"module\") {\n // eslint-disable-next-line no-console\n console.info(\"Found package.json with type: module, using ES6 as export for the config file\");\n\n exportTemplate = \"export default\";\n }\n } else {\n // eslint-disable-next-line no-console\n console.info(\"No package.json found\");\n }\n\n writeFileSync(\n configName,\n `${exportTemplate} {\n exclude: [\n 'coverage/**',\n '.github/**',\n 'packages/*/test{,s}/**',\n '**/*.d.ts',\n 'test{,s}/**',\n 'test{,-*}.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}',\n '**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}',\n '**/__tests__/**',\n '**/{ava,babel,nyc}.config.{js,cjs,mjs}',\n '**/jest.config.{js,cjs,mjs,ts}',\n '**/{karma,rollup,webpack}.config.js',\n '**/.{eslint,mocha}rc.{js,cjs}',\n '**/.{travis,yarnrc}.yml',\n '**/{docker-compose,docker}.yml',\n '**/.yamllint.{yaml,yml}',\n '**/node_modules/**',\n '**/pnpm-lock.yaml',\n '**/pnpm-workspace.yaml',\n '**/{package,package-lock}.json',\n '**/yarn.lock',\n '**/package.json5',\n '**/.next/**',\n ],\n followSymlinks: false,\n swaggerDefinition: {\n openapi: '3.0.0',\n info: {\n title: 'API',\n version: '1.0.0',\n },\n },\n};\n`,\n );\n\n // eslint-disable-next-line no-console\n console.log(`Created \"${configName}\"`);\n};\n\nexport default initCommand;\n","import { collect } from \"@visulima/readdir\";\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport cliProgress from \"cli-progress\";\nimport { lstatSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, normalize } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport type { BaseDefinition } from \"../../exported.d\";\nimport jsDocumentCommentsToOpenApi from \"../../jsdoc/comments-to-open-api\";\nimport parseFile from \"../../parse-file\";\nimport SpecBuilder from \"../../spec-builder\";\nimport swaggerJsDocumentCommentsToOpenApi from \"../../swagger-jsdoc/comments-to-open-api\";\nimport validate from \"../../validate\";\n\nconst generateCommand = async (\n configName: string,\n paths: string[],\n options: {\n config?: string;\n output?: string;\n verbose?: boolean;\n veryVerbose?: boolean;\n },\n // eslint-disable-next-line sonarjs/cognitive-complexity\n): Promise<void> => {\n let openapiConfig: {\n exclude: string[];\n followSymlinks?: boolean;\n swaggerDefinition: BaseDefinition;\n extensions?: string[];\n include?: string | readonly string[];\n } = {\n exclude: [],\n swaggerDefinition: {} as BaseDefinition,\n };\n\n try {\n // eslint-disable-next-line unicorn/prefer-module,import/no-dynamic-require\n let config = await import(pathToFileURL(normalize(options.config ?? configName)).href);\n\n if (config?.default) {\n config = config.default;\n }\n\n openapiConfig = config;\n } catch {\n throw new Error(`No config file found, on: ${options.config ?? \".openapirc.js\"}\\n`);\n }\n\n const multibar = new cliProgress.MultiBar(\n {\n clearOnComplete: false,\n hideCursor: true,\n format: \"{value}/{total} | {bar} | {filename}\",\n },\n cliProgress.Presets.shades_grey,\n );\n const spec = new SpecBuilder(openapiConfig.swaggerDefinition);\n\n // eslint-disable-next-line no-restricted-syntax,unicorn/prevent-abbreviations\n for await (const dir of paths) {\n // Check if the path is a directory\n lstatSync(dir).isDirectory();\n\n const files = await collect(dir, {\n // eslint-disable-next-line @rushstack/security/no-unsafe-regexp\n skip: [...openapiConfig.exclude, \"node_modules/**\"],\n extensions: openapiConfig.extensions ?? [\".js\", \".cjs\", \".mjs\", \".ts\", \".tsx\", \".jsx\", \".yaml\", \".yml\"],\n followSymlinks: openapiConfig.followSymlinks ?? false,\n match: openapiConfig.include,\n minimatchOptions: {\n match: {\n debug: options.verbose,\n matchBase: true,\n },\n skip: {\n debug: options.verbose,\n matchBase: true,\n },\n },\n });\n\n if (options.verbose ?? options.veryVerbose) {\n // eslint-disable-next-line no-console\n console.log(`\\nFound ${files.length} files in ${dir}`);\n }\n\n if (options.veryVerbose) {\n // eslint-disable-next-line no-console\n console.log(files);\n }\n\n const bar = multibar.create(files.length, 0);\n\n files.forEach((file) => {\n if (options.verbose) {\n // eslint-disable-next-line no-console\n console.log(`Parsing file ${file}`);\n }\n\n bar.increment(1, { filename: dir });\n\n const parsedJsDocumentFile = parseFile(file, jsDocumentCommentsToOpenApi, options.verbose);\n\n spec.addData(parsedJsDocumentFile.map((item) => item.spec));\n\n const parsedSwaggerJsDocumentFile = parseFile(file, swaggerJsDocumentCommentsToOpenApi, options.verbose);\n\n spec.addData(parsedSwaggerJsDocumentFile.map((item) => item.spec));\n });\n }\n\n if (options.verbose) {\n // eslint-disable-next-line no-console\n console.log(\"Validating swagger spec\");\n }\n\n if (options.veryVerbose) {\n // eslint-disable-next-line no-console\n console.log(JSON.stringify(spec, null, 2));\n }\n\n await validate(JSON.parse(JSON.stringify(spec)));\n\n const output = options.output ?? \"swagger.json\";\n\n multibar.stop();\n\n if (options.verbose) {\n // eslint-disable-next-line no-console\n console.log(`Written swagger spec to \"${output}\" file`);\n }\n\n // eslint-disable-next-line consistent-return\n mkdirSync(dirname(output), { recursive: true });\n writeFileSync(output, JSON.stringify(spec, null, 2));\n\n // eslint-disable-next-line no-console\n console.log(`\\nSwagger specification is ready, check the \"${output}\" file.`);\n};\n\nexport default generateCommand;\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import v from 'path';
|
|
3
|
+
import w from 'yaml';
|
|
4
|
+
import { parse } from 'comment-parser';
|
|
5
|
+
import D from 'lodash.mergewith';
|
|
6
|
+
import H from '@stoplight/spectral-core';
|
|
7
|
+
import { oas, asyncapi } from '@stoplight/spectral-rulesets';
|
|
8
|
+
|
|
9
|
+
var E=(t,s)=>{Object.keys(s).forEach(r=>{t[r]===void 0?t[r]={...s[r]}:Object.keys(s[r]).forEach(e=>{t[r][e]={...t[r][e],...s[r][e]};});});},y=E;var u=class{constructor(s){this.openapi=s.openapi,this.info=s.info,this.servers=s.servers,this.paths=s.paths??{},this.components=s.components,this.security=s.security,this.tags=s.tags,this.externalDocs=s.externalDocs;}addData(s){s.forEach(r=>{let{paths:e,components:i,...n}=r;y(this,{paths:e??{},components:i??{}}),Object.entries(n).forEach(([o,a])=>{this[o]=a;});});}},Z=u;function A(t){return t.split(/\r\n|\r|\n/).filter(e=>/^\s*(#\s*.*)?$/.test(e)?!1:e.trim().length>0).length}var g=A;var h=new Set(["openapi","info","servers","security","tags","externalDocs","components","paths"]),l=class extends Error{},$=(t,s,r)=>{let e=readFileSync(t,{encoding:"utf8"}),i=v.extname(t);if(i===".yaml"||i===".yml"){let n=w.parse(e),o=Object.keys(n).filter(a=>!h.has(a));if(o.length>0){let a=new l(`Unexpected keys: ${o.join(", ")}`);throw a.filePath=t,a}if(Object.keys(n).some(a=>h.has(a))){let a=g(e);return [{spec:n,loc:a}]}return []}try{return s(e,r)}catch(n){throw n.filePath=t,n}},ie=$;var k=(t,s)=>{if(Array.isArray(t))return [...t,...s]},m=k;function C(t){t.security&&(t.security=Object.keys(t.security).map(s=>({[s]:t.security[s]})));}var I=new Set(["integer","number","string","boolean","object","array"]),b={int32:"integer",int64:"integer",float:"number",double:"number",date:"string","date-time":"string",password:"string",byte:"string",binary:"string"};function q(t){let s=t.type,r=s.endsWith("[]"),e=s.replace(/\[]$/,""),i=I.has(e),n=Object.keys(b).includes(e),o;if(t.default)switch(e){case"integer":case"int32":case"int64":{o=Number.parseInt(t.default,10);break}case"number":case"double":case"float":{o=Number.parseFloat(t.default);break}default:{o=t.default;break}}let a;i?a={type:e,default:o}:n?a={type:b[e],format:e,default:o}:a={$ref:`#/components/schemas/${e}`};let c=r?{type:"array",items:{...a}}:{...a};e===""&&(c=void 0);let p=t.description.trim().replace(/^- /,"");return p===""&&(p=void 0),{name:t.name,description:p,required:!t.optional,schema:c,rawType:s}}function L(t,s){return t.map(r=>{let e=q(r),i="";switch(e.name&&(i+=e.name),e.description&&(i+=` ${e.description.trim()}`),r.tag){case"operationId":case"summary":case"description":return {[r.tag]:i};case"deprecated":return {deprecated:!0};case"externalDocs":return {externalDocs:{url:e.name,description:e.description}};case"server":return {servers:[{url:e.name,description:e.description}]};case"tag":return {tags:[i]};case"cookieParam":case"headerParam":case"queryParam":case"pathParam":return {parameters:[{name:e.name,in:r.tag.replace(/Param$/,""),description:e.description,required:e.required,schema:e.schema}]};case"bodyContent":return {requestBody:{content:{[e.name.replace("*\\/*","*/*")]:{schema:e.schema}}}};case"bodyExample":{let[n,o]=e.name.split(".");return {requestBody:{content:{[n]:{examples:{[o]:{$ref:`#/components/examples/${e.rawType}`}}}}}}}case"bodyDescription":return {requestBody:{description:i}};case"bodyRequired":return {requestBody:{required:!0}};case"response":return {responses:{[e.name]:{description:e.description}}};case"callback":return {callbacks:{[e.name]:{$ref:`#/components/callbacks/${e.rawType}`}}};case"responseContent":{let[n,o]=e.name.split(".");return {responses:{[n]:{content:{[o]:{schema:e.schema}}}}}}case"responseHeaderComponent":{let[n,o]=e.name.split(".");return {responses:{[n]:{headers:{[o]:{$ref:`#/components/headers/${e.rawType}`}}}}}}case"responseHeader":{let[n,o]=e.name.split(".");return {responses:{[n]:{headers:{[o]:{description:e.description,schema:e.schema}}}}}}case"responseExample":{let[n,o,a]=e.name.split(".");return {responses:{[n]:{content:{[o]:{examples:{[a]:{$ref:`#/components/examples/${e.rawType}`}}}}}}}}case"responseLink":{let[n,o]=e.name.split(".");return {responses:{[n]:{links:{[o]:{$ref:`#/components/links/${e.rawType}`}}}}}}case"bodyComponent":return {requestBody:{$ref:`#/components/requestBodies/${e.rawType}`}};case"responseComponent":return {responses:{[e.name]:{$ref:`#/components/responses/${e.rawType}`}}};case"paramComponent":return {parameters:[{$ref:`#/components/parameters/${e.rawType}`}]};case"security":{let[n,o]=e.name.split("."),a=[];return o&&(a=[o]),{security:{[n]:a}}}default:return {}}})}var R=(t,s)=>{let r=/^(GET|PUT|POST|DELETE|OPTIONS|HEAD|PATCH|TRACE) \/.*$/;return parse(t,{spacing:"preserve"}).filter(i=>r.test(i.description.trim())).map(i=>{let n=i.tags.length+1,o=D({},...L(i.tags),m);C(o);let[a,c]=i.description.split(" "),p={[c.trim()]:{[a.toLowerCase().trim()]:{...o}}};return {spec:JSON.parse(JSON.stringify({paths:p})),loc:n}})},le=R;var d=(t,s)=>D({},t,s,(r,e)=>e===null?r:void 0),O=t=>Object.keys(t).map(s=>t[s]).every(s=>typeof s=="object"&&Object.keys(s).every(r=>!(r in s))),f=(t,s)=>s.some(r=>t.name===r.name),j=t=>{switch(t.tag){case"openapi":return "v3";case"asyncapi":return "v4";case"swagger":return "v2";default:return "v2"}};var N=(t,s,r)=>{if(r==="x-webhooks"&&(t[r]=s[r]),r.startsWith("x-"))return;if(["components","consumes","produces","paths","schemas","securityDefinitions","responses","parameters","definitions","channels"].includes(r))Object.keys(s[r]).forEach(i=>{t[r][i]=d(t[r][i],s[r][i]);});else if(r==="tags"){let{tags:i}=s;Array.isArray(i)?i.forEach(n=>{f(n,t.tags)||t.tags.push(n);}):f(i,t.tags)||t.tags.push(i);}else if(r==="security"){let{security:i}=s;t.security=i;}else r.startsWith("/")&&(t.paths[r]=d(t.paths[r],s[r]));},x=N;var z={v2:["paths","definitions","responses","parameters","securityDefinitions"],v3:["paths","definitions","responses","parameters","securityDefinitions","components"],v4:["components","channels"]},F=(t,s)=>t.map(r=>{if((r.tag==="openapi"||r.tag==="swagger"||r.tag==="asyncapi")&&r.description!==""){let e=w.parseDocument(r.description);if(e.errors.length>0){e.errors.map(a=>{let c=a;return c.annotation=r.description,c});let o="Error parsing YAML in @openapi spec:";throw o+=s?e.errors.map(a=>`${a.toString()}
|
|
10
|
+
Imbedded within:
|
|
11
|
+
\`\`\`
|
|
12
|
+
${a.annotation?.replace(/\n/g,`
|
|
13
|
+
`)}
|
|
14
|
+
\`\`\``).join(`
|
|
15
|
+
`):e.errors.map(a=>a.toString()).join(`
|
|
16
|
+
`),new Error(o)}let i=e.toJSON(),n={tags:[]};return z[j(r)].forEach(o=>{n[o]=n[o]||{};}),Object.keys(i).forEach(o=>{x(n,i,o);}),n}return {}}),J=(t,s)=>parse(t,{spacing:"preserve"}).map(e=>{let i=e.tags.length+1,n=D({},...F(e.tags,s),m);return ["definitions","responses","parameters","securityDefinitions","components","tags"].forEach(a=>{n[a]!==void 0&&O(n[a])&&delete n[a];}),{spec:JSON.parse(JSON.stringify(n)),loc:i}}),Ae=J;var{Spectral:G}=H,S=new G;S.setRuleset({extends:[oas,asyncapi]});var _=async t=>{let s="";return typeof t=="object"?s=t.info.title:typeof t=="string"&&(s=t),S.run(t).then(r=>(r.forEach(e=>{if(e.code==="unrecognized-format")throw new Error(`Could not validate OpenAPI Specification '${s}'. ${e.message}`);if(e.severity<1)throw new Error(`Invalid OpenAPI Specification '${s}'. [${e.path.join(".")}] ${e.message}`)}),r)).catch(r=>{throw new Error(`Could not validate OpenAPI Specification '${s}'. ${r.message}`)})},$e=_;
|
|
17
|
+
|
|
18
|
+
export { Z as a, g as b, ie as c, le as d, Ae as e, $e as f };
|
|
19
|
+
//# sourceMappingURL=out.js.map
|
|
20
|
+
//# sourceMappingURL=chunk-SXATCZ56.mjs.map
|