json-schema-to-joi
Version:
Converts JSON schema to Joi typescript code
212 lines (211 loc) • 7.46 kB
JavaScript
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const minimist = require("minimist");
const minimistOptions = require("minimist-options");
const cli_color_1 = require("cli-color");
const mz_1 = require("mz");
const path_1 = require("path");
const $RefParser = require("@apidevtools/json-schema-ref-parser");
const joi_1 = require("./joi");
const stdin = require('stdin');
const _ = require("lodash");
const prettier = require("prettier");
const resolve_1 = require("./joi/resolve");
const defaultImportStatement = 'import * as Joi from \'@hapi/joi\';';
const legacyImportStatement = 'import * as Joi from \'joi\';';
const argOptions = minimistOptions.default({
input: {
type: 'string',
alias: 'i',
default: '',
},
output: {
type: 'string',
alias: 'o',
default: '',
},
help: {
type: 'boolean',
default: false,
alias: 'h',
},
version: {
type: 'boolean',
default: false,
alias: 'v',
},
cwd: {
type: 'string',
},
importStatement: {
type: 'array',
default: [defaultImportStatement],
},
joiName: {
type: 'string',
default: 'Joi',
},
extendedJoiName: {
type: 'string',
default: '',
},
useDeprecatedJoi: {
type: 'boolean',
default: false,
},
title: {
type: 'string',
alias: 't',
},
batch: {
type: 'boolean',
alias: 'b',
default: true,
},
banner: {
type: 'string',
}
});
async function main() {
const args = minimist(process.argv.slice(2), argOptions);
if (args.help) {
printHelp();
process.exit(0);
}
if (args.version) {
printVersion();
process.exit(0);
}
const banner = args.banner || '';
const batch = args.batch;
const title = !batch ? (args.title || '') : '';
const joiName = args.joiName;
const extendedJoiName = args.extendedJoiName;
const useDeprecatedJoi = args.useDeprecatedJoi;
let importStatement = args.importStatement;
const input = args.input;
const output = args.output;
if (useDeprecatedJoi && !importStatement) {
importStatement = [legacyImportStatement];
}
let allOutput = banner + '\n\n' + importStatement.join('\n') + '\n\n';
try {
const schemas = await $RefParser.bundle(JSON.parse(await readInput(input)));
if (batch) {
const definitions = _.get(schemas, 'definitions') ||
_.get(schemas, 'components.schemas');
if (!definitions) {
throw new Error(`batch mode: no "definitions" or "components/schemas" SECTION in the root of the JSON schema`);
}
const joiSchemas = resolve_1.resolveBundledJSONSchema(definitions, {
useDeprecatedJoi, useExtendedJoi: !!extendedJoiName,
rootSchema: schemas
});
const joiStats = [];
joiSchemas.forEach((subSchema) => {
joiStats.push(...joi_1.generateJoiStatement(subSchema, true));
});
allOutput = joi_1.formatJoi(joiStats, { withExport: true, });
}
else {
if (!schemas.title && title) {
schemas.title = title;
}
const joiSchema = joi_1.resolveJSONSchema(schemas, {
rootSchema: schemas,
useExtendedJoi: !!extendedJoiName,
useDeprecatedJoi,
});
const joiStatement = joi_1.generateJoiStatement(joiSchema, true);
const joiTypeScriptCode = joi_1.formatJoi(joiStatement, {
joiName, extendedJoiName,
});
allOutput += 'export ' + joiTypeScriptCode + '\n\n';
}
allOutput = prettier.format(allOutput, {
tabWidth: 2,
useTabs: false,
singleQuote: true,
trailingComma: 'all',
semi: true,
parser: 'typescript',
});
await writeOutput(allOutput, output);
}
catch (e) {
console.error(cli_color_1.whiteBright.bgRedBright('error'), e);
process.exit(1);
}
}
function writeOutput(ts, argOut) {
if (!argOut) {
try {
process.stdout.write(ts);
return Promise.resolve();
}
catch (err) {
return Promise.reject(err);
}
}
return mz_1.fs.writeFile(argOut, ts);
}
function readInput(argIn) {
if (!argIn) {
return new Promise(stdin);
}
return mz_1.fs.readFile(path_1.resolve(process.cwd(), argIn), 'utf-8');
}
function getPkgInfo() {
const pkg = require('../package.json');
return {
name: pkg.name,
version: pkg.version,
};
}
function printVersion() {
const { name, version } = getPkgInfo();
process.stdout.write(`${name} ${version}\n`);
}
function printHelp() {
const { name, version } = getPkgInfo();
const helpMsg = `${name} ${version}
Usage: json2joi [--banner, -b] [BANNER] [--batch] [SECTION]
[--title] [TITLE] [--cwd] [CWD] [--useDeprecatedJoi] [--useExtendedJoi]
[--importStatement] [IMPORT]
[--input, -i] [IN_FILE] [--output, -o] [OUT_FILE]
optional parameters:
-h, --help Show this help message and exit.
-v, --version Show the program version.
--title TITLE The title used as the Joi schema variable name
if the JSON schema doesn't have a title itself.
TITLE is meaningless when "--batch" option is present.
--cwd CWD CWD is used as the root directory of JSON sub schemas.
--joiName JOINAME JOINAME is the module name of joi library.
Default: "Joi".
--extendedJoiName EJOINAME EJOINAME is the module name of extended joi library.
If you don't want to use deprecated joi extension to support
"allOf" and "oneOf", please leave it empty.
--importStatement IMPORT IMPORT is the statement(s) to import joi library and extended joi library.
It can be multiple statements.
Default: "${defaultImportStatement}"
If "useDeprecatedJoi" is true ,IMPORT will be "${legacyImportStatement}".
If "extendedJoiName" is set, another IMPORT statement must be added.
--useDeprecatedJoi If the option is true, the prog will use deprecated library 'joi'
instead of '@hapi/joi'
Default: false.
--batch Convert the "definitions" section to generate multiple
-b, --banner BANNER Add BANNER in the beginning of the output.
-i, --input INPUT The input JSON schema file.
-o, --output OUTPUT The output source file including generated Joi schema(s).
If OUTPUT is absent, the prog will write to the standard output
`;
process.stdout.write(helpMsg);
}
main()
.then(() => {
})
.catch((err) => {
console.error(cli_color_1.whiteBright.bgRedBright('error'), err);
});
//# sourceMappingURL=cli.js.map