@sdk-it/spec 0.18.0 → 0.19.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/dist/lib/loaders/load-spec.d.ts +1 -0
- package/dist/lib/loaders/load-spec.d.ts.map +1 -1
- package/dist/lib/loaders/load-spec.js +13 -1
- package/dist/lib/loaders/load-spec.js.map +2 -2
- package/dist/lib/loaders/postman/postman-converter.d.ts +4 -0
- package/dist/lib/loaders/postman/postman-converter.d.ts.map +1 -0
- package/dist/lib/loaders/postman/postman-converter.js +486 -0
- package/dist/lib/loaders/postman/postman-converter.js.map +7 -0
- package/dist/lib/loaders/postman/spec-types.d.ts +581 -0
- package/dist/lib/loaders/postman/spec-types.d.ts.map +1 -0
- package/dist/lib/loaders/postman/spec-types.js +1 -0
- package/dist/lib/loaders/postman/spec-types.js.map +7 -0
- package/dist/lib/loaders/remote-loader.d.ts +1 -2
- package/dist/lib/loaders/remote-loader.d.ts.map +1 -1
- package/dist/lib/loaders/remote-loader.js.map +2 -2
- package/dist/lib/operation.test.d.ts +2 -0
- package/dist/lib/operation.test.d.ts.map +1 -0
- package/dist/lib/{test.js → operation.test.js} +1 -1
- package/dist/lib/{test.js.map → operation.test.js.map} +1 -1
- package/package.json +1 -1
- package/dist/lib/test.d.ts +0 -2
- package/dist/lib/test.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-spec.d.ts","sourceRoot":"","sources":["../../../src/lib/loaders/load-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"load-spec.d.ts","sourceRoot":"","sources":["../../../src/lib/loaders/load-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAqBvD,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAMvE;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAMxD"}
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { loadLocal } from "./local-loader.js";
|
|
2
|
+
import { convertPostmanToOpenAPI } from "./postman/postman-converter.js";
|
|
2
3
|
import { loadRemote } from "./remote-loader.js";
|
|
3
|
-
function
|
|
4
|
+
function isPostman(content) {
|
|
5
|
+
return typeof content === "object" && content !== null && "info" in content && typeof content.info === "object" && content.info !== null && "item" in content && Array.isArray(content.item) && "schema" in content.info && typeof content.info.schema === "string" && content.info.schema.includes("//schema.getpostman.com/");
|
|
6
|
+
}
|
|
7
|
+
async function loadSpec(location) {
|
|
8
|
+
const content = await loadFile(location);
|
|
9
|
+
if (isPostman(content)) {
|
|
10
|
+
return convertPostmanToOpenAPI(content);
|
|
11
|
+
}
|
|
12
|
+
return content;
|
|
13
|
+
}
|
|
14
|
+
function loadFile(location) {
|
|
4
15
|
const [protocol] = location.split(":");
|
|
5
16
|
if (protocol === "http" || protocol === "https") {
|
|
6
17
|
return loadRemote(location);
|
|
@@ -8,6 +19,7 @@ function loadSpec(location) {
|
|
|
8
19
|
return loadLocal(location);
|
|
9
20
|
}
|
|
10
21
|
export {
|
|
22
|
+
loadFile,
|
|
11
23
|
loadSpec
|
|
12
24
|
};
|
|
13
25
|
//# sourceMappingURL=load-spec.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/loaders/load-spec.ts"],
|
|
4
|
-
"sourcesContent": ["import type { OpenAPIObject } from 'openapi3-ts/oas31';\n\nimport { loadLocal } from './local-loader.js';\nimport { loadRemote } from './remote-loader.js';\n\nexport function loadSpec(location: string): Promise<OpenAPIObject> {\n const [protocol] = location.split(':');\n if (protocol === 'http' || protocol === 'https') {\n return loadRemote(location);\n }\n return loadLocal(location);\n}\n"],
|
|
5
|
-
"mappings": "AAEA,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import type { OpenAPIObject } from 'openapi3-ts/oas31';\n\nimport { loadLocal } from './local-loader.js';\nimport { convertPostmanToOpenAPI } from './postman/postman-converter.js';\nimport type { PostmanCollection } from './postman/spec-types.js';\nimport { loadRemote } from './remote-loader.js';\n\nfunction isPostman(content: unknown): content is PostmanCollection {\n return (\n typeof content === 'object' &&\n content !== null &&\n 'info' in content &&\n typeof content.info === 'object' &&\n content.info !== null &&\n 'item' in content &&\n Array.isArray(content.item) &&\n 'schema' in content.info &&\n typeof content.info.schema === 'string' &&\n content.info.schema.includes('//schema.getpostman.com/')\n );\n}\nexport async function loadSpec(location: string): Promise<OpenAPIObject> {\n const content = await loadFile(location);\n if (isPostman(content)) {\n return convertPostmanToOpenAPI(content);\n }\n return content as OpenAPIObject;\n}\n\nexport function loadFile<T>(location: string): Promise<T> {\n const [protocol] = location.split(':');\n if (protocol === 'http' || protocol === 'https') {\n return loadRemote(location);\n }\n return loadLocal(location);\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,iBAAiB;AAC1B,SAAS,+BAA+B;AAExC,SAAS,kBAAkB;AAE3B,SAAS,UAAU,SAAgD;AACjE,SACE,OAAO,YAAY,YACnB,YAAY,QACZ,UAAU,WACV,OAAO,QAAQ,SAAS,YACxB,QAAQ,SAAS,QACjB,UAAU,WACV,MAAM,QAAQ,QAAQ,IAAI,KAC1B,YAAY,QAAQ,QACpB,OAAO,QAAQ,KAAK,WAAW,YAC/B,QAAQ,KAAK,OAAO,SAAS,0BAA0B;AAE3D;AACA,eAAsB,SAAS,UAA0C;AACvE,QAAM,UAAU,MAAM,SAAS,QAAQ;AACvC,MAAI,UAAU,OAAO,GAAG;AACtB,WAAO,wBAAwB,OAAO;AAAA,EACxC;AACA,SAAO;AACT;AAEO,SAAS,SAAY,UAA8B;AACxD,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM,GAAG;AACrC,MAAI,aAAa,UAAU,aAAa,SAAS;AAC/C,WAAO,WAAW,QAAQ;AAAA,EAC5B;AACA,SAAO,UAAU,QAAQ;AAC3B;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postman-converter.d.ts","sourceRoot":"","sources":["../../../../src/lib/loaders/postman/postman-converter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EASd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAQV,iBAAiB,EAOlB,MAAM,cAAc,CAAC;AAglBtB,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,iBAAiB,GAC5B,aAAa,CA6Bf"}
|
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
function descriptionToText(description) {
|
|
2
|
+
if (!description) {
|
|
3
|
+
return void 0;
|
|
4
|
+
}
|
|
5
|
+
if (typeof description === "string") {
|
|
6
|
+
return description;
|
|
7
|
+
}
|
|
8
|
+
if (description.content) {
|
|
9
|
+
return description.content;
|
|
10
|
+
}
|
|
11
|
+
return void 0;
|
|
12
|
+
}
|
|
13
|
+
function isFolder(item) {
|
|
14
|
+
return "item" in item;
|
|
15
|
+
}
|
|
16
|
+
function isRequest(item) {
|
|
17
|
+
return !!item.request;
|
|
18
|
+
}
|
|
19
|
+
function processItems(items, parentTags, globalTags, paths, securitySchemes) {
|
|
20
|
+
for (const item of items) {
|
|
21
|
+
if (!isFolder(item) && !isRequest(item)) {
|
|
22
|
+
console.warn(
|
|
23
|
+
`Skipping item ${item.name} because it is not a folder or request`
|
|
24
|
+
);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (isFolder(item)) {
|
|
28
|
+
if (item.auth) {
|
|
29
|
+
processAuthScheme(item.auth, securitySchemes);
|
|
30
|
+
}
|
|
31
|
+
if (!globalTags.some((tag) => tag.name === item.name)) {
|
|
32
|
+
globalTags.push({
|
|
33
|
+
name: item.name,
|
|
34
|
+
description: descriptionToText(item.description)
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const currentTags = [...parentTags, item.name];
|
|
38
|
+
processItems(item.item, currentTags, globalTags, paths, securitySchemes);
|
|
39
|
+
} else if (isRequest(item)) {
|
|
40
|
+
let operation;
|
|
41
|
+
if (typeof item.request === "string") {
|
|
42
|
+
const url = new URL(item.request);
|
|
43
|
+
operation = requestToOperation(
|
|
44
|
+
{
|
|
45
|
+
name: url.pathname,
|
|
46
|
+
response: [{ code: 200 }],
|
|
47
|
+
request: {
|
|
48
|
+
method: "get",
|
|
49
|
+
url: {
|
|
50
|
+
path: url.pathname.split("/").slice(1)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
securitySchemes
|
|
55
|
+
);
|
|
56
|
+
} else {
|
|
57
|
+
const auth = item.request.auth;
|
|
58
|
+
operation = requestToOperation(
|
|
59
|
+
{
|
|
60
|
+
name: item.name,
|
|
61
|
+
request: { ...item.request, auth },
|
|
62
|
+
response: item.response
|
|
63
|
+
},
|
|
64
|
+
securitySchemes
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
paths[operation.path] ??= {};
|
|
68
|
+
Object.assign(paths[operation.path], {
|
|
69
|
+
[operation.method]: {
|
|
70
|
+
tags: parentTags.length ? parentTags : void 0,
|
|
71
|
+
...operation.operation
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function coerceVariable(query) {
|
|
78
|
+
if (!query.key) {
|
|
79
|
+
throw new Error("Invalid query parameter format");
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
key: query.key,
|
|
83
|
+
description: descriptionToText(query.description)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function coerceQuery(query) {
|
|
87
|
+
if (!query.key) {
|
|
88
|
+
throw new Error("Invalid query parameter format");
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
key: query.key,
|
|
92
|
+
description: descriptionToText(query.description)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function coerceUrl(url) {
|
|
96
|
+
if (!url) {
|
|
97
|
+
throw new Error("Invalid URL format");
|
|
98
|
+
}
|
|
99
|
+
if (typeof url === "string") {
|
|
100
|
+
return {
|
|
101
|
+
path: url.split("/").slice(1),
|
|
102
|
+
query: [],
|
|
103
|
+
variable: []
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (typeof url.path === "string") {
|
|
107
|
+
return {
|
|
108
|
+
path: url.path.split("/").slice(1),
|
|
109
|
+
query: (url.query ?? []).map(coerceQuery),
|
|
110
|
+
variable: (url.variable ?? []).map(coerceVariable)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
path: (url.path ?? []).map((p) => {
|
|
115
|
+
if (typeof p === "string") {
|
|
116
|
+
return p;
|
|
117
|
+
}
|
|
118
|
+
throw new Error("Invalid URL path format");
|
|
119
|
+
}),
|
|
120
|
+
query: (url.query ?? []).map(coerceQuery),
|
|
121
|
+
variable: (url.variable ?? []).map(coerceVariable)
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function coerceResponseHeader(header) {
|
|
125
|
+
if (!header) {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
if (typeof header === "string") {
|
|
129
|
+
throw new Error(`Invalid header format: ${header}`);
|
|
130
|
+
}
|
|
131
|
+
return header.map((h) => {
|
|
132
|
+
if (typeof h === "string") {
|
|
133
|
+
return {
|
|
134
|
+
key: h,
|
|
135
|
+
value: null
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return h;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function processAuthScheme(auth, securitySchemes) {
|
|
142
|
+
if (!auth || auth.type === "noauth")
|
|
143
|
+
return null;
|
|
144
|
+
const getAuthAttr = (key) => {
|
|
145
|
+
if (!auth || auth.type === "noauth")
|
|
146
|
+
return void 0;
|
|
147
|
+
const authType = auth[auth.type];
|
|
148
|
+
if (!authType)
|
|
149
|
+
return void 0;
|
|
150
|
+
const attr = authType.find((a) => a.key === key);
|
|
151
|
+
return attr ? String(attr.value) : void 0;
|
|
152
|
+
};
|
|
153
|
+
const schemeId = `${auth.type}Auth`;
|
|
154
|
+
switch (auth.type) {
|
|
155
|
+
case "apikey": {
|
|
156
|
+
const key = getAuthAttr("key") || "api_key";
|
|
157
|
+
const in_ = getAuthAttr("in") || "header";
|
|
158
|
+
securitySchemes[schemeId] = {
|
|
159
|
+
type: "apiKey",
|
|
160
|
+
name: key,
|
|
161
|
+
in: in_,
|
|
162
|
+
description: "API key authentication"
|
|
163
|
+
};
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case "basic":
|
|
167
|
+
securitySchemes[schemeId] = {
|
|
168
|
+
type: "http",
|
|
169
|
+
scheme: "basic",
|
|
170
|
+
description: "Basic HTTP authentication"
|
|
171
|
+
};
|
|
172
|
+
break;
|
|
173
|
+
case "bearer": {
|
|
174
|
+
const token = getAuthAttr("token");
|
|
175
|
+
securitySchemes[schemeId] = {
|
|
176
|
+
type: "http",
|
|
177
|
+
scheme: "bearer",
|
|
178
|
+
description: "Bearer token authentication",
|
|
179
|
+
...token ? { bearerFormat: "JWT" } : {}
|
|
180
|
+
};
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
case "oauth2": {
|
|
184
|
+
const flowType = getAuthAttr("grant_type") || "implicit";
|
|
185
|
+
securitySchemes[schemeId] = {
|
|
186
|
+
type: "oauth2",
|
|
187
|
+
description: "OAuth 2.0 authentication",
|
|
188
|
+
flows: {
|
|
189
|
+
[flowType === "authorization_code" ? "authorizationCode" : flowType]: {
|
|
190
|
+
authorizationUrl: getAuthAttr("authUrl") || "https://example.com/oauth/authorize",
|
|
191
|
+
tokenUrl: getAuthAttr("tokenUrl") || "https://example.com/oauth/token",
|
|
192
|
+
scopes: {}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
case "digest":
|
|
199
|
+
securitySchemes[schemeId] = {
|
|
200
|
+
type: "http",
|
|
201
|
+
scheme: "digest",
|
|
202
|
+
description: "Digest authentication"
|
|
203
|
+
};
|
|
204
|
+
break;
|
|
205
|
+
case "awsv4":
|
|
206
|
+
securitySchemes[schemeId] = {
|
|
207
|
+
type: "apiKey",
|
|
208
|
+
name: "Authorization",
|
|
209
|
+
in: "header",
|
|
210
|
+
description: "AWS Signature v4 authentication"
|
|
211
|
+
};
|
|
212
|
+
break;
|
|
213
|
+
default:
|
|
214
|
+
securitySchemes[schemeId] = {
|
|
215
|
+
type: "apiKey",
|
|
216
|
+
name: "Authorization",
|
|
217
|
+
in: "header",
|
|
218
|
+
description: `${auth.type} authentication`
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return schemeId;
|
|
222
|
+
}
|
|
223
|
+
function generateSecurityRequirement(auth, securitySchemes) {
|
|
224
|
+
if (!auth || auth.type === "noauth")
|
|
225
|
+
return [];
|
|
226
|
+
const schemeId = `${auth.type}Auth`;
|
|
227
|
+
if (securitySchemes[schemeId]) {
|
|
228
|
+
return [{ [schemeId]: [] }];
|
|
229
|
+
}
|
|
230
|
+
return [];
|
|
231
|
+
}
|
|
232
|
+
function requestToOperation(item, securitySchemes) {
|
|
233
|
+
const url = coerceUrl(item.request.url);
|
|
234
|
+
const headers = Array.isArray(item.request.header) ? item.request.header : [];
|
|
235
|
+
const parameters = [
|
|
236
|
+
...url.query.filter((param) => !param.disabled).map((param) => {
|
|
237
|
+
return {
|
|
238
|
+
in: "query",
|
|
239
|
+
name: param.key,
|
|
240
|
+
required: false,
|
|
241
|
+
description: param.description,
|
|
242
|
+
schema: {
|
|
243
|
+
...param.value && !isNaN(Number(param.value)) ? { type: "number" } : param.value === "true" || param.value === "false" ? { type: "boolean" } : { type: "string" }
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
}),
|
|
247
|
+
...url.variable.map((param) => {
|
|
248
|
+
return {
|
|
249
|
+
in: "path",
|
|
250
|
+
name: param.key,
|
|
251
|
+
required: true,
|
|
252
|
+
description: param.description,
|
|
253
|
+
schema: {
|
|
254
|
+
...param.value && !isNaN(Number(param.value)) ? { type: "number" } : param.value === "true" || param.value === "false" ? { type: "boolean" } : { type: "string" }
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}),
|
|
258
|
+
...headers.filter(
|
|
259
|
+
(h) => !h.disabled && h.key.toLowerCase() !== "accept" && h.key.toLowerCase() !== "content-type"
|
|
260
|
+
).map((header) => {
|
|
261
|
+
return {
|
|
262
|
+
in: "header",
|
|
263
|
+
name: header.key,
|
|
264
|
+
required: false,
|
|
265
|
+
description: descriptionToText(header.description),
|
|
266
|
+
schema: {
|
|
267
|
+
type: "string"
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
})
|
|
271
|
+
];
|
|
272
|
+
const acceptHeaderIdx = headers.findIndex(
|
|
273
|
+
(h) => h.key.toLowerCase() === "accept"
|
|
274
|
+
);
|
|
275
|
+
const contentTypeIdx = headers.findIndex(
|
|
276
|
+
(h) => h.key.toLowerCase() === "content-type"
|
|
277
|
+
);
|
|
278
|
+
const [acceptHeaderValue] = acceptHeaderIdx !== -1 ? headers.splice(acceptHeaderIdx, 1).map((h) => h.value) : [];
|
|
279
|
+
const [contentTypeValue] = contentTypeIdx !== -1 ? headers.splice(contentTypeIdx, 1).map((h) => h.value) : [];
|
|
280
|
+
let security;
|
|
281
|
+
if (item.request.auth) {
|
|
282
|
+
const schemeId = processAuthScheme(item.request.auth, securitySchemes);
|
|
283
|
+
if (schemeId) {
|
|
284
|
+
security = [{ [schemeId]: [] }];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
path: `/${url.path.join("/")}`.replace(/:([^/]+)/g, "{$1}"),
|
|
289
|
+
method: (item.request.method ?? "get").toLowerCase(),
|
|
290
|
+
operation: {
|
|
291
|
+
summary: item.name,
|
|
292
|
+
description: descriptionToText(item.request.description),
|
|
293
|
+
parameters,
|
|
294
|
+
security,
|
|
295
|
+
responses: !item.response || item.response.length === 0 ? {
|
|
296
|
+
200: {
|
|
297
|
+
description: "Successful response"
|
|
298
|
+
}
|
|
299
|
+
} : item.response.reduce((acc, response) => {
|
|
300
|
+
const headers2 = coerceResponseHeader(response.header);
|
|
301
|
+
const contentTypeIdx2 = headers2.findIndex(
|
|
302
|
+
(h) => h.key.toLowerCase() === "content-type"
|
|
303
|
+
);
|
|
304
|
+
const [contentTypeValue2] = contentTypeIdx2 !== -1 ? headers2.splice(contentTypeIdx2).map((h) => h.value) : [];
|
|
305
|
+
const contentType = response.body ? contentTypeValue2 || "application/json" : "application/octet-stream";
|
|
306
|
+
return {
|
|
307
|
+
...acc,
|
|
308
|
+
[response.code ?? 200]: {
|
|
309
|
+
description: response.name ? response.name : `Response for ${response.code}`,
|
|
310
|
+
content: {
|
|
311
|
+
[contentType]: {
|
|
312
|
+
schema: bodyToSchema(response.body)
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
}, {}),
|
|
318
|
+
requestBody: item.request.body ? requestBodyToOperationBody(
|
|
319
|
+
contentTypeValue || "application/json",
|
|
320
|
+
item.request.body
|
|
321
|
+
) : void 0
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function inferSchemaType(value) {
|
|
326
|
+
if (!value)
|
|
327
|
+
return { type: "string" };
|
|
328
|
+
if (!isNaN(Number(value))) {
|
|
329
|
+
return { type: "number" };
|
|
330
|
+
}
|
|
331
|
+
if (value === "true" || value === "false") {
|
|
332
|
+
return { type: "boolean" };
|
|
333
|
+
}
|
|
334
|
+
return { type: "string" };
|
|
335
|
+
}
|
|
336
|
+
function requestBodyToOperationBody(contentType, body) {
|
|
337
|
+
if (body.mode === "raw") {
|
|
338
|
+
return {
|
|
339
|
+
content: {
|
|
340
|
+
[contentType]: {
|
|
341
|
+
schema: bodyToSchema(body.raw)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
} else if (body.mode === "urlencoded") {
|
|
346
|
+
const properties = {};
|
|
347
|
+
(body.urlencoded || []).filter((param) => !param.disabled).forEach((param) => {
|
|
348
|
+
properties[param.key] = {
|
|
349
|
+
type: "string",
|
|
350
|
+
description: descriptionToText(param.description)
|
|
351
|
+
};
|
|
352
|
+
});
|
|
353
|
+
return {
|
|
354
|
+
content: {
|
|
355
|
+
"application/x-www-form-urlencoded": {
|
|
356
|
+
schema: {
|
|
357
|
+
type: "object",
|
|
358
|
+
properties
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
} else if (body.mode === "formdata") {
|
|
364
|
+
const properties = {};
|
|
365
|
+
(body.formdata || []).filter((param) => !param.disabled).forEach((param) => {
|
|
366
|
+
if (param.type === "text") {
|
|
367
|
+
properties[param.key] = {
|
|
368
|
+
type: "string",
|
|
369
|
+
description: descriptionToText(param.description)
|
|
370
|
+
};
|
|
371
|
+
} else if (param.type === "file") {
|
|
372
|
+
properties[param.key] = {
|
|
373
|
+
type: "string",
|
|
374
|
+
format: "binary",
|
|
375
|
+
description: descriptionToText(param.description)
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
return {
|
|
380
|
+
content: {
|
|
381
|
+
"multipart/form-data": {
|
|
382
|
+
schema: {
|
|
383
|
+
type: "object",
|
|
384
|
+
properties
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
throw new Error(
|
|
391
|
+
`Unsupported request body mode: ${body.mode}. Supported modes are: raw, urlencoded, formdata`
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
function bodyToSchema(bodyString) {
|
|
395
|
+
if (!bodyString) {
|
|
396
|
+
return void 0;
|
|
397
|
+
}
|
|
398
|
+
let body;
|
|
399
|
+
try {
|
|
400
|
+
body = JSON.parse(bodyString);
|
|
401
|
+
} catch (error) {
|
|
402
|
+
console.warn(
|
|
403
|
+
`Failed to parse JSON body: ${bodyString}. Treating as plain string.`,
|
|
404
|
+
error
|
|
405
|
+
);
|
|
406
|
+
return { type: "string", example: bodyString };
|
|
407
|
+
}
|
|
408
|
+
return toSchema(body);
|
|
409
|
+
}
|
|
410
|
+
function toSchema(body) {
|
|
411
|
+
const typeMap = {
|
|
412
|
+
"<number>": "number",
|
|
413
|
+
"<string>": "string",
|
|
414
|
+
"<boolean>": "boolean",
|
|
415
|
+
false: "boolean",
|
|
416
|
+
true: "boolean"
|
|
417
|
+
};
|
|
418
|
+
if (Array.isArray(body)) {
|
|
419
|
+
return {
|
|
420
|
+
type: "array",
|
|
421
|
+
items: toSchema(body[0])
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
if (typeof body === "object" && body !== null) {
|
|
425
|
+
const properties = {};
|
|
426
|
+
for (const [key, value] of Object.entries(body)) {
|
|
427
|
+
properties[key] = toSchema(value);
|
|
428
|
+
}
|
|
429
|
+
return {
|
|
430
|
+
type: "object",
|
|
431
|
+
properties
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
if (typeof body === "string") {
|
|
435
|
+
return {
|
|
436
|
+
type: typeMap[body] ?? "string"
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
if (typeof body === "number") {
|
|
440
|
+
return {
|
|
441
|
+
type: "number"
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
if (typeof body === "boolean") {
|
|
445
|
+
return {
|
|
446
|
+
type: "boolean"
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
if (body === null) {
|
|
450
|
+
return {
|
|
451
|
+
type: "null"
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
console.warn(`Unknown type for body: ${body}. Defaulting to string.`, body);
|
|
455
|
+
return {
|
|
456
|
+
type: "string"
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
function convertPostmanToOpenAPI(collection) {
|
|
460
|
+
const tags = [];
|
|
461
|
+
const paths = {};
|
|
462
|
+
const securitySchemes = {};
|
|
463
|
+
if (collection.auth) {
|
|
464
|
+
processAuthScheme(collection.auth, securitySchemes);
|
|
465
|
+
}
|
|
466
|
+
processItems(collection.item, [], tags, paths, securitySchemes);
|
|
467
|
+
return {
|
|
468
|
+
openapi: "3.1.0",
|
|
469
|
+
info: {
|
|
470
|
+
title: collection.info.name,
|
|
471
|
+
version: "1.0.0",
|
|
472
|
+
description: descriptionToText(collection.info.description)
|
|
473
|
+
},
|
|
474
|
+
tags,
|
|
475
|
+
paths,
|
|
476
|
+
// Only add security at top level if there's collection auth
|
|
477
|
+
security: collection.auth ? generateSecurityRequirement(collection.auth, securitySchemes) : void 0,
|
|
478
|
+
components: Object.keys(securitySchemes).length > 0 ? {
|
|
479
|
+
securitySchemes
|
|
480
|
+
} : void 0
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
export {
|
|
484
|
+
convertPostmanToOpenAPI
|
|
485
|
+
};
|
|
486
|
+
//# sourceMappingURL=postman-converter.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/loaders/postman/postman-converter.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n ContentObject,\n OpenAPIObject,\n OperationObject,\n ParameterObject,\n PathsObject,\n RequestBodyObject,\n ResponseObject,\n SchemaObject,\n SecuritySchemeObject,\n TagObject,\n} from 'openapi3-ts/oas31';\n\nimport type {\n Auth,\n Description,\n Folder,\n Header,\n Headers,\n Item,\n Items,\n PostmanCollection,\n PostmanRequest,\n QueryParam,\n Request,\n RequestBody,\n Url,\n Variable,\n} from './spec-types';\n\nfunction descriptionToText(description?: Description) {\n if (!description) {\n return undefined;\n }\n if (typeof description === 'string') {\n return description;\n }\n if (description.content) {\n return description.content;\n }\n return undefined;\n}\n\ntype OurQueryParam = Omit<QueryParam, 'key'> & {\n key: string;\n description?: string;\n};\ntype OurVariable = Omit<QueryParam, 'key'> & {\n key: string;\n description?: string;\n};\ntype OurUrl = {\n path: string[];\n query: OurQueryParam[];\n variable: OurVariable[];\n};\n\nfunction isFolder(item: Items): item is Folder & { name: string } {\n return 'item' in item;\n}\n\nfunction isRequest(\n item: Items,\n): item is Item & { name: string; request: Request } {\n return !!item.request;\n}\n\n/**\n * Recursively processes items and folders in a Postman collection\n * @param items Array of Postman items (requests or folders)\n * @param parentTags Array of parent folder tags for proper nesting\n */\nfunction processItems(\n items: Items[],\n parentTags: string[],\n globalTags: TagObject[],\n paths: PathsObject,\n securitySchemes: Record<string, SecuritySchemeObject>,\n) {\n for (const item of items) {\n if (!isFolder(item) && !isRequest(item)) {\n console.warn(\n `Skipping item ${item.name} because it is not a folder or request`,\n );\n continue;\n }\n\n if (isFolder(item)) {\n // Process folder-level auth if it exists\n if (item.auth) {\n processAuthScheme(item.auth, securitySchemes);\n }\n\n // Add this folder as a tag if not already added\n if (!globalTags.some((tag) => tag.name === item.name)) {\n globalTags.push({\n name: item.name,\n description: descriptionToText(item.description),\n });\n }\n\n const currentTags = [...parentTags, item.name];\n processItems(item.item, currentTags, globalTags, paths, securitySchemes);\n } else if (isRequest(item)) {\n // Process this request\n let operation: ReturnType<typeof requestToOperation>;\n if (typeof item.request === 'string') {\n const url = new URL(item.request);\n operation = requestToOperation(\n {\n name: url.pathname,\n response: [{ code: 200 }],\n request: {\n method: 'get',\n url: {\n path: url.pathname.split('/').slice(1),\n },\n },\n },\n securitySchemes,\n );\n } else {\n const auth = item.request.auth;\n operation = requestToOperation(\n {\n name: item.name,\n request: { ...item.request, auth },\n response: item.response,\n },\n securitySchemes,\n );\n }\n\n paths[operation.path] ??= {};\n Object.assign(paths[operation.path], {\n [operation.method]: {\n tags: parentTags.length ? parentTags : undefined,\n ...operation.operation,\n },\n });\n }\n }\n}\n\nfunction coerceVariable(query: Variable): OurVariable {\n if (!query.key) {\n throw new Error('Invalid query parameter format');\n }\n return {\n key: query.key,\n description: descriptionToText(query.description),\n };\n}\nfunction coerceQuery(query: QueryParam): OurQueryParam {\n if (!query.key) {\n throw new Error('Invalid query parameter format');\n }\n return {\n key: query.key,\n description: descriptionToText(query.description),\n };\n}\nfunction coerceUrl(url?: Url): OurUrl {\n if (!url) {\n throw new Error('Invalid URL format');\n }\n if (typeof url === 'string') {\n return {\n path: url.split('/').slice(1),\n query: [],\n variable: [],\n };\n }\n if (typeof url.path === 'string') {\n return {\n path: url.path.split('/').slice(1),\n query: (url.query ?? []).map(coerceQuery),\n variable: (url.variable ?? []).map(coerceVariable),\n };\n }\n return {\n path: (url.path ?? []).map((p) => {\n if (typeof p === 'string') {\n return p;\n }\n throw new Error('Invalid URL path format');\n }),\n query: (url.query ?? []).map(coerceQuery),\n variable: (url.variable ?? []).map(coerceVariable),\n };\n}\n\nfunction coerceResponseHeader(header?: Headers) {\n if (!header) {\n return [];\n }\n if (typeof header === 'string') {\n throw new Error(`Invalid header format: ${header}`);\n }\n return header.map((h) => {\n if (typeof h === 'string') {\n return {\n key: h,\n value: null,\n };\n }\n return h;\n });\n}\n\n/**\n * Process an auth scheme and add it to securitySchemes\n */\nfunction processAuthScheme(\n auth: Auth,\n securitySchemes: Record<string, SecuritySchemeObject>,\n): string | null {\n if (!auth || auth.type === 'noauth') return null;\n\n const getAuthAttr = (key: string): string | undefined => {\n if (!auth || auth.type === 'noauth') return undefined;\n const authType = auth[auth.type];\n if (!authType) return undefined;\n const attr = authType.find((a) => a.key === key);\n return attr ? String(attr.value) : undefined;\n };\n\n const schemeId = `${auth.type}Auth`;\n\n switch (auth.type) {\n case 'apikey': {\n const key = getAuthAttr('key') || 'api_key';\n const in_ = getAuthAttr('in') || 'header';\n securitySchemes[schemeId] = {\n type: 'apiKey',\n name: key,\n in: in_ as 'header' | 'query' | 'cookie',\n description: 'API key authentication',\n };\n break;\n }\n case 'basic':\n securitySchemes[schemeId] = {\n type: 'http',\n scheme: 'basic',\n description: 'Basic HTTP authentication',\n };\n break;\n case 'bearer': {\n const token = getAuthAttr('token');\n securitySchemes[schemeId] = {\n type: 'http',\n scheme: 'bearer',\n description: 'Bearer token authentication',\n ...(token ? { bearerFormat: 'JWT' } : {}),\n };\n break;\n }\n case 'oauth2': {\n const flowType = getAuthAttr('grant_type') || 'implicit';\n securitySchemes[schemeId] = {\n type: 'oauth2',\n description: 'OAuth 2.0 authentication',\n flows: {\n [flowType === 'authorization_code' ? 'authorizationCode' : flowType]:\n {\n authorizationUrl:\n getAuthAttr('authUrl') || 'https://example.com/oauth/authorize',\n tokenUrl:\n getAuthAttr('tokenUrl') || 'https://example.com/oauth/token',\n scopes: {},\n },\n },\n };\n break;\n }\n case 'digest':\n securitySchemes[schemeId] = {\n type: 'http',\n scheme: 'digest',\n description: 'Digest authentication',\n };\n break;\n case 'awsv4':\n securitySchemes[schemeId] = {\n type: 'apiKey',\n name: 'Authorization',\n in: 'header',\n description: 'AWS Signature v4 authentication',\n };\n break;\n default:\n securitySchemes[schemeId] = {\n type: 'apiKey',\n name: 'Authorization',\n in: 'header',\n description: `${auth.type} authentication`,\n };\n }\n\n return schemeId;\n}\n\nfunction generateSecurityRequirement(\n auth: Auth,\n securitySchemes: Record<string, SecuritySchemeObject>,\n) {\n if (!auth || auth.type === 'noauth') return [];\n\n const schemeId = `${auth.type}Auth`;\n\n // Only include if the scheme was successfully processed\n if (securitySchemes[schemeId]) {\n return [{ [schemeId]: [] }];\n }\n\n return [];\n}\n\nfunction requestToOperation(\n item: Exclude<Item, 'name' | 'request'> & {\n name: string;\n request: PostmanRequest;\n },\n securitySchemes: Record<string, SecuritySchemeObject>,\n) {\n const url = coerceUrl(item.request.url);\n const headers = Array.isArray(item.request.header)\n ? item.request.header\n : ([] as Header[]);\n\n const parameters: ParameterObject[] = [\n ...url.query\n .filter((param) => !param.disabled)\n .map((param) => {\n return {\n in: 'query',\n name: param.key,\n required: false,\n description: param.description,\n schema: {\n ...(param.value && !isNaN(Number(param.value))\n ? { type: 'number' }\n : param.value === 'true' || param.value === 'false'\n ? { type: 'boolean' }\n : { type: 'string' }),\n },\n } satisfies ParameterObject;\n }),\n\n ...url.variable.map((param) => {\n return {\n in: 'path',\n name: param.key,\n required: true,\n description: param.description,\n schema: {\n ...(param.value && !isNaN(Number(param.value))\n ? { type: 'number' }\n : param.value === 'true' || param.value === 'false'\n ? { type: 'boolean' }\n : { type: 'string' }),\n },\n } satisfies ParameterObject;\n }),\n\n ...headers\n .filter(\n (h) =>\n !h.disabled &&\n h.key.toLowerCase() !== 'accept' &&\n h.key.toLowerCase() !== 'content-type',\n )\n .map((header) => {\n return {\n in: 'header',\n name: header.key,\n required: false,\n description: descriptionToText(header.description),\n schema: {\n type: 'string',\n },\n } satisfies ParameterObject;\n }),\n ];\n\n // Extract Accept and Content-Type headers\n const acceptHeaderIdx = headers.findIndex(\n (h) => h.key.toLowerCase() === 'accept',\n );\n const contentTypeIdx = headers.findIndex(\n (h) => h.key.toLowerCase() === 'content-type',\n );\n const [acceptHeaderValue] =\n acceptHeaderIdx !== -1\n ? headers.splice(acceptHeaderIdx, 1).map((h) => h.value)\n : [];\n const [contentTypeValue] =\n contentTypeIdx !== -1\n ? headers.splice(contentTypeIdx, 1).map((h) => h.value)\n : [];\n\n let security;\n if (item.request.auth) {\n const schemeId = processAuthScheme(item.request.auth, securitySchemes);\n if (schemeId) {\n security = [{ [schemeId]: [] }];\n }\n }\n\n return {\n path: `/${url.path.join('/')}`.replace(/:([^/]+)/g, '{$1}'),\n method: (item.request.method ?? 'get').toLowerCase(),\n operation: {\n summary: item.name,\n description: descriptionToText(item.request.description),\n parameters,\n security,\n responses:\n !item.response || item.response.length === 0\n ? {\n 200: {\n description: 'Successful response',\n },\n }\n : item.response.reduce((acc, response) => {\n const headers = coerceResponseHeader(response.header);\n const contentTypeIdx = headers.findIndex(\n (h) => h.key.toLowerCase() === 'content-type',\n );\n const [contentTypeValue] =\n contentTypeIdx !== -1\n ? headers.splice(contentTypeIdx).map((h) => h.value)\n : [];\n const contentType = response.body\n ? contentTypeValue || 'application/json'\n : 'application/octet-stream';\n\n return {\n ...acc,\n [response.code ?? 200]: {\n description: response.name\n ? response.name\n : `Response for ${response.code}`,\n content: {\n [contentType]: {\n schema: bodyToSchema(response.body),\n },\n },\n } satisfies ResponseObject,\n };\n }, {}),\n requestBody: item.request.body\n ? requestBodyToOperationBody(\n contentTypeValue || 'application/json',\n item.request.body,\n )\n : undefined,\n } satisfies OperationObject,\n };\n}\n\n/**\n * Helper function to determine the likely type of a value\n */\nfunction inferSchemaType(value: string | null): { type: string } {\n if (!value) return { type: 'string' };\n\n // Check if value is a number\n if (!isNaN(Number(value))) {\n return { type: 'number' };\n }\n\n // Check if value is a boolean\n if (value === 'true' || value === 'false') {\n return { type: 'boolean' };\n }\n\n // Default to string\n return { type: 'string' };\n}\n\nfunction requestBodyToOperationBody(\n contentType: string,\n body: RequestBody,\n): RequestBodyObject {\n if (body.mode === 'raw') {\n return {\n content: {\n [contentType]: {\n schema: bodyToSchema(body.raw),\n },\n },\n };\n } else if (body.mode === 'urlencoded') {\n const properties: Record<string, any> = {};\n (body.urlencoded || [])\n .filter((param) => !param.disabled)\n .forEach((param) => {\n properties[param.key] = {\n type: 'string',\n description: descriptionToText(param.description),\n };\n });\n\n return {\n content: {\n 'application/x-www-form-urlencoded': {\n schema: {\n type: 'object',\n properties,\n },\n },\n } satisfies ContentObject,\n };\n } else if (body.mode === 'formdata') {\n const properties: SchemaObject['properties'] = {};\n (body.formdata || [])\n .filter((param) => !param.disabled)\n .forEach((param) => {\n if (param.type === 'text') {\n properties[param.key] = {\n type: 'string',\n description: descriptionToText(param.description),\n };\n } else if (param.type === 'file') {\n properties[param.key] = {\n type: 'string',\n format: 'binary',\n description: descriptionToText(param.description),\n };\n }\n });\n\n return {\n content: {\n 'multipart/form-data': {\n schema: {\n type: 'object',\n properties,\n },\n },\n } satisfies ContentObject,\n };\n }\n\n throw new Error(\n `Unsupported request body mode: ${body.mode}. Supported modes are: raw, urlencoded, formdata`,\n );\n}\n\nfunction bodyToSchema(bodyString?: string | null): SchemaObject | undefined {\n if (!bodyString) {\n return undefined;\n }\n\n let body: unknown;\n try {\n body = JSON.parse(bodyString);\n } catch (error) {\n console.warn(\n `Failed to parse JSON body: ${bodyString}. Treating as plain string.`,\n error,\n );\n return { type: 'string', example: bodyString };\n }\n\n return toSchema(body);\n}\n\nfunction toSchema(body: unknown | unknown[]): any {\n const typeMap: Record<string, string> = {\n '<number>': 'number',\n '<string>': 'string',\n '<boolean>': 'boolean',\n false: 'boolean',\n true: 'boolean',\n };\n if (Array.isArray(body)) {\n return {\n type: 'array',\n items: toSchema(body[0]),\n };\n }\n if (typeof body === 'object' && body !== null) {\n const properties: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(body)) {\n properties[key] = toSchema(value);\n }\n return {\n type: 'object',\n properties,\n };\n }\n if (typeof body === 'string') {\n return {\n type: typeMap[body] ?? 'string',\n };\n }\n if (typeof body === 'number') {\n return {\n type: 'number',\n };\n }\n if (typeof body === 'boolean') {\n return {\n type: 'boolean',\n };\n }\n if (body === null) {\n return {\n type: 'null',\n };\n }\n console.warn(`Unknown type for body: ${body}. Defaulting to string.`, body);\n return {\n type: 'string',\n };\n}\n\nexport function convertPostmanToOpenAPI(\n collection: PostmanCollection,\n): OpenAPIObject {\n const tags: TagObject[] = [];\n const paths: PathsObject = {};\n const securitySchemes: Record<string, SecuritySchemeObject> = {};\n\n if (collection.auth) {\n processAuthScheme(collection.auth, securitySchemes);\n }\n processItems(collection.item, [], tags, paths, securitySchemes);\n return {\n openapi: '3.1.0',\n info: {\n title: collection.info.name,\n version: '1.0.0',\n description: descriptionToText(collection.info.description),\n },\n tags,\n paths,\n // Only add security at top level if there's collection auth\n security: collection.auth\n ? generateSecurityRequirement(collection.auth, securitySchemes)\n : undefined,\n components:\n Object.keys(securitySchemes).length > 0\n ? {\n securitySchemes,\n }\n : undefined,\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["headers", "contentTypeIdx", "contentTypeValue"]
|
|
7
|
+
}
|