Skip to content

Commit

Permalink
completed the conversion from postman to asyncapi
Browse files Browse the repository at this point in the history
  • Loading branch information
ItshMoh committed Sep 5, 2024
1 parent 3499c27 commit 1888e5e
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 5 deletions.
39 changes: 38 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
"license": "Apache-2.0",
"dependencies": {
"@asyncapi/parser": "^3.1.0",
"js-yaml": "^3.14.1"
"js-yaml": "^3.14.1",
"path": "^0.12.7",
"postman2openapi": "^1.2.1"
},
"devDependencies": {
"@jest/types": "^27.5.1",
Expand Down
17 changes: 16 additions & 1 deletion src/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { converters as firstConverters } from "./first-version";
import { converters as secondConverters } from "./second-version";
import { converters as thirdConverters } from "./third-version";
import { converters as openapiConverters } from "./openapi";
import { converters as postmanConverters } from "./postman-collection";

import { serializeInput } from "./utils";

import type { AsyncAPIDocument, AsyncAPIConvertVersion, OpenAPIConvertVersion, ConvertOptions, ConvertFunction, ConvertOpenAPIFunction, OpenAPIDocument, OpenAPIToAsyncAPIOptions } from './interfaces';
import type { AsyncAPIDocument, AsyncAPIConvertVersion, OpenAPIConvertVersion, ConvertOptions, ConvertFunction, ConvertOpenAPIFunction, OpenAPIDocument, OpenAPIToAsyncAPIOptions, ConvertPostmanFunction } from './interfaces';

/**
* Value for key (version) represents the function which converts specification from previous version to the given as key.
Expand Down Expand Up @@ -78,3 +79,17 @@ export function convertOpenAPI(input: string | OpenAPIDocument, version: OpenAPI
}
return convertedAsyncAPI;
}

export function convertPostman(input: string, version: OpenAPIConvertVersion): string;
export function convertPostman(input: any, version: OpenAPIConvertVersion): AsyncAPIDocument;
export function convertPostman(input: string | any, version: OpenAPIConvertVersion): string | any {
const { format, document } = serializeInput(input);
const postmantoAsyncapiConverter = postmanConverters[version] as ConvertPostmanFunction;

const convertedAsyncAPI = postmantoAsyncapiConverter(document as any);

if (format === "yaml") {
return dump(convertedAsyncAPI, { skipInvalid: true });
}
return convertedAsyncAPI;
}
2 changes: 1 addition & 1 deletion src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ export type ConvertOptions = {
*/
export type ConvertFunction = (asyncapi: AsyncAPIDocument, options: ConvertOptions) => AsyncAPIDocument;
export type ConvertOpenAPIFunction = (openapi: OpenAPIDocument, options: OpenAPIToAsyncAPIOptions) => AsyncAPIDocument;

export type ConvertPostmanFunction = (postman: any) => AsyncAPIDocument;
2 changes: 1 addition & 1 deletion src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const converters: Record<string, ConvertOpenAPIFunction > = {
* @param {ConvertOptions} options - Conversion options.
* @returns {AsyncAPIDocument} The converted AsyncAPI document.
*/
function from_openapi_to_asyncapi(openapi: OpenAPIDocument, options: OpenAPIToAsyncAPIOptions = {}): AsyncAPIDocument {
export function from_openapi_to_asyncapi(openapi: OpenAPIDocument, options: OpenAPIToAsyncAPIOptions = {}): AsyncAPIDocument {
const perspective = options.perspective || 'server';
const asyncapi: Partial<AsyncAPIDocument> = {
asyncapi: '3.0.0',
Expand Down
23 changes: 23 additions & 0 deletions src/postman-collection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import collection from '../../collection.json';
import { transpile } from 'postman2openapi';
import { from_openapi_to_asyncapi } from './openapi';
import { ConvertPostmanFunction } from 'interfaces';

export const converters: Record<string, ConvertPostmanFunction > = {
'3.0.0': from_postman_to_asyncapi
}

// Returns a JavaScript object representation of the OpenAPI definition.
const openapi = transpile(collection);

// console.log(JSON.stringify(openapi, null, 2));

function from_postman_to_asyncapi(postman: any) {
const openapi = transpile(postman);
const asyncapi = from_openapi_to_asyncapi(openapi);
return asyncapi;
}

const output = from_postman_to_asyncapi(collection);
// console.log(JSON.stringify(output, null, 2));

38 changes: 38 additions & 0 deletions test/input/postman/basic-collection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
info:
name: Sample Postman Collection
schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json'
item:
- name: Sample Request
request:
method: GET
header: []
url:
raw: 'https://jsonplaceholder.typicode.com/posts/1'
protocol: https
host:
- jsonplaceholder
- typicode
- com
path:
- posts
- '1'
response: []
- name: Sample POST Request
request:
method: POST
header:
- key: Content-Type
value: application/json
body:
mode: raw
raw: '{ "title": "foo", "body": "bar", "userId": 1 }'
url:
raw: 'https://jsonplaceholder.typicode.com/posts'
protocol: https
host:
- jsonplaceholder
- typicode
- com
path:
- posts
response: []
22 changes: 22 additions & 0 deletions test/input/postman/header-authentication.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
info:
name: Headers and Authentication Test Collection
schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json'
item:
- name: GET Request with Headers and Authentication
request:
method: GET
header:
- key: Authorization
value: Bearer your_token
- key: Accept
value: application/json
url:
raw: 'https://example.com/api/authenticated'
protocol: https
host:
- example
- com
path:
- api
- authenticated
response: []
72 changes: 72 additions & 0 deletions test/output/postman-to-asyncapi/basic-collection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
asyncapi: 3.0.0
info:
title: Sample Postman Collection
version: 1.0.0
servers:
typicode_com:
host: jsonplaceholder.typicode.com
protocol: https
channels:
posts_1:
address: /posts/1
messages:
sampleRequestResponse200:
name: sampleRequestResponse200
title: GET response 200
summary: ''
posts:
address: /posts
messages:
samplePostRequestRequest:
name: samplePostRequestRequest
title: POST request
contentType: application/json
payload:
schemaFormat: application/vnd.oai.openapi;version=3.0.0
schema:
type: object
properties:
body:
type: string
example: bar
title:
type: string
example: foo
userId:
type: number
example: 1
samplePostRequestResponse200:
name: samplePostRequestResponse200
title: POST response 200
summary: ''
operations:
sampleRequest:
action: receive
channel:
$ref: '#/channels/posts_1'
summary: Sample Request
description: Sample Request
bindings:
http:
method: GET
reply:
channel:
$ref: '#/channels/posts_1'
messages:
- $ref: '#/channels/posts_1/messages/sampleRequestResponse200'
samplePostRequest:
action: receive
channel:
$ref: '#/channels/posts'
summary: Sample POST Request
description: Sample POST Request
bindings:
http:
method: POST
messages:
- $ref: '#/channels/posts/messages/samplePostRequestRequest'
reply:
channel:
$ref: '#/channels/posts'
messages:
- $ref: '#/channels/posts/messages/samplePostRequestResponse200'
32 changes: 32 additions & 0 deletions test/output/postman-to-asyncapi/header-authentication.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
asyncapi: 3.0.0
info:
title: Headers and Authentication Test Collection
version: 1.0.0
servers:
example_com:
host: example.com
protocol: https
channels:
api_authenticated:
address: /api/authenticated
messages:
getRequestWithHeadersAndAuthenticationResponse200:
name: getRequestWithHeadersAndAuthenticationResponse200
title: GET response 200
summary: ''
operations:
getRequestWithHeadersAndAuthentication:
action: receive
channel:
$ref: '#/channels/api_authenticated'
summary: GET Request with Headers and Authentication
description: GET Request with Headers and Authentication
bindings:
http:
method: GET
reply:
channel:
$ref: '#/channels/api_authenticated'
messages:
- $ref: >-
#/channels/api_authenticated/messages/getRequestWithHeadersAndAuthenticationResponse200
20 changes: 20 additions & 0 deletions test/postman_to_asyncapi.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import fs from 'fs';
import path from 'path';
import { convertPostman } from '../src/convert';
import { assertResults } from './helpers';

describe("convert() - postman to asyncapi", () => {
it("should convert the basic structure of postman collection to asyncapi", () => {
const input = fs.readFileSync(path.resolve(__dirname, "input", "postman", "basic-collection.yml"), "utf8");
const output = fs.readFileSync(path.resolve(__dirname, "output", "postman-to-asyncapi", "basic-collection.yml"), "utf8");
const result = convertPostman(input, '3.0.0');
assertResults(output, result);
});

it("should convert headers and authentication from postman collection to asyncapi", () => {
const input = fs.readFileSync(path.resolve(__dirname, "input", "postman", "header-authentication.yml"), "utf8");
const output = fs.readFileSync(path.resolve(__dirname, "output", "postman-to-asyncapi", "header-authentication.yml"), "utf8");
const result = convertPostman(input, '3.0.0');
assertResults(output, result);
});
});

0 comments on commit 1888e5e

Please sign in to comment.