@scalar/postman-to-openapi 0.5.3 → 0.6.0
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 +6 -0
- package/dist/convert.d.ts +29 -1
- package/dist/convert.d.ts.map +1 -1
- package/dist/convert.js +183 -51
- package/dist/helpers/generate-unique-value.d.ts +23 -0
- package/dist/helpers/generate-unique-value.d.ts.map +1 -0
- package/dist/helpers/generate-unique-value.js +29 -0
- package/dist/helpers/get-operation-examples.d.ts +40 -0
- package/dist/helpers/get-operation-examples.d.ts.map +1 -0
- package/dist/helpers/get-operation-examples.js +76 -0
- package/dist/helpers/merge-operation.d.ts +55 -0
- package/dist/helpers/merge-operation.d.ts.map +1 -0
- package/dist/helpers/merge-operation.js +125 -0
- package/dist/helpers/merge-path-item.d.ts +5 -0
- package/dist/helpers/merge-path-item.d.ts.map +1 -0
- package/dist/helpers/merge-path-item.js +37 -0
- package/dist/helpers/parameters.d.ts +2 -2
- package/dist/helpers/parameters.d.ts.map +1 -1
- package/dist/helpers/parameters.js +11 -6
- package/dist/helpers/path-items.d.ts +1 -1
- package/dist/helpers/path-items.d.ts.map +1 -1
- package/dist/helpers/path-items.js +6 -5
- package/dist/helpers/rename-operation-example.d.ts +40 -0
- package/dist/helpers/rename-operation-example.d.ts.map +1 -0
- package/dist/helpers/rename-operation-example.js +61 -0
- package/dist/helpers/request-body.d.ts +1 -1
- package/dist/helpers/request-body.d.ts.map +1 -1
- package/dist/helpers/request-body.js +23 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
package/dist/convert.d.ts
CHANGED
|
@@ -1,9 +1,37 @@
|
|
|
1
1
|
import type { OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
2
2
|
import type { PostmanCollection } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Indices from the collection root into nested `item` arrays.
|
|
5
|
+
* Example: `[0, 2, 1]` → `collection.item[0].item[2].item[1]`.
|
|
6
|
+
*/
|
|
7
|
+
export type PostmanRequestIndexPath = readonly number[];
|
|
8
|
+
export type ConvertOptions = {
|
|
9
|
+
/**
|
|
10
|
+
* Whether to merge operations with the same path and method.
|
|
11
|
+
* If true, the operations will be merged into a single operation.
|
|
12
|
+
* If false, the operations will be kept as separate operations.
|
|
13
|
+
* Default is true.
|
|
14
|
+
*/
|
|
15
|
+
mergeOperation?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* When set, only items at these paths are converted. Each path is a list of
|
|
18
|
+
* zero-based indices from `collection.item` through nested `item` arrays.
|
|
19
|
+
* The last index may point to a request or a folder; folders include every
|
|
20
|
+
* descendant request. Paths out of range or through non-folders are skipped.
|
|
21
|
+
* When omitted, the whole collection is converted (existing behavior).
|
|
22
|
+
*/
|
|
23
|
+
requestIndexPaths?: readonly PostmanRequestIndexPath[];
|
|
24
|
+
/**
|
|
25
|
+
* Existing OpenAPI document to merge into. The input is is updated with Postman paths,
|
|
26
|
+
* tags (union by name), security schemes, and servers.
|
|
27
|
+
* Root `info` and existing paths are preserved unless Postman adds or merges operations.
|
|
28
|
+
*/
|
|
29
|
+
document?: OpenAPIV3_1.Document;
|
|
30
|
+
};
|
|
3
31
|
/**
|
|
4
32
|
* Converts a Postman Collection to an OpenAPI 3.1.0 document.
|
|
5
33
|
* This function processes the collection's information, servers, authentication,
|
|
6
34
|
* and items to create a corresponding OpenAPI structure.
|
|
7
35
|
*/
|
|
8
|
-
export declare function convert(postmanCollection: PostmanCollection | string): OpenAPIV3_1.Document;
|
|
36
|
+
export declare function convert(postmanCollection: PostmanCollection | string, options?: ConvertOptions): OpenAPIV3_1.Document;
|
|
9
37
|
//# sourceMappingURL=convert.d.ts.map
|
package/dist/convert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAaxD,OAAO,KAAK,EAAgC,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAE9E;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,SAAS,MAAM,EAAE,CAAA;AA4SvD,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,SAAS,uBAAuB,EAAE,CAAA;IACtD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAA;CAChC,CAAA;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,iBAAiB,EAAE,iBAAiB,GAAG,MAAM,EAC7C,OAAO,GAAE,cAA0C,GAClD,WAAW,CAAC,QAAQ,CAwLtB"}
|
package/dist/convert.js
CHANGED
|
@@ -3,20 +3,11 @@ import { processContact } from './helpers/contact.js';
|
|
|
3
3
|
import { processExternalDocs } from './helpers/external-docs.js';
|
|
4
4
|
import { processLicense } from './helpers/license.js';
|
|
5
5
|
import { processLogo } from './helpers/logo.js';
|
|
6
|
+
import { DEFAULT_EXAMPLE_NAME, OPERATION_KEYS, mergePathItem } from './helpers/merge-path-item.js';
|
|
6
7
|
import { processItem } from './helpers/path-items.js';
|
|
7
8
|
import { pruneDocument } from './helpers/prune-document.js';
|
|
8
9
|
import { analyzeServerDistribution } from './helpers/servers.js';
|
|
9
10
|
import { normalizePath } from './helpers/urls.js';
|
|
10
|
-
const OPERATION_KEYS = [
|
|
11
|
-
'get',
|
|
12
|
-
'put',
|
|
13
|
-
'post',
|
|
14
|
-
'delete',
|
|
15
|
-
'options',
|
|
16
|
-
'head',
|
|
17
|
-
'patch',
|
|
18
|
-
'trace',
|
|
19
|
-
];
|
|
20
11
|
const normalizeDescription = (description) => {
|
|
21
12
|
if (typeof description === 'string') {
|
|
22
13
|
return description;
|
|
@@ -87,6 +78,95 @@ const extractTags = (items) => {
|
|
|
87
78
|
};
|
|
88
79
|
return items.flatMap((item) => collectTags(item));
|
|
89
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Folder tags for ancestors of each selected path only (same shape as {@link extractTags}).
|
|
83
|
+
*/
|
|
84
|
+
const extractTagsForSelectedPaths = (items, paths) => {
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
const result = [];
|
|
87
|
+
for (const path of paths) {
|
|
88
|
+
if (path.length === 0) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
let list = items;
|
|
92
|
+
let parentPath = '';
|
|
93
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
94
|
+
const idx = path[i];
|
|
95
|
+
if (idx === undefined || idx < 0 || idx >= list.length) {
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
const node = list[idx];
|
|
99
|
+
if (node === undefined || !isItemGroup(node)) {
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
const nextPath = node.name ? (parentPath ? `${parentPath} > ${node.name}` : node.name) : parentPath;
|
|
103
|
+
const description = normalizeDescription(node.description);
|
|
104
|
+
if (node.name?.length && !seen.has(nextPath)) {
|
|
105
|
+
seen.add(nextPath);
|
|
106
|
+
result.push({
|
|
107
|
+
name: nextPath,
|
|
108
|
+
...(description && { description }),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
parentPath = nextPath;
|
|
112
|
+
list = node.item;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
};
|
|
117
|
+
const getNodeAtPath = (items, path) => {
|
|
118
|
+
if (path.length === 0) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
let list = items;
|
|
122
|
+
let node;
|
|
123
|
+
for (let i = 0; i < path.length; i++) {
|
|
124
|
+
const idx = path[i];
|
|
125
|
+
if (idx === undefined || idx < 0 || idx >= list.length) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
node = list[idx];
|
|
129
|
+
if (node === undefined) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
if (i < path.length - 1) {
|
|
133
|
+
if (!isItemGroup(node)) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
list = node.item;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return node;
|
|
140
|
+
};
|
|
141
|
+
const collectParentTagSegments = (items, path) => {
|
|
142
|
+
const segments = [];
|
|
143
|
+
if (path.length <= 1) {
|
|
144
|
+
return segments;
|
|
145
|
+
}
|
|
146
|
+
let list = items;
|
|
147
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
148
|
+
const idx = path[i];
|
|
149
|
+
if (idx === undefined || idx < 0 || idx >= list.length) {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
const node = list[idx];
|
|
153
|
+
if (node === undefined || !isItemGroup(node)) {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
if (node.name) {
|
|
157
|
+
segments.push(node.name);
|
|
158
|
+
}
|
|
159
|
+
list = node.item;
|
|
160
|
+
}
|
|
161
|
+
return segments;
|
|
162
|
+
};
|
|
163
|
+
const dedupeIndexPaths = (paths) => {
|
|
164
|
+
const map = new Map();
|
|
165
|
+
for (const path of paths) {
|
|
166
|
+
map.set(JSON.stringify([...path]), path);
|
|
167
|
+
}
|
|
168
|
+
return [...map.values()];
|
|
169
|
+
};
|
|
90
170
|
const mergeSecuritySchemes = (openapi, securitySchemes) => {
|
|
91
171
|
if (!securitySchemes || Object.keys(securitySchemes).length === 0) {
|
|
92
172
|
return;
|
|
@@ -97,20 +177,40 @@ const mergeSecuritySchemes = (openapi, securitySchemes) => {
|
|
|
97
177
|
...securitySchemes,
|
|
98
178
|
};
|
|
99
179
|
};
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
180
|
+
const mergeServerLists = (existing, incoming) => {
|
|
181
|
+
const seen = new Set((existing ?? []).map((s) => s.url));
|
|
182
|
+
const out = [...(existing ?? [])];
|
|
183
|
+
for (const server of incoming) {
|
|
184
|
+
if (!seen.has(server.url)) {
|
|
185
|
+
seen.add(server.url);
|
|
186
|
+
out.push(server);
|
|
105
187
|
}
|
|
106
|
-
const isOperationKey = OPERATION_KEYS.includes(key);
|
|
107
|
-
if (isOperationKey && targetPath[key]) {
|
|
108
|
-
const operationName = typeof key === 'string' ? key.toUpperCase() : String(key);
|
|
109
|
-
console.warn(`Duplicate operation detected for ${operationName} ${normalizedPathKey}. Last operation will overwrite previous.`);
|
|
110
|
-
}
|
|
111
|
-
targetPath[key] = value;
|
|
112
188
|
}
|
|
113
|
-
|
|
189
|
+
return out;
|
|
190
|
+
};
|
|
191
|
+
const mergeTagsIntoDocument = (openapi, incoming) => {
|
|
192
|
+
if (incoming.length === 0) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const existing = openapi.tags ?? [];
|
|
196
|
+
if (existing.length === 0) {
|
|
197
|
+
openapi.tags = incoming;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const names = new Set(existing.map((t) => t.name));
|
|
201
|
+
const additions = incoming.filter((t) => t.name && !names.has(t.name));
|
|
202
|
+
openapi.tags = additions.length > 0 ? [...existing, ...additions] : existing;
|
|
203
|
+
};
|
|
204
|
+
const assignTagsFromPostman = (openapi, tags, isMergingIntoBase) => {
|
|
205
|
+
if (tags.length === 0) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (isMergingIntoBase) {
|
|
209
|
+
mergeTagsIntoDocument(openapi, tags);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
openapi.tags = tags;
|
|
213
|
+
}
|
|
114
214
|
};
|
|
115
215
|
const cleanupOperations = (paths) => {
|
|
116
216
|
Object.values(paths).forEach((pathItem) => {
|
|
@@ -145,7 +245,9 @@ const cleanupOperations = (paths) => {
|
|
|
145
245
|
* This function processes the collection's information, servers, authentication,
|
|
146
246
|
* and items to create a corresponding OpenAPI structure.
|
|
147
247
|
*/
|
|
148
|
-
export function convert(postmanCollection) {
|
|
248
|
+
export function convert(postmanCollection, options = { mergeOperation: false }) {
|
|
249
|
+
const { requestIndexPaths, mergeOperation = false, document: baseDocument } = options;
|
|
250
|
+
const isMergingIntoBase = baseDocument !== undefined;
|
|
149
251
|
const collection = validateCollectionShape(parseCollectionInput(postmanCollection));
|
|
150
252
|
// Extract title from collection info, fallback to 'API' if not provided
|
|
151
253
|
const title = collection.info.name || 'API';
|
|
@@ -158,8 +260,8 @@ export function convert(postmanCollection) {
|
|
|
158
260
|
const contact = processContact(collection);
|
|
159
261
|
// Process logo information
|
|
160
262
|
const logo = processLogo(collection);
|
|
161
|
-
// Initialize the OpenAPI document with required fields
|
|
162
|
-
const openapi = {
|
|
263
|
+
// Initialize the OpenAPI document with required fields (or clone a base document to merge into)
|
|
264
|
+
const openapi = baseDocument ?? {
|
|
163
265
|
openapi: '3.1.0',
|
|
164
266
|
info: {
|
|
165
267
|
title,
|
|
@@ -171,44 +273,72 @@ export function convert(postmanCollection) {
|
|
|
171
273
|
},
|
|
172
274
|
paths: {},
|
|
173
275
|
};
|
|
276
|
+
openapi.paths = openapi.paths ?? {};
|
|
174
277
|
// Process external docs
|
|
175
278
|
const externalDocs = processExternalDocs(collection);
|
|
176
|
-
if (externalDocs) {
|
|
279
|
+
if (externalDocs && (!isMergingIntoBase || !openapi.externalDocs)) {
|
|
177
280
|
openapi.externalDocs = externalDocs;
|
|
178
281
|
}
|
|
179
282
|
// Process authentication if present in the collection
|
|
180
283
|
if (collection.auth) {
|
|
181
284
|
const { securitySchemes, security } = processAuth(collection.auth);
|
|
182
285
|
mergeSecuritySchemes(openapi, securitySchemes);
|
|
183
|
-
|
|
286
|
+
if (security?.length) {
|
|
287
|
+
if (isMergingIntoBase && openapi.security?.length) {
|
|
288
|
+
openapi.security = [...openapi.security, ...security];
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
openapi.security = security;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
184
294
|
}
|
|
185
295
|
// Process each item in the collection and merge into OpenAPI spec
|
|
186
296
|
const allServerUsage = [];
|
|
187
297
|
if (collection.item) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
allServerUsage.push(...serverUsage);
|
|
197
|
-
// Merge paths from the current item
|
|
198
|
-
openapi.paths = openapi.paths || {};
|
|
199
|
-
for (const [pathKey, pathItem] of Object.entries(itemPaths)) {
|
|
200
|
-
// Convert colon-style params to curly brace style
|
|
201
|
-
const normalizedPathKey = normalizePath(pathKey);
|
|
202
|
-
if (!pathItem) {
|
|
298
|
+
const usePathFilter = requestIndexPaths !== undefined;
|
|
299
|
+
if (usePathFilter) {
|
|
300
|
+
const uniquePaths = dedupeIndexPaths(requestIndexPaths);
|
|
301
|
+
const tags = extractTagsForSelectedPaths(collection.item, uniquePaths);
|
|
302
|
+
assignTagsFromPostman(openapi, tags, isMergingIntoBase);
|
|
303
|
+
for (const path of uniquePaths) {
|
|
304
|
+
const node = getNodeAtPath(collection.item, path);
|
|
305
|
+
if (!node) {
|
|
203
306
|
continue;
|
|
204
307
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
308
|
+
const parentTags = collectParentTagSegments(collection.item, path);
|
|
309
|
+
const { paths: itemPaths, components: itemComponents, serverUsage, } = processItem(node, DEFAULT_EXAMPLE_NAME, parentTags, '');
|
|
310
|
+
allServerUsage.push(...serverUsage);
|
|
311
|
+
for (const [pathKey, pathItem] of Object.entries(itemPaths)) {
|
|
312
|
+
const normalizedPathKey = normalizePath(pathKey);
|
|
313
|
+
if (!pathItem) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
mergePathItem(openapi.paths, normalizedPathKey, pathItem, mergeOperation);
|
|
317
|
+
}
|
|
318
|
+
if (itemComponents?.securitySchemes) {
|
|
319
|
+
mergeSecuritySchemes(openapi, itemComponents.securitySchemes);
|
|
320
|
+
}
|
|
210
321
|
}
|
|
211
|
-
}
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
const tags = extractTags(collection.item);
|
|
325
|
+
assignTagsFromPostman(openapi, tags, isMergingIntoBase);
|
|
326
|
+
collection.item.forEach((item) => {
|
|
327
|
+
const { paths: itemPaths, components: itemComponents, serverUsage } = processItem(item, DEFAULT_EXAMPLE_NAME);
|
|
328
|
+
allServerUsage.push(...serverUsage);
|
|
329
|
+
openapi.paths = openapi.paths || {};
|
|
330
|
+
for (const [pathKey, pathItem] of Object.entries(itemPaths)) {
|
|
331
|
+
const normalizedPathKey = normalizePath(pathKey);
|
|
332
|
+
if (!pathItem) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
mergePathItem(openapi.paths, normalizedPathKey, pathItem, mergeOperation);
|
|
336
|
+
}
|
|
337
|
+
if (itemComponents?.securitySchemes) {
|
|
338
|
+
mergeSecuritySchemes(openapi, itemComponents.securitySchemes);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
212
342
|
}
|
|
213
343
|
// Extract all unique paths from the document
|
|
214
344
|
const allUniquePaths = new Set();
|
|
@@ -221,7 +351,9 @@ export function convert(postmanCollection) {
|
|
|
221
351
|
const serverPlacement = analyzeServerDistribution(allServerUsage, allUniquePaths);
|
|
222
352
|
// Add servers to document level
|
|
223
353
|
if (serverPlacement.document.length > 0) {
|
|
224
|
-
openapi.servers =
|
|
354
|
+
openapi.servers = isMergingIntoBase
|
|
355
|
+
? mergeServerLists(openapi.servers, serverPlacement.document)
|
|
356
|
+
: serverPlacement.document;
|
|
225
357
|
}
|
|
226
358
|
// Add servers to path items
|
|
227
359
|
if (openapi.paths) {
|
|
@@ -229,7 +361,7 @@ export function convert(postmanCollection) {
|
|
|
229
361
|
const normalizedPathKey = normalizePath(path);
|
|
230
362
|
const pathItem = openapi.paths[normalizedPathKey];
|
|
231
363
|
if (pathItem) {
|
|
232
|
-
pathItem.servers = servers;
|
|
364
|
+
pathItem.servers = isMergingIntoBase ? mergeServerLists(pathItem.servers, servers) : servers;
|
|
233
365
|
}
|
|
234
366
|
}
|
|
235
367
|
// Add servers to operations
|
|
@@ -243,7 +375,7 @@ export function convert(postmanCollection) {
|
|
|
243
375
|
if (method in pathItem) {
|
|
244
376
|
const operation = pathItem[method];
|
|
245
377
|
if (operation && typeof operation === 'object' && 'responses' in operation) {
|
|
246
|
-
operation.servers = servers;
|
|
378
|
+
operation.servers = isMergingIntoBase ? mergeServerLists(operation.servers, servers) : servers;
|
|
247
379
|
}
|
|
248
380
|
}
|
|
249
381
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a unique string value based on a default value and a validation function.
|
|
3
|
+
* The function tries the default value first. If validation fails, it appends
|
|
4
|
+
* an incrementing suffix (optionally with a prefix) until the validation passes.
|
|
5
|
+
*
|
|
6
|
+
* @param defaultValue - The initial base string value to try.
|
|
7
|
+
* @param validation - A function that receives a candidate value and returns true if it is valid.
|
|
8
|
+
* @param prefix - Optional prefix to add before the incrementing number (default is '').
|
|
9
|
+
* @returns The first value that passes the validation.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Case 1: Simple unused value
|
|
13
|
+
* generateUniqueValue('example', v => v !== 'example') // → "example 2"
|
|
14
|
+
*
|
|
15
|
+
* // Case 2: Avoids taken values in a set
|
|
16
|
+
* const taken = new Set(['foo', 'foo 1', 'foo 2']);
|
|
17
|
+
* generateUniqueValue('foo', v => !taken.has(v)) // → "foo 3"
|
|
18
|
+
*
|
|
19
|
+
* // Case 3: Using a prefix
|
|
20
|
+
* generateUniqueValue('base', v => v === 'base__3', '__') // → "base__3"
|
|
21
|
+
*/
|
|
22
|
+
export declare const generateUniqueValue: (defaultValue: string, validation: (value: string) => boolean, prefix?: string) => string;
|
|
23
|
+
//# sourceMappingURL=generate-unique-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-unique-value.d.ts","sourceRoot":"","sources":["../../src/helpers/generate-unique-value.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,mBAAmB,GAC9B,cAAc,MAAM,EACpB,YAAY,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,EACtC,eAAW,KACV,MAOF,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a unique string value based on a default value and a validation function.
|
|
3
|
+
* The function tries the default value first. If validation fails, it appends
|
|
4
|
+
* an incrementing suffix (optionally with a prefix) until the validation passes.
|
|
5
|
+
*
|
|
6
|
+
* @param defaultValue - The initial base string value to try.
|
|
7
|
+
* @param validation - A function that receives a candidate value and returns true if it is valid.
|
|
8
|
+
* @param prefix - Optional prefix to add before the incrementing number (default is '').
|
|
9
|
+
* @returns The first value that passes the validation.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Case 1: Simple unused value
|
|
13
|
+
* generateUniqueValue('example', v => v !== 'example') // → "example 2"
|
|
14
|
+
*
|
|
15
|
+
* // Case 2: Avoids taken values in a set
|
|
16
|
+
* const taken = new Set(['foo', 'foo 1', 'foo 2']);
|
|
17
|
+
* generateUniqueValue('foo', v => !taken.has(v)) // → "foo 3"
|
|
18
|
+
*
|
|
19
|
+
* // Case 3: Using a prefix
|
|
20
|
+
* generateUniqueValue('base', v => v === 'base__3', '__') // → "base__3"
|
|
21
|
+
*/
|
|
22
|
+
export const generateUniqueValue = (defaultValue, validation, prefix = '') => {
|
|
23
|
+
let i = 1;
|
|
24
|
+
let value = defaultValue;
|
|
25
|
+
while (!validation(value)) {
|
|
26
|
+
value = `${defaultValue} ${prefix}${i++}`;
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
2
|
+
/**
|
|
3
|
+
* Collects all example names used on parameters and requestBodies
|
|
4
|
+
* within all operations of a PathItemObject.
|
|
5
|
+
*
|
|
6
|
+
* This is useful for checking which example names are already present
|
|
7
|
+
* so you can avoid clashes (e.g., generating unique example names
|
|
8
|
+
* when merging path items).
|
|
9
|
+
*
|
|
10
|
+
* @param path - The OpenAPI PathItemObject to scan
|
|
11
|
+
* @returns Set of all unique example names found across parameters and requestBodies
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const operation: OpenAPIV3_1.OperationObject = {
|
|
15
|
+
* parameters: [
|
|
16
|
+
* {
|
|
17
|
+
* name: 'id',
|
|
18
|
+
* in: 'query',
|
|
19
|
+
* examples: {
|
|
20
|
+
* foo: { value: 'bar' },
|
|
21
|
+
* bar: { value: 'baz' }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ],
|
|
25
|
+
* requestBody: {
|
|
26
|
+
* content: {
|
|
27
|
+
* 'application/json': {
|
|
28
|
+
* examples: {
|
|
29
|
+
* default: { value: 1 },
|
|
30
|
+
* extra: { value: 2 }
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
* const path = { get: operation }
|
|
37
|
+
* // getOperationExamples(path) => Set { 'foo', 'bar', 'default', 'extra' }
|
|
38
|
+
*/
|
|
39
|
+
export declare const getOperationExamples: (path: OpenAPIV3_1.PathItemObject) => Set<string>;
|
|
40
|
+
//# sourceMappingURL=get-operation-examples.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-operation-examples.d.ts","sourceRoot":"","sources":["../../src/helpers/get-operation-examples.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,oBAAoB,GAAI,MAAM,WAAW,CAAC,cAAc,gBA2CpE,CAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { HTTP_METHODS } from '@scalar/helpers/http/http-methods';
|
|
2
|
+
/**
|
|
3
|
+
* Collects all example names used on parameters and requestBodies
|
|
4
|
+
* within all operations of a PathItemObject.
|
|
5
|
+
*
|
|
6
|
+
* This is useful for checking which example names are already present
|
|
7
|
+
* so you can avoid clashes (e.g., generating unique example names
|
|
8
|
+
* when merging path items).
|
|
9
|
+
*
|
|
10
|
+
* @param path - The OpenAPI PathItemObject to scan
|
|
11
|
+
* @returns Set of all unique example names found across parameters and requestBodies
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const operation: OpenAPIV3_1.OperationObject = {
|
|
15
|
+
* parameters: [
|
|
16
|
+
* {
|
|
17
|
+
* name: 'id',
|
|
18
|
+
* in: 'query',
|
|
19
|
+
* examples: {
|
|
20
|
+
* foo: { value: 'bar' },
|
|
21
|
+
* bar: { value: 'baz' }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ],
|
|
25
|
+
* requestBody: {
|
|
26
|
+
* content: {
|
|
27
|
+
* 'application/json': {
|
|
28
|
+
* examples: {
|
|
29
|
+
* default: { value: 1 },
|
|
30
|
+
* extra: { value: 2 }
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
* const path = { get: operation }
|
|
37
|
+
* // getOperationExamples(path) => Set { 'foo', 'bar', 'default', 'extra' }
|
|
38
|
+
*/
|
|
39
|
+
export const getOperationExamples = (path) => {
|
|
40
|
+
const exampleNames = new Set();
|
|
41
|
+
for (const key of HTTP_METHODS) {
|
|
42
|
+
const operation = path[key];
|
|
43
|
+
if (operation === undefined || typeof operation !== 'object') {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const op = operation;
|
|
47
|
+
if ('parameters' in op) {
|
|
48
|
+
op.parameters?.forEach((parameter) => {
|
|
49
|
+
if (parameter.examples) {
|
|
50
|
+
for (const exampleName of Object.keys(parameter.examples)) {
|
|
51
|
+
exampleNames.add(exampleName);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if ('requestBody' in op) {
|
|
57
|
+
const requestBody = op.requestBody;
|
|
58
|
+
if (requestBody?.content) {
|
|
59
|
+
for (const mediaTypeObject of Object.values(requestBody.content)) {
|
|
60
|
+
const examples = mediaTypeObject &&
|
|
61
|
+
typeof mediaTypeObject === 'object' &&
|
|
62
|
+
'examples' in mediaTypeObject &&
|
|
63
|
+
typeof mediaTypeObject.examples === 'object'
|
|
64
|
+
? mediaTypeObject.examples
|
|
65
|
+
: undefined;
|
|
66
|
+
if (examples) {
|
|
67
|
+
for (const exampleName of Object.keys(examples)) {
|
|
68
|
+
exampleNames.add(exampleName);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return exampleNames;
|
|
76
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
2
|
+
/**
|
|
3
|
+
* Merges two OpenAPI OperationObject instances.
|
|
4
|
+
* Assumes that all example names (keys in the 'examples' objects) are unique across both operations.
|
|
5
|
+
* This assumption allows us to shallowly merge example maps without risk of overwriting.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const op1: OpenAPIV3_1.OperationObject = {
|
|
9
|
+
* tags: ['user'],
|
|
10
|
+
* parameters: [
|
|
11
|
+
* {
|
|
12
|
+
* name: 'id',
|
|
13
|
+
* in: 'path',
|
|
14
|
+
* required: true,
|
|
15
|
+
* schema: { type: 'string' },
|
|
16
|
+
* examples: { A: { value: 1 } }
|
|
17
|
+
* }
|
|
18
|
+
* ],
|
|
19
|
+
* requestBody: {
|
|
20
|
+
* content: {
|
|
21
|
+
* 'application/json': {
|
|
22
|
+
* examples: { example1: { value: { foo: 'bar' } } }
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* const op2: OpenAPIV3_1.OperationObject = {
|
|
29
|
+
* tags: ['admin'],
|
|
30
|
+
* parameters: [
|
|
31
|
+
* {
|
|
32
|
+
* name: 'id',
|
|
33
|
+
* in: 'path',
|
|
34
|
+
* required: true,
|
|
35
|
+
* schema: { type: 'string' },
|
|
36
|
+
* examples: { B: { value: 2 } }
|
|
37
|
+
* }
|
|
38
|
+
* ],
|
|
39
|
+
* requestBody: {
|
|
40
|
+
* content: {
|
|
41
|
+
* 'application/json': {
|
|
42
|
+
* examples: { example2: { value: { hello: 'world' } } }
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
*
|
|
48
|
+
* const merged = mergeOperations(op1, op2)
|
|
49
|
+
* // merged.tags -> ['user', 'admin']
|
|
50
|
+
* // merged.parameters[0].examples -> { B: { value: 2 }, A: { value: 1 } }
|
|
51
|
+
* // merged.requestBody.content['application/json'].examples ->
|
|
52
|
+
* // { example2: {...}, example1: {...} }
|
|
53
|
+
*/
|
|
54
|
+
export declare const mergeOperations: (operation1: OpenAPIV3_1.OperationObject, operation2: OpenAPIV3_1.OperationObject) => OpenAPIV3_1.OperationObject;
|
|
55
|
+
//# sourceMappingURL=merge-operation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-operation.d.ts","sourceRoot":"","sources":["../../src/helpers/merge-operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,eAAO,MAAM,eAAe,GAC1B,YAAY,WAAW,CAAC,eAAe,EACvC,YAAY,WAAW,CAAC,eAAe,KACtC,WAAW,CAAC,eAiFd,CAAA"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges two OpenAPI OperationObject instances.
|
|
3
|
+
* Assumes that all example names (keys in the 'examples' objects) are unique across both operations.
|
|
4
|
+
* This assumption allows us to shallowly merge example maps without risk of overwriting.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const op1: OpenAPIV3_1.OperationObject = {
|
|
8
|
+
* tags: ['user'],
|
|
9
|
+
* parameters: [
|
|
10
|
+
* {
|
|
11
|
+
* name: 'id',
|
|
12
|
+
* in: 'path',
|
|
13
|
+
* required: true,
|
|
14
|
+
* schema: { type: 'string' },
|
|
15
|
+
* examples: { A: { value: 1 } }
|
|
16
|
+
* }
|
|
17
|
+
* ],
|
|
18
|
+
* requestBody: {
|
|
19
|
+
* content: {
|
|
20
|
+
* 'application/json': {
|
|
21
|
+
* examples: { example1: { value: { foo: 'bar' } } }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* const op2: OpenAPIV3_1.OperationObject = {
|
|
28
|
+
* tags: ['admin'],
|
|
29
|
+
* parameters: [
|
|
30
|
+
* {
|
|
31
|
+
* name: 'id',
|
|
32
|
+
* in: 'path',
|
|
33
|
+
* required: true,
|
|
34
|
+
* schema: { type: 'string' },
|
|
35
|
+
* examples: { B: { value: 2 } }
|
|
36
|
+
* }
|
|
37
|
+
* ],
|
|
38
|
+
* requestBody: {
|
|
39
|
+
* content: {
|
|
40
|
+
* 'application/json': {
|
|
41
|
+
* examples: { example2: { value: { hello: 'world' } } }
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* const merged = mergeOperations(op1, op2)
|
|
48
|
+
* // merged.tags -> ['user', 'admin']
|
|
49
|
+
* // merged.parameters[0].examples -> { B: { value: 2 }, A: { value: 1 } }
|
|
50
|
+
* // merged.requestBody.content['application/json'].examples ->
|
|
51
|
+
* // { example2: {...}, example1: {...} }
|
|
52
|
+
*/
|
|
53
|
+
export const mergeOperations = (operation1, operation2) => {
|
|
54
|
+
const operation = { ...operation2 };
|
|
55
|
+
// Merge tags (union, preserving uniqueness)
|
|
56
|
+
if (operation1.tags || operation.tags) {
|
|
57
|
+
operation.tags = Array.from(new Set([...(operation1.tags ?? []), ...(operation.tags ?? [])]));
|
|
58
|
+
}
|
|
59
|
+
const parameters = new Map();
|
|
60
|
+
const generateParameterId = (param) => `${param.name}/${param.in}`;
|
|
61
|
+
// Seed parameter list from operation2 (the base)
|
|
62
|
+
if (operation.parameters) {
|
|
63
|
+
for (const parameter of operation.parameters) {
|
|
64
|
+
const id = generateParameterId(parameter);
|
|
65
|
+
parameters.set(id, parameter);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Merge parameters from operation1 into parameters of operation2.
|
|
69
|
+
// For each parameter, merge their 'examples' objects, assuming example keys are unique.
|
|
70
|
+
if (operation1.parameters) {
|
|
71
|
+
for (const parameter of operation1.parameters) {
|
|
72
|
+
const id = generateParameterId(parameter);
|
|
73
|
+
if (parameters.has(id)) {
|
|
74
|
+
const existingParameter = parameters.get(id);
|
|
75
|
+
if (existingParameter) {
|
|
76
|
+
// Example keys are expected to be unique, so shallow merge is safe.
|
|
77
|
+
existingParameter.examples = {
|
|
78
|
+
...existingParameter.examples,
|
|
79
|
+
...parameter.examples,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
parameters.set(id, parameter);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (parameters.size > 0) {
|
|
89
|
+
operation.parameters = Array.from(parameters.values());
|
|
90
|
+
}
|
|
91
|
+
const contentMediaTypeMap = new Map();
|
|
92
|
+
// Seed requestBody content from operation2 (the base)
|
|
93
|
+
if (operation.requestBody?.content) {
|
|
94
|
+
for (const [contentType, mediaType] of Object.entries(operation.requestBody.content)) {
|
|
95
|
+
contentMediaTypeMap.set(contentType, mediaType);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Merge requestBody content from operation1 into the base.
|
|
99
|
+
// When merging 'examples', we expect example names to be unique (no overwrite).
|
|
100
|
+
if (operation1.requestBody?.content) {
|
|
101
|
+
for (const [contentType, mediaType] of Object.entries(operation1.requestBody.content)) {
|
|
102
|
+
const mediaTypeObj = mediaType;
|
|
103
|
+
if (contentMediaTypeMap.has(contentType)) {
|
|
104
|
+
const existingMediaType = contentMediaTypeMap.get(contentType);
|
|
105
|
+
if (existingMediaType && (existingMediaType.examples || mediaTypeObj.examples)) {
|
|
106
|
+
// Assumption: example names (keys) are unique, so this merge is safe
|
|
107
|
+
existingMediaType.examples = {
|
|
108
|
+
...existingMediaType.examples,
|
|
109
|
+
...mediaTypeObj.examples,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
contentMediaTypeMap.set(contentType, mediaTypeObj);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (contentMediaTypeMap.size > 0) {
|
|
119
|
+
operation.requestBody = {
|
|
120
|
+
...operation.requestBody,
|
|
121
|
+
content: Object.fromEntries(contentMediaTypeMap),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return operation;
|
|
125
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
2
|
+
export declare const DEFAULT_EXAMPLE_NAME = "Default example";
|
|
3
|
+
export declare const OPERATION_KEYS: readonly (keyof OpenAPIV3_1.PathItemObject)[];
|
|
4
|
+
export declare const mergePathItem: (paths: OpenAPIV3_1.PathsObject, normalizedPathKey: string, pathItem: OpenAPIV3_1.PathItemObject, mergeOperation?: boolean) => void;
|
|
5
|
+
//# sourceMappingURL=merge-path-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-path-item.d.ts","sourceRoot":"","sources":["../../src/helpers/merge-path-item.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAOxD,eAAO,MAAM,oBAAoB,oBAAoB,CAAA;AAErD,eAAO,MAAM,cAAc,EAAE,SAAS,CAAC,MAAM,WAAW,CAAC,cAAc,CAAC,EASvE,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,OAAO,WAAW,CAAC,WAAW,EAC9B,mBAAmB,MAAM,EACzB,UAAU,WAAW,CAAC,cAAc,EACpC,iBAAgB,OAAe,KAC9B,IA8BF,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { generateUniqueValue } from '../helpers/generate-unique-value.js';
|
|
2
|
+
import { getOperationExamples } from '../helpers/get-operation-examples.js';
|
|
3
|
+
import { mergeOperations } from '../helpers/merge-operation.js';
|
|
4
|
+
import { renameOperationExamples } from '../helpers/rename-operation-example.js';
|
|
5
|
+
export const DEFAULT_EXAMPLE_NAME = 'Default example';
|
|
6
|
+
export const OPERATION_KEYS = [
|
|
7
|
+
'get',
|
|
8
|
+
'put',
|
|
9
|
+
'post',
|
|
10
|
+
'delete',
|
|
11
|
+
'options',
|
|
12
|
+
'head',
|
|
13
|
+
'patch',
|
|
14
|
+
'trace',
|
|
15
|
+
];
|
|
16
|
+
export const mergePathItem = (paths, normalizedPathKey, pathItem, mergeOperation = false) => {
|
|
17
|
+
const targetPath = (paths[normalizedPathKey] ?? {});
|
|
18
|
+
for (const [key, value] of Object.entries(pathItem)) {
|
|
19
|
+
if (value === undefined) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const isOperationKey = OPERATION_KEYS.includes(key);
|
|
23
|
+
if (isOperationKey && targetPath[key] && mergeOperation) {
|
|
24
|
+
// Get all example names from the target path
|
|
25
|
+
const exampleNames = getOperationExamples(targetPath);
|
|
26
|
+
// Generate a unique example name
|
|
27
|
+
const newExampleName = generateUniqueValue(DEFAULT_EXAMPLE_NAME, (value) => !exampleNames.has(value), '#');
|
|
28
|
+
// Rename operation examples from the new path item (we know it's gonna have only the default example)
|
|
29
|
+
renameOperationExamples(pathItem[key], DEFAULT_EXAMPLE_NAME, newExampleName);
|
|
30
|
+
// Merge the operations
|
|
31
|
+
targetPath[key] = mergeOperations(targetPath[key], pathItem[key]);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
targetPath[key] = value;
|
|
35
|
+
}
|
|
36
|
+
paths[normalizedPathKey] = targetPath;
|
|
37
|
+
};
|
|
@@ -4,9 +4,9 @@ import type { Request } from '../types.js';
|
|
|
4
4
|
* Extracts parameters from a Postman request and converts them to OpenAPI parameter objects.
|
|
5
5
|
* Processes query, path, and header parameters from the request URL and headers.
|
|
6
6
|
*/
|
|
7
|
-
export declare function extractParameters(request: Request): OpenAPIV3_1.ParameterObject[];
|
|
7
|
+
export declare function extractParameters(request: Request, exampleName: string): OpenAPIV3_1.ParameterObject[];
|
|
8
8
|
/**
|
|
9
9
|
* Creates an OpenAPI parameter object from a Postman parameter.
|
|
10
10
|
*/
|
|
11
|
-
export declare function createParameterObject(param: any, paramIn: 'query' | 'path' | 'header'): OpenAPIV3_1.ParameterObject;
|
|
11
|
+
export declare function createParameterObject(param: any, paramIn: 'query' | 'path' | 'header', exampleName: string): OpenAPIV3_1.ParameterObject;
|
|
12
12
|
//# sourceMappingURL=parameters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../src/helpers/parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAU,OAAO,EAAE,MAAM,SAAS,CAAA;AAI9C;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAAC,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../src/helpers/parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAU,OAAO,EAAE,MAAM,SAAS,CAAA;AAI9C;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,WAAW,CAAC,eAAe,EAAE,CA2DtG;AAoBD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,GAAG,EACV,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,EACpC,WAAW,EAAE,MAAM,GAClB,WAAW,CAAC,eAAe,CAwD7B"}
|
|
@@ -3,7 +3,7 @@ import { inferSchemaType } from './schemas.js';
|
|
|
3
3
|
* Extracts parameters from a Postman request and converts them to OpenAPI parameter objects.
|
|
4
4
|
* Processes query, path, and header parameters from the request URL and headers.
|
|
5
5
|
*/
|
|
6
|
-
export function extractParameters(request) {
|
|
6
|
+
export function extractParameters(request, exampleName) {
|
|
7
7
|
const parameters = [];
|
|
8
8
|
const parameterMap = new Map();
|
|
9
9
|
if (typeof request === 'string' || !request.url) {
|
|
@@ -13,7 +13,7 @@ export function extractParameters(request) {
|
|
|
13
13
|
// Process query parameters
|
|
14
14
|
if (url.query) {
|
|
15
15
|
url.query.forEach((param) => {
|
|
16
|
-
const paramObj = createParameterObject(param, 'query');
|
|
16
|
+
const paramObj = createParameterObject(param, 'query', exampleName);
|
|
17
17
|
if (paramObj.name) {
|
|
18
18
|
parameterMap.set(paramObj.name, paramObj);
|
|
19
19
|
}
|
|
@@ -22,7 +22,7 @@ export function extractParameters(request) {
|
|
|
22
22
|
// Process path parameters
|
|
23
23
|
if (url.variable) {
|
|
24
24
|
url.variable.forEach((param) => {
|
|
25
|
-
const paramObj = createParameterObject(param, 'path');
|
|
25
|
+
const paramObj = createParameterObject(param, 'path', exampleName);
|
|
26
26
|
if (paramObj.name) {
|
|
27
27
|
parameterMap.set(paramObj.name, paramObj);
|
|
28
28
|
}
|
|
@@ -48,7 +48,7 @@ export function extractParameters(request) {
|
|
|
48
48
|
// Process header parameters
|
|
49
49
|
if (request.header && Array.isArray(request.header)) {
|
|
50
50
|
request.header.forEach((header) => {
|
|
51
|
-
const paramObj = createParameterObject(header, 'header');
|
|
51
|
+
const paramObj = createParameterObject(header, 'header', exampleName);
|
|
52
52
|
if (paramObj.name) {
|
|
53
53
|
parameterMap.set(paramObj.name, paramObj);
|
|
54
54
|
}
|
|
@@ -74,11 +74,17 @@ function extractPathVariablesFromPathArray(pathArray) {
|
|
|
74
74
|
/**
|
|
75
75
|
* Creates an OpenAPI parameter object from a Postman parameter.
|
|
76
76
|
*/
|
|
77
|
-
export function createParameterObject(param, paramIn) {
|
|
77
|
+
export function createParameterObject(param, paramIn, exampleName) {
|
|
78
78
|
const parameter = {
|
|
79
79
|
name: param.key || '',
|
|
80
80
|
in: paramIn,
|
|
81
81
|
description: param.description,
|
|
82
|
+
examples: {
|
|
83
|
+
[exampleName]: {
|
|
84
|
+
value: param.value,
|
|
85
|
+
'x-disabled': !!param.disabled,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
82
88
|
};
|
|
83
89
|
// Path parameters are always required in OpenAPI
|
|
84
90
|
if (paramIn === 'path') {
|
|
@@ -96,7 +102,6 @@ export function createParameterObject(param, paramIn) {
|
|
|
96
102
|
}
|
|
97
103
|
}
|
|
98
104
|
if (param.value !== undefined) {
|
|
99
|
-
parameter.example = param.value;
|
|
100
105
|
// For path parameters, prefer string type unless value is explicitly a number type
|
|
101
106
|
// This prevents converting string IDs like "testId" to integers
|
|
102
107
|
if (paramIn === 'path') {
|
|
@@ -15,7 +15,7 @@ export type ServerUsage = {
|
|
|
15
15
|
* Handles nested item groups, extracts request details, and generates corresponding
|
|
16
16
|
* OpenAPI path items and operations.
|
|
17
17
|
*/
|
|
18
|
-
export declare function processItem(item: Item | ItemGroup, parentTags?: string[], parentPath?: string): {
|
|
18
|
+
export declare function processItem(item: Item | ItemGroup, exampleName?: string, parentTags?: string[], parentPath?: string): {
|
|
19
19
|
paths: OpenAPIV3_1.PathsObject;
|
|
20
20
|
components: OpenAPIV3_1.ComponentsObject;
|
|
21
21
|
serverUsage: ServerUsage[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-items.d.ts","sourceRoot":"","sources":["../../src/helpers/path-items.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAW9C,KAAK,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;AAE7F;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,WAAW,CAAA;CACpB,CAAA;AAoBD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,UAAU,GAAE,MAAM,EAAO,EACzB,UAAU,GAAE,MAAW,GACtB;IACD,KAAK,EAAE,WAAW,CAAC,WAAW,CAAA;IAC9B,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAA;IACxC,WAAW,EAAE,WAAW,EAAE,CAAA;CAC3B,CA2KA"}
|
|
1
|
+
{"version":3,"file":"path-items.d.ts","sourceRoot":"","sources":["../../src/helpers/path-items.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAW9C,KAAK,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;AAE7F;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,WAAW,CAAA;CACpB,CAAA;AAoBD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,WAAW,GAAE,MAAkB,EAC/B,UAAU,GAAE,MAAM,EAAO,EACzB,UAAU,GAAE,MAAW,GACtB;IACD,KAAK,EAAE,WAAW,CAAC,WAAW,CAAA;IAC9B,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAA;IACxC,WAAW,EAAE,WAAW,EAAE,CAAA;CAC3B,CA2KA"}
|
|
@@ -27,14 +27,14 @@ function ensureRequestBodyContent(requestBody) {
|
|
|
27
27
|
* Handles nested item groups, extracts request details, and generates corresponding
|
|
28
28
|
* OpenAPI path items and operations.
|
|
29
29
|
*/
|
|
30
|
-
export function processItem(item, parentTags = [], parentPath = '') {
|
|
30
|
+
export function processItem(item, exampleName = 'default', parentTags = [], parentPath = '') {
|
|
31
31
|
const paths = {};
|
|
32
32
|
const components = {};
|
|
33
33
|
const serverUsage = [];
|
|
34
34
|
if ('item' in item && Array.isArray(item.item)) {
|
|
35
35
|
const newParentTags = item.name ? [...parentTags, item.name] : parentTags;
|
|
36
36
|
item.item.forEach((childItem) => {
|
|
37
|
-
const childResult = processItem(childItem, newParentTags, `${parentPath}/${item.name || ''}`);
|
|
37
|
+
const childResult = processItem(childItem, exampleName, newParentTags, `${parentPath}/${item.name || ''}`);
|
|
38
38
|
// Merge child paths and components
|
|
39
39
|
for (const [pathKey, pathItem] of Object.entries(childResult.paths)) {
|
|
40
40
|
if (!paths[pathKey]) {
|
|
@@ -109,7 +109,7 @@ export function processItem(item, parentTags = [], parentPath = '') {
|
|
|
109
109
|
}
|
|
110
110
|
// Extract parameters from the request (query, path, header)
|
|
111
111
|
// This should always happen, regardless of whether a description exists
|
|
112
|
-
const extractedParameters = extractParameters(request);
|
|
112
|
+
const extractedParameters = extractParameters(request, exampleName);
|
|
113
113
|
// Merge parameters, giving priority to those from the Markdown table if description exists
|
|
114
114
|
const mergedParameters = new Map();
|
|
115
115
|
// Add extracted parameters, filtering out path parameters not in the path
|
|
@@ -156,7 +156,7 @@ export function processItem(item, parentTags = [], parentPath = '') {
|
|
|
156
156
|
}
|
|
157
157
|
// Allow request bodies for all methods (including GET) if body is present
|
|
158
158
|
if (typeof request !== 'string' && request.body) {
|
|
159
|
-
const requestBody = extractRequestBody(request.body);
|
|
159
|
+
const requestBody = extractRequestBody(request.body, exampleName);
|
|
160
160
|
ensureRequestBodyContent(requestBody);
|
|
161
161
|
// Only add requestBody if it has content
|
|
162
162
|
if (requestBody.content && Object.keys(requestBody.content).length > 0) {
|
|
@@ -175,8 +175,9 @@ const OPENAPI_PARAM_SCHEMA_TYPES = ['string', 'number', 'integer', 'boolean', 'o
|
|
|
175
175
|
function toOpenApiParamSchemaType(s) {
|
|
176
176
|
const value = s ?? 'string';
|
|
177
177
|
for (const t of OPENAPI_PARAM_SCHEMA_TYPES) {
|
|
178
|
-
if (t === value)
|
|
178
|
+
if (t === value) {
|
|
179
179
|
return t;
|
|
180
|
+
}
|
|
180
181
|
}
|
|
181
182
|
return 'string';
|
|
182
183
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { OpenAPIV3_1 } from '@scalar/openapi-types';
|
|
2
|
+
/**
|
|
3
|
+
* Renames an example in all parameters and requestBody content of an operation object.
|
|
4
|
+
*
|
|
5
|
+
* This will copy the example (by name) and remove the old entry both for parameter examples
|
|
6
|
+
* and within every media type of the requestBody, if such examples exist.
|
|
7
|
+
*
|
|
8
|
+
* @param operation - The OpenAPI operation object to mutate
|
|
9
|
+
* @param exampleName - The existing example name to rename
|
|
10
|
+
* @param newExampleName - The new name to give that example
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Given:
|
|
14
|
+
* const operation = {
|
|
15
|
+
* parameters: [
|
|
16
|
+
* {
|
|
17
|
+
* name: 'foo',
|
|
18
|
+
* in: 'query',
|
|
19
|
+
* examples: {
|
|
20
|
+
* oldName: { value: 'fooValue' }
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* ],
|
|
24
|
+
* requestBody: {
|
|
25
|
+
* content: {
|
|
26
|
+
* 'application/json': {
|
|
27
|
+
* examples: {
|
|
28
|
+
* oldName: { value: 123 }
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* renameOperationExamples(operation, 'oldName', 'newName')
|
|
35
|
+
* // After:
|
|
36
|
+
* // operation.parameters[0].examples: { newName: { value: 'fooValue' } }
|
|
37
|
+
* // operation.requestBody.content['application/json'].examples: { newName: { value: 123 } }
|
|
38
|
+
*/
|
|
39
|
+
export declare const renameOperationExamples: (operation: OpenAPIV3_1.OperationObject, exampleName: string, newExampleName: string) => void;
|
|
40
|
+
//# sourceMappingURL=rename-operation-example.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rename-operation-example.d.ts","sourceRoot":"","sources":["../../src/helpers/rename-operation-example.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,uBAAuB,GAClC,WAAW,WAAW,CAAC,eAAe,EACtC,aAAa,MAAM,EACnB,gBAAgB,MAAM,KACrB,IA0BF,CAAA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renames an example in all parameters and requestBody content of an operation object.
|
|
3
|
+
*
|
|
4
|
+
* This will copy the example (by name) and remove the old entry both for parameter examples
|
|
5
|
+
* and within every media type of the requestBody, if such examples exist.
|
|
6
|
+
*
|
|
7
|
+
* @param operation - The OpenAPI operation object to mutate
|
|
8
|
+
* @param exampleName - The existing example name to rename
|
|
9
|
+
* @param newExampleName - The new name to give that example
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Given:
|
|
13
|
+
* const operation = {
|
|
14
|
+
* parameters: [
|
|
15
|
+
* {
|
|
16
|
+
* name: 'foo',
|
|
17
|
+
* in: 'query',
|
|
18
|
+
* examples: {
|
|
19
|
+
* oldName: { value: 'fooValue' }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* ],
|
|
23
|
+
* requestBody: {
|
|
24
|
+
* content: {
|
|
25
|
+
* 'application/json': {
|
|
26
|
+
* examples: {
|
|
27
|
+
* oldName: { value: 123 }
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* renameOperationExamples(operation, 'oldName', 'newName')
|
|
34
|
+
* // After:
|
|
35
|
+
* // operation.parameters[0].examples: { newName: { value: 'fooValue' } }
|
|
36
|
+
* // operation.requestBody.content['application/json'].examples: { newName: { value: 123 } }
|
|
37
|
+
*/
|
|
38
|
+
export const renameOperationExamples = (operation, exampleName, newExampleName) => {
|
|
39
|
+
// Rename in parameter examples (if present)
|
|
40
|
+
if ('parameters' in operation) {
|
|
41
|
+
operation.parameters?.forEach((parameter) => {
|
|
42
|
+
if (parameter.examples?.[exampleName] && exampleName !== newExampleName) {
|
|
43
|
+
parameter.examples[newExampleName] = parameter.examples[exampleName];
|
|
44
|
+
delete parameter.examples[exampleName];
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Rename in requestBody content examples (if present)
|
|
49
|
+
if ('requestBody' in operation) {
|
|
50
|
+
Object.values(operation.requestBody?.content ?? {}).forEach((mediaTypeObject) => {
|
|
51
|
+
if (mediaTypeObject.examples &&
|
|
52
|
+
typeof mediaTypeObject.examples === 'object') {
|
|
53
|
+
const mediaCasted = mediaTypeObject;
|
|
54
|
+
if (mediaCasted.examples?.[exampleName] && exampleName !== newExampleName) {
|
|
55
|
+
mediaCasted.examples[newExampleName] = mediaCasted.examples[exampleName];
|
|
56
|
+
delete mediaCasted.examples[exampleName];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
|
@@ -4,5 +4,5 @@ import type { RequestBody } from '../types.js';
|
|
|
4
4
|
* Extracts and converts the request body from a Postman request to an OpenAPI RequestBodyObject.
|
|
5
5
|
* Handles raw JSON, form-data, and URL-encoded body types, creating appropriate schemas and content types.
|
|
6
6
|
*/
|
|
7
|
-
export declare function extractRequestBody(body: RequestBody): OpenAPIV3_1.RequestBodyObject;
|
|
7
|
+
export declare function extractRequestBody(body: RequestBody, exampleName: string): OpenAPIV3_1.RequestBodyObject;
|
|
8
8
|
//# sourceMappingURL=request-body.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-body.d.ts","sourceRoot":"","sources":["../../src/helpers/request-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAiB,WAAW,EAAuB,MAAM,SAAS,CAAA;AAK9E;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"request-body.d.ts","sourceRoot":"","sources":["../../src/helpers/request-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAiB,WAAW,EAAuB,MAAM,SAAS,CAAA;AAK9E;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,GAAG,WAAW,CAAC,iBAAiB,CAqBxG"}
|
|
@@ -4,25 +4,25 @@ import { createParameterObject } from './parameters.js';
|
|
|
4
4
|
* Extracts and converts the request body from a Postman request to an OpenAPI RequestBodyObject.
|
|
5
5
|
* Handles raw JSON, form-data, and URL-encoded body types, creating appropriate schemas and content types.
|
|
6
6
|
*/
|
|
7
|
-
export function extractRequestBody(body) {
|
|
7
|
+
export function extractRequestBody(body, exampleName) {
|
|
8
8
|
const requestBody = {
|
|
9
9
|
content: {},
|
|
10
10
|
};
|
|
11
11
|
if (body.mode === 'raw') {
|
|
12
|
-
handleRawBody(body, requestBody);
|
|
12
|
+
handleRawBody(body, requestBody, exampleName);
|
|
13
13
|
return requestBody;
|
|
14
14
|
}
|
|
15
15
|
if (body.mode === 'formdata' && body.formdata) {
|
|
16
|
-
handleFormDataBody(body.formdata, requestBody);
|
|
16
|
+
handleFormDataBody(body.formdata, requestBody, exampleName);
|
|
17
17
|
return requestBody;
|
|
18
18
|
}
|
|
19
19
|
if (body.mode === 'urlencoded' && body.urlencoded) {
|
|
20
|
-
handleUrlEncodedBody(body.urlencoded, requestBody);
|
|
20
|
+
handleUrlEncodedBody(body.urlencoded, requestBody, exampleName);
|
|
21
21
|
return requestBody;
|
|
22
22
|
}
|
|
23
23
|
return requestBody;
|
|
24
24
|
}
|
|
25
|
-
function handleRawBody(body, requestBody) {
|
|
25
|
+
function handleRawBody(body, requestBody, exampleName) {
|
|
26
26
|
const rawBody = body.raw || '';
|
|
27
27
|
const isJsonLanguage = body.options?.raw?.language === 'json';
|
|
28
28
|
// Check if body contains Postman variables (like {{bodyData}})
|
|
@@ -44,7 +44,11 @@ function handleRawBody(body, requestBody) {
|
|
|
44
44
|
'application/json': {
|
|
45
45
|
schema: {
|
|
46
46
|
type: 'object',
|
|
47
|
-
|
|
47
|
+
},
|
|
48
|
+
examples: {
|
|
49
|
+
[exampleName]: {
|
|
50
|
+
value: jsonBody,
|
|
51
|
+
},
|
|
48
52
|
},
|
|
49
53
|
},
|
|
50
54
|
};
|
|
@@ -73,14 +77,19 @@ function handleRawBody(body, requestBody) {
|
|
|
73
77
|
},
|
|
74
78
|
};
|
|
75
79
|
}
|
|
76
|
-
function handleFormDataBody(formdata, requestBody) {
|
|
80
|
+
function handleFormDataBody(formdata, requestBody, exampleName) {
|
|
77
81
|
requestBody.content = {
|
|
78
82
|
'multipart/form-data': {
|
|
79
83
|
schema: processFormDataSchema(formdata),
|
|
84
|
+
examples: {
|
|
85
|
+
[exampleName]: {
|
|
86
|
+
value: formdata,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
80
89
|
},
|
|
81
90
|
};
|
|
82
91
|
}
|
|
83
|
-
function handleUrlEncodedBody(urlencoded, requestBody) {
|
|
92
|
+
function handleUrlEncodedBody(urlencoded, requestBody, exampleName) {
|
|
84
93
|
const schema = {
|
|
85
94
|
type: 'object',
|
|
86
95
|
properties: {},
|
|
@@ -88,7 +97,7 @@ function handleUrlEncodedBody(urlencoded, requestBody) {
|
|
|
88
97
|
};
|
|
89
98
|
urlencoded.forEach((item) => {
|
|
90
99
|
if (schema.properties) {
|
|
91
|
-
const paramObject = createParameterObject(item, 'query');
|
|
100
|
+
const paramObject = createParameterObject(item, 'query', exampleName);
|
|
92
101
|
const property = {
|
|
93
102
|
type: 'string',
|
|
94
103
|
examples: [item.value],
|
|
@@ -107,6 +116,11 @@ function handleUrlEncodedBody(urlencoded, requestBody) {
|
|
|
107
116
|
requestBody.content = {
|
|
108
117
|
'application/x-www-form-urlencoded': {
|
|
109
118
|
schema,
|
|
119
|
+
examples: {
|
|
120
|
+
[exampleName]: {
|
|
121
|
+
value: urlencoded,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
110
124
|
},
|
|
111
125
|
};
|
|
112
126
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,uBAAuB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACtF,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"export",
|
|
20
20
|
"scalar"
|
|
21
21
|
],
|
|
22
|
-
"version": "0.
|
|
22
|
+
"version": "0.6.0",
|
|
23
23
|
"engines": {
|
|
24
24
|
"node": ">=22"
|
|
25
25
|
},
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"CHANGELOG.md"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@scalar/
|
|
42
|
-
"@scalar/
|
|
41
|
+
"@scalar/helpers": "0.4.2",
|
|
42
|
+
"@scalar/openapi-types": "0.6.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^24.1.0",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
50
|
+
"generate:textures": "tsx ./scripts/generate-textures.ts",
|
|
50
51
|
"test": "vitest",
|
|
51
52
|
"types:check": "tsc --noEmit"
|
|
52
53
|
}
|