@visulima/jsdoc-open-api 3.0.0-alpha.4 → 3.0.0-alpha.6
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 +48 -0
- package/LICENSE.md +1 -1
- package/dist/cli/command/generate-command.d.cts +7 -0
- package/dist/cli/command/generate-command.d.mts +7 -0
- package/dist/cli/command/generate-command.d.ts +7 -0
- package/dist/cli/command/init-command.d.cts +2 -0
- package/dist/cli/command/init-command.d.mts +2 -0
- package/dist/cli/command/init-command.d.ts +2 -0
- package/dist/cli/commander/command/generate-command.d.cts +3 -0
- package/dist/cli/commander/command/generate-command.d.mts +3 -0
- package/dist/cli/commander/command/generate-command.d.ts +3 -0
- package/dist/cli/commander/command/init-command.d.cts +3 -0
- package/dist/cli/commander/command/init-command.d.mts +3 -0
- package/dist/cli/commander/command/init-command.d.ts +3 -0
- package/dist/cli/commander/index.cjs +11 -0
- package/dist/cli/commander/index.d.cts +2 -0
- package/dist/cli/commander/index.d.mts +2 -7
- package/dist/cli/commander/index.d.ts +2 -7
- package/dist/cli/commander/index.mjs +2 -30
- package/dist/cli/index.cjs +11 -0
- package/dist/cli/index.d.cts +2 -0
- package/dist/cli/index.d.mts +2 -10
- package/dist/cli/index.d.ts +2 -10
- package/dist/cli/index.mjs +2 -4
- package/dist/constants.d.cts +1 -0
- package/dist/constants.d.mts +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/exported.d.cts +198 -0
- package/dist/exported.d.mts +198 -0
- package/dist/exported.d.ts +198 -0
- package/dist/index.cjs +19 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.mts +7 -248
- package/dist/index.d.ts +7 -248
- package/dist/index.mjs +6 -85
- package/dist/jsdoc/comments-to-open-api.d.cts +6 -0
- package/dist/jsdoc/comments-to-open-api.d.mts +6 -0
- package/dist/jsdoc/comments-to-open-api.d.ts +6 -0
- package/dist/packem_shared/SpecBuilder-B7YiF7zR.mjs +61 -0
- package/dist/packem_shared/SpecBuilder-CCESkmm5.cjs +63 -0
- package/dist/packem_shared/SwaggerCompilerPlugin-BEbFO9Dt.mjs +86 -0
- package/dist/packem_shared/SwaggerCompilerPlugin-BHbHAPK-.cjs +88 -0
- package/dist/packem_shared/customizer-CoMXMU7a.mjs +8 -0
- package/dist/packem_shared/customizer-DDFwFqJl.cjs +10 -0
- package/dist/packem_shared/generateCommand-B1t3VSDX.mjs +15 -0
- package/dist/packem_shared/generateCommand-CZEFuXr9.mjs +83 -0
- package/dist/packem_shared/generateCommand-CmyavGTZ.cjs +17 -0
- package/dist/packem_shared/generateCommand-Cu0UQUh8.cjs +85 -0
- package/dist/packem_shared/initCommand-B6Z9EXHP.mjs +15 -0
- package/dist/packem_shared/initCommand-Ch-72dKZ.cjs +65 -0
- package/dist/packem_shared/initCommand-D3yVEMwO.cjs +17 -0
- package/dist/packem_shared/initCommand-zE4VRDGW.mjs +63 -0
- package/dist/packem_shared/jsDocumentCommentsToOpenApi-C8kxIQH2.cjs +334 -0
- package/dist/packem_shared/jsDocumentCommentsToOpenApi-eOlxMuMO.mjs +328 -0
- package/dist/packem_shared/parseFile-BJwu_na4.cjs +42 -0
- package/dist/packem_shared/parseFile-Bxis7tbW.mjs +35 -0
- package/dist/packem_shared/swaggerJsDocumentCommentsToOpenApi-Cb5s1J29.mjs +130 -0
- package/dist/packem_shared/swaggerJsDocumentCommentsToOpenApi-JFymRz50.cjs +137 -0
- package/dist/packem_shared/validate-DZHaKH07.mjs +30 -0
- package/dist/packem_shared/validate-FKieC3ln.cjs +37 -0
- package/dist/packem_shared/yamlLoc-BLoIYoXs.cjs +14 -0
- package/dist/packem_shared/yamlLoc-Cmx4vbRt.mjs +12 -0
- package/dist/parse-file.d.cts +9 -0
- package/dist/parse-file.d.mts +9 -0
- package/dist/parse-file.d.ts +9 -0
- package/dist/spec-builder.d.cts +14 -0
- package/dist/spec-builder.d.mts +14 -0
- package/dist/spec-builder.d.ts +14 -0
- package/dist/swagger-jsdoc/comments-to-open-api.d.cts +6 -0
- package/dist/swagger-jsdoc/comments-to-open-api.d.mts +6 -0
- package/dist/swagger-jsdoc/comments-to-open-api.d.ts +6 -0
- package/dist/swagger-jsdoc/organize-swagger-object.d.cts +7 -0
- package/dist/swagger-jsdoc/organize-swagger-object.d.mts +7 -0
- package/dist/swagger-jsdoc/organize-swagger-object.d.ts +7 -0
- package/dist/swagger-jsdoc/utils.d.cts +21 -0
- package/dist/swagger-jsdoc/utils.d.mts +21 -0
- package/dist/swagger-jsdoc/utils.d.ts +21 -0
- package/dist/util/customizer.d.cts +2 -0
- package/dist/util/customizer.d.mts +2 -0
- package/dist/util/customizer.d.ts +2 -0
- package/dist/util/object-merge.d.cts +2 -0
- package/dist/util/object-merge.d.mts +2 -0
- package/dist/util/object-merge.d.ts +2 -0
- package/dist/util/yaml-loc.d.cts +2 -0
- package/dist/util/yaml-loc.d.mts +2 -0
- package/dist/util/yaml-loc.d.ts +2 -0
- package/dist/validate.d.cts +2 -0
- package/dist/validate.d.mts +2 -0
- package/dist/validate.d.ts +2 -0
- package/dist/webpack/swagger-compiler-plugin.d.cts +15 -0
- package/dist/webpack/swagger-compiler-plugin.d.mts +15 -0
- package/dist/webpack/swagger-compiler-plugin.d.ts +15 -0
- package/package.json +33 -20
- package/dist/chunk-2T6HMUIL.mjs +0 -1215
- package/dist/chunk-2T6HMUIL.mjs.map +0 -1
- package/dist/chunk-PTFTJY7I.js +0 -1233
- package/dist/chunk-PTFTJY7I.js.map +0 -1
- package/dist/chunk-RGP6RTJO.mjs +0 -142
- package/dist/chunk-RGP6RTJO.mjs.map +0 -1
- package/dist/chunk-RVCK3H3U.js +0 -149
- package/dist/chunk-RVCK3H3U.js.map +0 -1
- package/dist/cli/commander/index.js +0 -33
- package/dist/cli/commander/index.js.map +0 -1
- package/dist/cli/commander/index.mjs.map +0 -1
- package/dist/cli/index.js +0 -17
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/index.mjs.map +0 -1
- package/dist/index.js +0 -106
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { exit } from 'node:process';
|
|
2
|
+
import generateCommand$1 from './generateCommand-CZEFuXr9.mjs';
|
|
3
|
+
|
|
4
|
+
const generateCommand = (program, commandName = "generate", configName = ".openapirc.js") => {
|
|
5
|
+
program.command(commandName).description("Generates OpenAPI (Swagger) documentation from JSDoc's").usage("[options] <path ...>").argument("[path ...]", "Paths to files or directories to parse").option("-c, --config [.openapirc.js]", "@visulima/jsdoc-open-api config file path.").option("-o, --output [swaggerSpec.json]", "Output swagger specification.").option("-v, --verbose", "Verbose output.").option("-d, --very-verbose", "Very verbose output.").action(async (paths, options) => {
|
|
6
|
+
try {
|
|
7
|
+
await generateCommand$1(configName, paths, options);
|
|
8
|
+
} catch (error) {
|
|
9
|
+
console.error(error);
|
|
10
|
+
exit(1);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { generateCommand as default };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { lstat, realpath, mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { normalize, dirname } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { collect } from '@visulima/fs';
|
|
5
|
+
import { MultiBar, Presets } from 'cli-progress';
|
|
6
|
+
import { v as validate, D as DEFAULT_EXCLUDE } from './validate-DZHaKH07.mjs';
|
|
7
|
+
import commentsToOpenApi from './jsDocumentCommentsToOpenApi-eOlxMuMO.mjs';
|
|
8
|
+
import parseFile from './parseFile-Bxis7tbW.mjs';
|
|
9
|
+
import SpecBuilder from './SpecBuilder-B7YiF7zR.mjs';
|
|
10
|
+
import commentsToOpenApi$1 from './swaggerJsDocumentCommentsToOpenApi-Cb5s1J29.mjs';
|
|
11
|
+
|
|
12
|
+
const generateCommand = async (configName, paths, options) => {
|
|
13
|
+
let openapiConfig = {
|
|
14
|
+
exclude: [],
|
|
15
|
+
swaggerDefinition: {}
|
|
16
|
+
};
|
|
17
|
+
try {
|
|
18
|
+
let config = await import(pathToFileURL(normalize(options.config ?? configName)).href);
|
|
19
|
+
if (config?.default) {
|
|
20
|
+
config = config.default;
|
|
21
|
+
}
|
|
22
|
+
openapiConfig = config;
|
|
23
|
+
} catch {
|
|
24
|
+
throw new Error(`No config file found, on: ${options.config ?? ".openapirc.js"}
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
const multibar = new MultiBar(
|
|
28
|
+
{
|
|
29
|
+
clearOnComplete: false,
|
|
30
|
+
format: "{value}/{total} | {bar} | {filename}",
|
|
31
|
+
hideCursor: true
|
|
32
|
+
},
|
|
33
|
+
Presets.shades_grey
|
|
34
|
+
);
|
|
35
|
+
const spec = new SpecBuilder(openapiConfig.swaggerDefinition);
|
|
36
|
+
const skip = /* @__PURE__ */ new Set([...DEFAULT_EXCLUDE, ...openapiConfig.exclude]);
|
|
37
|
+
for await (const dir of paths) {
|
|
38
|
+
(await lstat(dir)).isDirectory();
|
|
39
|
+
const realDirectory = await realpath(dir);
|
|
40
|
+
const files = await collect(realDirectory, {
|
|
41
|
+
extensions: openapiConfig.extensions ?? [".js", ".cjs", ".mjs", ".ts", ".tsx", ".jsx", ".yaml", ".yml"],
|
|
42
|
+
followSymlinks: openapiConfig.followSymlinks ?? false,
|
|
43
|
+
match: openapiConfig.include,
|
|
44
|
+
skip: [...skip]
|
|
45
|
+
});
|
|
46
|
+
if (options.verbose ?? options.veryVerbose) {
|
|
47
|
+
console.log(`
|
|
48
|
+
Found ${String(files.length)} files in ${realDirectory}`);
|
|
49
|
+
}
|
|
50
|
+
if (options.veryVerbose) {
|
|
51
|
+
console.log(files);
|
|
52
|
+
}
|
|
53
|
+
const bar = multibar.create(files.length, 0);
|
|
54
|
+
files.forEach((file) => {
|
|
55
|
+
if (options.verbose) {
|
|
56
|
+
console.log(`Parsing file ${file}`);
|
|
57
|
+
}
|
|
58
|
+
bar.increment(1, { filename: realDirectory });
|
|
59
|
+
const parsedJsDocumentFile = parseFile(file, commentsToOpenApi, options.verbose);
|
|
60
|
+
spec.addData(parsedJsDocumentFile.map((item) => item.spec));
|
|
61
|
+
const parsedSwaggerJsDocumentFile = parseFile(file, commentsToOpenApi$1, options.verbose);
|
|
62
|
+
spec.addData(parsedSwaggerJsDocumentFile.map((item) => item.spec));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (options.verbose) {
|
|
66
|
+
console.log("Validating swagger spec");
|
|
67
|
+
}
|
|
68
|
+
if (options.veryVerbose) {
|
|
69
|
+
console.log(JSON.stringify(spec, null, 2));
|
|
70
|
+
}
|
|
71
|
+
await validate(JSON.parse(JSON.stringify(spec)));
|
|
72
|
+
const output = options.output ?? "swagger.json";
|
|
73
|
+
multibar.stop();
|
|
74
|
+
if (options.verbose) {
|
|
75
|
+
console.log(`Written swagger spec to "${output}" file`);
|
|
76
|
+
}
|
|
77
|
+
await mkdir(dirname(output), { recursive: true });
|
|
78
|
+
await writeFile(output, JSON.stringify(spec, null, 2));
|
|
79
|
+
console.log(`
|
|
80
|
+
Swagger specification is ready, check the "${output}" file.`);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export { generateCommand as default };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const node_process = require('node:process');
|
|
4
|
+
const generateCommand$1 = require('./generateCommand-Cu0UQUh8.cjs');
|
|
5
|
+
|
|
6
|
+
const generateCommand = (program, commandName = "generate", configName = ".openapirc.js") => {
|
|
7
|
+
program.command(commandName).description("Generates OpenAPI (Swagger) documentation from JSDoc's").usage("[options] <path ...>").argument("[path ...]", "Paths to files or directories to parse").option("-c, --config [.openapirc.js]", "@visulima/jsdoc-open-api config file path.").option("-o, --output [swaggerSpec.json]", "Output swagger specification.").option("-v, --verbose", "Verbose output.").option("-d, --very-verbose", "Very verbose output.").action(async (paths, options) => {
|
|
8
|
+
try {
|
|
9
|
+
await generateCommand$1(configName, paths, options);
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.error(error);
|
|
12
|
+
node_process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
module.exports = generateCommand;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const promises = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const node_url = require('node:url');
|
|
6
|
+
const fs = require('@visulima/fs');
|
|
7
|
+
const cliProgress = require('cli-progress');
|
|
8
|
+
const validate = require('./validate-FKieC3ln.cjs');
|
|
9
|
+
const jsDocumentCommentsToOpenApi = require('./jsDocumentCommentsToOpenApi-C8kxIQH2.cjs');
|
|
10
|
+
const parseFile = require('./parseFile-BJwu_na4.cjs');
|
|
11
|
+
const SpecBuilder = require('./SpecBuilder-CCESkmm5.cjs');
|
|
12
|
+
const swaggerJsDocumentCommentsToOpenApi = require('./swaggerJsDocumentCommentsToOpenApi-JFymRz50.cjs');
|
|
13
|
+
|
|
14
|
+
const generateCommand = async (configName, paths, options) => {
|
|
15
|
+
let openapiConfig = {
|
|
16
|
+
exclude: [],
|
|
17
|
+
swaggerDefinition: {}
|
|
18
|
+
};
|
|
19
|
+
try {
|
|
20
|
+
let config = await import(node_url.pathToFileURL(path.normalize(options.config ?? configName)).href);
|
|
21
|
+
if (config?.default) {
|
|
22
|
+
config = config.default;
|
|
23
|
+
}
|
|
24
|
+
openapiConfig = config;
|
|
25
|
+
} catch {
|
|
26
|
+
throw new Error(`No config file found, on: ${options.config ?? ".openapirc.js"}
|
|
27
|
+
`);
|
|
28
|
+
}
|
|
29
|
+
const multibar = new cliProgress.MultiBar(
|
|
30
|
+
{
|
|
31
|
+
clearOnComplete: false,
|
|
32
|
+
format: "{value}/{total} | {bar} | {filename}",
|
|
33
|
+
hideCursor: true
|
|
34
|
+
},
|
|
35
|
+
cliProgress.Presets.shades_grey
|
|
36
|
+
);
|
|
37
|
+
const spec = new SpecBuilder(openapiConfig.swaggerDefinition);
|
|
38
|
+
const skip = /* @__PURE__ */ new Set([...validate.DEFAULT_EXCLUDE, ...openapiConfig.exclude]);
|
|
39
|
+
for await (const dir of paths) {
|
|
40
|
+
(await promises.lstat(dir)).isDirectory();
|
|
41
|
+
const realDirectory = await promises.realpath(dir);
|
|
42
|
+
const files = await fs.collect(realDirectory, {
|
|
43
|
+
extensions: openapiConfig.extensions ?? [".js", ".cjs", ".mjs", ".ts", ".tsx", ".jsx", ".yaml", ".yml"],
|
|
44
|
+
followSymlinks: openapiConfig.followSymlinks ?? false,
|
|
45
|
+
match: openapiConfig.include,
|
|
46
|
+
skip: [...skip]
|
|
47
|
+
});
|
|
48
|
+
if (options.verbose ?? options.veryVerbose) {
|
|
49
|
+
console.log(`
|
|
50
|
+
Found ${String(files.length)} files in ${realDirectory}`);
|
|
51
|
+
}
|
|
52
|
+
if (options.veryVerbose) {
|
|
53
|
+
console.log(files);
|
|
54
|
+
}
|
|
55
|
+
const bar = multibar.create(files.length, 0);
|
|
56
|
+
files.forEach((file) => {
|
|
57
|
+
if (options.verbose) {
|
|
58
|
+
console.log(`Parsing file ${file}`);
|
|
59
|
+
}
|
|
60
|
+
bar.increment(1, { filename: realDirectory });
|
|
61
|
+
const parsedJsDocumentFile = parseFile(file, jsDocumentCommentsToOpenApi, options.verbose);
|
|
62
|
+
spec.addData(parsedJsDocumentFile.map((item) => item.spec));
|
|
63
|
+
const parsedSwaggerJsDocumentFile = parseFile(file, swaggerJsDocumentCommentsToOpenApi, options.verbose);
|
|
64
|
+
spec.addData(parsedSwaggerJsDocumentFile.map((item) => item.spec));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (options.verbose) {
|
|
68
|
+
console.log("Validating swagger spec");
|
|
69
|
+
}
|
|
70
|
+
if (options.veryVerbose) {
|
|
71
|
+
console.log(JSON.stringify(spec, null, 2));
|
|
72
|
+
}
|
|
73
|
+
await validate.validate(JSON.parse(JSON.stringify(spec)));
|
|
74
|
+
const output = options.output ?? "swagger.json";
|
|
75
|
+
multibar.stop();
|
|
76
|
+
if (options.verbose) {
|
|
77
|
+
console.log(`Written swagger spec to "${output}" file`);
|
|
78
|
+
}
|
|
79
|
+
await promises.mkdir(path.dirname(output), { recursive: true });
|
|
80
|
+
await promises.writeFile(output, JSON.stringify(spec, null, 2));
|
|
81
|
+
console.log(`
|
|
82
|
+
Swagger specification is ready, check the "${output}" file.`);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
module.exports = generateCommand;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { exit } from 'node:process';
|
|
2
|
+
import initCommand$1 from './initCommand-zE4VRDGW.mjs';
|
|
3
|
+
|
|
4
|
+
const initCommand = (program, commandName = "init", description = "Inits a pre-configured @visulima/jsdoc-open-api config file.", configName = ".openapirc.js") => {
|
|
5
|
+
program.command(commandName).description(description).action(() => {
|
|
6
|
+
try {
|
|
7
|
+
initCommand$1(configName);
|
|
8
|
+
} catch (error) {
|
|
9
|
+
console.error(error);
|
|
10
|
+
exit(1);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { initCommand as default };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const node_fs = require('node:fs');
|
|
4
|
+
const fs = require('@visulima/fs');
|
|
5
|
+
|
|
6
|
+
const initCommand = (configName, packageJsonPath = process.cwd()) => {
|
|
7
|
+
if (node_fs.existsSync(configName)) {
|
|
8
|
+
throw new Error("Config file already exists");
|
|
9
|
+
}
|
|
10
|
+
const packagePath = fs.findUpSync("package.json", {
|
|
11
|
+
cwd: node_fs.realpathSync(packageJsonPath)
|
|
12
|
+
});
|
|
13
|
+
let exportTemplate = "module.exports =";
|
|
14
|
+
if (packagePath) {
|
|
15
|
+
const packageJson = fs.readJsonSync(packagePath);
|
|
16
|
+
console.info(`Found package.json at "${packagePath}"`);
|
|
17
|
+
if (packageJson.type === "module") {
|
|
18
|
+
console.info("Found package.json with type: module, using ES6 as export for the config file");
|
|
19
|
+
exportTemplate = "export default";
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
console.info("No package.json found");
|
|
23
|
+
}
|
|
24
|
+
node_fs.writeFileSync(
|
|
25
|
+
configName,
|
|
26
|
+
`${exportTemplate} {
|
|
27
|
+
exclude: [
|
|
28
|
+
'coverage/**',
|
|
29
|
+
'.github/**',
|
|
30
|
+
'packages/*/test{,s}/**',
|
|
31
|
+
'**/*.d.ts',
|
|
32
|
+
'test{,s}/**',
|
|
33
|
+
'test{,-*}.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}',
|
|
34
|
+
'**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}',
|
|
35
|
+
'**/__tests__/**',
|
|
36
|
+
'**/{ava,babel,nyc}.config.{js,cjs,mjs}',
|
|
37
|
+
'**/jest.config.{js,cjs,mjs,ts}',
|
|
38
|
+
'**/{karma,rollup,webpack}.config.js',
|
|
39
|
+
'**/.{eslint,mocha}rc.{js,cjs}',
|
|
40
|
+
'**/.{travis,yarnrc}.yml',
|
|
41
|
+
'**/{docker-compose,docker}.yml',
|
|
42
|
+
'**/.yamllint.{yaml,yml}',
|
|
43
|
+
'**/node_modules/**',
|
|
44
|
+
'**/pnpm-lock.yaml',
|
|
45
|
+
'**/pnpm-workspace.yaml',
|
|
46
|
+
'**/{package,package-lock}.json',
|
|
47
|
+
'**/yarn.lock',
|
|
48
|
+
'**/package.json5',
|
|
49
|
+
'**/.next/**',
|
|
50
|
+
],
|
|
51
|
+
followSymlinks: false,
|
|
52
|
+
swaggerDefinition: {
|
|
53
|
+
openapi: '3.0.0',
|
|
54
|
+
info: {
|
|
55
|
+
title: 'API',
|
|
56
|
+
version: '1.0.0',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
`
|
|
61
|
+
);
|
|
62
|
+
console.log(`Created "${configName}"`);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
module.exports = initCommand;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const node_process = require('node:process');
|
|
4
|
+
const initCommand$1 = require('./initCommand-Ch-72dKZ.cjs');
|
|
5
|
+
|
|
6
|
+
const initCommand = (program, commandName = "init", description = "Inits a pre-configured @visulima/jsdoc-open-api config file.", configName = ".openapirc.js") => {
|
|
7
|
+
program.command(commandName).description(description).action(() => {
|
|
8
|
+
try {
|
|
9
|
+
initCommand$1(configName);
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.error(error);
|
|
12
|
+
node_process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
module.exports = initCommand;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { existsSync, realpathSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { findUpSync, readJsonSync } from '@visulima/fs';
|
|
3
|
+
|
|
4
|
+
const initCommand = (configName, packageJsonPath = process.cwd()) => {
|
|
5
|
+
if (existsSync(configName)) {
|
|
6
|
+
throw new Error("Config file already exists");
|
|
7
|
+
}
|
|
8
|
+
const packagePath = findUpSync("package.json", {
|
|
9
|
+
cwd: realpathSync(packageJsonPath)
|
|
10
|
+
});
|
|
11
|
+
let exportTemplate = "module.exports =";
|
|
12
|
+
if (packagePath) {
|
|
13
|
+
const packageJson = readJsonSync(packagePath);
|
|
14
|
+
console.info(`Found package.json at "${packagePath}"`);
|
|
15
|
+
if (packageJson.type === "module") {
|
|
16
|
+
console.info("Found package.json with type: module, using ES6 as export for the config file");
|
|
17
|
+
exportTemplate = "export default";
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
console.info("No package.json found");
|
|
21
|
+
}
|
|
22
|
+
writeFileSync(
|
|
23
|
+
configName,
|
|
24
|
+
`${exportTemplate} {
|
|
25
|
+
exclude: [
|
|
26
|
+
'coverage/**',
|
|
27
|
+
'.github/**',
|
|
28
|
+
'packages/*/test{,s}/**',
|
|
29
|
+
'**/*.d.ts',
|
|
30
|
+
'test{,s}/**',
|
|
31
|
+
'test{,-*}.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}',
|
|
32
|
+
'**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}',
|
|
33
|
+
'**/__tests__/**',
|
|
34
|
+
'**/{ava,babel,nyc}.config.{js,cjs,mjs}',
|
|
35
|
+
'**/jest.config.{js,cjs,mjs,ts}',
|
|
36
|
+
'**/{karma,rollup,webpack}.config.js',
|
|
37
|
+
'**/.{eslint,mocha}rc.{js,cjs}',
|
|
38
|
+
'**/.{travis,yarnrc}.yml',
|
|
39
|
+
'**/{docker-compose,docker}.yml',
|
|
40
|
+
'**/.yamllint.{yaml,yml}',
|
|
41
|
+
'**/node_modules/**',
|
|
42
|
+
'**/pnpm-lock.yaml',
|
|
43
|
+
'**/pnpm-workspace.yaml',
|
|
44
|
+
'**/{package,package-lock}.json',
|
|
45
|
+
'**/yarn.lock',
|
|
46
|
+
'**/package.json5',
|
|
47
|
+
'**/.next/**',
|
|
48
|
+
],
|
|
49
|
+
followSymlinks: false,
|
|
50
|
+
swaggerDefinition: {
|
|
51
|
+
openapi: '3.0.0',
|
|
52
|
+
info: {
|
|
53
|
+
title: 'API',
|
|
54
|
+
version: '1.0.0',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
`
|
|
59
|
+
);
|
|
60
|
+
console.log(`Created "${configName}"`);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export { initCommand as default };
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const commentParser = require('comment-parser');
|
|
4
|
+
const mergeWith = require('lodash.mergewith');
|
|
5
|
+
const customizer = require('./customizer-DDFwFqJl.cjs');
|
|
6
|
+
|
|
7
|
+
const _interopDefaultCompat = e => e && typeof e === 'object' && 'default' in e ? e.default : e;
|
|
8
|
+
|
|
9
|
+
const mergeWith__default = /*#__PURE__*/_interopDefaultCompat(mergeWith);
|
|
10
|
+
|
|
11
|
+
const fixSecurityObject = (thing) => {
|
|
12
|
+
if (thing.security) {
|
|
13
|
+
thing.security = Object.keys(thing.security).map((s) => {
|
|
14
|
+
return {
|
|
15
|
+
[s]: thing.security[s]
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const primitiveTypes = /* @__PURE__ */ new Set(["array", "boolean", "integer", "number", "object", "string"]);
|
|
21
|
+
const formatMap = {
|
|
22
|
+
binary: "string",
|
|
23
|
+
byte: "string",
|
|
24
|
+
date: "string",
|
|
25
|
+
"date-time": "string",
|
|
26
|
+
double: "number",
|
|
27
|
+
float: "number",
|
|
28
|
+
int32: "integer",
|
|
29
|
+
int64: "integer",
|
|
30
|
+
password: "string"
|
|
31
|
+
};
|
|
32
|
+
const parseDescription = (tag) => {
|
|
33
|
+
const rawType = tag.type;
|
|
34
|
+
const isArray = rawType.endsWith("[]");
|
|
35
|
+
const parsedType = rawType.replace(/\[]$/, "");
|
|
36
|
+
const isPrimitive = primitiveTypes.has(parsedType);
|
|
37
|
+
const isFormat = Object.keys(formatMap).includes(parsedType);
|
|
38
|
+
let defaultValue;
|
|
39
|
+
if (tag.default) {
|
|
40
|
+
switch (parsedType) {
|
|
41
|
+
case "double":
|
|
42
|
+
case "float":
|
|
43
|
+
case "number": {
|
|
44
|
+
defaultValue = Number.parseFloat(tag.default);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case "int32":
|
|
48
|
+
case "int64":
|
|
49
|
+
case "integer": {
|
|
50
|
+
defaultValue = Number.parseInt(tag.default, 10);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
default: {
|
|
54
|
+
defaultValue = tag.default;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
let rootType;
|
|
60
|
+
if (isPrimitive) {
|
|
61
|
+
rootType = { default: defaultValue, type: parsedType };
|
|
62
|
+
} else if (isFormat) {
|
|
63
|
+
rootType = {
|
|
64
|
+
default: defaultValue,
|
|
65
|
+
format: parsedType,
|
|
66
|
+
type: formatMap[parsedType]
|
|
67
|
+
};
|
|
68
|
+
} else {
|
|
69
|
+
rootType = { $ref: `#/components/schemas/${parsedType}` };
|
|
70
|
+
}
|
|
71
|
+
let schema = isArray ? {
|
|
72
|
+
items: {
|
|
73
|
+
...rootType
|
|
74
|
+
},
|
|
75
|
+
type: "array"
|
|
76
|
+
} : {
|
|
77
|
+
...rootType
|
|
78
|
+
};
|
|
79
|
+
if (parsedType === "") {
|
|
80
|
+
schema = void 0;
|
|
81
|
+
}
|
|
82
|
+
let description = tag.description.trim().replace(/^- /u, "");
|
|
83
|
+
if (description === "") {
|
|
84
|
+
description = void 0;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
description,
|
|
88
|
+
name: tag.name,
|
|
89
|
+
rawType,
|
|
90
|
+
required: !tag.optional,
|
|
91
|
+
schema
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
const tagsToObjects = (tags, verbose) => tags.map((tag) => {
|
|
95
|
+
const parsedResponse = parseDescription(tag);
|
|
96
|
+
let nameAndDescription = "";
|
|
97
|
+
if (parsedResponse.name) {
|
|
98
|
+
nameAndDescription += parsedResponse.name;
|
|
99
|
+
}
|
|
100
|
+
if (parsedResponse.description) {
|
|
101
|
+
nameAndDescription += ` ${parsedResponse.description.trim()}`;
|
|
102
|
+
}
|
|
103
|
+
switch (tag.tag) {
|
|
104
|
+
case "bodyComponent": {
|
|
105
|
+
return {
|
|
106
|
+
requestBody: {
|
|
107
|
+
$ref: `#/components/requestBodies/${parsedResponse.rawType}`
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
case "bodyContent": {
|
|
112
|
+
return {
|
|
113
|
+
requestBody: {
|
|
114
|
+
content: {
|
|
115
|
+
[parsedResponse.name.replace(String.raw`*\/*`, "*/*")]: {
|
|
116
|
+
schema: parsedResponse.schema
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
case "bodyDescription": {
|
|
123
|
+
return { requestBody: { description: nameAndDescription } };
|
|
124
|
+
}
|
|
125
|
+
case "bodyExample": {
|
|
126
|
+
const [contentType, example] = parsedResponse.name.split(".");
|
|
127
|
+
return {
|
|
128
|
+
requestBody: {
|
|
129
|
+
content: {
|
|
130
|
+
[contentType]: {
|
|
131
|
+
examples: {
|
|
132
|
+
[example]: {
|
|
133
|
+
$ref: `#/components/examples/${parsedResponse.rawType}`
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
case "bodyRequired": {
|
|
142
|
+
return { requestBody: { required: true } };
|
|
143
|
+
}
|
|
144
|
+
case "callback": {
|
|
145
|
+
return {
|
|
146
|
+
callbacks: {
|
|
147
|
+
[parsedResponse.name]: {
|
|
148
|
+
$ref: `#/components/callbacks/${parsedResponse.rawType}`
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
case "cookieParam":
|
|
154
|
+
case "headerParam":
|
|
155
|
+
case "pathParam":
|
|
156
|
+
case "queryParam": {
|
|
157
|
+
return {
|
|
158
|
+
parameters: [
|
|
159
|
+
{
|
|
160
|
+
description: parsedResponse.description,
|
|
161
|
+
in: tag.tag.replace(/Param$/u, ""),
|
|
162
|
+
name: parsedResponse.name,
|
|
163
|
+
required: parsedResponse.required,
|
|
164
|
+
schema: parsedResponse.schema
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
case "deprecated": {
|
|
170
|
+
return { deprecated: true };
|
|
171
|
+
}
|
|
172
|
+
case "description":
|
|
173
|
+
case "operationId":
|
|
174
|
+
case "summary": {
|
|
175
|
+
return { [tag.tag]: nameAndDescription };
|
|
176
|
+
}
|
|
177
|
+
case "externalDocs": {
|
|
178
|
+
return {
|
|
179
|
+
externalDocs: {
|
|
180
|
+
description: parsedResponse.description,
|
|
181
|
+
url: parsedResponse.name
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
case "paramComponent": {
|
|
186
|
+
return {
|
|
187
|
+
parameters: [{ $ref: `#/components/parameters/${parsedResponse.rawType}` }]
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
case "response": {
|
|
191
|
+
return {
|
|
192
|
+
responses: {
|
|
193
|
+
[parsedResponse.name]: {
|
|
194
|
+
description: parsedResponse.description
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
case "responseComponent": {
|
|
200
|
+
return {
|
|
201
|
+
responses: {
|
|
202
|
+
[parsedResponse.name]: {
|
|
203
|
+
$ref: `#/components/responses/${parsedResponse.rawType}`
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
case "responseContent": {
|
|
209
|
+
const [status, contentType] = parsedResponse.name.split(".");
|
|
210
|
+
return {
|
|
211
|
+
responses: {
|
|
212
|
+
[status]: {
|
|
213
|
+
content: {
|
|
214
|
+
[contentType]: {
|
|
215
|
+
schema: parsedResponse.schema
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
case "responseExample": {
|
|
223
|
+
const [status, contentType, example] = parsedResponse.name.split(".");
|
|
224
|
+
return {
|
|
225
|
+
responses: {
|
|
226
|
+
[status]: {
|
|
227
|
+
content: {
|
|
228
|
+
[contentType]: {
|
|
229
|
+
examples: {
|
|
230
|
+
[example]: {
|
|
231
|
+
$ref: `#/components/examples/${parsedResponse.rawType}`
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
case "responseHeader": {
|
|
241
|
+
const [status, header] = parsedResponse.name.split(".");
|
|
242
|
+
return {
|
|
243
|
+
responses: {
|
|
244
|
+
[status]: {
|
|
245
|
+
headers: {
|
|
246
|
+
[header]: {
|
|
247
|
+
description: parsedResponse.description,
|
|
248
|
+
schema: parsedResponse.schema
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
case "responseHeaderComponent": {
|
|
256
|
+
const [status, header] = parsedResponse.name.split(".");
|
|
257
|
+
return {
|
|
258
|
+
responses: {
|
|
259
|
+
[status]: {
|
|
260
|
+
headers: {
|
|
261
|
+
[header]: {
|
|
262
|
+
$ref: `#/components/headers/${parsedResponse.rawType}`
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
case "responseLink": {
|
|
270
|
+
const [status, link] = parsedResponse.name.split(".");
|
|
271
|
+
return {
|
|
272
|
+
responses: {
|
|
273
|
+
[status]: {
|
|
274
|
+
links: {
|
|
275
|
+
[link]: {
|
|
276
|
+
$ref: `#/components/links/${parsedResponse.rawType}`
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
case "security": {
|
|
284
|
+
const [security, scopeItem] = parsedResponse.name.split(".");
|
|
285
|
+
let scope = [];
|
|
286
|
+
if (scopeItem) {
|
|
287
|
+
scope = [scopeItem];
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
security: { [security]: scope }
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
case "server": {
|
|
294
|
+
return {
|
|
295
|
+
servers: [
|
|
296
|
+
{
|
|
297
|
+
description: parsedResponse.description,
|
|
298
|
+
url: parsedResponse.name
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
case "tag": {
|
|
304
|
+
return { tags: [nameAndDescription] };
|
|
305
|
+
}
|
|
306
|
+
default: {
|
|
307
|
+
return {};
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
const commentsToOpenApi = (fileContents, verbose) => {
|
|
312
|
+
const openAPIRegex = /^(GET|PUT|POST|DELETE|OPTIONS|HEAD|PATCH|TRACE) \/.*$/;
|
|
313
|
+
const jsDocumentComments = commentParser.parse(fileContents, { spacing: "preserve" });
|
|
314
|
+
return jsDocumentComments.filter((comment) => openAPIRegex.test(comment.description.trim())).map((comment) => {
|
|
315
|
+
const loc = comment.tags.length + 1;
|
|
316
|
+
const result = mergeWith__default({}, ...tagsToObjects(comment.tags), customizer.customizer);
|
|
317
|
+
fixSecurityObject(result);
|
|
318
|
+
const [method, path] = comment.description.split(" ");
|
|
319
|
+
const pathsObject = {
|
|
320
|
+
[path.trim()]: {
|
|
321
|
+
[method.toLowerCase().trim()]: {
|
|
322
|
+
...result
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
const spec = JSON.parse(JSON.stringify({ paths: pathsObject }));
|
|
327
|
+
return {
|
|
328
|
+
loc,
|
|
329
|
+
spec
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
module.exports = commentsToOpenApi;
|