UNPKG

@matatbread/typia

Version:

Superfast runtime validators with only one line

129 lines (126 loc) 5.56 kB
import fs from 'fs'; import path from 'path'; import ts from 'typescript'; import { ImportTransformer } from '../transformers/ImportTransformer.mjs'; import { transform } from '../transform.mjs'; var TypiaProgrammer; (function (TypiaProgrammer) { TypiaProgrammer.build = async (location) => { location.input = path.resolve(location.input); location.output = path.resolve(location.output); if ((await is_directory(location.input)) === false) throw new URIError("Error on TypiaGenerator.generate(): input path is not a directory."); else if (fs.existsSync(location.output) === false) await fs.promises.mkdir(location.output, { recursive: true }); else if ((await is_directory(location.output)) === false) { const parent = path.join(location.output, ".."); if ((await is_directory(parent)) === false) throw new URIError("Error on TypiaGenerator.generate(): output path is not a directory."); await fs.promises.mkdir(location.output); } // CREATE PROGRAM const { options: compilerOptions } = ts.parseJsonConfigFileContent(ts.readConfigFile(location.project, ts.sys.readFile).config, { fileExists: ts.sys.fileExists, readFile: ts.sys.readFile, readDirectory: ts.sys.readDirectory, useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames, }, path.dirname(location.project)); const program = ts.createProgram(await (async () => { const container = []; await gather({ location, container, from: location.input, to: location.output, }); return container; })(), compilerOptions); // DO TRANSFORM const diagnostics = []; const result = ts.transform(program .getSourceFiles() .filter((file) => !file.isDeclarationFile && path.resolve(file.fileName).indexOf(location.input) !== -1), [ ImportTransformer.transform({ from: location.input, to: location.output, }), transform(program, (compilerOptions.plugins ?? []).find((p) => p.transform === "typia/lib/transform" || p.transform === "../src/transform.ts") ?? {}, { addDiagnostic: (diag) => diagnostics.push(diag), }), ], program.getCompilerOptions()); // TRACE ERRORS for (const diag of diagnostics) { const file = diag.file ? path.relative(diag.file.fileName, process.cwd()) : "(unknown file)"; const category = diag.category === ts.DiagnosticCategory.Warning ? "warning" : diag.category === ts.DiagnosticCategory.Error ? "error" : diag.category === ts.DiagnosticCategory.Suggestion ? "suggestion" : diag.category === ts.DiagnosticCategory.Message ? "message" : "unknown"; const [line, pos] = diag.file ? (() => { const lines = diag .file.text.substring(0, diag.start) .split("\n"); if (lines.length === 0) return [0, 0]; return [lines.length, lines.at(-1).length + 1]; })() : [0, 0]; console.error(`${file}:${line}:${pos} - ${category} TS${diag.code}: ${diag.messageText}`); } if (diagnostics.length) process.exit(-1); // ARCHIVE TRANSFORMED FILES const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, }); for (const file of result.transformed) { const to = path .resolve(file.fileName) .replace(location.input, location.output); const content = printer.printFile(file); await fs.promises.writeFile(to, content, "utf8"); } }; const is_directory = async (current) => { const stat = await fs.promises.stat(current); return stat.isDirectory(); }; const gather = async (props) => { if (props.from === props.location.output) return; else if (fs.existsSync(props.to) === false) await fs.promises.mkdir(props.to); for (const file of await fs.promises.readdir(props.from)) { const next = path.join(props.from, file); const stat = await fs.promises.stat(next); if (stat.isDirectory()) { await gather({ location: props.location, container: props.container, from: next, to: path.join(props.to, file), }); continue; } else if (is_supported_extension(file)) props.container.push(next); } }; const is_supported_extension = (filename) => { // avoid using look-behind assertion as it is not marked as Baseline Widely Available return TS_PATTERN.test(filename) && !DTS_PATTERN.test(filename); }; })(TypiaProgrammer || (TypiaProgrammer = {})); const TS_PATTERN = /\.[cm]?tsx?$/; const DTS_PATTERN = /\.d\.[cm]?tsx?$/; export { TypiaProgrammer }; //# sourceMappingURL=TypiaProgrammer.mjs.map