@scalar/postman-to-openapi 0.1.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +33 -0
  3. package/dist/convert.d.ts +9 -0
  4. package/dist/convert.d.ts.map +1 -0
  5. package/dist/convert.js +156 -0
  6. package/dist/helpers/authHelpers.d.ts +12 -0
  7. package/dist/helpers/authHelpers.d.ts.map +1 -0
  8. package/dist/helpers/authHelpers.js +99 -0
  9. package/dist/helpers/externalDocsHelper.d.ts +10 -0
  10. package/dist/helpers/externalDocsHelper.d.ts.map +1 -0
  11. package/dist/helpers/externalDocsHelper.js +40 -0
  12. package/dist/helpers/formDataHelpers.d.ts +8 -0
  13. package/dist/helpers/formDataHelpers.d.ts.map +1 -0
  14. package/dist/helpers/formDataHelpers.js +42 -0
  15. package/dist/helpers/itemHelpers.d.ts +13 -0
  16. package/dist/helpers/itemHelpers.d.ts.map +1 -0
  17. package/dist/helpers/itemHelpers.js +236 -0
  18. package/dist/helpers/licenseContactHelper.d.ts +14 -0
  19. package/dist/helpers/licenseContactHelper.d.ts.map +1 -0
  20. package/dist/helpers/licenseContactHelper.js +73 -0
  21. package/dist/helpers/logoHelper.d.ts +13 -0
  22. package/dist/helpers/logoHelper.d.ts.map +1 -0
  23. package/dist/helpers/logoHelper.js +24 -0
  24. package/dist/helpers/md-utils.d.ts +6 -0
  25. package/dist/helpers/md-utils.d.ts.map +1 -0
  26. package/dist/helpers/md-utils.js +40 -0
  27. package/dist/helpers/parameterHelpers.d.ts +12 -0
  28. package/dist/helpers/parameterHelpers.d.ts.map +1 -0
  29. package/dist/helpers/parameterHelpers.js +109 -0
  30. package/dist/helpers/requestBodyHelpers.d.ts +8 -0
  31. package/dist/helpers/requestBodyHelpers.d.ts.map +1 -0
  32. package/dist/helpers/requestBodyHelpers.js +79 -0
  33. package/dist/helpers/responseHelpers.d.ts +9 -0
  34. package/dist/helpers/responseHelpers.d.ts.map +1 -0
  35. package/dist/helpers/responseHelpers.js +52 -0
  36. package/dist/helpers/schemaHelpers.d.ts +15 -0
  37. package/dist/helpers/schemaHelpers.d.ts.map +1 -0
  38. package/dist/helpers/schemaHelpers.js +52 -0
  39. package/dist/helpers/serverHelpers.d.ts +9 -0
  40. package/dist/helpers/serverHelpers.d.ts.map +1 -0
  41. package/dist/helpers/serverHelpers.js +29 -0
  42. package/dist/helpers/statusCodeHelpers.d.ts +10 -0
  43. package/dist/helpers/statusCodeHelpers.d.ts.map +1 -0
  44. package/dist/helpers/statusCodeHelpers.js +47 -0
  45. package/dist/helpers/urlHelpers.d.ts +19 -0
  46. package/dist/helpers/urlHelpers.d.ts.map +1 -0
  47. package/dist/helpers/urlHelpers.js +52 -0
  48. package/dist/index.d.ts +3 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +2 -0
  51. package/dist/types.d.ts +229 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +1 -0
  54. package/package.json +58 -0
@@ -0,0 +1,236 @@
1
+ import { processAuth } from './authHelpers.js';
2
+ import { parseMdTable } from './md-utils.js';
3
+ import { extractParameters } from './parameterHelpers.js';
4
+ import { extractRequestBody } from './requestBodyHelpers.js';
5
+ import { extractResponses } from './responseHelpers.js';
6
+ import { extractStatusCodesFromTests } from './statusCodeHelpers.js';
7
+ import { extractPathFromUrl, extractPathParameterNames, normalizePath, } from './urlHelpers.js';
8
+ /**
9
+ * Processes a Postman collection item or item group and returns
10
+ * the corresponding OpenAPI paths and components.
11
+ * Handles nested item groups, extracts request details, and generates corresponding
12
+ * OpenAPI path items and operations.
13
+ */
14
+ export function processItem(item, parentTags = [], parentPath = '') {
15
+ const paths = {};
16
+ const components = {};
17
+ if ('item' in item && Array.isArray(item.item)) {
18
+ const newParentTags = item.name ? [...parentTags, item.name] : parentTags;
19
+ item.item.forEach((childItem) => {
20
+ const childResult = processItem(childItem, newParentTags, `${parentPath}/${item.name || ''}`);
21
+ // Merge child paths and components
22
+ for (const [pathKey, pathItem] of Object.entries(childResult.paths)) {
23
+ if (!paths[pathKey]) {
24
+ paths[pathKey] = pathItem;
25
+ }
26
+ else {
27
+ paths[pathKey] = {
28
+ ...paths[pathKey],
29
+ ...pathItem,
30
+ };
31
+ }
32
+ }
33
+ // Merge components.securitySchemes
34
+ if (childResult.components.securitySchemes) {
35
+ components.securitySchemes = {
36
+ ...components.securitySchemes,
37
+ ...childResult.components.securitySchemes,
38
+ };
39
+ }
40
+ });
41
+ return { paths, components };
42
+ }
43
+ if (!('request' in item)) {
44
+ return { paths, components };
45
+ }
46
+ const { request, name, response } = item;
47
+ const method = (typeof request === 'string' ? 'get' : request.method || 'get').toLowerCase();
48
+ const path = extractPathFromUrl(typeof request === 'string'
49
+ ? request
50
+ : typeof request.url === 'string'
51
+ ? request.url
52
+ : (request.url?.raw ?? ''));
53
+ // Normalize path parameters from ':param' to '{param}'
54
+ const normalizedPath = normalizePath(path);
55
+ // Extract path parameter names
56
+ const pathParameterNames = extractPathParameterNames(normalizedPath);
57
+ // Extract operation ID if present
58
+ const { operationId, summary } = extractOperationInfo(name);
59
+ const description = typeof request === 'string'
60
+ ? ''
61
+ : typeof request.description === 'string'
62
+ ? request.description
63
+ : (request.description?.content ?? '');
64
+ const operationObject = {
65
+ tags: parentTags.length > 0 ? [parentTags.join(' > ')] : ['default'],
66
+ summary,
67
+ description,
68
+ responses: extractResponses(response || []),
69
+ parameters: [],
70
+ };
71
+ // Only add operationId if it was explicitly provided
72
+ if (operationId) {
73
+ operationObject.operationId = operationId;
74
+ }
75
+ // Parse parameters from the description's Markdown table
76
+ if (operationObject.description) {
77
+ const { descriptionWithoutTable, parametersFromTable } = parseParametersFromDescription(operationObject.description);
78
+ operationObject.description = descriptionWithoutTable.trim();
79
+ // Extract parameters from the request (query, path, header)
80
+ const extractedParameters = extractParameters(request);
81
+ // Merge parameters, giving priority to those from the Markdown table
82
+ const mergedParameters = new Map();
83
+ // Add extracted parameters, filtering out path parameters not in the path
84
+ extractedParameters.forEach((param) => {
85
+ if (param.name) {
86
+ if (param.in === 'path' && !pathParameterNames.includes(param.name)) {
87
+ return;
88
+ }
89
+ mergedParameters.set(param.name, param);
90
+ }
91
+ });
92
+ // Add parameters from table, filtering out path parameters not in the path
93
+ parametersFromTable.forEach((param) => {
94
+ if (param.name) {
95
+ if (param.in === 'path' && !pathParameterNames.includes(param.name)) {
96
+ return;
97
+ }
98
+ mergedParameters.set(param.name, param);
99
+ }
100
+ });
101
+ operationObject.parameters = Array.from(mergedParameters.values());
102
+ }
103
+ if (typeof request !== 'string' && request.auth) {
104
+ if (!operationObject.security) {
105
+ operationObject.security = [];
106
+ }
107
+ const { securitySchemes, security } = processAuth(request.auth);
108
+ if (!components.securitySchemes) {
109
+ components.securitySchemes = {};
110
+ }
111
+ components.securitySchemes = {
112
+ ...components.securitySchemes,
113
+ ...securitySchemes,
114
+ };
115
+ operationObject.security.push(...security);
116
+ }
117
+ if (['post', 'put', 'patch'].includes(method) &&
118
+ typeof request !== 'string' &&
119
+ request.body) {
120
+ operationObject.requestBody = extractRequestBody(request.body);
121
+ }
122
+ if (!paths[path])
123
+ paths[path] = {};
124
+ const pathItem = paths[path];
125
+ pathItem[method] = operationObject;
126
+ // Extract status codes from tests
127
+ const statusCodes = extractStatusCodesFromTests(item);
128
+ // Handle responses
129
+ if (statusCodes.length > 0) {
130
+ const responses = {};
131
+ statusCodes.forEach((code) => {
132
+ responses[code.toString()] = {
133
+ description: 'Successful response',
134
+ content: {
135
+ 'application/json': {},
136
+ },
137
+ };
138
+ });
139
+ if (pathItem[method]) {
140
+ pathItem[method].responses = responses;
141
+ }
142
+ }
143
+ else if (item.response && item.response.length > 0) {
144
+ const firstResponse = item.response[0];
145
+ const statusCode = firstResponse.code || 200;
146
+ if (pathItem[method]) {
147
+ pathItem[method].responses = {
148
+ [statusCode.toString()]: {
149
+ description: firstResponse.status || 'Successful response',
150
+ content: {
151
+ 'application/json': {},
152
+ },
153
+ },
154
+ };
155
+ }
156
+ }
157
+ else {
158
+ if (pathItem[method]) {
159
+ pathItem[method].responses = {
160
+ '200': {
161
+ description: 'Successful response',
162
+ content: {
163
+ 'application/json': {},
164
+ },
165
+ },
166
+ };
167
+ }
168
+ }
169
+ return { paths, components };
170
+ }
171
+ // Helper function to parse parameters from the description if it is markdown
172
+ function parseParametersFromDescription(description) {
173
+ const lines = description.split('\n');
174
+ let inTable = false;
175
+ const tableLines = [];
176
+ const descriptionLines = [];
177
+ for (let i = 0; i < lines.length; i++) {
178
+ const line = lines[i];
179
+ // Detect the start of the table
180
+ if (line.trim().startsWith('|')) {
181
+ // Remove any preceding headers or empty lines before the table
182
+ while (descriptionLines.length > 0 &&
183
+ (descriptionLines[descriptionLines.length - 1].trim() === '' ||
184
+ descriptionLines[descriptionLines.length - 1].trim().startsWith('#'))) {
185
+ descriptionLines.pop();
186
+ }
187
+ // Start collecting table lines
188
+ inTable = true;
189
+ }
190
+ if (inTable) {
191
+ tableLines.push(line);
192
+ // Detect the end of the table (any line that doesn't start with '|', excluding the alignment line)
193
+ if (!line.trim().startsWith('|') && !line.trim().match(/^-+$/)) {
194
+ inTable = false;
195
+ }
196
+ }
197
+ else {
198
+ descriptionLines.push(line);
199
+ }
200
+ }
201
+ const tableMarkdown = tableLines.join('\n');
202
+ const parsedTable = parseMdTable(tableMarkdown);
203
+ const parametersFromTable = Object.values(parsedTable).map((paramData) => {
204
+ const paramIn = paramData.object;
205
+ const param = {
206
+ name: paramData.name,
207
+ in: paramIn,
208
+ description: paramData.description,
209
+ required: paramData.required === 'true',
210
+ schema: {
211
+ type: paramData.type,
212
+ },
213
+ };
214
+ if (paramData.example) {
215
+ param.example = paramData.example;
216
+ }
217
+ return param;
218
+ });
219
+ const descriptionWithoutTable = descriptionLines.join('\n');
220
+ return { descriptionWithoutTable, parametersFromTable };
221
+ }
222
+ // Instead of using regex with \s*, let's split this into two steps
223
+ function extractOperationInfo(name) {
224
+ if (!name)
225
+ return { operationId: undefined, summary: undefined };
226
+ // First check if the string ends with something in brackets
227
+ const match = name.match(/\[([^[\]]{0,1000})\]$/);
228
+ if (!match)
229
+ return { operationId: undefined, summary: name };
230
+ // Get the operation ID from inside brackets
231
+ const operationId = match[1];
232
+ // Trim the brackets part from the end using string operations instead of regex
233
+ const lastBracketIndex = name.lastIndexOf('[');
234
+ const summary = name.substring(0, lastBracketIndex).trim();
235
+ return { operationId, summary };
236
+ }
@@ -0,0 +1,14 @@
1
+ import type { OpenAPIV3_1 } from '@scalar/openapi-types';
2
+ import type { PostmanCollection } from '../types.js';
3
+ type InfoResult = {
4
+ license?: OpenAPIV3_1.LicenseObject;
5
+ contact?: OpenAPIV3_1.ContactObject;
6
+ };
7
+ /**
8
+ * Processes the license and contact information from a Postman Collection.
9
+ * This function checks for license and contact related variables in the collection
10
+ * and creates corresponding OpenAPI License and Contact Objects if the information is present.
11
+ */
12
+ export declare function processLicenseAndContact(collection: PostmanCollection): InfoResult;
13
+ export {};
14
+ //# sourceMappingURL=licenseContactHelper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"licenseContactHelper.d.ts","sourceRoot":"","sources":["../../src/helpers/licenseContactHelper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAY,MAAM,UAAU,CAAA;AAe3D,KAAK,UAAU,GAAG;IAChB,OAAO,CAAC,EAAE,WAAW,CAAC,aAAa,CAAA;IACnC,OAAO,CAAC,EAAE,WAAW,CAAC,aAAa,CAAA;CACpC,CAAA;AAmDD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,iBAAiB,GAC5B,UAAU,CAmBZ"}
@@ -0,0 +1,73 @@
1
+ // Constants for variable keys
2
+ const VARIABLE_KEYS = {
3
+ LICENSE: {
4
+ NAME: 'license.name',
5
+ URL: 'license.url',
6
+ },
7
+ CONTACT: {
8
+ NAME: 'contact.name',
9
+ URL: 'contact.url',
10
+ EMAIL: 'contact.email',
11
+ },
12
+ };
13
+ /**
14
+ * Finds a specific variable in the collection by its key
15
+ */
16
+ function findVariable(collection, key) {
17
+ return collection.variable?.find((v) => v.key === key);
18
+ }
19
+ /**
20
+ * Processes license information from collection variables
21
+ */
22
+ function processLicense(collection) {
23
+ const nameVar = findVariable(collection, VARIABLE_KEYS.LICENSE.NAME);
24
+ if (!nameVar?.value || typeof nameVar.value !== 'string')
25
+ return undefined;
26
+ const urlVar = findVariable(collection, VARIABLE_KEYS.LICENSE.URL);
27
+ return {
28
+ name: nameVar.value,
29
+ ...(urlVar?.value &&
30
+ typeof urlVar.value === 'string' && { url: urlVar.value }),
31
+ };
32
+ }
33
+ /**
34
+ * Processes contact information from collection variables
35
+ */
36
+ function processContact(collection) {
37
+ const nameVar = findVariable(collection, VARIABLE_KEYS.CONTACT.NAME);
38
+ const urlVar = findVariable(collection, VARIABLE_KEYS.CONTACT.URL);
39
+ const emailVar = findVariable(collection, VARIABLE_KEYS.CONTACT.EMAIL);
40
+ if (!nameVar?.value && !urlVar?.value && !emailVar?.value)
41
+ return undefined;
42
+ return {
43
+ ...(nameVar?.value &&
44
+ typeof nameVar.value === 'string' && { name: nameVar.value }),
45
+ ...(urlVar?.value &&
46
+ typeof urlVar.value === 'string' && { url: urlVar.value }),
47
+ ...(emailVar?.value &&
48
+ typeof emailVar.value === 'string' && { email: emailVar.value }),
49
+ };
50
+ }
51
+ /**
52
+ * Processes the license and contact information from a Postman Collection.
53
+ * This function checks for license and contact related variables in the collection
54
+ * and creates corresponding OpenAPI License and Contact Objects if the information is present.
55
+ */
56
+ export function processLicenseAndContact(collection) {
57
+ try {
58
+ const result = {};
59
+ const license = processLicense(collection);
60
+ if (license) {
61
+ result.license = license;
62
+ }
63
+ const contact = processContact(collection);
64
+ if (contact) {
65
+ result.contact = contact;
66
+ }
67
+ return result;
68
+ }
69
+ catch (error) {
70
+ console.error('Error processing license and contact information:', error);
71
+ throw error;
72
+ }
73
+ }
@@ -0,0 +1,13 @@
1
+ import type { PostmanCollection } from '../types.js';
2
+ /**
3
+ * Processes logo information from a Postman Collection.
4
+ * This function extracts logo-related variables from the collection
5
+ * and constructs an object with logo properties.
6
+ */
7
+ export declare function processLogo(postmanCollection: PostmanCollection): {
8
+ url: string;
9
+ backgroundColor: string;
10
+ altText: string;
11
+ href: string;
12
+ } | null;
13
+ //# sourceMappingURL=logoHelper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logoHelper.d.ts","sourceRoot":"","sources":["../../src/helpers/logoHelper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAEjD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,iBAAiB,EAAE,iBAAiB;;;;;SAoB/D"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Processes logo information from a Postman Collection.
3
+ * This function extracts logo-related variables from the collection
4
+ * and constructs an object with logo properties.
5
+ */
6
+ export function processLogo(postmanCollection) {
7
+ const logoVariables = postmanCollection.variable?.filter((v) => v.key?.startsWith('x-logo.')) ||
8
+ [];
9
+ if (logoVariables.length === 0)
10
+ return null;
11
+ const logo = {};
12
+ logoVariables.forEach((v) => {
13
+ if (v.key) {
14
+ const key = v.key.replace('x-logo.', '').replace('Var', '');
15
+ logo[key] = v.value;
16
+ }
17
+ });
18
+ return {
19
+ url: logo.url,
20
+ backgroundColor: logo.backgroundColor,
21
+ altText: logo.altText,
22
+ href: logo.href,
23
+ };
24
+ }
@@ -0,0 +1,6 @@
1
+ import type { TableObject } from '../types.js';
2
+ /**
3
+ * Parses a Markdown table and returns an object representation.
4
+ */
5
+ export declare function parseMdTable(md: string): TableObject;
6
+ //# sourceMappingURL=md-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md-utils.d.ts","sourceRoot":"","sources":["../../src/helpers/md-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,UAAU,CAAA;AAWtD;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAoCpD"}
@@ -0,0 +1,40 @@
1
+ const supHeaders = [
2
+ 'object',
3
+ 'name',
4
+ 'description',
5
+ 'example',
6
+ 'type',
7
+ 'required',
8
+ ];
9
+ /**
10
+ * Parses a Markdown table and returns an object representation.
11
+ */
12
+ export function parseMdTable(md) {
13
+ const lines = md.split('\n').filter((line) => line.trim() !== '');
14
+ if (lines.length < 3)
15
+ return {};
16
+ const header = lines[0]
17
+ .split('|')
18
+ .map((cell) => cell.trim())
19
+ .filter(Boolean);
20
+ if (!header.includes('object') || !header.includes('name'))
21
+ return {};
22
+ const headers = header.map((h) => (supHeaders.includes(h) ? h : false));
23
+ const rows = lines.slice(2).map((line) => line
24
+ .split('|')
25
+ .map((cell) => cell.trim())
26
+ .filter(Boolean));
27
+ const tableObj = rows.reduce((accTable, cell) => {
28
+ const cellObj = cell.reduce((accCell, field, index) => {
29
+ if (headers[index] && typeof headers[index] === 'string') {
30
+ accCell[headers[index]] = field;
31
+ }
32
+ return accCell;
33
+ }, {});
34
+ if (cellObj.name) {
35
+ accTable[cellObj.name] = cellObj;
36
+ }
37
+ return accTable;
38
+ }, {});
39
+ return tableObj;
40
+ }
@@ -0,0 +1,12 @@
1
+ import type { OpenAPIV3_1 } from '@scalar/openapi-types';
2
+ import type { Request } from '../types.js';
3
+ /**
4
+ * Extracts parameters from a Postman request and converts them to OpenAPI parameter objects.
5
+ * Processes query, path, and header parameters from the request URL and headers.
6
+ */
7
+ export declare function extractParameters(request: Request): OpenAPIV3_1.ParameterObject[];
8
+ /**
9
+ * Creates an OpenAPI parameter object from a Postman parameter.
10
+ */
11
+ export declare function createParameterObject(param: any, paramIn: 'query' | 'path' | 'header'): OpenAPIV3_1.ParameterObject;
12
+ //# sourceMappingURL=parameterHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parameterHelpers.d.ts","sourceRoot":"","sources":["../../src/helpers/parameterHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAU,OAAO,EAAE,MAAM,UAAU,CAAA;AAG/C;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,GACf,WAAW,CAAC,eAAe,EAAE,CA4D/B;AAsBD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,GAAG,EACV,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GACnC,WAAW,CAAC,eAAe,CAmC7B"}
@@ -0,0 +1,109 @@
1
+ import { inferSchemaType } from './schemaHelpers.js';
2
+ /**
3
+ * Extracts parameters from a Postman request and converts them to OpenAPI parameter objects.
4
+ * Processes query, path, and header parameters from the request URL and headers.
5
+ */
6
+ export function extractParameters(request) {
7
+ const parameters = [];
8
+ const parameterMap = new Map();
9
+ if (typeof request === 'string' || !request.url) {
10
+ return parameters;
11
+ }
12
+ const url = typeof request.url === 'string' ? { raw: request.url } : request.url;
13
+ // Process query parameters
14
+ if (url.query) {
15
+ url.query.forEach((param) => {
16
+ const paramObj = createParameterObject(param, 'query');
17
+ if (paramObj.name) {
18
+ parameterMap.set(paramObj.name, paramObj);
19
+ }
20
+ });
21
+ }
22
+ // Process path parameters
23
+ if (url.variable) {
24
+ url.variable.forEach((param) => {
25
+ const paramObj = createParameterObject(param, 'path');
26
+ if (paramObj.name) {
27
+ parameterMap.set(paramObj.name, paramObj);
28
+ }
29
+ });
30
+ }
31
+ // Include variables extracted from url.path array
32
+ if (url.path) {
33
+ const pathArray = Array.isArray(url.path) ? url.path : [url.path];
34
+ const extractedVariables = extractPathVariablesFromPathArray(pathArray);
35
+ extractedVariables.forEach((varName) => {
36
+ if (!parameterMap.has(varName)) {
37
+ parameterMap.set(varName, {
38
+ name: varName,
39
+ in: 'path',
40
+ required: true,
41
+ schema: {
42
+ type: 'string',
43
+ },
44
+ });
45
+ }
46
+ });
47
+ }
48
+ // Process header parameters
49
+ if (request.header && Array.isArray(request.header)) {
50
+ request.header.forEach((header) => {
51
+ const paramObj = createParameterObject(header, 'header');
52
+ if (paramObj.name) {
53
+ parameterMap.set(paramObj.name, paramObj);
54
+ }
55
+ });
56
+ }
57
+ return Array.from(parameterMap.values());
58
+ }
59
+ /**
60
+ * Helper function to extract variables from the url.path array.
61
+ */
62
+ function extractPathVariablesFromPathArray(pathArray) {
63
+ const variables = [];
64
+ const variableRegex = /{{\s*([\w.-]+)\s*}}/;
65
+ pathArray.forEach((segment) => {
66
+ const segmentString = typeof segment === 'string' ? segment : segment.value;
67
+ const match = segmentString.match(variableRegex);
68
+ if (match?.[1]) {
69
+ variables.push(match[1]);
70
+ }
71
+ });
72
+ return variables;
73
+ }
74
+ /**
75
+ * Creates an OpenAPI parameter object from a Postman parameter.
76
+ */
77
+ export function createParameterObject(param, paramIn) {
78
+ const parameter = {
79
+ name: param.key || '',
80
+ in: paramIn,
81
+ description: param.description,
82
+ };
83
+ // Path parameters are always required in OpenAPI
84
+ if (paramIn === 'path') {
85
+ parameter.required = true;
86
+ }
87
+ else if (paramIn === 'query') {
88
+ // Check if the parameter is required based on description or name
89
+ const isRequired = param.description?.toLowerCase().includes('[required]') ||
90
+ (param.key && param.key.toLowerCase() === 'required');
91
+ if (isRequired) {
92
+ parameter.required = true;
93
+ // Remove '[required]' from the description
94
+ if (parameter.description) {
95
+ parameter.description = parameter.description
96
+ .replace(/\[required\]/gi, '')
97
+ .trim();
98
+ }
99
+ }
100
+ }
101
+ if (param.value !== undefined) {
102
+ parameter.example = param.value;
103
+ parameter.schema = inferSchemaType(param.value);
104
+ }
105
+ else {
106
+ parameter.schema = { type: 'string' }; // Default to string if no value is provided
107
+ }
108
+ return parameter;
109
+ }
@@ -0,0 +1,8 @@
1
+ import type { OpenAPIV3_1 } from '@scalar/openapi-types';
2
+ import type { RequestBody } from '../types.js';
3
+ /**
4
+ * Extracts and converts the request body from a Postman request to an OpenAPI RequestBodyObject.
5
+ * Handles raw JSON, form-data, and URL-encoded body types, creating appropriate schemas and content types.
6
+ */
7
+ export declare function extractRequestBody(body: RequestBody): OpenAPIV3_1.RequestBodyObject;
8
+ //# sourceMappingURL=requestBodyHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestBodyHelpers.d.ts","sourceRoot":"","sources":["../../src/helpers/requestBodyHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAiB,WAAW,EAAuB,MAAM,UAAU,CAAA;AAI/E;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,WAAW,GAChB,WAAW,CAAC,iBAAiB,CAqB/B"}
@@ -0,0 +1,79 @@
1
+ import { processFormDataSchema } from './formDataHelpers.js';
2
+ import { createParameterObject } from './parameterHelpers.js';
3
+ /**
4
+ * Extracts and converts the request body from a Postman request to an OpenAPI RequestBodyObject.
5
+ * Handles raw JSON, form-data, and URL-encoded body types, creating appropriate schemas and content types.
6
+ */
7
+ export function extractRequestBody(body) {
8
+ const requestBody = {
9
+ content: {},
10
+ };
11
+ if (body.mode === 'raw') {
12
+ handleRawBody(body, requestBody);
13
+ return requestBody;
14
+ }
15
+ if (body.mode === 'formdata' && body.formdata) {
16
+ handleFormDataBody(body.formdata, requestBody);
17
+ return requestBody;
18
+ }
19
+ if (body.mode === 'urlencoded' && body.urlencoded) {
20
+ handleUrlEncodedBody(body.urlencoded, requestBody);
21
+ return requestBody;
22
+ }
23
+ return requestBody;
24
+ }
25
+ function handleRawBody(body, requestBody) {
26
+ try {
27
+ const jsonBody = JSON.parse(body.raw || '');
28
+ requestBody.content = {
29
+ 'application/json': {
30
+ schema: {
31
+ type: 'object',
32
+ examples: { default: { value: jsonBody } },
33
+ },
34
+ },
35
+ };
36
+ }
37
+ catch (error) {
38
+ requestBody.content = {
39
+ 'text/plain': {
40
+ schema: {
41
+ type: 'string',
42
+ examples: [body.raw],
43
+ },
44
+ },
45
+ };
46
+ }
47
+ }
48
+ function handleFormDataBody(formdata, requestBody) {
49
+ requestBody.content = {
50
+ 'multipart/form-data': {
51
+ schema: processFormDataSchema(formdata),
52
+ },
53
+ };
54
+ }
55
+ function handleUrlEncodedBody(urlencoded, requestBody) {
56
+ const schema = {
57
+ type: 'object',
58
+ properties: {},
59
+ required: [],
60
+ };
61
+ urlencoded.forEach((item) => {
62
+ if (schema.properties) {
63
+ const paramObject = createParameterObject(item, 'query');
64
+ schema.properties[item.key] = {
65
+ type: 'string',
66
+ examples: [item.value],
67
+ description: paramObject.description,
68
+ };
69
+ if (paramObject.required) {
70
+ schema.required?.push(item.key);
71
+ }
72
+ }
73
+ });
74
+ requestBody.content = {
75
+ 'application/x-www-form-urlencoded': {
76
+ schema,
77
+ },
78
+ };
79
+ }
@@ -0,0 +1,9 @@
1
+ import type { OpenAPIV3_1 } from '@scalar/openapi-types';
2
+ import type { Response } from '../types.js';
3
+ /**
4
+ * Extracts and converts Postman response objects to OpenAPI response objects.
5
+ * Processes response status codes, descriptions, headers, and body content,
6
+ * inferring schemas from example responses when possible.
7
+ */
8
+ export declare function extractResponses(responses: Response[]): OpenAPIV3_1.ResponsesObject;
9
+ //# sourceMappingURL=responseHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseHelpers.d.ts","sourceRoot":"","sources":["../../src/helpers/responseHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAc,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGpD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,QAAQ,EAAE,GACpB,WAAW,CAAC,eAAe,CAsB7B"}