Skip to content

Instantly share code, notes, and snippets.

@kazuyaseki
Created October 9, 2022 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kazuyaseki/533326b97895f1000115959bd73546d4 to your computer and use it in GitHub Desktop.
Save kazuyaseki/533326b97895f1000115959bd73546d4 to your computer and use it in GitHub Desktop.
import { readFileSync, writeFileSync } from 'fs';
import { load } from 'js-yaml';
type Responses = { [key: string]: any };
type METHODS = 'get' | 'post' | 'put' | 'delete';
type Components = {
schemas: any;
};
type ObjectType = 'array' | 'object' | 'integer' | 'string' | 'boolean';
type OpenAPIObject = {
type: ObjectType;
items?: any;
properties: { [key: string]: { type: ObjectType } };
};
type OpenAPI = {
openapi: string;
info: { title: string; version: string };
paths: {
[key: string]: {
[key in METHODS]: {
description: string;
responses: Responses;
};
};
};
components: Components;
};
function findSuccessResponseKey(responses: Responses) {
return Object.keys(responses).find((key) => key.startsWith('2'));
}
function openapiObjToObject(openapiObj: OpenAPIObject, components: Components) {
const copy: any = { ...openapiObj.properties };
if (openapiObj.type === 'object') {
Object.keys(openapiObj.properties).map((key) => {
switch (openapiObj.properties[key].type) {
case 'string':
copy[key] = 'string';
return;
case 'integer':
copy[key] = 1;
return;
case 'boolean':
copy[key] = true;
return;
case 'object':
copy[key] = openapiObjToObject(copy[key], components);
return;
case 'array':
copy[key] = openapiObjToObject(copy[key], components);
return;
default:
copy[key] = null;
}
});
return copy;
}
if (openapiObj.type === 'array') {
const obj: any = openapiObjToObject(
getComponentObj(openapiObj.items['$ref'], components.schemas),
components
);
return [obj];
}
if (openapiObj.type === 'string') {
return 'string';
}
if (openapiObj.type === 'integer') {
return 1;
}
return '';
}
function getComponentObj(path: string, schemas: Components['schemas']) {
// remove first 2 elements since it's "#/components/schema"
const componentsPaths = path.split('/').slice(3);
let componentValue = schemas;
componentsPaths.forEach((path) => {
componentValue = componentValue[path];
});
return componentValue;
}
function getSchemaFromResponse(response: any, components: Components) {
if (
response.content &&
response.content['application/json'] &&
response.content['application/json'].schema
) {
const values = response.content['application/json'].schema;
if ('$ref' in values) {
return openapiObjToObject(
getComponentObj(values['$ref'] as string, components.schemas),
components
);
}
return values;
}
return null;
}
function generate(_doc: OpenAPI) {
let mswString = `import { rest } from 'msw'
export const handlers = [
`;
const paths: any = [];
Object.keys(_doc.paths).forEach((path) => {
const value = _doc.paths[path];
(['get', 'post', 'put', 'delete'] as METHODS[]).forEach((method) => {
if (value[method]) {
const successResponseKey = findSuccessResponseKey(
value[method].responses
);
paths.push(
` rest.${method}('${path}', (req, res, ctx) => {
return res(ctx.json(${
successResponseKey
? JSON.stringify(
getSchemaFromResponse(
value[method].responses[successResponseKey],
doc.components
)
)
: null
}));
})`
);
}
});
});
mswString += paths.join(',\n');
mswString += '\n]';
return mswString;
}
const doc = load(
readFileSync('./openapi_only_pharmacy.yml', 'utf8')
) as OpenAPI;
const docString = generate(doc);
writeFileSync('./src/tests/mswHandlers.ts', docString);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment