openapi-jsonrpc-jsdoc 1.4.1 → 1.4.2
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/README.md +3 -5
- package/index.mjs +154 -57
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ npm i openapi-jsonrpc-jsdoc
|
|
|
8
8
|
|
|
9
9
|
## Examples
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### Usage Example
|
|
12
12
|
|
|
13
13
|
```js
|
|
14
14
|
// api/api-v1.js
|
|
@@ -28,11 +28,9 @@ module.exports = (parameters) => {
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### Generate OpenAPI JSON
|
|
32
32
|
|
|
33
33
|
```js
|
|
34
|
-
// index.js
|
|
35
|
-
const fs = require('fs');
|
|
36
34
|
const openapiJSONRpcJSDoc = require('openapi-jsonrpc-jsdoc');
|
|
37
35
|
openapiJSONRpcJSDoc({
|
|
38
36
|
api: '/',
|
|
@@ -44,7 +42,7 @@ openapiJSONRpcJSDoc({
|
|
|
44
42
|
packageUrl: './package.json',
|
|
45
43
|
files: './api/*.js',
|
|
46
44
|
}).then(data => {
|
|
47
|
-
|
|
45
|
+
JSON.stringify(data, null, 2);// openapi.json
|
|
48
46
|
});
|
|
49
47
|
```
|
|
50
48
|
|
package/index.mjs
CHANGED
|
@@ -1,5 +1,132 @@
|
|
|
1
1
|
import jsdoc from 'jsdoc-api';
|
|
2
2
|
|
|
3
|
+
function extractName(name) {
|
|
4
|
+
try {
|
|
5
|
+
return name.match(/\.(.+)/i)[1]; //eslint-disable-line
|
|
6
|
+
} catch {
|
|
7
|
+
return name;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function resolveSchemaFromTypeNames(names) {
|
|
12
|
+
let type;
|
|
13
|
+
let format;
|
|
14
|
+
let items;
|
|
15
|
+
let oneOf;
|
|
16
|
+
let nullable;
|
|
17
|
+
let constant;
|
|
18
|
+
let enumData;
|
|
19
|
+
|
|
20
|
+
if (names.length === 0) {
|
|
21
|
+
type = 'null';
|
|
22
|
+
} else if (names.length === 1) {
|
|
23
|
+
[type] = names;
|
|
24
|
+
} else {
|
|
25
|
+
type = 'enum';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
switch (type) {
|
|
29
|
+
case 'Array.<string>': {
|
|
30
|
+
type = 'array';
|
|
31
|
+
items = {type: 'string'};
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
case 'Array.<number>': {
|
|
35
|
+
type = 'array';
|
|
36
|
+
items = {type: 'number'};
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
case 'URL': {
|
|
40
|
+
type = 'string';
|
|
41
|
+
format = 'url';
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
case 'String':
|
|
45
|
+
case 'string': {
|
|
46
|
+
type = 'string';
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case 'Number':
|
|
50
|
+
case 'number': {
|
|
51
|
+
type = 'number';
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'Boolean':
|
|
55
|
+
case 'boolean': {
|
|
56
|
+
type = 'boolean';
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case 'Date': {
|
|
60
|
+
type = 'string';
|
|
61
|
+
format = 'date-time';
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
case 'enum': {
|
|
65
|
+
enumData = names;
|
|
66
|
+
if (enumData.includes('null')) {
|
|
67
|
+
nullable = true;
|
|
68
|
+
enumData = enumData.filter(n => n !== 'null');
|
|
69
|
+
}
|
|
70
|
+
oneOf = enumData.map((n) => {
|
|
71
|
+
if (!Number.isNaN(Number(n))) {
|
|
72
|
+
return Number(n);
|
|
73
|
+
}
|
|
74
|
+
return n;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
if (enumData.every(n => Number.isInteger(Number(n)))) {
|
|
78
|
+
type = 'integer';
|
|
79
|
+
} else if (enumData.every(n => !Number.isNaN(Number(n)))) {
|
|
80
|
+
type = 'number';
|
|
81
|
+
} else if (enumData.every(n => n?.toLowerCase() === 'boolean')) {
|
|
82
|
+
type = 'boolean';
|
|
83
|
+
} else if (enumData.every(n => n?.toLowerCase() === 'number')) {
|
|
84
|
+
type = 'number';
|
|
85
|
+
} else if (enumData.every(n => n?.toLowerCase() === 'string')) {
|
|
86
|
+
type = 'string';
|
|
87
|
+
} else if (enumData.every(n => n?.toLowerCase() === 'date')) {
|
|
88
|
+
type = 'string';
|
|
89
|
+
format = 'date-time';
|
|
90
|
+
} else if (enumData.every(n => n === 'URL')) {
|
|
91
|
+
type = 'string';
|
|
92
|
+
format = 'url';
|
|
93
|
+
} else if (enumData.every(n => n?.toLowerCase() === 'true')) {
|
|
94
|
+
type = 'boolean';
|
|
95
|
+
constant = true;
|
|
96
|
+
} else if (enumData.every(n => n?.toLowerCase() === 'false')) {
|
|
97
|
+
type = 'boolean';
|
|
98
|
+
constant = false;
|
|
99
|
+
} else {
|
|
100
|
+
type = 'string';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (enumData?.length === 1 && oneOf?.length === 1) {
|
|
104
|
+
if (enumData[0] === oneOf[0]) {
|
|
105
|
+
if (!format) {
|
|
106
|
+
[format] = enumData;
|
|
107
|
+
}
|
|
108
|
+
oneOf = undefined;
|
|
109
|
+
enumData = undefined;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
default: {
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
type,
|
|
121
|
+
format,
|
|
122
|
+
oneOf,
|
|
123
|
+
nullable,
|
|
124
|
+
items,
|
|
125
|
+
constant,
|
|
126
|
+
enumData,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
3
130
|
export default async function openapiJsonrpcJsdoc({ files, securitySchemes = {}, packageUrl, servers, api = '/' }) {
|
|
4
131
|
const allData = await jsdoc.explain({
|
|
5
132
|
files: Array.isArray(files) ? files : [files],
|
|
@@ -157,69 +284,31 @@ export default async function openapiJsonrpcJsdoc({ files, securitySchemes = {},
|
|
|
157
284
|
if (parameter.type.names[0] === 'object') {
|
|
158
285
|
return accumulator;
|
|
159
286
|
}
|
|
160
|
-
let type;
|
|
161
|
-
if (parameter.type.names.length === 0) {
|
|
162
|
-
type = 'null';
|
|
163
|
-
} else if (parameter.type.names.length === 1) {
|
|
164
|
-
type = parameter.type.names[0];
|
|
165
|
-
} else {
|
|
166
|
-
type = 'enum';
|
|
167
|
-
}
|
|
168
|
-
let items;
|
|
169
|
-
let enumData;
|
|
170
|
-
let oneOf;
|
|
171
287
|
|
|
172
|
-
switch (type) {
|
|
173
|
-
case 'Array.<string>': {
|
|
174
|
-
type = 'array';
|
|
175
|
-
items = { type: 'string' };
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
case 'Array.<number>': {
|
|
179
|
-
type = 'array';
|
|
180
|
-
items = { type: 'number' };
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
case 'enum': {
|
|
184
|
-
enumData = parameter.type.names;
|
|
185
|
-
oneOf = parameter.type.names.map((n) => {
|
|
186
|
-
if (!Number.isNaN(Number(n))) {
|
|
187
|
-
return Number(n);
|
|
188
|
-
}
|
|
189
|
-
return n;
|
|
190
|
-
});
|
|
191
|
-
if (parameter.type.names.every(n => Number.isInteger(Number(n)))) {
|
|
192
|
-
type = 'integer';
|
|
193
|
-
} else if (parameter.type.names.every(n => !Number.isNaN(Number(n)))) {
|
|
194
|
-
type = 'number';
|
|
195
|
-
} else {
|
|
196
|
-
type = 'string';
|
|
197
|
-
}
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
default: {
|
|
201
|
-
break;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
288
|
const description = parameter.description;
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
289
|
+
const name = extractName(parameter.name);
|
|
290
|
+
accumulator.properties[name] = accumulator.properties[name] ?? {};
|
|
291
|
+
|
|
292
|
+
const {
|
|
293
|
+
items,
|
|
294
|
+
constant,
|
|
295
|
+
enumData,
|
|
296
|
+
type,
|
|
297
|
+
format,
|
|
298
|
+
oneOf,
|
|
299
|
+
nullable,
|
|
300
|
+
} = resolveSchemaFromTypeNames(parameter.type.names)
|
|
211
301
|
if (!parameter.optional) {
|
|
212
302
|
accumulator.required.push(name);
|
|
213
303
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
accumulator.properties[name].type = type;
|
|
304
|
+
if (nullable) {
|
|
305
|
+
accumulator.properties[name].nullable = nullable;
|
|
217
306
|
}
|
|
218
|
-
if (
|
|
219
|
-
accumulator.properties[name].
|
|
307
|
+
if (constant) {
|
|
308
|
+
accumulator.properties[name].const = constant;
|
|
220
309
|
}
|
|
221
|
-
if (
|
|
222
|
-
accumulator.properties[name].
|
|
310
|
+
if (format) {
|
|
311
|
+
accumulator.properties[name].format = format;
|
|
223
312
|
}
|
|
224
313
|
if (enumData) {
|
|
225
314
|
accumulator.properties[name].enum = enumData;
|
|
@@ -227,7 +316,15 @@ export default async function openapiJsonrpcJsdoc({ files, securitySchemes = {},
|
|
|
227
316
|
if (oneOf) {
|
|
228
317
|
accumulator.properties[name].oneOf = oneOf;
|
|
229
318
|
}
|
|
230
|
-
|
|
319
|
+
if (type) {
|
|
320
|
+
accumulator.properties[name].type = type;
|
|
321
|
+
}
|
|
322
|
+
if (description) {
|
|
323
|
+
accumulator.properties[name].description = description;
|
|
324
|
+
}
|
|
325
|
+
if (items) {
|
|
326
|
+
accumulator.properties[name].items = items;
|
|
327
|
+
}
|
|
231
328
|
return accumulator;
|
|
232
329
|
},
|
|
233
330
|
{
|