create-validator-ts
Version:
Create JSON Schema validator from TypeScript.
146 lines • 5.41 kB
JavaScript
import globWatch from "glob-watcher";
import fs from "node:fs/promises";
import * as globby from "globby";
import assert from "node:assert";
import { generateValidator } from "./create-validator-ts.js";
import path from "node:path";
import { createCache } from "@file-cache/core";
import { createNpmPackageKey } from "@file-cache/npm";
import { pathToFileURL } from "node:url";
// dynamic import wrapper
// import() can not load Window file path
// convert file path to file URL before import()
// https://github.com/nodejs/node/issues/31710
export async function dynamicImport(targetPath) {
const fileUrl = pathToFileURL(targetPath).href;
return import(fileUrl);
}
export async function watchValidator(options) {
const { generator, generatorOptions = {} } = (await dynamicImport(path.resolve(options.cwd, options.codeGeneratorScript)));
const watcher = globWatch(options.targetGlobs, {
ignoreInitial: true
});
const { sortProps, strictTuples, encodeRefs, skipTypeCheck, additionalProperties } = options;
return new Promise((resolve, reject) => {
watcher.on("change", async (filePath) => {
const result = await generateValidator({
cwd: options.cwd,
filePath: filePath,
tsconfigFilePath: options.tsconfigFilePath,
validatorGenerator: generator,
extraTags: generatorOptions.extraTags || [],
sortProps,
strictTuples,
encodeRefs,
skipTypeCheck,
additionalProperties
});
if (!result) {
return;
}
if (options.verbose) {
console.log("Update validator: " + result.validatorFilePath);
}
return fs.writeFile(result.validatorFilePath, result.code, "utf-8");
});
watcher.on("close", () => {
resolve();
});
watcher.on("error", (error) => {
reject(error);
});
});
}
// --check: validate the difference current of source
export async function testGeneratedValidator(options) {
const files = await globby.globby(options.targetGlobs, {
cwd: options.cwd,
absolute: true
});
const { generator, generatorOptions = {} } = (await dynamicImport(path.resolve(options.cwd, options.codeGeneratorScript)));
const { sortProps, strictTuples, encodeRefs, skipTypeCheck, additionalProperties } = options;
return Promise.all(files.map(async (filePath) => {
const result = await generateValidator({
cwd: options.cwd,
filePath: filePath,
tsconfigFilePath: options.tsconfigFilePath,
validatorGenerator: generator,
extraTags: generatorOptions.extraTags || [],
sortProps,
strictTuples,
encodeRefs,
skipTypeCheck,
additionalProperties
});
if (!result) {
return;
}
try {
await fs.access(result.validatorFilePath);
}
catch (_a) {
return;
}
const prevValidatorCode = await fs.readFile(result.validatorFilePath, {
encoding: "utf-8"
});
try {
assert.strictEqual(result.code, prevValidatorCode);
}
catch (error) {
console.error("Found diff between types and validator.\nPlease update validator: $ npx create-validator-ts " +
filePath);
throw error;
}
if (options.verbose) {
console.log("OK: " + filePath);
}
}));
}
export async function createValidator(options) {
var _a;
const { generator, generatorOptions = {} } = (await dynamicImport(path.resolve(options.cwd, options.codeGeneratorScript)));
const files = await globby.globby(options.targetGlobs, {
cwd: options.cwd,
absolute: true
});
const { sortProps, strictTuples, encodeRefs, skipTypeCheck, additionalProperties } = options;
const cache = await createCache({
name: "create-validator-ts",
mode: "content",
keys: [() => createNpmPackageKey(["create-validator-ts"]), () => JSON.stringify(options)],
// disable cache by default
noCache: (_a = options.noCache) !== null && _a !== void 0 ? _a : true
});
return Promise.all(files.map(async (filePath) => {
const cacheStatus = await cache.getAndUpdateCache(filePath);
if (!cacheStatus.changed) {
if (options.verbose) {
console.log("Cached: " + filePath);
}
return;
}
const result = await generateValidator({
cwd: options.cwd,
filePath: filePath,
tsconfigFilePath: options.tsconfigFilePath,
validatorGenerator: generator,
extraTags: generatorOptions.extraTags || [],
sortProps,
strictTuples,
encodeRefs,
skipTypeCheck,
additionalProperties
});
if (!result) {
return;
}
if (options.verbose) {
console.log("Create: " + filePath);
}
return fs.writeFile(result.validatorFilePath, result.code, "utf-8");
})).finally(() => {
return cache.reconcile();
});
}
//# sourceMappingURL=index.js.map