Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Kinjalrk2k committed Dec 4, 2021
1 parent fab4cee commit 3a0edc4
Show file tree
Hide file tree
Showing 7 changed files with 885 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,5 @@ dist

# TernJS port file
.tern-port

.DS_Store
62 changes: 62 additions & 0 deletions bin/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env node

const postmanToOpenApi = require("postman-to-openapi");
const YAML = require("yamljs");
const fs = require("fs");
const path = require("path");
const _ = require("lodash");
const $RefParser = require("json-schema-ref-parser");
const colors = require("colors");

const openapiJSONPath = "./openapi.json";

const importSchemas = async (obj) => {
const jsonFiles = fs
.readdirSync(path.resolve("schemas"))
.filter((filename) => filename.endsWith(".json"));

console.log(
`${jsonFiles.length} files found on the schemas directory`.italic.underline
);

await Promise.all(
jsonFiles.map(async (jsonFile) => {
const content = require(path.resolve("schemas", jsonFile));

const refsJSON = await $RefParser.dereference(content);

for (const nestedPath in refsJSON) {
_.set(obj, nestedPath, {
..._.get(obj, nestedPath),
...refsJSON[nestedPath],
});
}
})
);

return obj;
};

const writeToJSONFile = (data, filePath) =>
fs.writeFileSync(
path.resolve(path.join(filePath)),
JSON.stringify(data, null, 2)
);

module.exports = async (postmanCollectionPath, config) => {
const rawOpenapiYAML = await postmanToOpenApi(
path.resolve(postmanCollectionPath),
null,
config
);

const rawOpenapiJSON = YAML.parse(rawOpenapiYAML);
const openapiJSON = await importSchemas(rawOpenapiJSON);

writeToJSONFile(openapiJSON, openapiJSONPath);

console.log(
"\n[✓] Build the OpenAPI spec file and saved in `openapi.json` file".green,
"\n"
);
};
100 changes: 100 additions & 0 deletions bin/extract.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env node

const flatten = require("obj-flatten");
const postmanToOpenApi = require("postman-to-openapi");
const YAML = require("yamljs");
const fs = require("fs");
const path = require("path");
const _ = require("lodash");
const GenerateSchema = require("generate-schema");
const colors = require("colors");
const SCHEMA_DIR = "schemas";

const extractedJSONPath = "./schemas/_extracted.json";

const isValidPath = (p) => {
const regexs = [
/paths.*.requestBody.*.application\/json.schema.type/,
/paths.*.responses.*.application\/json.schema.type/,
];
return regexs.map((re) => re.test(p)).some((v) => v === true);
};

const writeToJSONFile = (data, filePath) =>
fs.writeFileSync(
path.resolve(path.join(filePath)),
JSON.stringify(data, null, 2)
);

const getExsistingPaths = () => {
const jsonFiles = fs
.readdirSync(path.join(SCHEMA_DIR))
.filter((filename) => filename.endsWith(".json"));

let exsitingPaths = [];
jsonFiles.forEach((jsonFile) => {
const content = require(path.resolve("schemas", jsonFile));
exsitingPaths = [...exsitingPaths, ...Object.keys(content)];
});

return exsitingPaths;
};

module.exports = async (postmanCollectionPath) => {
if (!fs.existsSync(path.resolve(SCHEMA_DIR))) {
fs.mkdirSync(path.resolve(SCHEMA_DIR));
}

const exsitingPaths = getExsistingPaths();

const rawOpenapiYAML = await postmanToOpenApi(postmanCollectionPath, null, {
defaultTag: "General",
});

const rawOpenapiJSON = YAML.parse(rawOpenapiYAML);

const targetPaths = Object.keys(flatten(rawOpenapiJSON))
.filter(isValidPath)
.map((p) => p.split(".").slice(0, -1).join("."));

let differencePaths = targetPaths.filter((x) => !exsitingPaths.includes(x));
console.log(`${differencePaths.length} paths found!`.italic.underline);

const pathsWithExampleSchema = {};
differencePaths.forEach((p) => {
const requestExample = _.get(rawOpenapiJSON, `${p}.example`);
const responseExample = _.get(
rawOpenapiJSON,
`${p.split(".").slice(0, -1).join(".")}.example`
);

if (requestExample) {
pathsWithExampleSchema[p] = {
...GenerateSchema.json(requestExample),
$schema: undefined,
};
} else if (responseExample) {
pathsWithExampleSchema[p] = {
...GenerateSchema.json(responseExample),
$schema: undefined,
};
} else {
pathsWithExampleSchema[p] = {};
}
});

writeToJSONFile(pathsWithExampleSchema, extractedJSONPath);
console.log(
"\n[✓] Saved the extracted paths with schemas from examples at: schemas/_extracted.json"
.green,
"\n[⚈] Remove/Rename the file before you run `extract` for the next time or it'll get reset"
.blue,
"\n[ ] Run `p2ojx build` to compile the complete OpenAPI specfile".yellow,
"\n",
"\nGood to know:".gray,
"\n[?] You can break up the whole list of extracted schemas into smaller files. Make sure, they're present in the schemas directory"
.gray,
"\n[?] You can use JSON refs in your schemas".gray,
"\n"
);
};
80 changes: 80 additions & 0 deletions bin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env node

const { Command } = require("commander");
const fs = require("fs");
const path = require("path");
const extract = require("./extract");
const colors = require("colors");
const build = require("./build");
const NOT_FOUND = "NOT_FOUND";

const program = new Command();
program.version("0.0.1");

program
.command("extract")
.description(
"Extract requests and responses schemas from the postman collection"
)
.argument("[input file path]", "The postman_collection.json file")
.action(async (postmanCollectionPath) => {
if (!postmanCollectionPath) {
const avaliableCollection = fs
.readdirSync(path.resolve())
.filter((file) => file.endsWith(".postman_collection.json"))[0];

if (!avaliableCollection) {
console.error("No postman collection found!".red);
return;
}
postmanCollectionPath = avaliableCollection;
}

console.log(`Postman collection: ${postmanCollectionPath}`.magenta);
await extract(postmanCollectionPath);
});

program
.command("build")
.description(
"Build the OpenAPI specs file with the extended schemas specified"
)
.option("-p <postmanCollectionPath>", "Pass the postman_collection.json file")
.option(
"-c <configPath>",
"Pass the additional configurations as a `.p2ojx.json` file. See: https://joolfe.github.io/postman-to-openapi/#options"
)
.action(async ({ p: postmanCollectionPath, c: configPath }) => {
if (!postmanCollectionPath) {
const avaliableCollection = fs
.readdirSync(path.resolve())
.filter((file) => file.endsWith(".postman_collection.json"))[0];

if (!avaliableCollection) {
console.error("No postman collection found!".red);
return;
}
postmanCollectionPath = avaliableCollection;
}

if (!configPath) {
const availableConfigFile = fs
.readdirSync(path.resolve())
.filter((file) => file.endsWith(".p2ojx.json"))[0];

if (!availableConfigFile) {
configPath = {};
} else {
configPath = path.resolve(availableConfigFile);
}
}

const config = require(configPath);

console.log(`Postman collection: ${postmanCollectionPath}`.magenta);
console.log(`Configuration: ${configPath}`.magenta);

await build(postmanCollectionPath, config);
});

program.parse(process.argv);
Loading

0 comments on commit 3a0edc4

Please sign in to comment.