@plugjs/build
Version:
Simple shared build using PlugJS
305 lines (304 loc) • 11.6 kB
JavaScript
// index.ts
import "@plugjs/cov8";
import "@plugjs/eslint";
import "@plugjs/expect5";
import {
banner,
find,
fixExtensions,
isDirectory,
merge,
noop,
plugjs,
resolve,
rmrf
} from "@plugjs/plug";
import "@plugjs/typescript";
export * from "@plugjs/plug";
var esbuildDefaults = {
platform: "node",
sourcemap: "linked",
sourcesContent: false,
plugins: [fixExtensions()]
};
function tasks(options = {}) {
const {
sourceDir: _sourceDir = "src",
destDir: _destDir = "dist",
testDir: _testDir = "test",
coverageDir: _coverageDir = "coverage",
coverageDataDir: _coverageDataDir = ".coverage-data",
extraTypesDir: _extraTypesDir = "types",
tsconfigJson: _tsconfigJson = "tsconfig.json",
extraLint: _extraLint = [],
extraCoverage: _extraCoverage = [],
packageJson: _packageJson = "package.json",
outputPackageJson: _outputPackageJson = _packageJson,
cjsExtension: _cjsExtension = ".cjs",
esmExtension: _esmExtension = ".mjs",
cjs: _cjs = true,
esm: _esm = true,
parallelize: _parallelize = false,
banners: _banners = !_parallelize,
testGlob: _testGlob = "**/*.test.([cm])?ts",
exportsGlob: _exportsGlob = "index.*",
exportsGlobs: _exportsGlobs = [],
coverage: _coverage = true,
minimumCoverage: _minimumCoverage = 100,
minimumFileCoverage: _minimumFileCoverage = 100,
optimalCoverage: _optimalCoverage = void 0,
optimalFileCoverage: _optimalFileCoverage = void 0,
esbuildOptions: _esbuildOptions = {}
} = options;
const emitBanner = _banners ? banner : (...args) => void args;
const esbuildMergedOptions = Object.assign({}, esbuildDefaults, _esbuildOptions);
return plugjs({
/** The directory for the original sources (default: `src`) */
sourceDir: _sourceDir,
/** The destination directory of the transpiled sources (default: `dist`) */
destDir: _destDir,
/** The directory for the test files (default: `test`) */
testDir: _testDir,
/** The directory for the coverage report (default: `coverage`) */
coverageDir: _coverageDir,
/** The directory for the coverage data (default: `.coverage-data`) */
coverageDataDir: _coverageDataDir,
/** A directory containing extra types to use while transpiling (default: `types`) */
extraTypesDir: _extraTypesDir,
/** The `tsconfig.json` file used for _transpiling_ source TypeScript files (default: `tsconfig.json`) */
tsconfigJson: _tsconfigJson,
/** The source `package.json` file (default: `package.json`) */
packageJson: _packageJson,
/** The source `package.json` file (default: same as `packageJson` option) */
outputPackageJson: _outputPackageJson,
/** The extension used for CommonJS modules (default: `.cjs`) */
cjsExtension: _cjsExtension,
/** The extension used for EcmaScript modules (default: `.mjs`) */
esmExtension: _esmExtension,
/** The extension used for CommonJS modules (default: `.cjs`) */
cjs: _cjs ? "true" : "false",
/** The extension used for EcmaScript modules (default: `.mjs`) */
esm: _esm ? "true" : "false",
/** A glob pattern matching all test files (default: `**∕*.test.([cm])?ts`) */
testGlob: _testGlob,
/** A glob pattern matching files to be exported (default: `index.*`) */
exportsGlob: _exportsGlob,
/* ====================================================================== *
* SOURCES STRUCTURE *
* ====================================================================== */
/** Find all CommonJS source files (`*.cts`) */
_find_sources_cts() {
return find("**/*.(c)?ts", { directory: this.sourceDir, ignore: "**/*.d.ts" });
},
/** Find all EcmaScript Module source files (`*.mts`) */
_find_sources_mts() {
return find("**/*.(m)?ts", { directory: this.sourceDir, ignore: "**/*.d.ts" });
},
/** Find all typescript source files (`*.ts`, `*.mts` and `*.cts`) */
_find_sources() {
return merge([
this.cjs === "true" ? this._find_sources_cts() : noop(),
this.esm === "true" ? this._find_sources_mts() : noop()
]);
},
/** Find all types definition files within sources */
_find_types() {
return find("**/*.d.([cm])?ts", { directory: this.sourceDir });
},
/** Find all resource files (non-typescript files) within sources */
_find_resources() {
return find("**/*", { directory: this.sourceDir, ignore: "**/*.([cm])?ts" });
},
/** Find all test source files */
_find_tests() {
return find(this.testGlob, { directory: this.testDir, ignore: "**/*.d.([cm])?ts" });
},
/** Find all source files to lint */
_find_lint_sources() {
return merge([
find("**/*.([cm])?ts", "**/*.([cm])?js", { directory: this.sourceDir }),
find("**/*.([cm])?ts", "**/*.([cm])?js", { directory: this.testDir }),
isDirectory(this.extraTypesDir) ? find("**/*.([cm])?ts", "**/*.([cm])?js", { directory: this.extraTypesDir }) : noop(),
..._extraLint.map((args) => find(...args))
]);
},
/** Find all source files for coverage */
_find_coverage_sources() {
return merge([
find("**/*.([cm])?ts", "**/*.([cm])?js", {
directory: this.sourceDir,
ignore: "**/*.d.([cm])?ts"
}),
..._extraCoverage.map((args) => find(...args))
]);
},
/* ====================================================================== *
* TRANSPILE *
* ====================================================================== */
/** Transpile to CJS */
transpile_cjs() {
return this._find_sources_cts().esbuild({
...esbuildMergedOptions,
format: "cjs",
outdir: this.destDir,
outExtension: { ".js": this.cjsExtension }
});
},
/** Transpile to ESM */
transpile_esm() {
return this._find_sources_mts().esbuild({
...esbuildMergedOptions,
format: "esm",
outdir: this.destDir,
outExtension: { ".js": this.esmExtension }
});
},
/** Generate all .d.ts files */
transpile_types() {
const extraTypesDir = isDirectory(this.extraTypesDir) ? this.extraTypesDir : void 0;
return merge([
this._find_sources(),
this._find_types()
]).tsc(this.tsconfigJson, {
noEmit: false,
declaration: true,
emitDeclarationOnly: true,
outDir: this.destDir,
extraTypesDir
});
},
/** Copy all resources coming alongside our sources */
copy_resources() {
return merge([
this._find_resources(),
this._find_types()
]).copy(this.destDir);
},
/** Transpile all source code */
async transpile() {
emitBanner("Transpiling source files");
if (isDirectory(this.destDir)) await rmrf(this.destDir);
const result = await merge([
this.cjs === "true" ? this.transpile_cjs() : noop(),
this.esm === "true" ? this.transpile_esm() : noop(),
this.transpile_types(),
this.copy_resources()
]);
return result;
},
/* ====================================================================== *
* TEST & COVERAGE *
* ====================================================================== */
/** Check test types */
async test_types() {
emitBanner("Checking test types");
const tsconfig = resolve(this.testDir, "tsconfig.json");
const extraTypesDir = isDirectory(this.extraTypesDir) ? this.extraTypesDir : void 0;
await this._find_tests().tsc(tsconfig, {
noEmit: true,
declaration: false,
emitDeclarationOnly: false,
extraTypesDir
});
},
/** Run tests */
async test_cjs() {
emitBanner("Running tests (CommonJS)");
await this._find_tests().test({
coverageDir: _coverage ? this.coverageDataDir : void 0,
forceModule: "commonjs"
});
},
/** Run tests */
async test_esm() {
emitBanner("Running tests (ES Modules)");
await this._find_tests().test({
coverageDir: _coverage ? this.coverageDataDir : void 0,
forceModule: "module"
});
},
/** Run tests */
async test() {
if (_coverage && isDirectory(this.coverageDataDir)) await rmrf(this.coverageDataDir);
if (this.esm === "true") await this.test_esm();
if (this.cjs === "true") await this.test_cjs();
},
/** Ensure tests have run and generate a coverage report */
async coverage() {
let coveragePipe;
try {
await this.test();
} finally {
emitBanner("Preparing coverage report");
coveragePipe = this._find_coverage_sources().coverage(this.coverageDataDir, {
reportDir: this.coverageDir,
minimumCoverage: _minimumCoverage,
minimumFileCoverage: _minimumFileCoverage,
optimalCoverage: _optimalCoverage,
optimalFileCoverage: _optimalFileCoverage
});
}
return coveragePipe;
},
/* ====================================================================== *
* LINTING *
* ====================================================================== */
/** Lint all sources */
async lint() {
emitBanner("Linting sources");
await this._find_lint_sources().eslint();
},
/* ====================================================================== *
* PACKAGE.JSON EXPORTS *
* ====================================================================== */
/** Inject `exports` into the `package.json` file */
async exports() {
const files = await this.transpile();
emitBanner('Updating exports in "package.json"');
const globs = [this.exportsGlob, ..._exportsGlobs];
return merge([files]).filter(...globs, { directory: this.destDir, ignore: "**/*.map" }).exports({
cjsExtension: this.cjsExtension,
esmExtension: this.esmExtension,
packageJson: this.packageJson,
outputPackageJson: this.outputPackageJson
});
},
/* ====================================================================== *
* ALL: DO EVERYTHING *
* ====================================================================== */
/* coverage ignore next */
/** Build everything. */
async all() {
if (_parallelize) {
await Promise.all([
this.transpile(),
this.test_types(),
_coverage ? this.coverage() : this.test(),
this.lint()
]);
} else {
await this.transpile();
await this.test_types();
await (_coverage ? this.coverage() : this.test());
await this.lint();
}
},
/* ====================================================================== *
* DEFAULT: DO EVERYTHING *
* ====================================================================== */
/* coverage ignore next */
/**
* Default task (simply invokes `this._all()`).
*
* Override this and invoke `this._all()` to inject tasks _before_ or
* _after_ the normal build execution.
*/
async default() {
await this.all();
}
});
}
export {
tasks
};
//# sourceMappingURL=index.mjs.map