@gyeonghokim/bruno-to-openapi 0.0.0 → 1.0.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/.github/workflows/release.yml +5 -2
- package/.github/workflows/test.yml +37 -0
- package/.releaserc.json +3 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/models/bruno-collection.d.ts +35 -0
- package/dist/models/bruno-collection.d.ts.map +1 -0
- package/dist/models/bruno-collection.js +56 -0
- package/dist/services/conversion-service.d.ts +17 -0
- package/dist/services/conversion-service.d.ts.map +1 -0
- package/dist/services/conversion-service.js +18 -0
- package/dist/types/bruno.d.ts +267 -0
- package/dist/types/bruno.d.ts.map +1 -0
- package/dist/types/bruno.js +4 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/openapi.d.ts +251 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +4 -0
- package/dist/types/result.d.ts +26 -0
- package/dist/types/result.d.ts.map +1 -0
- package/dist/types/result.js +4 -0
- package/dist/utils/bruno-parser.d.ts +51 -0
- package/dist/utils/bruno-parser.d.ts.map +1 -0
- package/dist/utils/bruno-parser.js +391 -0
- package/dist/utils/file-reader.d.ts +34 -0
- package/dist/utils/file-reader.d.ts.map +1 -0
- package/dist/utils/file-reader.js +104 -0
- package/dist/utils/openapi-generator.d.ts +53 -0
- package/dist/utils/openapi-generator.d.ts.map +1 -0
- package/dist/utils/openapi-generator.js +524 -0
- package/package.json +14 -1
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for generating OpenAPI specifications
|
|
3
|
+
*/
|
|
4
|
+
export class OpenApiGenerator {
|
|
5
|
+
/**
|
|
6
|
+
* Generates an OpenAPI specification from a Bruno collection
|
|
7
|
+
*/
|
|
8
|
+
static generateOpenApiSpec(collection) {
|
|
9
|
+
const warnings = [];
|
|
10
|
+
const info = {
|
|
11
|
+
title: collection.name || 'Bruno Collection',
|
|
12
|
+
version: collection.brunoConfig &&
|
|
13
|
+
typeof collection.brunoConfig === 'object' &&
|
|
14
|
+
'version' in collection.brunoConfig
|
|
15
|
+
? String(collection.brunoConfig.version) || '1.0.0'
|
|
16
|
+
: '1.0.0',
|
|
17
|
+
description: collection.brunoConfig &&
|
|
18
|
+
typeof collection.brunoConfig === 'object' &&
|
|
19
|
+
'description' in collection.brunoConfig
|
|
20
|
+
? String(collection.brunoConfig.description) ||
|
|
21
|
+
`OpenAPI specification generated from Bruno collection: ${collection.name}`
|
|
22
|
+
: `OpenAPI specification generated from Bruno collection: ${collection.name}`,
|
|
23
|
+
};
|
|
24
|
+
const paths = {};
|
|
25
|
+
// Process collection items to build paths
|
|
26
|
+
OpenApiGenerator.processCollectionItems(collection.items, paths, warnings);
|
|
27
|
+
const openApiSpec = {
|
|
28
|
+
openapi: '3.0.0',
|
|
29
|
+
info,
|
|
30
|
+
paths,
|
|
31
|
+
};
|
|
32
|
+
// Add servers if base URL is defined in collection
|
|
33
|
+
if (collection.brunoConfig &&
|
|
34
|
+
typeof collection.brunoConfig === 'object' &&
|
|
35
|
+
'baseUrl' in collection.brunoConfig) {
|
|
36
|
+
const baseUrl = collection.brunoConfig.baseUrl;
|
|
37
|
+
if (typeof baseUrl === 'string' && baseUrl) {
|
|
38
|
+
openApiSpec.servers = [
|
|
39
|
+
{
|
|
40
|
+
url: baseUrl,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
spec: openApiSpec,
|
|
47
|
+
warnings,
|
|
48
|
+
content: JSON.stringify(openApiSpec, null, 2), // Optional JSON content
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Processes collection items to build OpenAPI paths
|
|
53
|
+
*/
|
|
54
|
+
static processCollectionItems(items, paths, warnings) {
|
|
55
|
+
for (const item of items) {
|
|
56
|
+
if (item.type === 'folder') {
|
|
57
|
+
// Process folder items recursively
|
|
58
|
+
if (item.items && item.items.length > 0) {
|
|
59
|
+
OpenApiGenerator.processCollectionItems(item.items, paths, warnings);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else if (item.type === 'http-request' && item.request) {
|
|
63
|
+
OpenApiGenerator.processHttpRequest(item, paths, warnings);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Processes an HTTP request item to add to OpenAPI paths
|
|
69
|
+
*/
|
|
70
|
+
static processHttpRequest(item, paths, warnings) {
|
|
71
|
+
const request = item.request;
|
|
72
|
+
if (!(request?.method && request.url)) {
|
|
73
|
+
warnings.push({
|
|
74
|
+
message: `Skipping item '${item.name}' - missing method or URL`,
|
|
75
|
+
itemName: item.name,
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Normalize the URL to extract path
|
|
80
|
+
let normalizedPath = request.url || '';
|
|
81
|
+
// Remove the base URL part if it exists
|
|
82
|
+
if (request.url?.includes('://')) {
|
|
83
|
+
try {
|
|
84
|
+
const urlObj = new URL(request.url);
|
|
85
|
+
normalizedPath = urlObj.pathname + urlObj.search;
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
// If URL parsing fails, use the original URL
|
|
89
|
+
warnings.push({
|
|
90
|
+
message: `Could not parse URL for item '${item.name}': ${request.url}`,
|
|
91
|
+
itemName: item.name,
|
|
92
|
+
});
|
|
93
|
+
// Fallback to using the original URL as the path
|
|
94
|
+
normalizedPath = request.url;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Ensure path starts with /
|
|
98
|
+
if (!normalizedPath.startsWith('/')) {
|
|
99
|
+
normalizedPath = `/${normalizedPath}`;
|
|
100
|
+
}
|
|
101
|
+
// Initialize the path object if it doesn't exist
|
|
102
|
+
if (!paths[normalizedPath]) {
|
|
103
|
+
paths[normalizedPath] = {};
|
|
104
|
+
}
|
|
105
|
+
// Create operation based on the request
|
|
106
|
+
const operation = OpenApiGenerator.createOperationFromRequest(item, request);
|
|
107
|
+
// Add the operation to the appropriate method in the path
|
|
108
|
+
const pathObject = paths[normalizedPath];
|
|
109
|
+
if (pathObject) {
|
|
110
|
+
switch (request.method?.toUpperCase()) {
|
|
111
|
+
case 'GET':
|
|
112
|
+
pathObject.get = operation;
|
|
113
|
+
break;
|
|
114
|
+
case 'POST':
|
|
115
|
+
pathObject.post = operation;
|
|
116
|
+
break;
|
|
117
|
+
case 'PUT':
|
|
118
|
+
pathObject.put = operation;
|
|
119
|
+
break;
|
|
120
|
+
case 'DELETE':
|
|
121
|
+
pathObject.delete = operation;
|
|
122
|
+
break;
|
|
123
|
+
case 'PATCH':
|
|
124
|
+
pathObject.patch = operation;
|
|
125
|
+
break;
|
|
126
|
+
case 'HEAD':
|
|
127
|
+
pathObject.head = operation;
|
|
128
|
+
break;
|
|
129
|
+
case 'OPTIONS':
|
|
130
|
+
pathObject.options = operation;
|
|
131
|
+
break;
|
|
132
|
+
case 'TRACE':
|
|
133
|
+
pathObject.trace = operation;
|
|
134
|
+
break;
|
|
135
|
+
default:
|
|
136
|
+
warnings.push({
|
|
137
|
+
message: `Unsupported HTTP method '${request.method}' for item '${item.name}'`,
|
|
138
|
+
itemName: item.name,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Creates an OpenAPI operation from a Bruno request
|
|
145
|
+
*/
|
|
146
|
+
static createOperationFromRequest(item, request) {
|
|
147
|
+
const operation = {
|
|
148
|
+
summary: item.name,
|
|
149
|
+
description: request?.docs || `Operation for ${item.name}`,
|
|
150
|
+
responses: OpenApiGenerator.createDefaultResponses(),
|
|
151
|
+
};
|
|
152
|
+
// Add tags if available in Bruno config
|
|
153
|
+
if (request?.tags && Array.isArray(request.tags)) {
|
|
154
|
+
operation.tags = request.tags;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
// Default to using the folder path as tags
|
|
158
|
+
if (item.pathname) {
|
|
159
|
+
const folderPath = item.pathname.substring(0, item.pathname.lastIndexOf('/'));
|
|
160
|
+
if (folderPath) {
|
|
161
|
+
operation.tags = [folderPath.split('/').pop() || 'default'];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Add parameters from Bruno request
|
|
166
|
+
if (request?.params && request.params.length > 0) {
|
|
167
|
+
const pathParams = request.params.filter(param => param.enabled !== false && param.type === 'path');
|
|
168
|
+
const queryParams = request.params.filter(param => param.enabled !== false && param.type === 'query');
|
|
169
|
+
if (pathParams.length > 0) {
|
|
170
|
+
const pathParamObjs = OpenApiGenerator.createParametersFromBrunoParams(pathParams);
|
|
171
|
+
operation.parameters = [...(operation.parameters || []), ...pathParamObjs];
|
|
172
|
+
}
|
|
173
|
+
if (queryParams.length > 0) {
|
|
174
|
+
const queryParamObjs = OpenApiGenerator.createParametersFromBrunoParams(queryParams);
|
|
175
|
+
operation.parameters = [...(operation.parameters || []), ...queryParamObjs];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Add headers as parameters if needed
|
|
179
|
+
if (request?.headers && request.headers.length > 0) {
|
|
180
|
+
const headerParams = OpenApiGenerator.createParametersFromBrunoHeaders(request.headers);
|
|
181
|
+
if (headerParams.length > 0) {
|
|
182
|
+
operation.parameters = [...(operation.parameters || []), ...headerParams];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Add request body if present
|
|
186
|
+
if (request?.body) {
|
|
187
|
+
operation.requestBody = OpenApiGenerator.createRequestBodyFromBrunoBody(request.body);
|
|
188
|
+
}
|
|
189
|
+
// Add authentication information to operation if needed
|
|
190
|
+
if (request?.auth) {
|
|
191
|
+
operation.security = OpenApiGenerator.createSecurityRequirementsFromAuth(request.auth);
|
|
192
|
+
}
|
|
193
|
+
return operation;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Creates OpenAPI parameters from Bruno parameters
|
|
197
|
+
*/
|
|
198
|
+
static createParametersFromBrunoParams(brunoParams) {
|
|
199
|
+
return brunoParams
|
|
200
|
+
.filter(param => param.enabled !== false) // Only enabled params
|
|
201
|
+
.map(param => {
|
|
202
|
+
// Determine if parameter is required based on Bruno param content
|
|
203
|
+
const isRequired = param.value !== undefined && param.value !== '';
|
|
204
|
+
const paramObj = {
|
|
205
|
+
name: param.name || '',
|
|
206
|
+
in: param.type || 'query', // Use the Bruno param's type or default to query
|
|
207
|
+
required: isRequired,
|
|
208
|
+
schema: {
|
|
209
|
+
type: 'string',
|
|
210
|
+
example: param.value || undefined,
|
|
211
|
+
},
|
|
212
|
+
description: param.name || '',
|
|
213
|
+
};
|
|
214
|
+
return paramObj;
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Creates OpenAPI header parameters from Bruno headers
|
|
219
|
+
*/
|
|
220
|
+
static createParametersFromBrunoHeaders(brunoHeaders) {
|
|
221
|
+
return brunoHeaders
|
|
222
|
+
.filter(header => header.enabled !== false) // Only enabled headers
|
|
223
|
+
.map(header => {
|
|
224
|
+
const isRequired = header.value !== undefined && header.value !== '';
|
|
225
|
+
return {
|
|
226
|
+
name: header.name || '',
|
|
227
|
+
in: 'header',
|
|
228
|
+
required: isRequired,
|
|
229
|
+
schema: {
|
|
230
|
+
type: 'string',
|
|
231
|
+
example: header.value || undefined,
|
|
232
|
+
},
|
|
233
|
+
description: header.name || '',
|
|
234
|
+
};
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Creates security requirements from Bruno auth configuration
|
|
239
|
+
*/
|
|
240
|
+
static createSecurityRequirementsFromAuth(brunoAuth) {
|
|
241
|
+
if (brunoAuth.mode === 'none') {
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
const securityRequirements = [];
|
|
245
|
+
switch (brunoAuth.mode) {
|
|
246
|
+
case 'bearer':
|
|
247
|
+
securityRequirements.push({
|
|
248
|
+
bearerAuth: [],
|
|
249
|
+
});
|
|
250
|
+
break;
|
|
251
|
+
case 'basic':
|
|
252
|
+
securityRequirements.push({
|
|
253
|
+
basicAuth: [],
|
|
254
|
+
});
|
|
255
|
+
break;
|
|
256
|
+
case 'oauth2':
|
|
257
|
+
securityRequirements.push({
|
|
258
|
+
oauth2: [],
|
|
259
|
+
});
|
|
260
|
+
break;
|
|
261
|
+
case 'apikey':
|
|
262
|
+
securityRequirements.push({
|
|
263
|
+
apiKey: [],
|
|
264
|
+
});
|
|
265
|
+
break;
|
|
266
|
+
default:
|
|
267
|
+
// For other auth types, we create a generic security requirement
|
|
268
|
+
securityRequirements.push({
|
|
269
|
+
[`${brunoAuth.mode}Auth`]: [],
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
return securityRequirements;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Creates an OpenAPI request body from Bruno body
|
|
276
|
+
*/
|
|
277
|
+
static createRequestBodyFromBrunoBody(brunoBody) {
|
|
278
|
+
if (!brunoBody.mode) {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
const requestBody = {
|
|
282
|
+
content: {},
|
|
283
|
+
};
|
|
284
|
+
switch (brunoBody.mode) {
|
|
285
|
+
case 'json':
|
|
286
|
+
if (brunoBody.json) {
|
|
287
|
+
try {
|
|
288
|
+
// Attempt to parse JSON to create a proper schema
|
|
289
|
+
const parsedJson = JSON.parse(brunoBody.json);
|
|
290
|
+
const schema = OpenApiGenerator.inferSchemaFromValue(parsedJson);
|
|
291
|
+
requestBody.content['application/json'] = {
|
|
292
|
+
schema,
|
|
293
|
+
example: parsedJson,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
// If JSON parsing fails, use string schema
|
|
298
|
+
requestBody.content['application/json'] = {
|
|
299
|
+
schema: { type: 'string' },
|
|
300
|
+
example: brunoBody.json,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
// If no JSON content provided, use an empty object schema as default
|
|
306
|
+
requestBody.content['application/json'] = {
|
|
307
|
+
schema: { type: 'object', properties: {} },
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
break;
|
|
311
|
+
case 'xml':
|
|
312
|
+
if (brunoBody.xml) {
|
|
313
|
+
requestBody.content['application/xml'] = {
|
|
314
|
+
schema: { type: 'string' },
|
|
315
|
+
example: brunoBody.xml,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
break;
|
|
319
|
+
case 'formUrlEncoded':
|
|
320
|
+
if (brunoBody.formUrlEncoded && brunoBody.formUrlEncoded.length > 0) {
|
|
321
|
+
const schema = {
|
|
322
|
+
type: 'object',
|
|
323
|
+
properties: {},
|
|
324
|
+
};
|
|
325
|
+
for (const param of brunoBody.formUrlEncoded) {
|
|
326
|
+
const paramName = param.name || 'defaultParam';
|
|
327
|
+
schema.properties[paramName] =
|
|
328
|
+
{
|
|
329
|
+
type: 'string',
|
|
330
|
+
example: param.value || undefined,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
requestBody.content['application/x-www-form-urlencoded'] = {
|
|
334
|
+
schema,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
// Default to empty object if no form parameters
|
|
339
|
+
requestBody.content['application/x-www-form-urlencoded'] = {
|
|
340
|
+
schema: {
|
|
341
|
+
type: 'object',
|
|
342
|
+
properties: {},
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
break;
|
|
347
|
+
case 'multipartForm':
|
|
348
|
+
if (brunoBody.multipartForm && brunoBody.multipartForm.length > 0) {
|
|
349
|
+
const schema = {
|
|
350
|
+
type: 'object',
|
|
351
|
+
properties: {},
|
|
352
|
+
};
|
|
353
|
+
for (const param of brunoBody.multipartForm) {
|
|
354
|
+
const paramName = param.name || 'defaultParam';
|
|
355
|
+
schema.properties[paramName] =
|
|
356
|
+
{
|
|
357
|
+
type: param.type === 'file' ? 'string' : 'string',
|
|
358
|
+
format: param.type === 'file' ? 'binary' : undefined,
|
|
359
|
+
example: param.value || undefined,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
requestBody.content['multipart/form-data'] = {
|
|
363
|
+
schema,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
// Default to empty object if no multipart form parameters
|
|
368
|
+
requestBody.content['multipart/form-data'] = {
|
|
369
|
+
schema: {
|
|
370
|
+
type: 'object',
|
|
371
|
+
properties: {},
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
break;
|
|
376
|
+
case 'text':
|
|
377
|
+
if (brunoBody.text) {
|
|
378
|
+
requestBody.content['text/plain'] = {
|
|
379
|
+
schema: { type: 'string' },
|
|
380
|
+
example: brunoBody.text,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
requestBody.content['text/plain'] = {
|
|
385
|
+
schema: { type: 'string' },
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
break;
|
|
389
|
+
default:
|
|
390
|
+
// For unknown modes, add a generic application/json content type
|
|
391
|
+
requestBody.content['application/json'] = {
|
|
392
|
+
schema: { type: 'object' },
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
return requestBody;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Infers a schema from JSON content
|
|
399
|
+
*/
|
|
400
|
+
static inferSchemaFromJson(jsonStr) {
|
|
401
|
+
try {
|
|
402
|
+
const parsed = JSON.parse(jsonStr);
|
|
403
|
+
return OpenApiGenerator.inferSchemaFromValue(parsed);
|
|
404
|
+
}
|
|
405
|
+
catch (e) {
|
|
406
|
+
// If JSON parsing fails, return a generic string schema
|
|
407
|
+
return { type: 'string', description: 'Could not parse JSON content, treating as string' };
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Infers a schema from a JavaScript value
|
|
412
|
+
*/
|
|
413
|
+
static inferSchemaFromValue(value) {
|
|
414
|
+
const schema = {
|
|
415
|
+
type: typeof value,
|
|
416
|
+
};
|
|
417
|
+
if (value === null) {
|
|
418
|
+
schema.type = 'null';
|
|
419
|
+
return schema;
|
|
420
|
+
}
|
|
421
|
+
if (Array.isArray(value)) {
|
|
422
|
+
schema.type = 'array';
|
|
423
|
+
if (value.length > 0) {
|
|
424
|
+
// Use the first element to infer item schema
|
|
425
|
+
schema.items = OpenApiGenerator.inferSchemaFromValue(value[0]);
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
// For empty arrays, provide a generic item schema
|
|
429
|
+
schema.items = { type: 'object' };
|
|
430
|
+
}
|
|
431
|
+
return schema;
|
|
432
|
+
}
|
|
433
|
+
if (typeof value === 'object' && value !== null) {
|
|
434
|
+
schema.type = 'object';
|
|
435
|
+
schema.properties = {};
|
|
436
|
+
// Use for...of to avoid forEach and non-null assertion
|
|
437
|
+
for (const [key, propertyValue] of Object.entries(value)) {
|
|
438
|
+
const propertySchema = OpenApiGenerator.inferSchemaFromValue(propertyValue);
|
|
439
|
+
if (schema.properties) {
|
|
440
|
+
schema.properties[key] = propertySchema;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return schema;
|
|
444
|
+
}
|
|
445
|
+
// For primitive types, just return the basic schema
|
|
446
|
+
return schema;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Creates default responses for an operation
|
|
450
|
+
*/
|
|
451
|
+
static createDefaultResponses() {
|
|
452
|
+
const responses = {};
|
|
453
|
+
// Add a default 200 OK response
|
|
454
|
+
responses['200'] = {
|
|
455
|
+
description: 'Successful response',
|
|
456
|
+
content: {
|
|
457
|
+
'application/json': {
|
|
458
|
+
schema: {
|
|
459
|
+
type: 'object',
|
|
460
|
+
description: 'Default response schema',
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
// Add 400 Bad Request response
|
|
466
|
+
responses['400'] = {
|
|
467
|
+
description: 'Bad Request - The request was invalid',
|
|
468
|
+
content: {
|
|
469
|
+
'application/json': {
|
|
470
|
+
schema: {
|
|
471
|
+
type: 'object',
|
|
472
|
+
properties: {
|
|
473
|
+
error: { type: 'string', description: 'Error message' },
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
};
|
|
479
|
+
// Add 401 Unauthorized response
|
|
480
|
+
responses['401'] = {
|
|
481
|
+
description: 'Unauthorized - Authentication required',
|
|
482
|
+
content: {
|
|
483
|
+
'application/json': {
|
|
484
|
+
schema: {
|
|
485
|
+
type: 'object',
|
|
486
|
+
properties: {
|
|
487
|
+
error: { type: 'string', description: 'Error message' },
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
};
|
|
493
|
+
// Add 404 Not Found response
|
|
494
|
+
responses['404'] = {
|
|
495
|
+
description: 'Not Found - The requested resource does not exist',
|
|
496
|
+
content: {
|
|
497
|
+
'application/json': {
|
|
498
|
+
schema: {
|
|
499
|
+
type: 'object',
|
|
500
|
+
properties: {
|
|
501
|
+
error: { type: 'string', description: 'Error message' },
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
};
|
|
507
|
+
// Add 500 Internal Server Error response
|
|
508
|
+
responses['500'] = {
|
|
509
|
+
description: 'Internal Server Error',
|
|
510
|
+
content: {
|
|
511
|
+
'application/json': {
|
|
512
|
+
schema: {
|
|
513
|
+
type: 'object',
|
|
514
|
+
properties: {
|
|
515
|
+
error: { type: 'string', description: 'Error message' },
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
};
|
|
521
|
+
return responses;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
//# sourceMappingURL=openapi-generator.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gyeonghokim/bruno-to-openapi",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"description": "Convert Bruno API collections to OpenAPI 3.0 specification",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -12,6 +12,15 @@
|
|
|
12
12
|
"types": "./dist/index.d.ts"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"registry": "https://registry.npmjs.org/",
|
|
17
|
+
"tag": "latest",
|
|
18
|
+
"provenance": true
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/GyeongHoKim/bruno2openapi.git"
|
|
23
|
+
},
|
|
15
24
|
"scripts": {
|
|
16
25
|
"build": "tsc",
|
|
17
26
|
"test": "vitest run",
|
|
@@ -36,7 +45,11 @@
|
|
|
36
45
|
"devDependencies": {
|
|
37
46
|
"@apidevtools/swagger-parser": "^12.1.0",
|
|
38
47
|
"@biomejs/biome": "^1.0.0",
|
|
48
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
49
|
+
"@semantic-release/npm": "^13.1.3",
|
|
50
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
39
51
|
"@types/node": "^18.0.0",
|
|
52
|
+
"semantic-release": "^25.0.2",
|
|
40
53
|
"typescript": "^5.9.3",
|
|
41
54
|
"vitest": "^1.0.0"
|
|
42
55
|
},
|