@matatbread/typia
Version:
Superfast runtime validators with only one line
129 lines (126 loc) • 5.56 kB
JavaScript
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