Improved Postman and OpenAPI import

This commit is contained in:
Gregory Schier
2024-07-22 18:00:13 -07:00
parent 75a7cac783
commit 6a24b31c6c
5 changed files with 73 additions and 23 deletions

View File

@@ -2,7 +2,7 @@
"name": "filter-jsonpath", "name": "filter-jsonpath",
"version": "0.0.1", "version": "0.0.1",
"scripts": { "scripts": {
"build": "yaakcli src/index.ts" "build": "BUILD_PLATFORM=browser yaakcli src/index.ts"
}, },
"dependencies": { "dependencies": {
"jsonpath": "^1.1.1" "jsonpath": "^1.1.1"

View File

@@ -1,5 +1,5 @@
{ {
"name": "importer-postman", "name": "importer-openapi",
"version": "0.0.1", "version": "0.0.1",
"scripts": { "scripts": {
"build": "yaakcli ./src/index.js" "build": "yaakcli ./src/index.js"

View File

@@ -1,5 +1,5 @@
import { convert } from 'openapi-to-postmanv2'; import { convert } from 'openapi-to-postmanv2';
import { pluginHookImport as pluginHookImportPostman } from '../../importer-postman/build'; import { pluginHookImport as pluginHookImportPostman } from '../../importer-postman';
import { Folder, HttpRequest, Workspace, Environment } from '../../../types/models'; import { Folder, HttpRequest, Workspace, Environment } from '../../../types/models';
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>; type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
@@ -15,15 +15,21 @@ export async function pluginHookImport(
ctx: any, ctx: any,
contents: string, contents: string,
): Promise<{ resources: ExportResources } | undefined> { ): Promise<{ resources: ExportResources } | undefined> {
const result = await new Promise((resolve, reject) => { let postmanCollection;
convert({ type: 'string', data: contents }, {}, (err, result) => { try {
if (err != null) reject(err); postmanCollection = await new Promise((resolve, reject) => {
convert({ type: 'string', data: contents }, {}, (err, result) => {
if (err != null) reject(err);
if (Array.isArray(result.output) && result.output.length > 0) { if (Array.isArray(result.output) && result.output.length > 0) {
resolve(JSON.stringify(result.output[0].data)); resolve(result.output[0].data);
} }
});
}); });
}); } catch (err) {
// Probably not an OpenAPI file, so skip it
return undefined;
}
return pluginHookImportPostman(ctx, result); return pluginHookImportPostman(ctx, JSON.stringify(postmanCollection));
} }

View File

@@ -7,6 +7,11 @@ describe('importer-openapi', () => {
const p = path.join(__dirname, 'fixtures'); const p = path.join(__dirname, 'fixtures');
const fixtures = fs.readdirSync(p); const fixtures = fs.readdirSync(p);
test('Skips invalid file', async () => {
const imported = await pluginHookImport({}, '{}');
expect(imported).toBeUndefined();
})
for (const fixture of fixtures) { for (const fixture of fixtures) {
test('Imports ' + fixture, async () => { test('Imports ' + fixture, async () => {
const contents = fs.readFileSync(path.join(p, fixture), 'utf-8'); const contents = fs.readFileSync(path.join(p, fixture), 'utf-8');
@@ -14,6 +19,7 @@ describe('importer-openapi', () => {
expect(imported?.resources.workspaces).toEqual([ expect(imported?.resources.workspaces).toEqual([
expect.objectContaining({ expect.objectContaining({
name: 'Swagger Petstore - OpenAPI 3.0', name: 'Swagger Petstore - OpenAPI 3.0',
description: expect.stringContaining('This is a sample Pet Store Server'),
}), }),
]); ]);
expect(imported?.resources.httpRequests.length).toBe(19); expect(imported?.resources.httpRequests.length).toBe(19);

View File

@@ -39,7 +39,7 @@ export function pluginHookImport(
model: 'workspace', model: 'workspace',
id: generateId('workspace'), id: generateId('workspace'),
name: info.name || 'Postman Import', name: info.name || 'Postman Import',
description: info.description || '', description: info.description?.content ?? info.description ?? '',
variables: variables:
root.variable?.map((v: any) => ({ root.variable?.map((v: any) => ({
name: v.key, name: v.key,
@@ -73,7 +73,7 @@ export function pluginHookImport(
folderId, folderId,
name: v.name, name: v.name,
method: r.method || 'GET', method: r.method || 'GET',
url: typeof r.url === 'string' ? r.url : toRecord(r.url).raw, url: typeof r.url === 'string' ? r.url : convertUrl(toRecord(r.url)),
body: bodyPatch.body, body: bodyPatch.body,
bodyType: bodyPatch.bodyType, bodyType: bodyPatch.bodyType,
authentication: authPatch.authentication, authentication: authPatch.authentication,
@@ -103,6 +103,43 @@ export function pluginHookImport(
return { resources: convertTemplateSyntax(exportResources) }; return { resources: convertTemplateSyntax(exportResources) };
} }
function convertUrl(url: Record<string, any>) {
if ('raw' in url) {
return url.raw;
}
let v = '';
if ('protocol' in url && typeof url.protocol === 'string') {
v += `${url.protocol}://`;
}
if ('host' in url) {
v += `${Array.isArray(url.host) ? url.host.join('.') : url.host}`;
}
if ('port' in url && typeof url.port === 'string') {
v += `:${url.port}`;
}
if ('path' in url && Array.isArray(url.path) && url.path.length > 0) {
v += `/${Array.isArray(url.path) ? url.path.join('/') : url.path}`;
}
if ('query' in url && Array.isArray(url.query) && url.query.length > 0) {
const qs = url.query.map(q => `${q.key ?? ''}=${q.value ?? ''}`).join('&');
v += `?${qs}`;
}
if ('hash' in url && typeof url.hash === 'string') {
v += `#${url.hash}`;
}
// TODO: Implement url.variables (path variables)
return v;
}
function importAuth( function importAuth(
rawAuth: any, rawAuth: any,
): Pick<HttpRequest, 'authentication' | 'authenticationType' | 'headers'> { ): Pick<HttpRequest, 'authentication' | 'authenticationType' | 'headers'> {
@@ -181,16 +218,16 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
form: toArray(body.formdata).map((f) => form: toArray(body.formdata).map((f) =>
f.src != null f.src != null
? { ? {
enabled: !f.disabled, enabled: !f.disabled,
contentType: f.contentType ?? null, contentType: f.contentType ?? null,
name: f.key ?? '', name: f.key ?? '',
file: f.src ?? '', file: f.src ?? '',
} }
: { : {
enabled: !f.disabled, enabled: !f.disabled,
name: f.key ?? '', name: f.key ?? '',
value: f.value ?? '', value: f.value ?? '',
}, },
), ),
}, },
}; };
@@ -216,7 +253,8 @@ function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'head
function parseJSONToRecord(jsonStr: string): Record<string, any> | null { function parseJSONToRecord(jsonStr: string): Record<string, any> | null {
try { try {
return toRecord(JSON.parse(jsonStr)); return toRecord(JSON.parse(jsonStr));
} catch (err) {} } catch (err) {
}
return null; return null;
} }