Config modules and the CLI
load-populate-files loads the files to write from a module, and passes them to populateFiles. The module holds only what to generate; the CLI (or a script, or an Nx target) decides where and when.
npm i -D load-populate-filespnpm add -D load-populate-filesyarn add -D load-populate-filesWrite a config module
The module's default export is one file, or an array of them, with the same params as populateFile. Use satisfies to check it at compile time:
// src/file-content.ts
import type { PopulateFileParams } from 'load-populate-files';
const routes = ['/', '/about', '/blog'];
export default [
{ filePath: 'routes.json', content: routes },
{
filePath: 'sitemap.txt',
content: `${routes.map(route => `https://example.com${route}`).join('\n')}\n`,
},
] satisfies PopulateFileParams[];The module is loaded with import(), so it must be JavaScript that Node can run: point the CLI at the compiled file. Anything the module imports runs as usual, so it can build content from your own code. For example, nx-lifecycle writes its JSON Schemas from the Juniper schemas it validates with, so the published schema can't drift from the code.
A default export that isn't a valid config fails with File content does not fulfill populate-file input at: <path>, followed by a line for each problem, such as - filePath: must have required property 'filePath'.
Run the CLI
npx load-populate-files --file-path ./dist/file-content.js --target-dir ./generatedFile paths in the config are resolved from --target-dir, which is resolved from --cwd. Like populateFiles, it checks instead of writing in CI, and --ci or --no-ci choose yourself:
load-populate-files --file-path ./dist/file-content.js --ci # fail if out of date
load-populate-files --file-path ./dist/file-content.js --no-ci # write, even in CISee the CLI reference for every flag.
From code
import { loadAndPopulateFiles } from 'load-populate-files';
const results = await loadAndPopulateFiles(
{ filePath: './dist/file-content.js' },
{ targetDir: './generated', clean: true }
);It takes the same options as populateFiles, and returns its results.
In an Nx workspace
Run it as a cached target after the module is compiled, and before anything that reads the output:
// nx.json
{
"targetDefaults": {
"populate-files": {
"executor": "nx:run-commands",
"options": {
"command": "load-populate-files --file-path ./dist/file-content.js --target-dir ./out --manifest ./out/.generated.json --clean",
"cwd": "{projectRoot}"
},
"dependsOn": ["build"],
"cache": true,
"inputs": ["{projectRoot}/src/**/*"],
"outputs": ["{projectRoot}/out"]
}
}
}With nx-lifecycle, bind the target to a stage instead of writing dependsOn by hand. See Stages and hooks.
The manifest lets --clean share out/ with other files, and catches hand edits to the JSON. Exclude it from the published package, e.g. with "!out/.generated.json" in package.json files.