@scalar/postman-to-openapi 0.3.58 → 0.4.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 +21 -0
- package/dist/convert.d.ts.map +1 -1
- package/dist/convert.js +224 -159
- package/dist/convert.js.map +2 -2
- package/dist/helpers/{authHelpers.d.ts → auth.d.ts} +1 -1
- package/dist/helpers/auth.d.ts.map +1 -0
- package/dist/helpers/auth.js +113 -0
- package/dist/helpers/auth.js.map +7 -0
- package/dist/helpers/contact.d.ts +8 -0
- package/dist/helpers/contact.d.ts.map +1 -0
- package/dist/helpers/contact.js +25 -0
- package/dist/helpers/contact.js.map +7 -0
- package/dist/helpers/{externalDocsHelper.d.ts → external-docs.d.ts} +1 -1
- package/dist/helpers/external-docs.d.ts.map +1 -0
- package/dist/helpers/external-docs.js +32 -0
- package/dist/helpers/external-docs.js.map +7 -0
- package/dist/helpers/{formDataHelpers.d.ts → form-data.d.ts} +1 -1
- package/dist/helpers/form-data.d.ts.map +1 -0
- package/dist/helpers/form-data.js +39 -0
- package/dist/helpers/form-data.js.map +7 -0
- package/dist/helpers/license.d.ts +8 -0
- package/dist/helpers/license.d.ts.map +1 -0
- package/dist/helpers/license.js +22 -0
- package/dist/helpers/license.js.map +7 -0
- package/dist/helpers/{logoHelper.d.ts → logo.d.ts} +1 -1
- package/dist/helpers/logo.d.ts.map +1 -0
- package/dist/helpers/logo.js +23 -0
- package/dist/helpers/logo.js.map +7 -0
- package/dist/helpers/{md-utils.d.ts → markdown.d.ts} +1 -1
- package/dist/helpers/markdown.d.ts.map +1 -0
- package/dist/helpers/markdown.js +32 -0
- package/dist/helpers/markdown.js.map +7 -0
- package/dist/helpers/{parameterHelpers.d.ts → parameters.d.ts} +1 -1
- package/dist/helpers/parameters.d.ts.map +1 -0
- package/dist/helpers/parameters.js +103 -0
- package/dist/helpers/parameters.js.map +7 -0
- package/dist/helpers/{itemHelpers.d.ts → path-items.d.ts} +12 -1
- package/dist/helpers/path-items.d.ts.map +1 -0
- package/dist/helpers/path-items.js +204 -0
- package/dist/helpers/path-items.js.map +7 -0
- package/dist/helpers/post-response-scripts.d.ts +7 -0
- package/dist/helpers/post-response-scripts.d.ts.map +1 -0
- package/dist/helpers/post-response-scripts.js +13 -0
- package/dist/helpers/post-response-scripts.js.map +7 -0
- package/dist/helpers/pre-request-scripts.d.ts +7 -0
- package/dist/helpers/pre-request-scripts.d.ts.map +1 -0
- package/dist/helpers/pre-request-scripts.js +13 -0
- package/dist/helpers/pre-request-scripts.js.map +7 -0
- package/dist/helpers/prune-document.d.ts +8 -0
- package/dist/helpers/prune-document.d.ts.map +1 -0
- package/dist/helpers/prune-document.js +39 -0
- package/dist/helpers/prune-document.js.map +7 -0
- package/dist/helpers/{requestBodyHelpers.d.ts → request-body.d.ts} +1 -1
- package/dist/helpers/request-body.d.ts.map +1 -0
- package/dist/helpers/request-body.js +102 -0
- package/dist/helpers/request-body.js.map +7 -0
- package/dist/helpers/{responseHelpers.d.ts → responses.d.ts} +1 -1
- package/dist/helpers/responses.d.ts.map +1 -0
- package/dist/helpers/responses.js +64 -0
- package/dist/helpers/responses.js.map +7 -0
- package/dist/helpers/{schemaHelpers.d.ts → schemas.d.ts} +1 -1
- package/dist/helpers/schemas.d.ts.map +1 -0
- package/dist/helpers/schemas.js +44 -0
- package/dist/helpers/{schemaHelpers.js.map → schemas.js.map} +1 -1
- package/dist/helpers/servers.d.ts +21 -0
- package/dist/helpers/servers.d.ts.map +1 -0
- package/dist/helpers/servers.js +64 -0
- package/dist/helpers/servers.js.map +7 -0
- package/dist/helpers/{statusCodeHelpers.d.ts → status-codes.d.ts} +1 -1
- package/dist/helpers/status-codes.d.ts.map +1 -0
- package/dist/helpers/status-codes.js +35 -0
- package/dist/helpers/status-codes.js.map +7 -0
- package/dist/helpers/{urlHelpers.d.ts → urls.d.ts} +7 -1
- package/dist/helpers/urls.d.ts.map +1 -0
- package/dist/helpers/urls.js +58 -0
- package/dist/helpers/urls.js.map +7 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +12 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/package.json +7 -6
- package/dist/helpers/authHelpers.d.ts.map +0 -1
- package/dist/helpers/authHelpers.js +0 -112
- package/dist/helpers/authHelpers.js.map +0 -7
- package/dist/helpers/externalDocsHelper.d.ts.map +0 -1
- package/dist/helpers/externalDocsHelper.js +0 -40
- package/dist/helpers/externalDocsHelper.js.map +0 -7
- package/dist/helpers/formDataHelpers.d.ts.map +0 -1
- package/dist/helpers/formDataHelpers.js +0 -41
- package/dist/helpers/formDataHelpers.js.map +0 -7
- package/dist/helpers/itemHelpers.d.ts.map +0 -1
- package/dist/helpers/itemHelpers.js +0 -194
- package/dist/helpers/itemHelpers.js.map +0 -7
- package/dist/helpers/licenseContactHelper.d.ts +0 -14
- package/dist/helpers/licenseContactHelper.d.ts.map +0 -1
- package/dist/helpers/licenseContactHelper.js +0 -71
- package/dist/helpers/licenseContactHelper.js.map +0 -7
- package/dist/helpers/logoHelper.d.ts.map +0 -1
- package/dist/helpers/logoHelper.js +0 -24
- package/dist/helpers/logoHelper.js.map +0 -7
- package/dist/helpers/md-utils.d.ts.map +0 -1
- package/dist/helpers/md-utils.js +0 -35
- package/dist/helpers/md-utils.js.map +0 -7
- package/dist/helpers/parameterHelpers.d.ts.map +0 -1
- package/dist/helpers/parameterHelpers.js +0 -106
- package/dist/helpers/parameterHelpers.js.map +0 -7
- package/dist/helpers/postResponseScripts.d.ts +0 -5
- package/dist/helpers/postResponseScripts.d.ts.map +0 -1
- package/dist/helpers/postResponseScripts.js +0 -12
- package/dist/helpers/postResponseScripts.js.map +0 -7
- package/dist/helpers/requestBodyHelpers.d.ts.map +0 -1
- package/dist/helpers/requestBodyHelpers.js +0 -79
- package/dist/helpers/requestBodyHelpers.js.map +0 -7
- package/dist/helpers/responseHelpers.d.ts.map +0 -1
- package/dist/helpers/responseHelpers.js +0 -69
- package/dist/helpers/responseHelpers.js.map +0 -7
- package/dist/helpers/schemaHelpers.d.ts.map +0 -1
- package/dist/helpers/schemaHelpers.js +0 -50
- package/dist/helpers/serverHelpers.d.ts +0 -7
- package/dist/helpers/serverHelpers.d.ts.map +0 -1
- package/dist/helpers/serverHelpers.js +0 -44
- package/dist/helpers/serverHelpers.js.map +0 -7
- package/dist/helpers/statusCodeHelpers.d.ts.map +0 -1
- package/dist/helpers/statusCodeHelpers.js +0 -45
- package/dist/helpers/statusCodeHelpers.js.map +0 -7
- package/dist/helpers/urlHelpers.d.ts.map +0 -1
- package/dist/helpers/urlHelpers.js +0 -53
- package/dist/helpers/urlHelpers.js.map +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @scalar/postman-to-openapi
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#7571](https://github.com/scalar/scalar/pull/7571): feat: major refactor, improves everything, keeps all the data now
|
|
8
|
+
|
|
9
|
+
## 0.3.60
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
#### Updated Dependencies
|
|
14
|
+
|
|
15
|
+
- **@scalar/helpers@0.2.8**
|
|
16
|
+
- [#7751](https://github.com/scalar/scalar/pull/7751): fix: auth persistence
|
|
17
|
+
|
|
18
|
+
## 0.3.59
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- [#7626](https://github.com/scalar/scalar/pull/7626): fix: remove `@scalar/oas-utils` unused dependency
|
|
23
|
+
|
|
3
24
|
## 0.3.58
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
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;AAYxD,OAAO,KAAK,EAAgC,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAkL9E;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,MAAM,GAAG,WAAW,CAAC,QAAQ,CA6I3F"}
|
package/dist/convert.js
CHANGED
|
@@ -1,168 +1,233 @@
|
|
|
1
|
-
import { processAuth } from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { processLogo } from
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
import { processAuth } from "./helpers/auth.js";
|
|
2
|
+
import { processContact } from "./helpers/contact.js";
|
|
3
|
+
import { processExternalDocs } from "./helpers/external-docs.js";
|
|
4
|
+
import { processLicense } from "./helpers/license.js";
|
|
5
|
+
import { processLogo } from "./helpers/logo.js";
|
|
6
|
+
import { processItem } from "./helpers/path-items.js";
|
|
7
|
+
import { pruneDocument } from "./helpers/prune-document.js";
|
|
8
|
+
import { analyzeServerDistribution } from "./helpers/servers.js";
|
|
9
|
+
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
|
+
const normalizeDescription = (description) => {
|
|
21
|
+
if (typeof description === "string") {
|
|
22
|
+
return description;
|
|
23
|
+
}
|
|
24
|
+
return description?.content;
|
|
25
|
+
};
|
|
26
|
+
const parseCollectionInput = (postmanCollection) => {
|
|
27
|
+
if (typeof postmanCollection !== "string") {
|
|
28
|
+
return postmanCollection;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(postmanCollection);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
const details = error instanceof Error ? error.message : "Unknown parse error";
|
|
34
|
+
const parseError = new Error(`Invalid Postman collection JSON: ${details}`);
|
|
35
|
+
parseError.name = "PostmanCollectionParseError";
|
|
36
|
+
throw parseError;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const validateCollectionShape = (collection) => {
|
|
40
|
+
if (!collection || typeof collection !== "object") {
|
|
41
|
+
throw new Error("Invalid Postman collection: expected an object");
|
|
42
|
+
}
|
|
43
|
+
const candidate = collection;
|
|
44
|
+
if (!candidate.info) {
|
|
45
|
+
throw new Error("Missing required info on Postman collection");
|
|
46
|
+
}
|
|
47
|
+
if (!candidate.item || !Array.isArray(candidate.item)) {
|
|
48
|
+
throw new Error("Invalid Postman collection: item must be an array");
|
|
49
|
+
}
|
|
50
|
+
if (typeof candidate.info !== "object") {
|
|
51
|
+
throw new Error("Invalid Postman collection: info must be an object");
|
|
52
|
+
}
|
|
53
|
+
if (!candidate.info.name) {
|
|
54
|
+
throw new Error("Missing required info.name on Postman collection");
|
|
55
|
+
}
|
|
56
|
+
if (!candidate.info.schema) {
|
|
57
|
+
throw new Error("Invalid Postman collection: missing info.schema");
|
|
58
|
+
}
|
|
59
|
+
if (candidate.variable && !Array.isArray(candidate.variable)) {
|
|
60
|
+
throw new Error("Invalid Postman collection: variable must be an array when provided");
|
|
61
|
+
}
|
|
62
|
+
return candidate;
|
|
63
|
+
};
|
|
64
|
+
const isItemGroup = (item) => "item" in item && Array.isArray(item.item);
|
|
65
|
+
const extractTags = (items) => {
|
|
66
|
+
const collectTags = (item, parentPath = "") => {
|
|
67
|
+
if (!isItemGroup(item)) {
|
|
68
|
+
return [];
|
|
24
69
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
servers: parseServers(collection),
|
|
60
|
-
paths: {},
|
|
61
|
-
};
|
|
62
|
-
// Process external docs
|
|
63
|
-
const externalDocs = processExternalDocs(collection);
|
|
64
|
-
if (externalDocs) {
|
|
65
|
-
openapi.externalDocs = externalDocs;
|
|
70
|
+
const nextPath = item.name ? parentPath ? `${parentPath} > ${item.name}` : item.name : parentPath;
|
|
71
|
+
const description = normalizeDescription(item.description);
|
|
72
|
+
const currentTag = item.name?.length ? [
|
|
73
|
+
{
|
|
74
|
+
name: nextPath,
|
|
75
|
+
...description && { description }
|
|
76
|
+
}
|
|
77
|
+
] : [];
|
|
78
|
+
return [...currentTag, ...item.item.flatMap((subItem) => collectTags(subItem, nextPath))];
|
|
79
|
+
};
|
|
80
|
+
return items.flatMap((item) => collectTags(item));
|
|
81
|
+
};
|
|
82
|
+
const mergeSecuritySchemes = (openapi, securitySchemes) => {
|
|
83
|
+
if (!securitySchemes || Object.keys(securitySchemes).length === 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
openapi.components = openapi.components || {};
|
|
87
|
+
openapi.components.securitySchemes = {
|
|
88
|
+
...openapi.components.securitySchemes ?? {},
|
|
89
|
+
...securitySchemes
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
const mergePathItem = (paths, normalizedPathKey, pathItem) => {
|
|
93
|
+
const targetPath = paths[normalizedPathKey] ?? {};
|
|
94
|
+
for (const [key, value] of Object.entries(pathItem)) {
|
|
95
|
+
if (value === void 0) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const isOperationKey = OPERATION_KEYS.includes(key);
|
|
99
|
+
if (isOperationKey && targetPath[key]) {
|
|
100
|
+
const operationName = typeof key === "string" ? key.toUpperCase() : String(key);
|
|
101
|
+
console.warn(
|
|
102
|
+
`Duplicate operation detected for ${operationName} ${normalizedPathKey}. Last operation will overwrite previous.`
|
|
103
|
+
);
|
|
66
104
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
openapi.security = security;
|
|
105
|
+
targetPath[key] = value;
|
|
106
|
+
}
|
|
107
|
+
paths[normalizedPathKey] = targetPath;
|
|
108
|
+
};
|
|
109
|
+
const cleanupOperations = (paths) => {
|
|
110
|
+
Object.values(paths).forEach((pathItem) => {
|
|
111
|
+
if (!pathItem) {
|
|
112
|
+
return;
|
|
76
113
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
114
|
+
OPERATION_KEYS.forEach((operationKey) => {
|
|
115
|
+
const operation = pathItem[operationKey];
|
|
116
|
+
if (!operation) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if ("parameters" in operation && operation.parameters?.length === 0) {
|
|
120
|
+
delete operation.parameters;
|
|
121
|
+
}
|
|
122
|
+
if ("requestBody" in operation && operation.requestBody && "content" in operation.requestBody) {
|
|
123
|
+
const content = operation.requestBody.content;
|
|
124
|
+
if (content && "text/plain" in content) {
|
|
125
|
+
const text = content["text/plain"];
|
|
126
|
+
if (!text?.schema || text.schema && Object.keys(text.schema).length === 0) {
|
|
127
|
+
content["text/plain"] = {};
|
|
128
|
+
}
|
|
83
129
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
130
|
+
}
|
|
131
|
+
if (!operation.description) {
|
|
132
|
+
delete operation.description;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
function convert(postmanCollection) {
|
|
138
|
+
const collection = validateCollectionShape(parseCollectionInput(postmanCollection));
|
|
139
|
+
const title = collection.info.name || "API";
|
|
140
|
+
const version = collection.variable?.find((v) => v.key === "version")?.value || "1.0.0";
|
|
141
|
+
const description = normalizeDescription(collection.info.description) || "";
|
|
142
|
+
const license = processLicense(collection);
|
|
143
|
+
const contact = processContact(collection);
|
|
144
|
+
const logo = processLogo(collection);
|
|
145
|
+
const openapi = {
|
|
146
|
+
openapi: "3.1.0",
|
|
147
|
+
info: {
|
|
148
|
+
title,
|
|
149
|
+
version,
|
|
150
|
+
...description && { description },
|
|
151
|
+
...license && { license },
|
|
152
|
+
...contact && { contact },
|
|
153
|
+
...logo && { "x-logo": logo }
|
|
154
|
+
},
|
|
155
|
+
paths: {}
|
|
156
|
+
};
|
|
157
|
+
const externalDocs = processExternalDocs(collection);
|
|
158
|
+
if (externalDocs) {
|
|
159
|
+
openapi.externalDocs = externalDocs;
|
|
160
|
+
}
|
|
161
|
+
if (collection.auth) {
|
|
162
|
+
const { securitySchemes, security } = processAuth(collection.auth);
|
|
163
|
+
mergeSecuritySchemes(openapi, securitySchemes);
|
|
164
|
+
openapi.security = security;
|
|
165
|
+
}
|
|
166
|
+
const allServerUsage = [];
|
|
167
|
+
if (collection.item) {
|
|
168
|
+
const tags = extractTags(collection.item);
|
|
169
|
+
if (tags.length > 0) {
|
|
170
|
+
openapi.tags = tags;
|
|
113
171
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
else if ('text/plain' in content) {
|
|
136
|
-
// Preserve schema if it exists, otherwise keep an empty object
|
|
137
|
-
if (!content['text/plain'].schema || Object.keys(content['text/plain'].schema).length === 0) {
|
|
138
|
-
content['text/plain'] = {};
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// Ensure all methods have a description, but don't add an empty one if it doesn't exist
|
|
143
|
-
if (!method.description) {
|
|
144
|
-
delete method.description;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
});
|
|
172
|
+
collection.item.forEach((item) => {
|
|
173
|
+
const { paths: itemPaths, components: itemComponents, serverUsage } = processItem(item);
|
|
174
|
+
allServerUsage.push(...serverUsage);
|
|
175
|
+
openapi.paths = openapi.paths || {};
|
|
176
|
+
for (const [pathKey, pathItem] of Object.entries(itemPaths)) {
|
|
177
|
+
const normalizedPathKey = normalizePath(pathKey);
|
|
178
|
+
if (!pathItem) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
mergePathItem(openapi.paths, normalizedPathKey, pathItem);
|
|
182
|
+
}
|
|
183
|
+
if (itemComponents?.securitySchemes) {
|
|
184
|
+
mergeSecuritySchemes(openapi, itemComponents.securitySchemes);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const allUniquePaths = /* @__PURE__ */ new Set();
|
|
189
|
+
if (openapi.paths) {
|
|
190
|
+
for (const pathKey of Object.keys(openapi.paths)) {
|
|
191
|
+
allUniquePaths.add(pathKey);
|
|
150
192
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
193
|
+
}
|
|
194
|
+
const serverPlacement = analyzeServerDistribution(allServerUsage, allUniquePaths);
|
|
195
|
+
if (serverPlacement.document.length > 0) {
|
|
196
|
+
openapi.servers = serverPlacement.document;
|
|
197
|
+
}
|
|
198
|
+
if (openapi.paths) {
|
|
199
|
+
for (const [path, servers] of serverPlacement.pathItems.entries()) {
|
|
200
|
+
const normalizedPathKey = normalizePath(path);
|
|
201
|
+
const pathItem = openapi.paths[normalizedPathKey];
|
|
202
|
+
if (pathItem) {
|
|
203
|
+
pathItem.servers = servers;
|
|
204
|
+
}
|
|
154
205
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
206
|
+
for (const [path, methods] of serverPlacement.operations.entries()) {
|
|
207
|
+
const normalizedPathKey = normalizePath(path);
|
|
208
|
+
const pathItem = openapi.paths[normalizedPathKey];
|
|
209
|
+
if (!pathItem) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
for (const [method, servers] of methods.entries()) {
|
|
213
|
+
if (method in pathItem) {
|
|
214
|
+
const operation = pathItem[method];
|
|
215
|
+
if (operation && typeof operation === "object" && "responses" in operation) {
|
|
216
|
+
operation.servers = servers;
|
|
217
|
+
}
|
|
164
218
|
}
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (openapi.paths) {
|
|
223
|
+
cleanupOperations(openapi.paths);
|
|
224
|
+
}
|
|
225
|
+
if (Object.keys(openapi.components || {}).length === 0) {
|
|
226
|
+
delete openapi.components;
|
|
227
|
+
}
|
|
228
|
+
return pruneDocument(openapi);
|
|
168
229
|
}
|
|
230
|
+
export {
|
|
231
|
+
convert
|
|
232
|
+
};
|
|
233
|
+
//# sourceMappingURL=convert.js.map
|
package/dist/convert.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/convert.ts"],
|
|
4
|
-
"sourcesContent": ["import type { OpenAPIV3_1 } from '@scalar/openapi-types'\n\nimport { processAuth } from './helpers/authHelpers'\nimport { processExternalDocs } from './helpers/externalDocsHelper'\nimport { processItem } from './helpers/itemHelpers'\nimport { processLicenseAndContact } from './helpers/licenseContactHelper'\nimport { processLogo } from './helpers/logoHelper'\nimport { parseServers } from './helpers/serverHelpers'\nimport { normalizePath } from './helpers/urlHelpers'\nimport type { PostmanCollection } from './types'\n\n/**\n * Extracts tags from Postman collection folders\n */\nfunction extractTags(items: PostmanCollection['item']): OpenAPIV3_1.TagObject[] {\n const tags: OpenAPIV3_1.TagObject[] = []\n\n function processTagItem(item: any, parentPath: string = '') {\n if (item.item) {\n const currentPath = parentPath ? `${parentPath} > ${item.name}` : item.name\n\n // Add tag for the current folder\n tags.push({\n name: currentPath,\n ...(item.description && { description: item.description }),\n })\n\n // Process nested folders\n item.item.forEach((subItem: any) => processTagItem(subItem, currentPath))\n }\n }\n\n items.forEach((item) => processTagItem(item))\n return tags\n}\n\n/**\n * Converts a Postman Collection to an OpenAPI 3.1.0 document.\n * This function processes the collection's information, servers, authentication,\n * and items to create a corresponding OpenAPI structure.\n */\nexport function convert(postmanCollection: PostmanCollection | string): OpenAPIV3_1.Document {\n // Parse string input if provided\n const collection: PostmanCollection =\n typeof postmanCollection === 'string' ? JSON.parse(postmanCollection) : postmanCollection\n\n // Extract title from collection info, fallback to 'API' if not provided\n const title = collection.info.name || 'API'\n\n // Look for version in collection variables, default to '1.0.0'\n const version = (collection.variable?.find((v) => v.key === 'version')?.value as string) || '1.0.0'\n\n // Handle different description formats in Postman\n const description =\n typeof collection.info.description === 'string'\n ? collection.info.description\n : collection.info.description?.content || ''\n\n // Process license and contact information\n const { license, contact } = processLicenseAndContact(collection)\n\n // Process logo information\n const logo = processLogo(collection)\n\n // Initialize the OpenAPI document with required fields\n const openapi: OpenAPIV3_1.Document = {\n openapi: '3.1.0',\n info: {\n title,\n version,\n ...(description && { description }),\n ...(license && { license }),\n ...(contact && { contact }),\n ...(logo && { 'x-logo': logo }),\n },\n servers: parseServers(collection),\n paths: {},\n }\n\n // Process external docs\n const externalDocs = processExternalDocs(collection)\n if (externalDocs) {\n openapi.externalDocs = externalDocs\n }\n\n // Process authentication if present in the collection\n if (collection.auth) {\n const { securitySchemes, security } = processAuth(collection.auth)\n openapi.components = openapi.components || {}\n openapi.components.securitySchemes = {\n ...openapi.components.securitySchemes,\n ...securitySchemes,\n }\n openapi.security = security\n }\n\n // Process each item in the collection and merge into OpenAPI spec\n if (collection.item) {\n // Extract tags from folders\n const tags = extractTags(collection.item)\n if (tags.length > 0) {\n openapi.tags = tags\n }\n\n collection.item.forEach((item) => {\n const { paths: itemPaths, components: itemComponents } = processItem(item)\n\n // Merge paths from the current item\n openapi.paths = openapi.paths || {}\n for (const [pathKey, pathItem] of Object.entries(itemPaths)) {\n // Convert colon-style params to curly brace style\n const normalizedPathKey = normalizePath(pathKey)\n\n if (!pathItem) {\n continue\n }\n\n if (!openapi.paths[normalizedPathKey]) {\n openapi.paths[normalizedPathKey] = pathItem\n } else {\n openapi.paths[normalizedPathKey] = {\n ...openapi.paths[normalizedPathKey],\n ...pathItem,\n }\n }\n }\n\n // Merge security schemes from the current item\n if (itemComponents?.securitySchemes) {\n openapi.components = openapi.components || {}\n openapi.components.securitySchemes = {\n ...openapi.components.securitySchemes,\n ...itemComponents.securitySchemes,\n }\n }\n })\n }\n\n // Clean up the generated paths\n if (openapi.paths) {\n Object.values(openapi.paths).forEach((path) => {\n if (path) {\n Object.values(path).forEach((method) => {\n if (method && 'parameters' in method) {\n // Remove empty parameters array to keep spec clean\n if (method.parameters?.length === 0) {\n delete method.parameters\n }\n\n // Handle request bodies\n if (method.requestBody?.content) {\n const content = method.requestBody.content\n if (Object.keys(content).length === 0) {\n // Keep an empty requestBody with text/plain content\n method.requestBody = {\n content: {\n 'text/plain': {},\n },\n }\n } else if ('text/plain' in content) {\n // Preserve schema if it exists, otherwise keep an empty object\n if (!content['text/plain'].schema || Object.keys(content['text/plain'].schema).length === 0) {\n content['text/plain'] = {}\n }\n }\n }\n\n // Ensure all methods have a description, but don't add an empty one if it doesn't exist\n if (!method.description) {\n delete method.description\n }\n }\n })\n }\n })\n }\n\n // Remove empty components object\n if (Object.keys(openapi.components || {}).length === 0) {\n delete openapi.components\n }\n\n // Remove undefined properties recursively\n const removeUndefined = (obj: any): any => {\n if (Array.isArray(obj)) {\n return obj.map(removeUndefined).filter((item) => item !== undefined)\n }\n\n if (obj && typeof obj === 'object') {\n return Object.fromEntries(\n Object.entries(obj)\n .map(([key, value]) => [key, removeUndefined(value)])\n .filter(([_, value]) => value !== undefined),\n )\n }\n\n return obj\n }\n\n return removeUndefined(openapi)\n}\n"],
|
|
5
|
-
"mappings": "AAEA,SAAS,mBAAmB;AAC5B,SAAS,2BAA2B;AACpC,SAAS,
|
|
4
|
+
"sourcesContent": ["import type { OpenAPIV3_1 } from '@scalar/openapi-types'\n\nimport { processAuth } from '@/helpers/auth'\nimport { processContact } from '@/helpers/contact'\nimport { processExternalDocs } from '@/helpers/external-docs'\nimport { processLicense } from '@/helpers/license'\nimport { processLogo } from '@/helpers/logo'\nimport { processItem } from '@/helpers/path-items'\nimport { pruneDocument } from '@/helpers/prune-document'\nimport { analyzeServerDistribution } from '@/helpers/servers'\nimport { normalizePath } from '@/helpers/urls'\n\nimport type { Description, Item, ItemGroup, PostmanCollection } from './types'\n\nconst OPERATION_KEYS: readonly (keyof OpenAPIV3_1.PathItemObject)[] = [\n 'get',\n 'put',\n 'post',\n 'delete',\n 'options',\n 'head',\n 'patch',\n 'trace',\n]\n\nconst normalizeDescription = (description?: Description): string | undefined => {\n if (typeof description === 'string') {\n return description\n }\n\n return description?.content\n}\n\nconst parseCollectionInput = (postmanCollection: PostmanCollection | string): unknown => {\n if (typeof postmanCollection !== 'string') {\n return postmanCollection\n }\n\n try {\n return JSON.parse(postmanCollection) as PostmanCollection\n } catch (error) {\n const details = error instanceof Error ? error.message : 'Unknown parse error'\n const parseError = new Error(`Invalid Postman collection JSON: ${details}`)\n parseError.name = 'PostmanCollectionParseError'\n throw parseError\n }\n}\n\nconst validateCollectionShape = (collection: unknown): PostmanCollection => {\n if (!collection || typeof collection !== 'object') {\n throw new Error('Invalid Postman collection: expected an object')\n }\n\n const candidate = collection as Partial<PostmanCollection>\n\n if (!candidate.info) {\n throw new Error('Missing required info on Postman collection')\n }\n\n if (!candidate.item || !Array.isArray(candidate.item)) {\n throw new Error('Invalid Postman collection: item must be an array')\n }\n\n if (typeof candidate.info !== 'object') {\n throw new Error('Invalid Postman collection: info must be an object')\n }\n\n if (!candidate.info.name) {\n throw new Error('Missing required info.name on Postman collection')\n }\n\n if (!candidate.info.schema) {\n throw new Error('Invalid Postman collection: missing info.schema')\n }\n\n if (candidate.variable && !Array.isArray(candidate.variable)) {\n throw new Error('Invalid Postman collection: variable must be an array when provided')\n }\n\n return candidate as PostmanCollection\n}\n\n/**\n * Extracts tags from Postman collection folders.\n * We keep folder nesting using \" > \" so tag names stay readable while preserving hierarchy.\n * Requests do not produce tags; only folders are reflected as tags.\n */\nconst isItemGroup = (item: Item | ItemGroup): item is ItemGroup => 'item' in item && Array.isArray(item.item)\n\nconst extractTags = (items: PostmanCollection['item']): OpenAPIV3_1.TagObject[] => {\n const collectTags = (item: Item | ItemGroup, parentPath: string = ''): OpenAPIV3_1.TagObject[] => {\n if (!isItemGroup(item)) {\n return []\n }\n\n const nextPath = item.name ? (parentPath ? `${parentPath} > ${item.name}` : item.name) : parentPath\n const description = normalizeDescription(item.description)\n const currentTag: OpenAPIV3_1.TagObject[] = item.name?.length\n ? [\n {\n name: nextPath,\n ...(description && { description }),\n },\n ]\n : []\n\n return [...currentTag, ...item.item.flatMap((subItem) => collectTags(subItem, nextPath))]\n }\n\n return items.flatMap((item) => collectTags(item))\n}\n\nconst mergeSecuritySchemes = (\n openapi: OpenAPIV3_1.Document,\n securitySchemes?: OpenAPIV3_1.ComponentsObject['securitySchemes'],\n): void => {\n if (!securitySchemes || Object.keys(securitySchemes).length === 0) {\n return\n }\n\n openapi.components = openapi.components || {}\n openapi.components.securitySchemes = {\n ...(openapi.components.securitySchemes ?? {}),\n ...securitySchemes,\n }\n}\n\nconst mergePathItem = (\n paths: OpenAPIV3_1.PathsObject,\n normalizedPathKey: string,\n pathItem: OpenAPIV3_1.PathItemObject,\n): void => {\n const targetPath = (paths[normalizedPathKey] ?? {}) as OpenAPIV3_1.PathItemObject\n\n for (const [key, value] of Object.entries(pathItem) as [\n keyof OpenAPIV3_1.PathItemObject,\n OpenAPIV3_1.PathItemObject[keyof OpenAPIV3_1.PathItemObject],\n ][]) {\n if (value === undefined) {\n continue\n }\n\n const isOperationKey = OPERATION_KEYS.includes(key)\n\n if (isOperationKey && targetPath[key]) {\n const operationName = typeof key === 'string' ? key.toUpperCase() : String(key)\n console.warn(\n `Duplicate operation detected for ${operationName} ${normalizedPathKey}. Last operation will overwrite previous.`,\n )\n }\n\n targetPath[key] = value\n }\n\n paths[normalizedPathKey] = targetPath\n}\n\nconst cleanupOperations = (paths: OpenAPIV3_1.PathsObject): void => {\n Object.values(paths).forEach((pathItem) => {\n if (!pathItem) {\n return\n }\n\n OPERATION_KEYS.forEach((operationKey) => {\n const operation = pathItem[operationKey]\n if (!operation) {\n return\n }\n\n if ('parameters' in operation && operation.parameters?.length === 0) {\n delete operation.parameters\n }\n\n if ('requestBody' in operation && operation.requestBody && 'content' in operation.requestBody) {\n const content = operation.requestBody.content\n if (content && 'text/plain' in content) {\n const text = content['text/plain']\n if (!text?.schema || (text.schema && Object.keys(text.schema).length === 0)) {\n content['text/plain'] = {}\n }\n }\n }\n\n if (!operation.description) {\n delete operation.description\n }\n })\n })\n}\n\n/**\n * Converts a Postman Collection to an OpenAPI 3.1.0 document.\n * This function processes the collection's information, servers, authentication,\n * and items to create a corresponding OpenAPI structure.\n */\nexport function convert(postmanCollection: PostmanCollection | string): OpenAPIV3_1.Document {\n const collection = validateCollectionShape(parseCollectionInput(postmanCollection))\n\n // Extract title from collection info, fallback to 'API' if not provided\n const title = collection.info.name || 'API'\n\n // Look for version in collection variables, default to '1.0.0'\n const version = (collection.variable?.find((v) => v.key === 'version')?.value as string) || '1.0.0'\n\n // Handle different description formats in Postman\n const description = normalizeDescription(collection.info.description) || ''\n\n // Process license and contact information\n const license = processLicense(collection)\n const contact = processContact(collection)\n\n // Process logo information\n const logo = processLogo(collection)\n\n // Initialize the OpenAPI document with required fields\n const openapi: OpenAPIV3_1.Document = {\n openapi: '3.1.0',\n info: {\n title,\n version,\n ...(description && { description }),\n ...(license && { license }),\n ...(contact && { contact }),\n ...(logo && { 'x-logo': logo }),\n },\n paths: {},\n }\n\n // Process external docs\n const externalDocs = processExternalDocs(collection)\n if (externalDocs) {\n openapi.externalDocs = externalDocs\n }\n\n // Process authentication if present in the collection\n if (collection.auth) {\n const { securitySchemes, security } = processAuth(collection.auth)\n mergeSecuritySchemes(openapi, securitySchemes)\n openapi.security = security\n }\n\n // Process each item in the collection and merge into OpenAPI spec\n const allServerUsage: Array<{\n serverUrl: string\n path: string\n method: 'get' | 'put' | 'post' | 'delete' | 'options' | 'head' | 'patch' | 'trace'\n }> = []\n\n if (collection.item) {\n // Extract tags from folders\n const tags = extractTags(collection.item)\n if (tags.length > 0) {\n openapi.tags = tags\n }\n\n collection.item.forEach((item) => {\n const { paths: itemPaths, components: itemComponents, serverUsage } = processItem(item)\n\n // Collect server usage information\n allServerUsage.push(...serverUsage)\n\n // Merge paths from the current item\n openapi.paths = openapi.paths || {}\n for (const [pathKey, pathItem] of Object.entries(itemPaths)) {\n // Convert colon-style params to curly brace style\n const normalizedPathKey = normalizePath(pathKey)\n\n if (!pathItem) {\n continue\n }\n\n mergePathItem(openapi.paths, normalizedPathKey, pathItem)\n }\n\n // Merge security schemes from the current item\n if (itemComponents?.securitySchemes) {\n mergeSecuritySchemes(openapi, itemComponents.securitySchemes)\n }\n })\n }\n\n // Extract all unique paths from the document\n const allUniquePaths = new Set<string>()\n if (openapi.paths) {\n for (const pathKey of Object.keys(openapi.paths)) {\n allUniquePaths.add(pathKey)\n }\n }\n\n // Analyze server distribution and place servers at appropriate levels\n const serverPlacement = analyzeServerDistribution(allServerUsage, allUniquePaths)\n\n // Add servers to document level\n if (serverPlacement.document.length > 0) {\n openapi.servers = serverPlacement.document\n }\n\n // Add servers to path items\n if (openapi.paths) {\n for (const [path, servers] of serverPlacement.pathItems.entries()) {\n const normalizedPathKey = normalizePath(path)\n const pathItem = openapi.paths[normalizedPathKey]\n if (pathItem) {\n pathItem.servers = servers\n }\n }\n\n // Add servers to operations\n for (const [path, methods] of serverPlacement.operations.entries()) {\n const normalizedPathKey = normalizePath(path)\n const pathItem = openapi.paths[normalizedPathKey]\n if (!pathItem) {\n continue\n }\n for (const [method, servers] of methods.entries()) {\n if (method in pathItem) {\n const operation = pathItem[method as keyof typeof pathItem]\n if (operation && typeof operation === 'object' && 'responses' in operation) {\n operation.servers = servers\n }\n }\n }\n }\n }\n\n // Clean up the generated paths\n if (openapi.paths) {\n cleanupOperations(openapi.paths)\n }\n\n // Remove empty components object\n if (Object.keys(openapi.components || {}).length === 0) {\n delete openapi.components\n }\n\n return pruneDocument(openapi)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/helpers/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAkInC;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG;IACvC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAA;IACjE,QAAQ,EAAE,WAAW,CAAC,yBAAyB,EAAE,CAAA;CAClD,CAwBA"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const AUTH_SCHEMES = {
|
|
2
|
+
API_KEY: "apikeyAuth",
|
|
3
|
+
BASIC: "basicAuth",
|
|
4
|
+
BEARER: "bearerAuth",
|
|
5
|
+
OAUTH2: "oauth2Auth"
|
|
6
|
+
};
|
|
7
|
+
const OAUTH2_DEFAULTS = {
|
|
8
|
+
AUTHORIZE_URL: "/oauth/authorize",
|
|
9
|
+
TOKEN_URL: "/oauth/token"
|
|
10
|
+
};
|
|
11
|
+
function createApiKeyConfig() {
|
|
12
|
+
return {
|
|
13
|
+
scheme: {
|
|
14
|
+
type: "apiKey",
|
|
15
|
+
name: "api_key",
|
|
16
|
+
in: "header"
|
|
17
|
+
},
|
|
18
|
+
requirement: { [AUTH_SCHEMES.API_KEY]: [] }
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function createBasicConfig() {
|
|
22
|
+
return {
|
|
23
|
+
scheme: {
|
|
24
|
+
type: "http",
|
|
25
|
+
scheme: "basic"
|
|
26
|
+
},
|
|
27
|
+
requirement: { [AUTH_SCHEMES.BASIC]: [] }
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function createBearerConfig() {
|
|
31
|
+
return {
|
|
32
|
+
scheme: {
|
|
33
|
+
type: "http",
|
|
34
|
+
scheme: "bearer"
|
|
35
|
+
},
|
|
36
|
+
requirement: { [AUTH_SCHEMES.BEARER]: [] }
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function createOAuth2Config(auth) {
|
|
40
|
+
if (!auth) {
|
|
41
|
+
return {
|
|
42
|
+
scheme: {},
|
|
43
|
+
requirement: {}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const oauth2Attrs = auth.oauth2 || [];
|
|
47
|
+
const attrMap = /* @__PURE__ */ new Map();
|
|
48
|
+
oauth2Attrs.forEach((attr) => {
|
|
49
|
+
if (attr.key && attr.value !== void 0) {
|
|
50
|
+
attrMap.set(attr.key, String(attr.value));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const authUrl = attrMap.get("authUrl") || attrMap.get("authorizationUrl") || OAUTH2_DEFAULTS.AUTHORIZE_URL;
|
|
54
|
+
const tokenUrl = attrMap.get("accessTokenUrl") || attrMap.get("tokenUrl") || OAUTH2_DEFAULTS.TOKEN_URL;
|
|
55
|
+
const scopeValue = attrMap.get("scope") || "";
|
|
56
|
+
const scopes = {};
|
|
57
|
+
if (scopeValue) {
|
|
58
|
+
const scopeList = scopeValue.split(/[,\s]+/).filter(Boolean);
|
|
59
|
+
scopeList.forEach((scope) => {
|
|
60
|
+
scopes[scope] = scope;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
scheme: {
|
|
65
|
+
type: "oauth2",
|
|
66
|
+
flows: {
|
|
67
|
+
authorizationCode: {
|
|
68
|
+
authorizationUrl: authUrl,
|
|
69
|
+
tokenUrl,
|
|
70
|
+
scopes
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
requirement: { [AUTH_SCHEMES.OAUTH2]: Object.keys(scopes) }
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function createNoAuthConfig() {
|
|
78
|
+
return {
|
|
79
|
+
scheme: {},
|
|
80
|
+
requirement: {}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const AUTH_TYPE_HANDLERS = {
|
|
84
|
+
apikey: createApiKeyConfig,
|
|
85
|
+
basic: createBasicConfig,
|
|
86
|
+
bearer: createBearerConfig,
|
|
87
|
+
oauth2: createOAuth2Config,
|
|
88
|
+
noauth: createNoAuthConfig
|
|
89
|
+
};
|
|
90
|
+
function processAuth(auth) {
|
|
91
|
+
const securitySchemes = {};
|
|
92
|
+
const security = [];
|
|
93
|
+
try {
|
|
94
|
+
const handler = AUTH_TYPE_HANDLERS[auth.type];
|
|
95
|
+
if (!handler) {
|
|
96
|
+
throw new Error(`Unsupported authentication type: ${auth.type}`);
|
|
97
|
+
}
|
|
98
|
+
const { scheme, requirement } = handler(auth);
|
|
99
|
+
if (Object.keys(scheme).length > 0) {
|
|
100
|
+
const schemeKey = `${auth.type}Auth`;
|
|
101
|
+
securitySchemes[schemeKey] = scheme;
|
|
102
|
+
security.push(requirement);
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error("Error processing authentication:", error);
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
return { securitySchemes, security };
|
|
109
|
+
}
|
|
110
|
+
export {
|
|
111
|
+
processAuth
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=auth.js.map
|