@scalar/postman-to-openapi 0.1.49 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @scalar/postman-to-openapi
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [18b1be9]
8
+ - @scalar/oas-utils@0.2.128
9
+
10
+ ## 0.2.0
11
+
12
+ ### Minor Changes
13
+
14
+ - 018e8b2: feat: import Postman post-response scripts
15
+
16
+ ### Patch Changes
17
+
18
+ - 018e8b2: feat: cleaner Postman import (no 'default' tag, no made up responses)
19
+ - 018e8b2: fix: /raw and / paths are handled specifically
20
+ - Updated dependencies [bf961b1]
21
+ - Updated dependencies [a176b7e]
22
+ - @scalar/oas-utils@0.2.127
23
+
3
24
  ## 0.1.49
4
25
 
5
26
  ### Patch Changes
@@ -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;AASxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AA2BhD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,MAAM,GAAG,WAAW,CAAC,QAAQ,CAsK3F"}
1
+ {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AASxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AA2BhD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,MAAM,GAAG,WAAW,CAAC,QAAQ,CA+J3F"}
package/dist/convert.js CHANGED
@@ -88,17 +88,8 @@ export function convert(postmanCollection) {
88
88
  for (const [pathKey, pathItem] of Object.entries(itemPaths)) {
89
89
  // Convert colon-style params to curly brace style
90
90
  const normalizedPathKey = normalizePath(pathKey);
91
- /**
92
- * this is a bit of a hack to skip empty paths only if they have no parameters
93
- * because there is a test where if I remove the empty path it breaks the test
94
- * but there is another test where if I leave the empty path it breaks the test
95
- * so I added this check to only remove the empty path if all the methods on it have no parameters
96
- */
97
- if (normalizedPathKey === '/') {
98
- const allMethodsHaveEmptyParams = Object.values(pathItem || {}).every((method) => !method.parameters || method.parameters.length === 0);
99
- if (allMethodsHaveEmptyParams) {
100
- continue;
101
- }
91
+ if (!pathItem) {
92
+ continue;
102
93
  }
103
94
  if (!openapi.paths[normalizedPathKey]) {
104
95
  openapi.paths[normalizedPathKey] = pathItem;
@@ -109,18 +100,6 @@ export function convert(postmanCollection) {
109
100
  ...pathItem,
110
101
  };
111
102
  }
112
- // Handle the /raw endpoint specifically
113
- if (normalizedPathKey === '/raw' && pathItem?.post) {
114
- if (pathItem.post.requestBody?.content['text/plain']) {
115
- pathItem.post.requestBody.content['application/json'] = {
116
- schema: {
117
- type: 'object',
118
- examples: [],
119
- },
120
- };
121
- delete pathItem.post.requestBody.content['text/plain'];
122
- }
123
- }
124
103
  }
125
104
  // Merge security schemes from the current item
126
105
  if (itemComponents?.securitySchemes) {
@@ -173,5 +152,17 @@ export function convert(postmanCollection) {
173
152
  if (Object.keys(openapi.components || {}).length === 0) {
174
153
  delete openapi.components;
175
154
  }
176
- return openapi;
155
+ // Remove undefined properties recursively
156
+ const removeUndefined = (obj) => {
157
+ if (Array.isArray(obj)) {
158
+ return obj.map(removeUndefined).filter((item) => item !== undefined);
159
+ }
160
+ if (obj && typeof obj === 'object') {
161
+ return Object.fromEntries(Object.entries(obj)
162
+ .map(([key, value]) => [key, removeUndefined(value)])
163
+ .filter(([_, value]) => value !== undefined));
164
+ }
165
+ return obj;
166
+ };
167
+ return removeUndefined(openapi);
177
168
  }
@@ -1 +1 @@
1
- {"version":3,"file":"itemHelpers.d.ts","sourceRoot":"","sources":["../../src/helpers/itemHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAU/C;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,UAAU,GAAE,MAAM,EAAO,EACzB,UAAU,GAAE,MAAW,GACtB;IACD,KAAK,EAAE,WAAW,CAAC,WAAW,CAAA;IAC9B,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAA;CACzC,CAqIA"}
1
+ {"version":3,"file":"itemHelpers.d.ts","sourceRoot":"","sources":["../../src/helpers/itemHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAW/C;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,UAAU,GAAE,MAAM,EAAO,EACzB,UAAU,GAAE,MAAW,GACtB;IACD,KAAK,EAAE,WAAW,CAAC,WAAW,CAAA;IAC9B,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAA;CACzC,CA2IA"}
@@ -1,6 +1,7 @@
1
1
  import { processAuth } from './authHelpers.js';
2
2
  import { parseMdTable } from './md-utils.js';
3
3
  import { extractParameters } from './parameterHelpers.js';
4
+ import { processPostResponseScripts } from './postResponseScripts.js';
4
5
  import { extractRequestBody } from './requestBodyHelpers.js';
5
6
  import { extractResponses } from './responseHelpers.js';
6
7
  import { extractPathFromUrl, extractPathParameterNames, normalizePath } from './urlHelpers.js';
@@ -57,12 +58,17 @@ export function processItem(item, parentTags = [], parentPath = '') {
57
58
  ? request.description
58
59
  : (request.description?.content ?? '');
59
60
  const operationObject = {
60
- tags: parentTags.length > 0 ? [parentTags.join(' > ')] : ['default'],
61
+ tags: parentTags.length > 0 ? [parentTags.join(' > ')] : undefined,
61
62
  summary,
62
63
  description,
63
64
  responses: extractResponses(response || [], item),
64
65
  parameters: [],
65
66
  };
67
+ // Add post-response scripts if present
68
+ const postResponseScript = processPostResponseScripts(item.event);
69
+ if (postResponseScript) {
70
+ operationObject['x-post-response'] = postResponseScript;
71
+ }
66
72
  // Only add operationId if it was explicitly provided
67
73
  if (operationId) {
68
74
  operationObject.operationId = operationId;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Processes Postman test scripts and converts them to OpenAPI x-post-response extension
3
+ */
4
+ export declare function processPostResponseScripts(events?: any[]): string | undefined;
5
+ //# sourceMappingURL=postResponseScripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postResponseScripts.d.ts","sourceRoot":"","sources":["../../src/helpers/postResponseScripts.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,GAAE,GAAG,EAAO,GAAG,MAAM,GAAG,SAAS,CASjF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Processes Postman test scripts and converts them to OpenAPI x-post-response extension
3
+ */
4
+ export function processPostResponseScripts(events = []) {
5
+ // Find test event
6
+ const testEvent = events.find((event) => event.listen === 'test');
7
+ if (!testEvent?.script?.exec) {
8
+ return undefined;
9
+ }
10
+ // Join script lines into a single string
11
+ return testEvent.script.exec.join('\n').trim();
12
+ }
@@ -5,5 +5,5 @@ import type { Item, Response } from '../types.js';
5
5
  * Processes response status codes, descriptions, headers, and body content,
6
6
  * inferring schemas from example responses when possible.
7
7
  */
8
- export declare function extractResponses(responses: Response[], item?: Item): OpenAPIV3_1.ResponsesObject;
8
+ export declare function extractResponses(responses: Response[], item?: Item): OpenAPIV3_1.ResponsesObject | undefined;
9
9
  //# sourceMappingURL=responseHelpers.d.ts.map
@@ -1 +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,IAAI,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAI1D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,WAAW,CAAC,eAAe,CA8ChG"}
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,IAAI,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAI1D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,WAAW,CAAC,eAAe,GAAG,SAAS,CAwC5G"}
@@ -37,14 +37,8 @@ export function extractResponses(responses, item) {
37
37
  };
38
38
  }
39
39
  });
40
- // If no responses and no status codes, return default 200
41
40
  if (Object.keys(responseMap).length === 0) {
42
- responseMap['200'] = {
43
- description: 'Successful response',
44
- content: {
45
- 'application/json': {},
46
- },
47
- };
41
+ return undefined;
48
42
  }
49
43
  return responseMap;
50
44
  }
package/package.json CHANGED
@@ -19,7 +19,7 @@
19
19
  "export",
20
20
  "scalar"
21
21
  ],
22
- "version": "0.1.49",
22
+ "version": "0.2.1",
23
23
  "engines": {
24
24
  "node": ">=18"
25
25
  },
@@ -38,8 +38,8 @@
38
38
  ],
39
39
  "module": "dist/index.js",
40
40
  "dependencies": {
41
- "@scalar/oas-utils": "0.2.126",
42
- "@scalar/openapi-types": "0.2.0"
41
+ "@scalar/openapi-types": "0.2.0",
42
+ "@scalar/oas-utils": "0.2.128"
43
43
  },
44
44
  "devDependencies": {
45
45
  "vite": "^5.4.10",