@roots/bud-extensions
Version:
bud.js core module
151 lines (150 loc) • 6.29 kB
JavaScript
import { __decorate } from "tslib";
import { isAbsolute, join } from 'node:path';
import { Extension } from '@roots/bud-framework/extension';
import { bind, disabled, expose, label, options, } from '@roots/bud-framework/extension/decorators';
import isString from '@roots/bud-support/isString';
/**
* The BudTsConfigValues class configures the bud.js application using settings
* defined in a tsconfig.json file. This includes several options such as compilerOptions,
* include, exclude, and a special bud key. The compilerOptions property provides configuration for the
* TypeScript compiler, while include and exclude specify which files are to be included
* in or excluded from the process. The bud property allows for enabling the use of compilerOptions.
*/
let BudTsConfigValues = class BudTsConfigValues extends Extension {
get derivedBaseDir() {
return (this.getCompilerOptions()?.rootDir ??
this.getCompilerOptions()?.baseUrl);
}
/**
* The `configAfter` method adjusts the bud.js application
* configuration by setting up paths and determining file inclusion and exclusion
* based on the tsconfig.json settings.
*
* {@link Extension.configAfter}
*/
async configAfter(bud) {
if (!this.isEnabled())
return;
// If a base directory has been defined in the tsconfig.json (either as rootDir or baseUrl),
// it is set as the @src path in the bud.js application.
if (this.derivedBaseDir) {
this.logger.log(`setting @src dir as specified in jsconfig/tsconfig: ${this.derivedBaseDir}`);
bud.setPath({ '@src': this.derivedBaseDir });
}
// If an output directory has been defined in the tsconfig.json, it is set as the @dist path in the bud.js application.
if (this.compilerOptions?.outDir) {
this.logger.log(`setting @dist dir as specified in jsconfig/tsconfig: ${this.compilerOptions.outDir}`);
bud.setPath({ '@dist': this.compilerOptions.outDir });
}
// If paths have been defined in the tsconfig.json, these paths are normalized (i.e., made absolute)
// and then set as paths w/ aliases in the bud.js application.
if (this.compilerOptions?.paths) {
const normalPaths = this.normalizePaths(this.compilerOptions.paths);
if (normalPaths)
bud
.setPath(normalPaths)
// @ts-ignore
.alias(Object.entries(normalPaths).reduce((a, [k, v]) => ({
...a,
[k]: this.makeAbsolute(v),
}), {}));
}
// If specific directories have been defined to be included in the tsconfig.json,
// those directories are added to the Bud.js application's compilation paths.
if (this.include) {
const directories = (await Promise.all(this.include.map(async (path) => {
const type = await bud.fs.exists(path);
// If the path exists, is a directory (not a file),
// and it doesn't match the config path pattern, then it's added to the directories array.
// The config directory is often ignored in this context because it typically contains
// configuration files for various tools and libraries used in your project. These
// files are not part of the actual source code that needs to be compiled or transformed,
// but are instead used to control the behavior of these processes.
return type === `dir` && !path.match(/^\.?\/?config/)
? path
: undefined;
}))).filter(isString);
directories &&
// Include these directories in Bud.js' compilePaths
// @ts-ignore
bud.compilePaths(directories.map(dir => bud.path(dir)));
}
}
/**
* Make absolute path
*
* @param path string
* @returns string
*/
makeAbsolute(path) {
return isAbsolute(path) ? path : this.app.path(path);
}
/**
* Resolve {@link CompilerOptions.paths} against {@link BudTsConfigValues.derivedBaseDir}
*
* @remarks
* Operates on the first item in the array of paths
*
* @param paths
* @returns
*/
normalizePaths(paths) {
if (!paths)
return;
const normalPaths = Object.entries(paths)
.filter(([k, v]) => Array.isArray(v))
.map(([k, v]) => [k, v[0]])
.filter(Boolean)
.map(tuple => tuple.map((str) => str.replace(`/*`, ``)))
.reduce((acc, [key, value]) => ({
...acc,
[key]: this.derivedBaseDir
? join(this.derivedBaseDir, value)
: value,
}), {});
this.logger.log(`normalized paths`, normalPaths);
return normalPaths;
}
/**
* {@link Extension.register}
*/
async register(bud) {
const fetchConfigModule = bud.context.files[`tsconfig`]?.module ??
bud.context.files[`jsconfig`]?.module;
if (!fetchConfigModule)
return;
const tsConfig = await fetchConfigModule();
if (!tsConfig)
return;
if (tsConfig.compilerOptions)
this.setCompilerOptions(tsConfig.compilerOptions);
tsConfig.include && this.setInclude(tsConfig.include);
tsConfig.exclude && this.setExclude(tsConfig.exclude);
tsConfig.bud && this.setBud(tsConfig.bud);
tsConfig.bud?.useCompilerOptions && this.enable();
}
};
__decorate([
bind
], BudTsConfigValues.prototype, "configAfter", null);
__decorate([
bind
], BudTsConfigValues.prototype, "makeAbsolute", null);
__decorate([
bind
], BudTsConfigValues.prototype, "normalizePaths", null);
__decorate([
bind
], BudTsConfigValues.prototype, "register", null);
BudTsConfigValues = __decorate([
label(`@roots/bud-extensions/tsconfig-values`),
expose(`tsconfig`),
options({
bud: undefined,
compilerOptions: undefined,
exclude: undefined,
include: undefined,
}),
disabled
], BudTsConfigValues);
export default BudTsConfigValues;