openapi-jsonrpc-jsdoc 1.4.3 → 1.5.1
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 +51 -95
- package/index.mjs +67 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,15 +17,19 @@ npm i openapi-jsonrpc-jsdoc
|
|
|
17
17
|
* @description Название API
|
|
18
18
|
* @param {object} parameters - params
|
|
19
19
|
* @param {string} parameters.id - id
|
|
20
|
+
* @param {string} [parameters.test] - test
|
|
21
|
+
* @param {string[]} parameters.array - array
|
|
22
|
+
* @param {1|2} parameters.num - enum
|
|
23
|
+
* @tags api
|
|
20
24
|
* @example
|
|
21
25
|
* {
|
|
22
|
-
* "
|
|
23
|
-
* "type": "Note"
|
|
26
|
+
* "id": "https://www.w3.org/ns/activitystreams"
|
|
24
27
|
* }
|
|
25
28
|
*/
|
|
26
29
|
module.exports = (parameters) => {
|
|
27
|
-
|
|
28
|
-
}
|
|
30
|
+
return parameters.id;
|
|
31
|
+
};
|
|
32
|
+
|
|
29
33
|
```
|
|
30
34
|
|
|
31
35
|
### Generate OpenAPI JSON
|
|
@@ -39,6 +43,9 @@ openapiJSONRpcJSDoc({
|
|
|
39
43
|
url: '0.0.0.0:8080',
|
|
40
44
|
},
|
|
41
45
|
],
|
|
46
|
+
info: {
|
|
47
|
+
title: 'Test API',
|
|
48
|
+
},
|
|
42
49
|
packageUrl: './package.json',
|
|
43
50
|
files: './api/*.js',
|
|
44
51
|
}).then(data => {
|
|
@@ -51,22 +58,16 @@ openapiJSONRpcJSDoc({
|
|
|
51
58
|
|
|
52
59
|
```json
|
|
53
60
|
{
|
|
54
|
-
"x-send-defaults": true,
|
|
55
61
|
"openapi": "3.1.0",
|
|
56
|
-
"x-api-id": "json-rpc-example",
|
|
57
|
-
"x-headers": [],
|
|
58
|
-
"x-explorer-enabled": true,
|
|
59
|
-
"x-proxy-enabled": true,
|
|
60
62
|
"x-samples-enabled": true,
|
|
61
63
|
"x-samples-languages": [
|
|
62
|
-
"curl",
|
|
63
64
|
"node",
|
|
64
65
|
"javascript"
|
|
65
66
|
],
|
|
66
67
|
"info": {
|
|
67
|
-
"version": "1.
|
|
68
|
-
"title": "
|
|
69
|
-
"description": "OpenAPI
|
|
68
|
+
"version": "1.4.3",
|
|
69
|
+
"title": "Test API",
|
|
70
|
+
"description": "Transform JSDoc-annotated JSON-RPC 2.0 methods into OpenAPI specifications."
|
|
70
71
|
},
|
|
71
72
|
"servers": [
|
|
72
73
|
{
|
|
@@ -81,7 +82,7 @@ openapiJSONRpcJSDoc({
|
|
|
81
82
|
"summary": "/v1",
|
|
82
83
|
"description": "Название API",
|
|
83
84
|
"tags": [
|
|
84
|
-
"
|
|
85
|
+
"api"
|
|
85
86
|
],
|
|
86
87
|
"parameters": [],
|
|
87
88
|
"responses": {
|
|
@@ -107,32 +108,31 @@ openapiJSONRpcJSDoc({
|
|
|
107
108
|
}
|
|
108
109
|
},
|
|
109
110
|
"requestBody": {
|
|
111
|
+
"required": true,
|
|
110
112
|
"content": {
|
|
111
113
|
"application/json": {
|
|
112
114
|
"schema": {
|
|
113
115
|
"type": "object",
|
|
114
116
|
"required": [
|
|
115
117
|
"method",
|
|
116
|
-
"
|
|
117
|
-
"jsonrpc",
|
|
118
|
-
"params"
|
|
118
|
+
"jsonrpc"
|
|
119
119
|
],
|
|
120
120
|
"properties": {
|
|
121
121
|
"method": {
|
|
122
122
|
"type": "string",
|
|
123
|
-
"default": "v1",
|
|
124
123
|
"description": "API method v1"
|
|
125
124
|
},
|
|
126
125
|
"id": {
|
|
127
|
-
"type":
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
"type": [
|
|
127
|
+
"string",
|
|
128
|
+
"integer"
|
|
129
|
+
],
|
|
130
130
|
"description": "Request ID"
|
|
131
131
|
},
|
|
132
132
|
"jsonrpc": {
|
|
133
133
|
"type": "string",
|
|
134
134
|
"default": "2.0",
|
|
135
|
-
"description": "JSON-RPC
|
|
135
|
+
"description": "JSON-RPC 2.0 protocol"
|
|
136
136
|
},
|
|
137
137
|
"params": {
|
|
138
138
|
"title": "Parameters",
|
|
@@ -142,15 +142,33 @@ openapiJSONRpcJSDoc({
|
|
|
142
142
|
"type": "Note"
|
|
143
143
|
},
|
|
144
144
|
"required": [
|
|
145
|
-
"method",
|
|
146
145
|
"id",
|
|
147
|
-
"
|
|
148
|
-
"
|
|
146
|
+
"array",
|
|
147
|
+
"num"
|
|
149
148
|
],
|
|
150
149
|
"properties": {
|
|
151
150
|
"id": {
|
|
152
151
|
"type": "string",
|
|
153
152
|
"description": "id"
|
|
153
|
+
},
|
|
154
|
+
"test": {
|
|
155
|
+
"type": "string",
|
|
156
|
+
"description": "test"
|
|
157
|
+
},
|
|
158
|
+
"array": {
|
|
159
|
+
"type": "array",
|
|
160
|
+
"description": "array",
|
|
161
|
+
"items": {
|
|
162
|
+
"type": "string"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"num": {
|
|
166
|
+
"enum": [
|
|
167
|
+
1,
|
|
168
|
+
2
|
|
169
|
+
],
|
|
170
|
+
"type": "integer",
|
|
171
|
+
"description": "enum"
|
|
154
172
|
}
|
|
155
173
|
}
|
|
156
174
|
}
|
|
@@ -160,83 +178,18 @@ openapiJSONRpcJSDoc({
|
|
|
160
178
|
}
|
|
161
179
|
}
|
|
162
180
|
}
|
|
163
|
-
},
|
|
164
|
-
"/api/v2": {
|
|
165
|
-
"post": {
|
|
166
|
-
"operationId": "v2.js",
|
|
167
|
-
"deprecated": true,
|
|
168
|
-
"summary": "/v2",
|
|
169
|
-
"description": "Название API 2",
|
|
170
|
-
"tags": [
|
|
171
|
-
"JSONRPC"
|
|
172
|
-
],
|
|
173
|
-
"parameters": [],
|
|
174
|
-
"responses": {
|
|
175
|
-
"200": {
|
|
176
|
-
"description": "OK",
|
|
177
|
-
"content": {
|
|
178
|
-
"application/json": {
|
|
179
|
-
"schema": {
|
|
180
|
-
"type": "object"
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
},
|
|
185
|
-
"default": {
|
|
186
|
-
"description": "unexpected error",
|
|
187
|
-
"content": {
|
|
188
|
-
"application/json": {
|
|
189
|
-
"schema": {
|
|
190
|
-
"$ref": "#/components/schemas/Error"
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
},
|
|
196
|
-
"requestBody": {
|
|
197
|
-
"content": {
|
|
198
|
-
"application/json": {
|
|
199
|
-
"schema": {
|
|
200
|
-
"type": "object",
|
|
201
|
-
"required": [
|
|
202
|
-
"method",
|
|
203
|
-
"id",
|
|
204
|
-
"jsonrpc"
|
|
205
|
-
],
|
|
206
|
-
"properties": {
|
|
207
|
-
"method": {
|
|
208
|
-
"type": "string",
|
|
209
|
-
"default": "v2",
|
|
210
|
-
"description": "API method v2"
|
|
211
|
-
},
|
|
212
|
-
"id": {
|
|
213
|
-
"type": "integer",
|
|
214
|
-
"default": 1,
|
|
215
|
-
"format": "int32",
|
|
216
|
-
"description": "Request ID"
|
|
217
|
-
},
|
|
218
|
-
"jsonrpc": {
|
|
219
|
-
"type": "string",
|
|
220
|
-
"default": "2.0",
|
|
221
|
-
"description": "JSON-RPC Version (2.0)"
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
181
|
}
|
|
230
182
|
},
|
|
231
183
|
"components": {
|
|
232
184
|
"securitySchemes": {
|
|
233
185
|
"BasicAuth": {
|
|
234
186
|
"type": "http",
|
|
235
|
-
"scheme": "
|
|
187
|
+
"scheme": "basic"
|
|
236
188
|
}
|
|
237
189
|
},
|
|
238
190
|
"schemas": {
|
|
239
191
|
"Error": {
|
|
192
|
+
"type": "object",
|
|
240
193
|
"required": [
|
|
241
194
|
"error",
|
|
242
195
|
"id",
|
|
@@ -244,14 +197,17 @@ openapiJSONRpcJSDoc({
|
|
|
244
197
|
],
|
|
245
198
|
"properties": {
|
|
246
199
|
"id": {
|
|
247
|
-
"type":
|
|
248
|
-
|
|
200
|
+
"type": [
|
|
201
|
+
"string",
|
|
202
|
+
"integer"
|
|
203
|
+
]
|
|
249
204
|
},
|
|
250
205
|
"error": {
|
|
251
206
|
"type": "object"
|
|
252
207
|
},
|
|
253
208
|
"jsonrpc": {
|
|
254
|
-
"type": "string"
|
|
209
|
+
"type": "string",
|
|
210
|
+
"default": "2.0"
|
|
255
211
|
}
|
|
256
212
|
}
|
|
257
213
|
}
|
package/index.mjs
CHANGED
|
@@ -20,6 +20,15 @@ function extractTypeName(names = []) {
|
|
|
20
20
|
return typeName;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
function isBigInt64(n) {
|
|
24
|
+
try {
|
|
25
|
+
const b = BigInt(n);
|
|
26
|
+
return b >= -9223372036854775808n && b <= 9223372036854775807n;
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
function resolveSchemaFromTypeNames(names) {
|
|
24
33
|
let type;
|
|
25
34
|
let format;
|
|
@@ -73,20 +82,29 @@ function resolveSchemaFromTypeNames(names) {
|
|
|
73
82
|
enumData = enumData.map((n) => {
|
|
74
83
|
if (!Number.isNaN(Number(n))) {
|
|
75
84
|
return Number(n);
|
|
85
|
+
} else if (isBigInt64(n)) {
|
|
86
|
+
return n;
|
|
76
87
|
}
|
|
77
|
-
return n;
|
|
88
|
+
return String(n);
|
|
78
89
|
});
|
|
79
90
|
|
|
80
|
-
if (enumData.every(n => Number.
|
|
91
|
+
if (enumData.every(n => Number.isSafeInteger(n))) {
|
|
81
92
|
type = 'integer';
|
|
93
|
+
} else if (enumData.every(n => Number.isInteger(n))) {
|
|
94
|
+
type = 'number';
|
|
95
|
+
format = 'float';
|
|
96
|
+
} else if (enumData.every(n => typeof n === 'number' && n === Math.fround(n))) {
|
|
97
|
+
type = 'number';
|
|
98
|
+
format = 'double';
|
|
99
|
+
} else if (enumData.every(n => isBigInt64(n))) {
|
|
100
|
+
type = 'integer';
|
|
101
|
+
format = 'int64';
|
|
82
102
|
} else if (enumData.every(n => !Number.isNaN(Number(n)))) {
|
|
83
103
|
type = 'number';
|
|
84
104
|
} else if (enumData.every(n => n?.toLowerCase() === 'boolean')) {
|
|
85
105
|
type = 'boolean';
|
|
86
106
|
} else if (enumData.every(n => n?.toLowerCase() === 'number')) {
|
|
87
107
|
type = 'number';
|
|
88
|
-
} else if (enumData.every(n => n?.toLowerCase() === 'string')) {
|
|
89
|
-
type = 'string';
|
|
90
108
|
} else if (enumData.every(n => n?.toLowerCase() === 'date')) {
|
|
91
109
|
type = 'string';
|
|
92
110
|
format = 'date-time';
|
|
@@ -99,8 +117,13 @@ function resolveSchemaFromTypeNames(names) {
|
|
|
99
117
|
} else if (enumData.every(n => n?.toLowerCase() === 'false')) {
|
|
100
118
|
type = 'boolean';
|
|
101
119
|
constant = false;
|
|
102
|
-
} else {
|
|
120
|
+
} else if (enumData.every(n => typeof n === 'string')) {
|
|
103
121
|
type = 'string';
|
|
122
|
+
} else if (enumData.length === 1) {
|
|
123
|
+
type = enumData[0];
|
|
124
|
+
constant = true;
|
|
125
|
+
} else {
|
|
126
|
+
type = undefined;
|
|
104
127
|
}
|
|
105
128
|
|
|
106
129
|
if (enumData?.length === 1) {
|
|
@@ -108,6 +131,8 @@ function resolveSchemaFromTypeNames(names) {
|
|
|
108
131
|
[format] = enumData;
|
|
109
132
|
}
|
|
110
133
|
enumData = undefined;
|
|
134
|
+
} else if (nullable) {
|
|
135
|
+
enumData.push(null);
|
|
111
136
|
}
|
|
112
137
|
break;
|
|
113
138
|
}
|
|
@@ -128,44 +153,58 @@ function resolveSchemaFromTypeNames(names) {
|
|
|
128
153
|
|
|
129
154
|
export default async function openapiJsonrpcJsdoc({
|
|
130
155
|
openapi = '3.1.0',
|
|
156
|
+
encoding = 'utf8',
|
|
157
|
+
access = 'public',
|
|
131
158
|
files,
|
|
159
|
+
info = {},
|
|
132
160
|
securitySchemes = {},
|
|
133
161
|
packageUrl,
|
|
134
162
|
servers,
|
|
135
163
|
api = '/',
|
|
164
|
+
samples = ['node', 'javascript'],
|
|
165
|
+
...xHeaders
|
|
136
166
|
}) {
|
|
137
|
-
const
|
|
167
|
+
const options = {
|
|
168
|
+
access,
|
|
169
|
+
encoding,
|
|
170
|
+
samples,
|
|
138
171
|
files: Array.isArray(files) ? files : [files],
|
|
139
|
-
package: packageUrl,
|
|
140
|
-
access: 'public',
|
|
141
|
-
encoding: 'utf8',
|
|
142
172
|
undocumented: false,
|
|
143
173
|
allowUnknownTags: true,
|
|
144
174
|
dictionaries: ['jsdoc'],
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
175
|
+
};
|
|
176
|
+
if (info.title) {
|
|
177
|
+
options.cache = true;
|
|
178
|
+
} else {
|
|
179
|
+
options.package = packageUrl;
|
|
180
|
+
}
|
|
181
|
+
let documents;
|
|
182
|
+
if (options.cache) {
|
|
183
|
+
documents = await jsdoc.explain(options);
|
|
184
|
+
} else {
|
|
185
|
+
const allData = await jsdoc.explain(options);
|
|
186
|
+
documents = allData.filter(item => item.kind !== 'package');
|
|
187
|
+
const package_ = allData.find(item => item.kind === 'package');
|
|
188
|
+
info.version = package_.version;
|
|
189
|
+
info.title = package_.name;
|
|
190
|
+
info.description = package_.description;
|
|
191
|
+
}
|
|
192
|
+
if (!info.title) {
|
|
193
|
+
throw new Error('API title is required. Please set packageUrl or info object.');
|
|
194
|
+
}
|
|
149
195
|
const temporaryDocument = {
|
|
150
196
|
'openapi': openapi,
|
|
151
|
-
'x-
|
|
152
|
-
'x-
|
|
153
|
-
|
|
154
|
-
'
|
|
155
|
-
'x-proxy-enabled': true,
|
|
156
|
-
'x-samples-enabled': true,
|
|
157
|
-
'x-samples-languages': ['node', 'javascript'],
|
|
158
|
-
'info': {
|
|
159
|
-
version: package_.version,
|
|
160
|
-
title: package_.name,
|
|
161
|
-
description: package_.description,
|
|
162
|
-
},
|
|
197
|
+
'x-samples-enabled': samples.length > 0,
|
|
198
|
+
'x-samples-languages': samples,
|
|
199
|
+
...xHeaders,
|
|
200
|
+
'info': info,
|
|
163
201
|
'servers': servers,
|
|
164
202
|
'paths': {},
|
|
165
203
|
'components': {
|
|
166
204
|
securitySchemes,
|
|
167
205
|
schemas: {
|
|
168
206
|
Error: {
|
|
207
|
+
type: 'object',
|
|
169
208
|
required: [
|
|
170
209
|
'error',
|
|
171
210
|
'id',
|
|
@@ -173,14 +212,14 @@ export default async function openapiJsonrpcJsdoc({
|
|
|
173
212
|
],
|
|
174
213
|
properties: {
|
|
175
214
|
id: {
|
|
176
|
-
type: 'integer',
|
|
177
|
-
format: 'int32',
|
|
215
|
+
type: ['string', 'integer'],
|
|
178
216
|
},
|
|
179
217
|
error: {
|
|
180
218
|
type: 'object',
|
|
181
219
|
},
|
|
182
220
|
jsonrpc: {
|
|
183
221
|
type: 'string',
|
|
222
|
+
default: '2.0',
|
|
184
223
|
},
|
|
185
224
|
},
|
|
186
225
|
},
|
|
@@ -249,11 +288,10 @@ export default async function openapiJsonrpcJsdoc({
|
|
|
249
288
|
properties: {
|
|
250
289
|
method: {
|
|
251
290
|
type: 'string',
|
|
252
|
-
default: apiName,
|
|
253
291
|
description: `API method ${apiName}`,
|
|
254
292
|
},
|
|
255
293
|
id: {
|
|
256
|
-
type: ['string'],
|
|
294
|
+
type: ['string', 'integer'],
|
|
257
295
|
description: 'Request ID',
|
|
258
296
|
},
|
|
259
297
|
jsonrpc: {
|