UNPKG

json-schema-to-typescript

Version:
221 lines (218 loc) 9.22 kB
#!/usr/bin/env node "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const minimist_1 = __importDefault(require("minimist")); const fs_1 = require("fs"); const tinyglobby_1 = require("tinyglobby"); const is_glob_1 = __importDefault(require("is-glob")); const path_1 = require("path"); const index_1 = require("./index"); const utils_1 = require("./utils"); main((0, minimist_1.default)(process.argv.slice(2), { alias: { help: ['h'], input: ['i'], output: ['o'], }, boolean: [ 'additionalProperties', 'declareExternallyReferenced', 'enableConstEnums', 'format', 'ignoreMinAndMaxItems', 'strictIndexSignatures', 'unknownAny', 'unreachableDefinitions', ], default: index_1.DEFAULT_OPTIONS, string: ['bannerComment', 'cwd'], })); function main(argv) { return __awaiter(this, void 0, void 0, function* () { if (argv.help) { printHelp(); process.exit(0); } const argIn = argv._[0] || argv.input; const argOut = argv._[1] || argv.output; // the output can be omitted so this can be undefined const ISGLOB = (0, is_glob_1.default)(argIn); const ISDIR = isDir(argIn); if ((ISGLOB || ISDIR) && argOut && argOut.includes('.d.ts')) { throw new ReferenceError(`You have specified a single file ${argOut} output for a multi file input ${argIn}. This feature is not yet supported, refer to issue #272 (https://github.com/bcherny/json-schema-to-typescript/issues/272)`); } try { // Process input as either glob, directory, or single file if (ISGLOB) { yield processGlob(argIn, argOut, argv); } else if (ISDIR) { yield processDir(argIn, argOut, argv); } else { const result = yield processFile(argIn, argv); outputResult(result, argOut); } } catch (e) { (0, utils_1.error)(e); process.exit(1); } }); } // check if path is an existing directory function isDir(path) { return (0, fs_1.existsSync)(path) && (0, fs_1.lstatSync)(path).isDirectory(); } function processGlob(argIn, argOut, argv) { return __awaiter(this, void 0, void 0, function* () { const files = yield (0, tinyglobby_1.glob)(argIn, { expandDirectories: false }); // execute glob pattern match if (files.length === 0) { throw ReferenceError(`You passed a glob pattern "${argIn}", but there are no files that match that pattern in ${process.cwd()}`); } // we can do this concurrently for perf const results = yield Promise.all(files.map((file) => __awaiter(this, void 0, void 0, function* () { return [file, yield processFile(file, argv)]; }))); // careful to do this serially results.forEach(([file, result]) => { const outputPath = argOut && `${argOut}/${(0, utils_1.justName)(file)}.d.ts`; outputResult(result, outputPath); }); }); } function processDir(argIn, argOut, argv) { return __awaiter(this, void 0, void 0, function* () { const files = getPaths(argIn); // we can do this concurrently for perf const results = yield Promise.all(files.map((file) => __awaiter(this, void 0, void 0, function* () { if (!argOut) { return [file, yield processFile(file, argv)]; } else { const outputPath = (0, utils_1.pathTransform)(argOut, argIn, file); return [file, yield processFile(file, argv), outputPath]; } }))); // careful to do this serially results.forEach(([file, result, outputPath]) => outputResult(result, outputPath ? `${outputPath}/${(0, utils_1.justName)(file)}.d.ts` : undefined)); }); } function outputResult(result, outputPath) { if (!outputPath) { process.stdout.write(result); } else { if (!isDir((0, path_1.dirname)(outputPath))) { (0, fs_1.mkdirSync)((0, path_1.dirname)(outputPath), { recursive: true }); } return (0, fs_1.writeFileSync)(outputPath, result); } } function processFile(argIn, argv) { return __awaiter(this, void 0, void 0, function* () { const { filename, contents } = yield readInput(argIn); const schema = (0, utils_1.parseFileAsJSONSchema)(filename, contents); return (0, index_1.compile)(schema, argIn, argv); }); } function getPaths(path, paths = []) { if ((0, fs_1.existsSync)(path) && (0, fs_1.lstatSync)(path).isDirectory()) { (0, fs_1.readdirSync)((0, path_1.resolve)(path)).forEach(item => getPaths((0, path_1.join)(path, item), paths)); } else { paths.push(path); } return paths; } function readInput(argIn) { return __awaiter(this, void 0, void 0, function* () { if (!argIn) { return { filename: null, contents: yield readStream(process.stdin), }; } return { filename: argIn, contents: (0, fs_1.readFileSync)((0, path_1.resolve)(process.cwd(), argIn), 'utf-8'), }; }); } function readStream(stream) { return __awaiter(this, void 0, void 0, function* () { var _a, stream_1, stream_1_1; var _b, e_1, _c, _d; const chunks = []; try { for (_a = true, stream_1 = __asyncValues(stream); stream_1_1 = yield stream_1.next(), _b = stream_1_1.done, !_b; _a = true) { _d = stream_1_1.value; _a = false; const chunk = _d; chunks.push(chunk); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_a && !_b && (_c = stream_1.return)) yield _c.call(stream_1); } finally { if (e_1) throw e_1.error; } } return Buffer.concat(chunks).toString('utf8'); }); } function printHelp() { const pkg = require('../../package.json'); process.stdout.write(` ${pkg.name} ${pkg.version} Usage: json2ts [--input, -i] [IN_FILE] [--output, -o] [OUT_FILE] [OPTIONS] With no IN_FILE, or when IN_FILE is -, read standard input. With no OUT_FILE and when IN_FILE is specified, create .d.ts file in the same directory. With no OUT_FILE nor IN_FILE, write to standard output. You can use any of the following options by adding them at the end. Boolean values can be set to false using the 'no-' prefix. --additionalProperties Default value for additionalProperties, when it is not explicitly set --cwd=XXX Root directory for resolving $ref --declareExternallyReferenced Declare external schemas referenced via '$ref'? --enableConstEnums Prepend enums with 'const'? --inferStringEnumKeysFromValues Create enums from JSON enums instead of union types --format Format code? Set this to false to improve performance. --maxItems Maximum number of unioned tuples to emit when representing bounded-size array types, before falling back to emitting unbounded arrays. Increase this to improve precision of emitted types, decrease it to improve performance, or set it to -1 to ignore minItems and maxItems. --style.XXX=YYY Prettier configuration --unknownAny Output unknown type instead of any type --unreachableDefinitions Generates code for definitions that aren't referenced by the schema `); } //# sourceMappingURL=cli.js.map