@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.
Files changed (110) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE.md +1 -1
  3. package/dist/cli/command/generate-command.d.cts +7 -0
  4. package/dist/cli/command/generate-command.d.mts +7 -0
  5. package/dist/cli/command/generate-command.d.ts +7 -0
  6. package/dist/cli/command/init-command.d.cts +2 -0
  7. package/dist/cli/command/init-command.d.mts +2 -0
  8. package/dist/cli/command/init-command.d.ts +2 -0
  9. package/dist/cli/commander/command/generate-command.d.cts +3 -0
  10. package/dist/cli/commander/command/generate-command.d.mts +3 -0
  11. package/dist/cli/commander/command/generate-command.d.ts +3 -0
  12. package/dist/cli/commander/command/init-command.d.cts +3 -0
  13. package/dist/cli/commander/command/init-command.d.mts +3 -0
  14. package/dist/cli/commander/command/init-command.d.ts +3 -0
  15. package/dist/cli/commander/index.cjs +11 -0
  16. package/dist/cli/commander/index.d.cts +2 -0
  17. package/dist/cli/commander/index.d.mts +2 -7
  18. package/dist/cli/commander/index.d.ts +2 -7
  19. package/dist/cli/commander/index.mjs +2 -30
  20. package/dist/cli/index.cjs +11 -0
  21. package/dist/cli/index.d.cts +2 -0
  22. package/dist/cli/index.d.mts +2 -10
  23. package/dist/cli/index.d.ts +2 -10
  24. package/dist/cli/index.mjs +2 -4
  25. package/dist/constants.d.cts +1 -0
  26. package/dist/constants.d.mts +1 -0
  27. package/dist/constants.d.ts +1 -0
  28. package/dist/exported.d.cts +198 -0
  29. package/dist/exported.d.mts +198 -0
  30. package/dist/exported.d.ts +198 -0
  31. package/dist/index.cjs +19 -0
  32. package/dist/index.d.cts +7 -0
  33. package/dist/index.d.mts +7 -248
  34. package/dist/index.d.ts +7 -248
  35. package/dist/index.mjs +6 -85
  36. package/dist/jsdoc/comments-to-open-api.d.cts +6 -0
  37. package/dist/jsdoc/comments-to-open-api.d.mts +6 -0
  38. package/dist/jsdoc/comments-to-open-api.d.ts +6 -0
  39. package/dist/packem_shared/SpecBuilder-B7YiF7zR.mjs +61 -0
  40. package/dist/packem_shared/SpecBuilder-CCESkmm5.cjs +63 -0
  41. package/dist/packem_shared/SwaggerCompilerPlugin-BEbFO9Dt.mjs +86 -0
  42. package/dist/packem_shared/SwaggerCompilerPlugin-BHbHAPK-.cjs +88 -0
  43. package/dist/packem_shared/customizer-CoMXMU7a.mjs +8 -0
  44. package/dist/packem_shared/customizer-DDFwFqJl.cjs +10 -0
  45. package/dist/packem_shared/generateCommand-B1t3VSDX.mjs +15 -0
  46. package/dist/packem_shared/generateCommand-CZEFuXr9.mjs +83 -0
  47. package/dist/packem_shared/generateCommand-CmyavGTZ.cjs +17 -0
  48. package/dist/packem_shared/generateCommand-Cu0UQUh8.cjs +85 -0
  49. package/dist/packem_shared/initCommand-B6Z9EXHP.mjs +15 -0
  50. package/dist/packem_shared/initCommand-Ch-72dKZ.cjs +65 -0
  51. package/dist/packem_shared/initCommand-D3yVEMwO.cjs +17 -0
  52. package/dist/packem_shared/initCommand-zE4VRDGW.mjs +63 -0
  53. package/dist/packem_shared/jsDocumentCommentsToOpenApi-C8kxIQH2.cjs +334 -0
  54. package/dist/packem_shared/jsDocumentCommentsToOpenApi-eOlxMuMO.mjs +328 -0
  55. package/dist/packem_shared/parseFile-BJwu_na4.cjs +42 -0
  56. package/dist/packem_shared/parseFile-Bxis7tbW.mjs +35 -0
  57. package/dist/packem_shared/swaggerJsDocumentCommentsToOpenApi-Cb5s1J29.mjs +130 -0
  58. package/dist/packem_shared/swaggerJsDocumentCommentsToOpenApi-JFymRz50.cjs +137 -0
  59. package/dist/packem_shared/validate-DZHaKH07.mjs +30 -0
  60. package/dist/packem_shared/validate-FKieC3ln.cjs +37 -0
  61. package/dist/packem_shared/yamlLoc-BLoIYoXs.cjs +14 -0
  62. package/dist/packem_shared/yamlLoc-Cmx4vbRt.mjs +12 -0
  63. package/dist/parse-file.d.cts +9 -0
  64. package/dist/parse-file.d.mts +9 -0
  65. package/dist/parse-file.d.ts +9 -0
  66. package/dist/spec-builder.d.cts +14 -0
  67. package/dist/spec-builder.d.mts +14 -0
  68. package/dist/spec-builder.d.ts +14 -0
  69. package/dist/swagger-jsdoc/comments-to-open-api.d.cts +6 -0
  70. package/dist/swagger-jsdoc/comments-to-open-api.d.mts +6 -0
  71. package/dist/swagger-jsdoc/comments-to-open-api.d.ts +6 -0
  72. package/dist/swagger-jsdoc/organize-swagger-object.d.cts +7 -0
  73. package/dist/swagger-jsdoc/organize-swagger-object.d.mts +7 -0
  74. package/dist/swagger-jsdoc/organize-swagger-object.d.ts +7 -0
  75. package/dist/swagger-jsdoc/utils.d.cts +21 -0
  76. package/dist/swagger-jsdoc/utils.d.mts +21 -0
  77. package/dist/swagger-jsdoc/utils.d.ts +21 -0
  78. package/dist/util/customizer.d.cts +2 -0
  79. package/dist/util/customizer.d.mts +2 -0
  80. package/dist/util/customizer.d.ts +2 -0
  81. package/dist/util/object-merge.d.cts +2 -0
  82. package/dist/util/object-merge.d.mts +2 -0
  83. package/dist/util/object-merge.d.ts +2 -0
  84. package/dist/util/yaml-loc.d.cts +2 -0
  85. package/dist/util/yaml-loc.d.mts +2 -0
  86. package/dist/util/yaml-loc.d.ts +2 -0
  87. package/dist/validate.d.cts +2 -0
  88. package/dist/validate.d.mts +2 -0
  89. package/dist/validate.d.ts +2 -0
  90. package/dist/webpack/swagger-compiler-plugin.d.cts +15 -0
  91. package/dist/webpack/swagger-compiler-plugin.d.mts +15 -0
  92. package/dist/webpack/swagger-compiler-plugin.d.ts +15 -0
  93. package/package.json +33 -20
  94. package/dist/chunk-2T6HMUIL.mjs +0 -1215
  95. package/dist/chunk-2T6HMUIL.mjs.map +0 -1
  96. package/dist/chunk-PTFTJY7I.js +0 -1233
  97. package/dist/chunk-PTFTJY7I.js.map +0 -1
  98. package/dist/chunk-RGP6RTJO.mjs +0 -142
  99. package/dist/chunk-RGP6RTJO.mjs.map +0 -1
  100. package/dist/chunk-RVCK3H3U.js +0 -149
  101. package/dist/chunk-RVCK3H3U.js.map +0 -1
  102. package/dist/cli/commander/index.js +0 -33
  103. package/dist/cli/commander/index.js.map +0 -1
  104. package/dist/cli/commander/index.mjs.map +0 -1
  105. package/dist/cli/index.js +0 -17
  106. package/dist/cli/index.js.map +0 -1
  107. package/dist/cli/index.mjs.map +0 -1
  108. package/dist/index.js +0 -106
  109. package/dist/index.js.map +0 -1
  110. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,328 @@
1
+ import { parse } from 'comment-parser';
2
+ import mergeWith from 'lodash.mergewith';
3
+ import { c as customizer } from './customizer-CoMXMU7a.mjs';
4
+
5
+ const fixSecurityObject = (thing) => {
6
+ if (thing.security) {
7
+ thing.security = Object.keys(thing.security).map((s) => {
8
+ return {
9
+ [s]: thing.security[s]
10
+ };
11
+ });
12
+ }
13
+ };
14
+ const primitiveTypes = /* @__PURE__ */ new Set(["array", "boolean", "integer", "number", "object", "string"]);
15
+ const formatMap = {
16
+ binary: "string",
17
+ byte: "string",
18
+ date: "string",
19
+ "date-time": "string",
20
+ double: "number",
21
+ float: "number",
22
+ int32: "integer",
23
+ int64: "integer",
24
+ password: "string"
25
+ };
26
+ const parseDescription = (tag) => {
27
+ const rawType = tag.type;
28
+ const isArray = rawType.endsWith("[]");
29
+ const parsedType = rawType.replace(/\[]$/, "");
30
+ const isPrimitive = primitiveTypes.has(parsedType);
31
+ const isFormat = Object.keys(formatMap).includes(parsedType);
32
+ let defaultValue;
33
+ if (tag.default) {
34
+ switch (parsedType) {
35
+ case "double":
36
+ case "float":
37
+ case "number": {
38
+ defaultValue = Number.parseFloat(tag.default);
39
+ break;
40
+ }
41
+ case "int32":
42
+ case "int64":
43
+ case "integer": {
44
+ defaultValue = Number.parseInt(tag.default, 10);
45
+ break;
46
+ }
47
+ default: {
48
+ defaultValue = tag.default;
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ let rootType;
54
+ if (isPrimitive) {
55
+ rootType = { default: defaultValue, type: parsedType };
56
+ } else if (isFormat) {
57
+ rootType = {
58
+ default: defaultValue,
59
+ format: parsedType,
60
+ type: formatMap[parsedType]
61
+ };
62
+ } else {
63
+ rootType = { $ref: `#/components/schemas/${parsedType}` };
64
+ }
65
+ let schema = isArray ? {
66
+ items: {
67
+ ...rootType
68
+ },
69
+ type: "array"
70
+ } : {
71
+ ...rootType
72
+ };
73
+ if (parsedType === "") {
74
+ schema = void 0;
75
+ }
76
+ let description = tag.description.trim().replace(/^- /u, "");
77
+ if (description === "") {
78
+ description = void 0;
79
+ }
80
+ return {
81
+ description,
82
+ name: tag.name,
83
+ rawType,
84
+ required: !tag.optional,
85
+ schema
86
+ };
87
+ };
88
+ const tagsToObjects = (tags, verbose) => tags.map((tag) => {
89
+ const parsedResponse = parseDescription(tag);
90
+ let nameAndDescription = "";
91
+ if (parsedResponse.name) {
92
+ nameAndDescription += parsedResponse.name;
93
+ }
94
+ if (parsedResponse.description) {
95
+ nameAndDescription += ` ${parsedResponse.description.trim()}`;
96
+ }
97
+ switch (tag.tag) {
98
+ case "bodyComponent": {
99
+ return {
100
+ requestBody: {
101
+ $ref: `#/components/requestBodies/${parsedResponse.rawType}`
102
+ }
103
+ };
104
+ }
105
+ case "bodyContent": {
106
+ return {
107
+ requestBody: {
108
+ content: {
109
+ [parsedResponse.name.replace(String.raw`*\/*`, "*/*")]: {
110
+ schema: parsedResponse.schema
111
+ }
112
+ }
113
+ }
114
+ };
115
+ }
116
+ case "bodyDescription": {
117
+ return { requestBody: { description: nameAndDescription } };
118
+ }
119
+ case "bodyExample": {
120
+ const [contentType, example] = parsedResponse.name.split(".");
121
+ return {
122
+ requestBody: {
123
+ content: {
124
+ [contentType]: {
125
+ examples: {
126
+ [example]: {
127
+ $ref: `#/components/examples/${parsedResponse.rawType}`
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ };
134
+ }
135
+ case "bodyRequired": {
136
+ return { requestBody: { required: true } };
137
+ }
138
+ case "callback": {
139
+ return {
140
+ callbacks: {
141
+ [parsedResponse.name]: {
142
+ $ref: `#/components/callbacks/${parsedResponse.rawType}`
143
+ }
144
+ }
145
+ };
146
+ }
147
+ case "cookieParam":
148
+ case "headerParam":
149
+ case "pathParam":
150
+ case "queryParam": {
151
+ return {
152
+ parameters: [
153
+ {
154
+ description: parsedResponse.description,
155
+ in: tag.tag.replace(/Param$/u, ""),
156
+ name: parsedResponse.name,
157
+ required: parsedResponse.required,
158
+ schema: parsedResponse.schema
159
+ }
160
+ ]
161
+ };
162
+ }
163
+ case "deprecated": {
164
+ return { deprecated: true };
165
+ }
166
+ case "description":
167
+ case "operationId":
168
+ case "summary": {
169
+ return { [tag.tag]: nameAndDescription };
170
+ }
171
+ case "externalDocs": {
172
+ return {
173
+ externalDocs: {
174
+ description: parsedResponse.description,
175
+ url: parsedResponse.name
176
+ }
177
+ };
178
+ }
179
+ case "paramComponent": {
180
+ return {
181
+ parameters: [{ $ref: `#/components/parameters/${parsedResponse.rawType}` }]
182
+ };
183
+ }
184
+ case "response": {
185
+ return {
186
+ responses: {
187
+ [parsedResponse.name]: {
188
+ description: parsedResponse.description
189
+ }
190
+ }
191
+ };
192
+ }
193
+ case "responseComponent": {
194
+ return {
195
+ responses: {
196
+ [parsedResponse.name]: {
197
+ $ref: `#/components/responses/${parsedResponse.rawType}`
198
+ }
199
+ }
200
+ };
201
+ }
202
+ case "responseContent": {
203
+ const [status, contentType] = parsedResponse.name.split(".");
204
+ return {
205
+ responses: {
206
+ [status]: {
207
+ content: {
208
+ [contentType]: {
209
+ schema: parsedResponse.schema
210
+ }
211
+ }
212
+ }
213
+ }
214
+ };
215
+ }
216
+ case "responseExample": {
217
+ const [status, contentType, example] = parsedResponse.name.split(".");
218
+ return {
219
+ responses: {
220
+ [status]: {
221
+ content: {
222
+ [contentType]: {
223
+ examples: {
224
+ [example]: {
225
+ $ref: `#/components/examples/${parsedResponse.rawType}`
226
+ }
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ };
233
+ }
234
+ case "responseHeader": {
235
+ const [status, header] = parsedResponse.name.split(".");
236
+ return {
237
+ responses: {
238
+ [status]: {
239
+ headers: {
240
+ [header]: {
241
+ description: parsedResponse.description,
242
+ schema: parsedResponse.schema
243
+ }
244
+ }
245
+ }
246
+ }
247
+ };
248
+ }
249
+ case "responseHeaderComponent": {
250
+ const [status, header] = parsedResponse.name.split(".");
251
+ return {
252
+ responses: {
253
+ [status]: {
254
+ headers: {
255
+ [header]: {
256
+ $ref: `#/components/headers/${parsedResponse.rawType}`
257
+ }
258
+ }
259
+ }
260
+ }
261
+ };
262
+ }
263
+ case "responseLink": {
264
+ const [status, link] = parsedResponse.name.split(".");
265
+ return {
266
+ responses: {
267
+ [status]: {
268
+ links: {
269
+ [link]: {
270
+ $ref: `#/components/links/${parsedResponse.rawType}`
271
+ }
272
+ }
273
+ }
274
+ }
275
+ };
276
+ }
277
+ case "security": {
278
+ const [security, scopeItem] = parsedResponse.name.split(".");
279
+ let scope = [];
280
+ if (scopeItem) {
281
+ scope = [scopeItem];
282
+ }
283
+ return {
284
+ security: { [security]: scope }
285
+ };
286
+ }
287
+ case "server": {
288
+ return {
289
+ servers: [
290
+ {
291
+ description: parsedResponse.description,
292
+ url: parsedResponse.name
293
+ }
294
+ ]
295
+ };
296
+ }
297
+ case "tag": {
298
+ return { tags: [nameAndDescription] };
299
+ }
300
+ default: {
301
+ return {};
302
+ }
303
+ }
304
+ });
305
+ const commentsToOpenApi = (fileContents, verbose) => {
306
+ const openAPIRegex = /^(GET|PUT|POST|DELETE|OPTIONS|HEAD|PATCH|TRACE) \/.*$/;
307
+ const jsDocumentComments = parse(fileContents, { spacing: "preserve" });
308
+ return jsDocumentComments.filter((comment) => openAPIRegex.test(comment.description.trim())).map((comment) => {
309
+ const loc = comment.tags.length + 1;
310
+ const result = mergeWith({}, ...tagsToObjects(comment.tags), customizer);
311
+ fixSecurityObject(result);
312
+ const [method, path] = comment.description.split(" ");
313
+ const pathsObject = {
314
+ [path.trim()]: {
315
+ [method.toLowerCase().trim()]: {
316
+ ...result
317
+ }
318
+ }
319
+ };
320
+ const spec = JSON.parse(JSON.stringify({ paths: pathsObject }));
321
+ return {
322
+ loc,
323
+ spec
324
+ };
325
+ });
326
+ };
327
+
328
+ export { commentsToOpenApi as default };
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ const node_fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const yaml = require('yaml');
6
+ const yamlLoc = require('./yamlLoc-BLoIYoXs.cjs');
7
+
8
+ const _interopDefaultCompat = e => e && typeof e === 'object' && 'default' in e ? e.default : e;
9
+
10
+ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
11
+ const yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
12
+
13
+ const ALLOWED_KEYS = /* @__PURE__ */ new Set(["components", "externalDocs", "info", "openapi", "paths", "security", "servers", "tags"]);
14
+ class ParseError extends Error {
15
+ filePath;
16
+ }
17
+ const parseFile = (file, commentsToOpenApi, verbose) => {
18
+ const fileContent = node_fs.readFileSync(file, { encoding: "utf8" });
19
+ const extension = path__default.extname(file);
20
+ if (extension === ".yaml" || extension === ".yml") {
21
+ const spec = yaml__default.parse(fileContent);
22
+ const invalidKeys = Object.keys(spec).filter((key) => !ALLOWED_KEYS.has(key));
23
+ if (invalidKeys.length > 0) {
24
+ const error = new ParseError(`Unexpected keys: ${invalidKeys.join(", ")}`);
25
+ error.filePath = file;
26
+ throw error;
27
+ }
28
+ if (Object.keys(spec).some((key) => ALLOWED_KEYS.has(key))) {
29
+ const loc = yamlLoc(fileContent);
30
+ return [{ loc, spec }];
31
+ }
32
+ return [];
33
+ }
34
+ try {
35
+ return commentsToOpenApi(fileContent, verbose);
36
+ } catch (error) {
37
+ error.filePath = file;
38
+ throw error;
39
+ }
40
+ };
41
+
42
+ module.exports = parseFile;
@@ -0,0 +1,35 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import yaml from 'yaml';
4
+ import yamlLoc from './yamlLoc-Cmx4vbRt.mjs';
5
+
6
+ const ALLOWED_KEYS = /* @__PURE__ */ new Set(["components", "externalDocs", "info", "openapi", "paths", "security", "servers", "tags"]);
7
+ class ParseError extends Error {
8
+ filePath;
9
+ }
10
+ const parseFile = (file, commentsToOpenApi, verbose) => {
11
+ const fileContent = readFileSync(file, { encoding: "utf8" });
12
+ const extension = path.extname(file);
13
+ if (extension === ".yaml" || extension === ".yml") {
14
+ const spec = yaml.parse(fileContent);
15
+ const invalidKeys = Object.keys(spec).filter((key) => !ALLOWED_KEYS.has(key));
16
+ if (invalidKeys.length > 0) {
17
+ const error = new ParseError(`Unexpected keys: ${invalidKeys.join(", ")}`);
18
+ error.filePath = file;
19
+ throw error;
20
+ }
21
+ if (Object.keys(spec).some((key) => ALLOWED_KEYS.has(key))) {
22
+ const loc = yamlLoc(fileContent);
23
+ return [{ loc, spec }];
24
+ }
25
+ return [];
26
+ }
27
+ try {
28
+ return commentsToOpenApi(fileContent, verbose);
29
+ } catch (error) {
30
+ error.filePath = file;
31
+ throw error;
32
+ }
33
+ };
34
+
35
+ export { parseFile as default };
@@ -0,0 +1,130 @@
1
+ import { parse } from 'comment-parser';
2
+ import mergeWith from 'lodash.mergewith';
3
+ import yaml from 'yaml';
4
+ import { c as customizer } from './customizer-CoMXMU7a.mjs';
5
+
6
+ const mergeDeep = (first, second) => mergeWith({}, first, second, (a, b) => b === null ? a : void 0);
7
+ const hasEmptyProperty = (object) => Object.keys(object).map((key) => object[key]).every((keyObject) => typeof keyObject === "object" && Object.keys(keyObject).every((key) => !(key in keyObject)));
8
+ const isTagPresentInTags = (tag, tags) => tags.some((targetTag) => tag.name === targetTag.name);
9
+ const getSwaggerVersionFromSpec = (tag) => {
10
+ switch (tag.tag) {
11
+ case "asyncapi": {
12
+ return "v4";
13
+ }
14
+ case "openapi": {
15
+ return "v3";
16
+ }
17
+ case "swagger": {
18
+ return "v2";
19
+ }
20
+ default: {
21
+ return "v2";
22
+ }
23
+ }
24
+ };
25
+
26
+ const organizeSwaggerObject = (swaggerObject, annotation, property) => {
27
+ if (property === "x-webhooks") {
28
+ swaggerObject[property] = annotation[property];
29
+ }
30
+ if (property.startsWith("x-")) {
31
+ return;
32
+ }
33
+ const commonProperties = [
34
+ "components",
35
+ "consumes",
36
+ "produces",
37
+ "paths",
38
+ "schemas",
39
+ "securityDefinitions",
40
+ "responses",
41
+ "parameters",
42
+ "definitions",
43
+ "channels"
44
+ ];
45
+ if (commonProperties.includes(property)) {
46
+ Object.keys(annotation[property]).forEach((definition) => {
47
+ swaggerObject[property][definition] = mergeDeep(swaggerObject[property][definition], annotation[property][definition]);
48
+ });
49
+ } else if (property === "tags") {
50
+ const { tags } = annotation;
51
+ if (Array.isArray(tags)) {
52
+ tags.forEach((tag) => {
53
+ if (!isTagPresentInTags(tag, swaggerObject.tags)) {
54
+ swaggerObject.tags.push(tag);
55
+ }
56
+ });
57
+ } else if (!isTagPresentInTags(tags, swaggerObject.tags)) {
58
+ swaggerObject.tags.push(tags);
59
+ }
60
+ } else if (property === "security") {
61
+ const { security } = annotation;
62
+ swaggerObject.security = security;
63
+ } else if (property.startsWith("/")) {
64
+ swaggerObject.paths[property] = mergeDeep(swaggerObject.paths[property], annotation[property]);
65
+ }
66
+ };
67
+
68
+ const specificationTemplate = {
69
+ v2: ["paths", "definitions", "responses", "parameters", "securityDefinitions"],
70
+ v3: ["paths", "definitions", "responses", "parameters", "securityDefinitions", "components"],
71
+ v4: ["components", "channels"]
72
+ };
73
+ const tagsToObjects = (specs, verbose) => specs.map((spec) => {
74
+ const hasContent = spec.description !== "" || spec.name !== void 0 && (spec.name.startsWith("/") || spec.name.endsWith(":"));
75
+ if ((spec.tag === "openapi" || spec.tag === "swagger" || spec.tag === "asyncapi") && hasContent) {
76
+ let yamlContent = spec.description;
77
+ if (spec.name !== void 0 && (spec.name.startsWith("/") || spec.name.endsWith(":"))) {
78
+ yamlContent = yamlContent.trim() === "" ? spec.name : `${spec.name}
79
+ ${yamlContent}`;
80
+ }
81
+ const parsed = yaml.parseDocument(yamlContent);
82
+ if (parsed.errors.length > 0) {
83
+ parsed.errors.map((error) => {
84
+ const newError = error;
85
+ newError.annotation = yamlContent;
86
+ return newError;
87
+ });
88
+ let errorString = "Error parsing YAML in @openapi spec:";
89
+ errorString += verbose ? parsed.errors.map(
90
+ (error) => `${error.toString()}
91
+ Imbedded within:
92
+ \`\`\`
93
+ ${error.annotation?.replaceAll("\n", "\n ")}
94
+ \`\`\``
95
+ ).join("\n") : parsed.errors.map((error) => error.toString()).join("\n");
96
+ throw new Error(errorString);
97
+ }
98
+ const parsedDocument = parsed.toJSON();
99
+ const specification = {
100
+ tags: []
101
+ };
102
+ specificationTemplate[getSwaggerVersionFromSpec(spec)].forEach((property) => {
103
+ specification[property] = specification[property] || {};
104
+ });
105
+ Object.keys(parsedDocument).forEach((property) => {
106
+ organizeSwaggerObject(specification, parsedDocument, property);
107
+ });
108
+ return specification;
109
+ }
110
+ return {};
111
+ });
112
+ const commentsToOpenApi = (fileContents, verbose) => {
113
+ const jsDocumentComments = parse(fileContents, { spacing: "preserve" });
114
+ return jsDocumentComments.map((comment) => {
115
+ const loc = comment.tags.length + 1;
116
+ const result = mergeWith({}, ...tagsToObjects(comment.tags, verbose), customizer);
117
+ ["definitions", "responses", "parameters", "securityDefinitions", "components", "tags"].forEach((property) => {
118
+ if (result[property] !== void 0 && hasEmptyProperty(result[property])) {
119
+ delete result[property];
120
+ }
121
+ });
122
+ const spec = JSON.parse(JSON.stringify(result));
123
+ return {
124
+ loc,
125
+ spec
126
+ };
127
+ });
128
+ };
129
+
130
+ export { commentsToOpenApi as default };
@@ -0,0 +1,137 @@
1
+ 'use strict';
2
+
3
+ const commentParser = require('comment-parser');
4
+ const mergeWith = require('lodash.mergewith');
5
+ const yaml = require('yaml');
6
+ const customizer = require('./customizer-DDFwFqJl.cjs');
7
+
8
+ const _interopDefaultCompat = e => e && typeof e === 'object' && 'default' in e ? e.default : e;
9
+
10
+ const mergeWith__default = /*#__PURE__*/_interopDefaultCompat(mergeWith);
11
+ const yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
12
+
13
+ const mergeDeep = (first, second) => mergeWith__default({}, first, second, (a, b) => b === null ? a : void 0);
14
+ const hasEmptyProperty = (object) => Object.keys(object).map((key) => object[key]).every((keyObject) => typeof keyObject === "object" && Object.keys(keyObject).every((key) => !(key in keyObject)));
15
+ const isTagPresentInTags = (tag, tags) => tags.some((targetTag) => tag.name === targetTag.name);
16
+ const getSwaggerVersionFromSpec = (tag) => {
17
+ switch (tag.tag) {
18
+ case "asyncapi": {
19
+ return "v4";
20
+ }
21
+ case "openapi": {
22
+ return "v3";
23
+ }
24
+ case "swagger": {
25
+ return "v2";
26
+ }
27
+ default: {
28
+ return "v2";
29
+ }
30
+ }
31
+ };
32
+
33
+ const organizeSwaggerObject = (swaggerObject, annotation, property) => {
34
+ if (property === "x-webhooks") {
35
+ swaggerObject[property] = annotation[property];
36
+ }
37
+ if (property.startsWith("x-")) {
38
+ return;
39
+ }
40
+ const commonProperties = [
41
+ "components",
42
+ "consumes",
43
+ "produces",
44
+ "paths",
45
+ "schemas",
46
+ "securityDefinitions",
47
+ "responses",
48
+ "parameters",
49
+ "definitions",
50
+ "channels"
51
+ ];
52
+ if (commonProperties.includes(property)) {
53
+ Object.keys(annotation[property]).forEach((definition) => {
54
+ swaggerObject[property][definition] = mergeDeep(swaggerObject[property][definition], annotation[property][definition]);
55
+ });
56
+ } else if (property === "tags") {
57
+ const { tags } = annotation;
58
+ if (Array.isArray(tags)) {
59
+ tags.forEach((tag) => {
60
+ if (!isTagPresentInTags(tag, swaggerObject.tags)) {
61
+ swaggerObject.tags.push(tag);
62
+ }
63
+ });
64
+ } else if (!isTagPresentInTags(tags, swaggerObject.tags)) {
65
+ swaggerObject.tags.push(tags);
66
+ }
67
+ } else if (property === "security") {
68
+ const { security } = annotation;
69
+ swaggerObject.security = security;
70
+ } else if (property.startsWith("/")) {
71
+ swaggerObject.paths[property] = mergeDeep(swaggerObject.paths[property], annotation[property]);
72
+ }
73
+ };
74
+
75
+ const specificationTemplate = {
76
+ v2: ["paths", "definitions", "responses", "parameters", "securityDefinitions"],
77
+ v3: ["paths", "definitions", "responses", "parameters", "securityDefinitions", "components"],
78
+ v4: ["components", "channels"]
79
+ };
80
+ const tagsToObjects = (specs, verbose) => specs.map((spec) => {
81
+ const hasContent = spec.description !== "" || spec.name !== void 0 && (spec.name.startsWith("/") || spec.name.endsWith(":"));
82
+ if ((spec.tag === "openapi" || spec.tag === "swagger" || spec.tag === "asyncapi") && hasContent) {
83
+ let yamlContent = spec.description;
84
+ if (spec.name !== void 0 && (spec.name.startsWith("/") || spec.name.endsWith(":"))) {
85
+ yamlContent = yamlContent.trim() === "" ? spec.name : `${spec.name}
86
+ ${yamlContent}`;
87
+ }
88
+ const parsed = yaml__default.parseDocument(yamlContent);
89
+ if (parsed.errors.length > 0) {
90
+ parsed.errors.map((error) => {
91
+ const newError = error;
92
+ newError.annotation = yamlContent;
93
+ return newError;
94
+ });
95
+ let errorString = "Error parsing YAML in @openapi spec:";
96
+ errorString += verbose ? parsed.errors.map(
97
+ (error) => `${error.toString()}
98
+ Imbedded within:
99
+ \`\`\`
100
+ ${error.annotation?.replaceAll("\n", "\n ")}
101
+ \`\`\``
102
+ ).join("\n") : parsed.errors.map((error) => error.toString()).join("\n");
103
+ throw new Error(errorString);
104
+ }
105
+ const parsedDocument = parsed.toJSON();
106
+ const specification = {
107
+ tags: []
108
+ };
109
+ specificationTemplate[getSwaggerVersionFromSpec(spec)].forEach((property) => {
110
+ specification[property] = specification[property] || {};
111
+ });
112
+ Object.keys(parsedDocument).forEach((property) => {
113
+ organizeSwaggerObject(specification, parsedDocument, property);
114
+ });
115
+ return specification;
116
+ }
117
+ return {};
118
+ });
119
+ const commentsToOpenApi = (fileContents, verbose) => {
120
+ const jsDocumentComments = commentParser.parse(fileContents, { spacing: "preserve" });
121
+ return jsDocumentComments.map((comment) => {
122
+ const loc = comment.tags.length + 1;
123
+ const result = mergeWith__default({}, ...tagsToObjects(comment.tags, verbose), customizer.customizer);
124
+ ["definitions", "responses", "parameters", "securityDefinitions", "components", "tags"].forEach((property) => {
125
+ if (result[property] !== void 0 && hasEmptyProperty(result[property])) {
126
+ delete result[property];
127
+ }
128
+ });
129
+ const spec = JSON.parse(JSON.stringify(result));
130
+ return {
131
+ loc,
132
+ spec
133
+ };
134
+ });
135
+ };
136
+
137
+ module.exports = commentsToOpenApi;
@@ -0,0 +1,30 @@
1
+ import SwaggerParser from '@apidevtools/swagger-parser';
2
+
3
+ const DEFAULT_EXCLUDE = [
4
+ "coverage/**",
5
+ ".github/**",
6
+ "**/*.d.ts",
7
+ "**/test{,s}/**",
8
+ "**/test{,-*}.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}",
9
+ "**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx,yaml,yml}",
10
+ "**/__tests__/**",
11
+ "**/{ava,babel,nyc}.config.{js,cjs,mjs}",
12
+ "**/jest.config.{js,cjs,mjs,ts}",
13
+ "**/{karma,rollup,webpack}.config.js",
14
+ "**/.{eslint,mocha}rc.{js,cjs}",
15
+ "**/.{travis,yarnrc}.yml",
16
+ "**/{docker-compose,docker}.yml",
17
+ "**/.yamllint.{yaml,yml}",
18
+ "**/node_modules/**",
19
+ "**/{pnpm-workspace,pnpm-lock}.yaml",
20
+ "**/{package,package-lock}.json",
21
+ "**/yarn.lock",
22
+ "**/package.json5",
23
+ "**/.next/**"
24
+ ];
25
+
26
+ const validate = async (spec) => {
27
+ await SwaggerParser.validate(spec);
28
+ };
29
+
30
+ export { DEFAULT_EXCLUDE as D, validate as v };