@scalar/postman-to-openapi 0.5.2 → 0.5.3

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 (44) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/convert.js +240 -212
  3. package/dist/helpers/auth.js +116 -92
  4. package/dist/helpers/contact.js +24 -20
  5. package/dist/helpers/external-docs.js +33 -25
  6. package/dist/helpers/form-data.js +42 -36
  7. package/dist/helpers/license.js +21 -17
  8. package/dist/helpers/logo.js +22 -21
  9. package/dist/helpers/markdown.js +33 -30
  10. package/dist/helpers/parameters.js +119 -96
  11. package/dist/helpers/path-items.js +244 -202
  12. package/dist/helpers/post-response-scripts.js +12 -12
  13. package/dist/helpers/pre-request-scripts.js +12 -12
  14. package/dist/helpers/prune-document.js +42 -35
  15. package/dist/helpers/request-body.js +102 -92
  16. package/dist/helpers/responses.js +62 -57
  17. package/dist/helpers/schemas.js +43 -37
  18. package/dist/helpers/servers.js +83 -57
  19. package/dist/helpers/status-codes.js +40 -30
  20. package/dist/helpers/urls.js +74 -51
  21. package/dist/index.js +1 -5
  22. package/dist/types.js +1 -1
  23. package/package.json +6 -11
  24. package/dist/convert.js.map +0 -7
  25. package/dist/helpers/auth.js.map +0 -7
  26. package/dist/helpers/contact.js.map +0 -7
  27. package/dist/helpers/external-docs.js.map +0 -7
  28. package/dist/helpers/form-data.js.map +0 -7
  29. package/dist/helpers/license.js.map +0 -7
  30. package/dist/helpers/logo.js.map +0 -7
  31. package/dist/helpers/markdown.js.map +0 -7
  32. package/dist/helpers/parameters.js.map +0 -7
  33. package/dist/helpers/path-items.js.map +0 -7
  34. package/dist/helpers/post-response-scripts.js.map +0 -7
  35. package/dist/helpers/pre-request-scripts.js.map +0 -7
  36. package/dist/helpers/prune-document.js.map +0 -7
  37. package/dist/helpers/request-body.js.map +0 -7
  38. package/dist/helpers/responses.js.map +0 -7
  39. package/dist/helpers/schemas.js.map +0 -7
  40. package/dist/helpers/servers.js.map +0 -7
  41. package/dist/helpers/status-codes.js.map +0 -7
  42. package/dist/helpers/urls.js.map +0 -7
  43. package/dist/index.js.map +0 -7
  44. package/dist/types.js.map +0 -7
@@ -1,113 +1,137 @@
1
+ // Constants for security scheme names and URLs
1
2
  const AUTH_SCHEMES = {
2
- API_KEY: "apikeyAuth",
3
- BASIC: "basicAuth",
4
- BEARER: "bearerAuth",
5
- OAUTH2: "oauth2Auth"
3
+ API_KEY: 'apikeyAuth',
4
+ BASIC: 'basicAuth',
5
+ BEARER: 'bearerAuth',
6
+ OAUTH2: 'oauth2Auth',
6
7
  };
7
8
  const OAUTH2_DEFAULTS = {
8
- AUTHORIZE_URL: "/oauth/authorize",
9
- TOKEN_URL: "/oauth/token"
9
+ AUTHORIZE_URL: '/oauth/authorize',
10
+ TOKEN_URL: '/oauth/token',
10
11
  };
12
+ /**
13
+ * Creates security configuration for API key authentication
14
+ */
11
15
  function createApiKeyConfig() {
12
- return {
13
- scheme: {
14
- type: "apiKey",
15
- name: "api_key",
16
- in: "header"
17
- },
18
- requirement: { [AUTH_SCHEMES.API_KEY]: [] }
19
- };
16
+ return {
17
+ scheme: {
18
+ type: 'apiKey',
19
+ name: 'api_key',
20
+ in: 'header',
21
+ },
22
+ requirement: { [AUTH_SCHEMES.API_KEY]: [] },
23
+ };
20
24
  }
25
+ /**
26
+ * Creates security configuration for Basic authentication
27
+ */
21
28
  function createBasicConfig() {
22
- return {
23
- scheme: {
24
- type: "http",
25
- scheme: "basic"
26
- },
27
- requirement: { [AUTH_SCHEMES.BASIC]: [] }
28
- };
29
+ return {
30
+ scheme: {
31
+ type: 'http',
32
+ scheme: 'basic',
33
+ },
34
+ requirement: { [AUTH_SCHEMES.BASIC]: [] },
35
+ };
29
36
  }
37
+ /**
38
+ * Creates security configuration for Bearer token authentication
39
+ */
30
40
  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
41
  return {
42
- scheme: {},
43
- requirement: {}
42
+ scheme: {
43
+ type: 'http',
44
+ scheme: 'bearer',
45
+ },
46
+ requirement: { [AUTH_SCHEMES.BEARER]: [] },
44
47
  };
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));
48
+ }
49
+ /**
50
+ * Creates security configuration for OAuth2 authentication
51
+ * Extracts actual OAuth2 URLs and scopes from the Postman auth object
52
+ */
53
+ function createOAuth2Config(auth) {
54
+ if (!auth) {
55
+ return {
56
+ scheme: {},
57
+ requirement: {},
58
+ };
51
59
  }
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
60
+ const oauth2Attrs = auth.oauth2 || [];
61
+ const attrMap = new Map();
62
+ oauth2Attrs.forEach((attr) => {
63
+ if (attr.key && attr.value !== undefined) {
64
+ attrMap.set(attr.key, String(attr.value));
71
65
  }
72
- }
73
- },
74
- requirement: { [AUTH_SCHEMES.OAUTH2]: Object.keys(scopes) }
75
- };
66
+ });
67
+ const authUrl = attrMap.get('authUrl') || attrMap.get('authorizationUrl') || OAUTH2_DEFAULTS.AUTHORIZE_URL;
68
+ const tokenUrl = attrMap.get('accessTokenUrl') || attrMap.get('tokenUrl') || OAUTH2_DEFAULTS.TOKEN_URL;
69
+ const scopeValue = attrMap.get('scope') || '';
70
+ // Parse scopes from the scope value (can be space or comma separated)
71
+ const scopes = {};
72
+ if (scopeValue) {
73
+ const scopeList = scopeValue.split(/[,\s]+/).filter(Boolean);
74
+ scopeList.forEach((scope) => {
75
+ scopes[scope] = scope;
76
+ });
77
+ }
78
+ return {
79
+ scheme: {
80
+ type: 'oauth2',
81
+ flows: {
82
+ authorizationCode: {
83
+ authorizationUrl: authUrl,
84
+ tokenUrl,
85
+ scopes,
86
+ },
87
+ },
88
+ },
89
+ requirement: { [AUTH_SCHEMES.OAUTH2]: Object.keys(scopes) },
90
+ };
76
91
  }
92
+ /**
93
+ * Creates security configuration for no authentication
94
+ */
77
95
  function createNoAuthConfig() {
78
- return {
79
- scheme: {},
80
- requirement: {}
81
- };
96
+ return {
97
+ scheme: {},
98
+ requirement: {},
99
+ };
82
100
  }
101
+ /**
102
+ * Maps authentication types to their configuration creators
103
+ */
83
104
  const AUTH_TYPE_HANDLERS = {
84
- apikey: createApiKeyConfig,
85
- basic: createBasicConfig,
86
- bearer: createBearerConfig,
87
- oauth2: createOAuth2Config,
88
- noauth: createNoAuthConfig
105
+ apikey: createApiKeyConfig,
106
+ basic: createBasicConfig,
107
+ bearer: createBearerConfig,
108
+ oauth2: createOAuth2Config,
109
+ noauth: createNoAuthConfig,
89
110
  };
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}`);
111
+ /**
112
+ * Processes authentication information from a Postman collection and updates
113
+ * the OpenAPI document with the corresponding security schemes and requirements.
114
+ * Supports API key, basic auth, bearer token, OAuth2, and no authentication types.
115
+ */
116
+ export function processAuth(auth) {
117
+ const securitySchemes = {};
118
+ const security = [];
119
+ try {
120
+ const handler = AUTH_TYPE_HANDLERS[auth.type];
121
+ if (!handler) {
122
+ throw new Error(`Unsupported authentication type: ${auth.type}`);
123
+ }
124
+ const { scheme, requirement } = handler(auth);
125
+ // Only add security schemes and requirements if they're not empty
126
+ if (Object.keys(scheme).length > 0) {
127
+ const schemeKey = `${auth.type}Auth`;
128
+ securitySchemes[schemeKey] = scheme;
129
+ security.push(requirement);
130
+ }
97
131
  }
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);
132
+ catch (error) {
133
+ console.error('Error processing authentication:', error);
134
+ throw error;
103
135
  }
104
- } catch (error) {
105
- console.error("Error processing authentication:", error);
106
- throw error;
107
- }
108
- return { securitySchemes, security };
136
+ return { securitySchemes, security };
109
137
  }
110
- export {
111
- processAuth
112
- };
113
- //# sourceMappingURL=auth.js.map
@@ -1,25 +1,29 @@
1
+ // Constants for contact variable keys
1
2
  const VARIABLE_KEYS = {
2
- NAME: "contact.name",
3
- URL: "contact.url",
4
- EMAIL: "contact.email"
3
+ NAME: 'contact.name',
4
+ URL: 'contact.url',
5
+ EMAIL: 'contact.email',
5
6
  };
7
+ /**
8
+ * Finds a specific variable in the collection by its key
9
+ */
6
10
  function findVariable(collection, key) {
7
- return collection.variable?.find((v) => v.key === key);
11
+ return collection.variable?.find((v) => v.key === key);
8
12
  }
9
- function processContact(collection) {
10
- const nameVar = findVariable(collection, VARIABLE_KEYS.NAME);
11
- const urlVar = findVariable(collection, VARIABLE_KEYS.URL);
12
- const emailVar = findVariable(collection, VARIABLE_KEYS.EMAIL);
13
- if (!nameVar?.value && !urlVar?.value && !emailVar?.value) {
14
- return void 0;
15
- }
16
- return {
17
- ...nameVar?.value && typeof nameVar.value === "string" && { name: nameVar.value },
18
- ...urlVar?.value && typeof urlVar.value === "string" && { url: urlVar.value },
19
- ...emailVar?.value && typeof emailVar.value === "string" && { email: emailVar.value }
20
- };
13
+ /**
14
+ * Processes contact information from collection variables.
15
+ * Returns an OpenAPI Contact Object if at least one contact field is present.
16
+ */
17
+ export function processContact(collection) {
18
+ const nameVar = findVariable(collection, VARIABLE_KEYS.NAME);
19
+ const urlVar = findVariable(collection, VARIABLE_KEYS.URL);
20
+ const emailVar = findVariable(collection, VARIABLE_KEYS.EMAIL);
21
+ if (!nameVar?.value && !urlVar?.value && !emailVar?.value) {
22
+ return undefined;
23
+ }
24
+ return {
25
+ ...(nameVar?.value && typeof nameVar.value === 'string' && { name: nameVar.value }),
26
+ ...(urlVar?.value && typeof urlVar.value === 'string' && { url: urlVar.value }),
27
+ ...(emailVar?.value && typeof emailVar.value === 'string' && { email: emailVar.value }),
28
+ };
21
29
  }
22
- export {
23
- processContact
24
- };
25
- //# sourceMappingURL=contact.js.map
@@ -1,32 +1,40 @@
1
+ // Constants for variable keys
1
2
  const VARIABLE_KEYS = {
2
- URL: "externalDocs.url",
3
- DESCRIPTION: "externalDocs.description"
3
+ URL: 'externalDocs.url',
4
+ DESCRIPTION: 'externalDocs.description',
4
5
  };
6
+ /**
7
+ * Finds a specific variable in the collection by its key
8
+ */
5
9
  function findVariable(collection, key) {
6
- return collection.variable?.find((v) => v.key === key);
10
+ return collection.variable?.find((v) => v.key === key);
7
11
  }
8
- function processExternalDocs(collection) {
9
- try {
10
- const urlVariable = findVariable(collection, VARIABLE_KEYS.URL);
11
- const descriptionVariable = findVariable(collection, VARIABLE_KEYS.DESCRIPTION);
12
- if (!urlVariable?.value) {
13
- return void 0;
12
+ /**
13
+ * Processes the external documentation information from a Postman Collection.
14
+ * This function checks for 'externalDocs.url' and 'externalDocs.description'
15
+ * in the collection variables and creates an OpenAPI External Documentation Object
16
+ * if the URL is present.
17
+ */
18
+ export function processExternalDocs(collection) {
19
+ try {
20
+ const urlVariable = findVariable(collection, VARIABLE_KEYS.URL);
21
+ const descriptionVariable = findVariable(collection, VARIABLE_KEYS.DESCRIPTION);
22
+ if (!urlVariable?.value) {
23
+ return undefined;
24
+ }
25
+ if (typeof urlVariable.value !== 'string') {
26
+ throw new Error('External docs URL must be a string');
27
+ }
28
+ return {
29
+ url: urlVariable.value,
30
+ ...(descriptionVariable?.value &&
31
+ typeof descriptionVariable.value === 'string' && {
32
+ description: descriptionVariable.value,
33
+ }),
34
+ };
14
35
  }
15
- if (typeof urlVariable.value !== "string") {
16
- throw new Error("External docs URL must be a string");
36
+ catch (error) {
37
+ console.error('Error processing external docs:', error);
38
+ throw error;
17
39
  }
18
- return {
19
- url: urlVariable.value,
20
- ...descriptionVariable?.value && typeof descriptionVariable.value === "string" && {
21
- description: descriptionVariable.value
22
- }
23
- };
24
- } catch (error) {
25
- console.error("Error processing external docs:", error);
26
- throw error;
27
- }
28
40
  }
29
- export {
30
- processExternalDocs
31
- };
32
- //# sourceMappingURL=external-docs.js.map
@@ -1,39 +1,45 @@
1
- function processFormDataSchema(formdata) {
2
- const schema = {
3
- type: "object",
4
- properties: {},
5
- required: []
6
- };
7
- formdata.forEach((item) => {
8
- if (!schema.properties) {
9
- return;
10
- }
11
- const property = {
12
- type: "string"
1
+ /**
2
+ * Processes form data parameters from a Postman request and converts them into an OpenAPI schema.
3
+ * Handles file uploads, required fields, and descriptions.
4
+ */
5
+ export function processFormDataSchema(formdata) {
6
+ const schema = {
7
+ type: 'object',
8
+ properties: {},
9
+ required: [],
13
10
  };
14
- if (item.description) {
15
- const descriptionText = typeof item.description === "string" ? item.description : item.description.content || "";
16
- property.description = descriptionText.replace(" [required]", "");
17
- if (descriptionText.includes("[required]")) {
18
- schema.required?.push(item.key);
19
- }
20
- }
21
- if (item.type === "file") {
22
- property.format = "binary";
23
- } else {
24
- property.example = item.value;
25
- }
26
- if (item.disabled === true) {
27
- property["x-scalar-disabled"] = true;
11
+ formdata.forEach((item) => {
12
+ if (!schema.properties) {
13
+ return;
14
+ }
15
+ const property = {
16
+ type: 'string',
17
+ };
18
+ // Add description if present, handling both string and object descriptions
19
+ if (item.description) {
20
+ const descriptionText = typeof item.description === 'string' ? item.description : item.description.content || '';
21
+ property.description = descriptionText.replace(' [required]', '');
22
+ // If [required] was present, add to required array
23
+ if (descriptionText.includes('[required]')) {
24
+ schema.required?.push(item.key);
25
+ }
26
+ }
27
+ // Handle file type fields
28
+ if (item.type === 'file') {
29
+ property.format = 'binary';
30
+ }
31
+ else {
32
+ property.example = item.value;
33
+ }
34
+ // Add x-scalar-disabled extension if parameter is disabled
35
+ if (item.disabled === true) {
36
+ property['x-scalar-disabled'] = true;
37
+ }
38
+ schema.properties[item.key] = property;
39
+ });
40
+ // Only keep required array if it has items
41
+ if (schema.required?.length === 0) {
42
+ delete schema.required;
28
43
  }
29
- schema.properties[item.key] = property;
30
- });
31
- if (schema.required?.length === 0) {
32
- delete schema.required;
33
- }
34
- return schema;
44
+ return schema;
35
45
  }
36
- export {
37
- processFormDataSchema
38
- };
39
- //# sourceMappingURL=form-data.js.map
@@ -1,22 +1,26 @@
1
+ // Constants for license variable keys
1
2
  const VARIABLE_KEYS = {
2
- NAME: "license.name",
3
- URL: "license.url"
3
+ NAME: 'license.name',
4
+ URL: 'license.url',
4
5
  };
6
+ /**
7
+ * Finds a specific variable in the collection by its key
8
+ */
5
9
  function findVariable(collection, key) {
6
- return collection.variable?.find((v) => v.key === key);
10
+ return collection.variable?.find((v) => v.key === key);
7
11
  }
8
- function processLicense(collection) {
9
- const nameVar = findVariable(collection, VARIABLE_KEYS.NAME);
10
- if (!nameVar?.value || typeof nameVar.value !== "string") {
11
- return void 0;
12
- }
13
- const urlVar = findVariable(collection, VARIABLE_KEYS.URL);
14
- return {
15
- name: nameVar.value,
16
- ...urlVar?.value && typeof urlVar.value === "string" && { url: urlVar.value }
17
- };
12
+ /**
13
+ * Processes license information from collection variables.
14
+ * Returns an OpenAPI License Object if the license name is present.
15
+ */
16
+ export function processLicense(collection) {
17
+ const nameVar = findVariable(collection, VARIABLE_KEYS.NAME);
18
+ if (!nameVar?.value || typeof nameVar.value !== 'string') {
19
+ return undefined;
20
+ }
21
+ const urlVar = findVariable(collection, VARIABLE_KEYS.URL);
22
+ return {
23
+ name: nameVar.value,
24
+ ...(urlVar?.value && typeof urlVar.value === 'string' && { url: urlVar.value }),
25
+ };
18
26
  }
19
- export {
20
- processLicense
21
- };
22
- //# sourceMappingURL=license.js.map
@@ -1,23 +1,24 @@
1
- function processLogo(postmanCollection) {
2
- const logoVariables = postmanCollection.variable?.filter((v) => v.key?.startsWith("x-logo.")) || [];
3
- if (logoVariables.length === 0) {
4
- return null;
5
- }
6
- const logo = {};
7
- logoVariables.forEach((v) => {
8
- if (v.key) {
9
- const key = v.key.replace("x-logo.", "").replace("Var", "");
10
- logo[key] = v.value;
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
+ if (logoVariables.length === 0) {
9
+ return null;
11
10
  }
12
- });
13
- return {
14
- url: logo.url,
15
- backgroundColor: logo.backgroundColor,
16
- altText: logo.altText,
17
- href: logo.href
18
- };
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
+ };
19
24
  }
20
- export {
21
- processLogo
22
- };
23
- //# sourceMappingURL=logo.js.map
@@ -1,32 +1,35 @@
1
- const supHeaders = ["object", "name", "description", "example", "type", "required"];
2
- function parseMdTable(md) {
3
- const lines = md.split("\n").filter((line) => line.trim() !== "");
4
- if (typeof lines[0] === "undefined" || lines.length < 3) {
5
- return {};
6
- }
7
- const header = lines[0].split("|").map((cell) => cell.trim()).filter(Boolean);
8
- if (!header.includes("object") || !header.includes("name")) {
9
- return {};
10
- }
11
- const headers = header.map((h) => supHeaders.includes(h) ? h : false);
12
- const rows = lines.slice(2).map(
13
- (line) => line.split("|").map((cell) => cell.trim()).filter(Boolean)
14
- );
15
- const tableObj = rows.reduce((accTable, cell) => {
16
- const cellObj = cell.reduce((accCell, field, index) => {
17
- if (headers[index] && typeof headers[index] === "string") {
18
- accCell[headers[index]] = field;
19
- }
20
- return accCell;
21
- }, {});
22
- if (cellObj.name) {
23
- accTable[cellObj.name] = cellObj;
1
+ const supHeaders = ['object', 'name', 'description', 'example', 'type', 'required'];
2
+ /**
3
+ * Parses a Markdown table and returns an object representation.
4
+ */
5
+ export function parseMdTable(md) {
6
+ const lines = md.split('\n').filter((line) => line.trim() !== '');
7
+ if (typeof lines[0] === 'undefined' || lines.length < 3) {
8
+ return {};
9
+ }
10
+ const header = lines[0]
11
+ .split('|')
12
+ .map((cell) => cell.trim())
13
+ .filter(Boolean);
14
+ if (!header.includes('object') || !header.includes('name')) {
15
+ return {};
24
16
  }
25
- return accTable;
26
- }, {});
27
- return tableObj;
17
+ const headers = header.map((h) => (supHeaders.includes(h) ? h : false));
18
+ const rows = lines.slice(2).map((line) => line
19
+ .split('|')
20
+ .map((cell) => cell.trim())
21
+ .filter(Boolean));
22
+ const tableObj = rows.reduce((accTable, cell) => {
23
+ const cellObj = cell.reduce((accCell, field, index) => {
24
+ if (headers[index] && typeof headers[index] === 'string') {
25
+ accCell[headers[index]] = field;
26
+ }
27
+ return accCell;
28
+ }, {});
29
+ if (cellObj.name) {
30
+ accTable[cellObj.name] = cellObj;
31
+ }
32
+ return accTable;
33
+ }, {});
34
+ return tableObj;
28
35
  }
29
- export {
30
- parseMdTable
31
- };
32
- //# sourceMappingURL=markdown.js.map