@intlayer/chokidar
Version:
Uses chokidar to scan and build Intlayer declaration files into dictionaries based on Intlayer configuration.
128 lines (126 loc) • 5.59 kB
JavaScript
import { parallelize } from "../utils/parallelize.mjs";
import { filterInvalidDictionaries } from "../filterInvalidDictionaries.mjs";
import { processContentDeclaration } from "../buildIntlayerDictionary/processContentDeclaration.mjs";
import { getIntlayerBundle } from "./getIntlayerBundle.mjs";
import { loadMarkdownContentDeclaration } from "./loadMarkdownContentDeclaration.mjs";
import { loadYamlContentDeclaration } from "./loadYamlContentDeclaration.mjs";
import { logTypeScriptErrors } from "./logTypeScriptErrors.mjs";
import { readFile, writeFile } from "node:fs/promises";
import { dirname, extname, join, relative } from "node:path";
import { cacheDisk, getPackageJsonPath, getProjectRequire } from "@intlayer/config/utils";
import { loadExternalFile } from "@intlayer/config/file";
//#region src/loadDictionaries/loadContentDeclaration.ts
const formatLocalDictionaries = (dictionariesRecord, configuration) => Object.entries(dictionariesRecord).map(([relativePath, dict]) => ({
...dict,
location: dict.location ?? configuration.dictionary?.location ?? "local",
localId: `${dict.key}::local::${relativePath}`,
filePath: relativePath
}));
const ensureIntlayerBundle = async (configuration) => {
const { system } = configuration;
const { set, isValid } = cacheDisk(configuration, ["intlayer-bundle"], { ttlMs: 1e3 * 60 * 60 * 24 * 5 });
const filePath = join(system.cacheDir, "intlayer-bundle.cjs");
if (!await isValid()) {
await writeFile(filePath, await getIntlayerBundle(configuration));
await set("ok");
}
return filePath;
};
let cachedExternalDeps = null;
const getExternalDeps = async (baseDir) => {
if (cachedExternalDeps) return cachedExternalDeps;
try {
const packageJSON = await readFile(getPackageJsonPath(baseDir).packageJsonPath, "utf-8");
const parsedPackages = JSON.parse(packageJSON);
const allDependencies = Object.keys({
...parsedPackages.dependencies,
...parsedPackages.devDependencies
});
const esmPackagesToBundle = [];
const externalDeps = allDependencies.filter((dep) => !esmPackagesToBundle.includes(dep));
externalDeps.push("esbuild");
cachedExternalDeps = externalDeps;
} catch (error) {
console.warn("Could not read package.json for externalizing dependencies, fallback to empty array", error);
cachedExternalDeps = ["esbuild"];
}
return cachedExternalDeps;
};
const loadContentDeclaration = async (path, configuration, bundleFilePath, options) => {
if (extname(path) === ".md" || extname(path) === ".mdx") return loadMarkdownContentDeclaration(path);
if (extname(path) === ".yaml" || extname(path) === ".yml") return loadYamlContentDeclaration(path);
const { build, system } = configuration;
const externalDeps = await getExternalDeps(system.baseDir);
const resolvedBundleFilePath = bundleFilePath ?? await ensureIntlayerBundle(configuration);
try {
return await loadExternalFile(path, {
logError: options?.logError,
projectRequire: build.require ?? getProjectRequire(),
buildOptions: {
packages: void 0,
external: externalDeps,
banner: { js: [
`var __filename = ${JSON.stringify(path)};`,
`var __dirname = ${JSON.stringify(dirname(path))};`,
`globalThis.INTLAYER_FILE_PATH = '${path}';`,
`globalThis.INTLAYER_BASE_DIR = '${configuration.system.baseDir}';`
].join("\n") }
},
aliases: { intlayer: resolvedBundleFilePath },
preloadGlobals: {
INTLAYER_FILE_PATH: path,
INTLAYER_BASE_DIR: configuration.system.baseDir
}
});
} catch (error) {
console.error(`Error loading content declaration at ${path}:`, error);
return;
}
};
const loadContentDeclarations = async (contentDeclarationFilePath, configuration, onStatusUpdate, options) => {
const { build, system } = configuration;
if (build.checkTypes) logTypeScriptErrors(contentDeclarationFilePath, configuration).catch((e) => {
console.error("Error during TypeScript validation:", e);
});
const bundleFilePath = await ensureIntlayerBundle(configuration);
try {
const dictionariesPromises = contentDeclarationFilePath.map(async (path) => {
return {
relativePath: relative(system.baseDir, path),
dictionary: await loadContentDeclaration(path, configuration, bundleFilePath, options)
};
});
const contentDeclarations = formatLocalDictionaries((await Promise.all(dictionariesPromises)).reduce((acc, { relativePath, dictionary }) => {
if (dictionary) acc[relativePath] = dictionary;
return acc;
}, {}), configuration).filter((dictionary) => dictionary.location !== "remote");
const listFoundDictionaries = contentDeclarations.map((declaration) => ({
dictionaryKey: declaration.key,
type: "local",
status: "found"
}));
onStatusUpdate?.(listFoundDictionaries);
return filterInvalidDictionaries(await parallelize(contentDeclarations, async (contentDeclaration) => {
if (!contentDeclaration) return;
onStatusUpdate?.([{
dictionaryKey: contentDeclaration.key,
type: "local",
status: "building"
}]);
const processedContentDeclaration = await processContentDeclaration(contentDeclaration, configuration);
if (!processedContentDeclaration) return;
onStatusUpdate?.([{
dictionaryKey: processedContentDeclaration.key,
type: "local",
status: "built"
}]);
return processedContentDeclaration;
}), configuration, { checkSchema: false });
} catch {
console.error("Error loading content declarations");
}
return [];
};
//#endregion
export { ensureIntlayerBundle, formatLocalDictionaries, loadContentDeclaration, loadContentDeclarations };
//# sourceMappingURL=loadContentDeclaration.mjs.map