Files
csx/packages/csx/cfg/config.js

171 lines
5.8 KiB
JavaScript

// @cerxes
import { host, Host } from "@cerxes/host";
// Rollup and plugins
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import { terser } from 'rollup-plugin-terser';
// Proc args (this is weird to be here, but it is the same for build/watch, and should be kept in sync as much as possible
import process from "process";
import * as rollup from "rollup";
import { logBundle } from "./log-bundle";
let args = process.argv.slice(2);
const runArgSeperator = args.indexOf('--');
export let buildTargets = ['lib-es', 'lib-cjs', 'dist-es', 'dist-es-min', 'dist-cjs', 'dist-cjs-min'];
if (runArgSeperator >= 0) {
buildTargets = args.slice(runArgSeperator + 1);
args = args.slice(0, runArgSeperator);
}
export class CsxConfig {
constructor({
src,
dist,
root,
opts
} = {}) {
const { watch } = opts || {};
this.root = root ? host.from(root) : host.from('.');// (This host.from('.') would not've been necessary if @cerxes/host did not have a bug on this one)
this.src = this.root.from(src || 'src');
this.dist = this.root.from(dist || 'dist');
this.lib = this.root.from(dist || 'lib');
}
/** @type {Host} */
src;
/**
* Directory to use for dist output (single bundle)
* @type {Host} */
dist;
/**
* Directory to use for library output (transpiled, file by file)
* @type {Host} */
lib;
/** @type {string} */
sourceGlob = "**/*.@(*.js|js)";
/**
* Get rollup-config to compile a source file
* @param {string} file
* @param {string} out
* @param {object} [opts]
* @param {boolean} [opts.es] - Export in es6 format (or cjs when false)
* @param {boolean} [opts.single] - Compile single file (e.g. don't follow imports)
* @param {boolean} [opts.sourcemap] - Include sourcemaps
* @param {boolean} [opts.minified] - Minify the output (e.g. Terser-plugin)
* @returns {{output: {file: string, sourcemap: boolean, plugins: Array<Object>, format: string}, input: string, plugins: ...*[]}}
*/
srcCfg = (file, out = undefined, opts) => {
let inputFile = this.src.resolve(file);
let outputFile = this.dist.resolve(out || file);
return ({
// Compile the actual app
input: inputFile,
output: {
file: outputFile,
format: opts?.es? 'es' : 'cjs', // NodeJS
sourcemap: opts?.sourcemap ?? true,
},
external: (id, parentId, isResolved) => {
if (!id || id[0] === '\0') return false;// Special cases
else {
let split = (id || "").split('/');
let first = id[0] === '@' ? split.slice(0, 2).join('/') : split[0];
let absId = first === '..' || first === '.' ? this.src.resolve(parentId, id) : id;
if (absId) {
if(absId.indexOf(this.src.workingDirectory) >= 0 && opts?.single) return true; // Own source-file => external when single mode enabled
}
// Any other unresolved identifier(which should be resolved further)
return false; // The light, inline them
}
},
treeshake: !opts?.single,
plugins: [
// babel
babel({
babelrc: true,
}),
// NodeJS-style resolving (Its a shame this is not a Rollup-default, we need this for index.js files to work!)
resolve({
extensions: ['.mjs', '.js', '.jsx', '.json'],
preferBuiltins: true, mainFields: ['browser']
}),
opts?.minified ? terser() : null
].filter(t=>t)
})
};
/**
* @param {string} sources
* @returns {TargetConfig[]}
*/
configureTargets = (sources)=>{
return buildTargets.map(target=>{
let {lib,dist,root} = this;
let [type, format, minified] = target.split("-");
let inputs = type==='lib'? sources : ['index.js'];
let srcOpts = {
es: format==='es',
single: type==='lib',
sourcemap: true,// Just always there for now
minified: !!minified
};
let outDir = type==='lib'? lib : dist;
return new TargetConfig({
target,
sources: inputs.map(input=>{
let outName = input.replace(
/\.js$/,
`.${[
type==='dist'? srcOpts.es?'es':'cjs' : null,
srcOpts.minified?'min':null,
'js'
].filter(x=>x).join('.')}`);
if(type==='lib') outName = [srcOpts.es?'es':'cjs',outName].join('/');
return new SourceConfig({
source: input,
config: this.srcCfg(input, outDir.resolve(outName), srcOpts)
});
})
});
});
}
}
/**
* Configure a source-file for build (single target)
*/
export class SourceConfig{
/** @param {SourceConfig} c */
constructor(c){
this.source = c.source;
this.config = c.config;
}
/** @type {string} */
source;
/** @type {RollupOptions} */
config;
}
/**
* Represent the configuration for a specific build target (e.g. lib-es, dist-cjs, ...)
*/
export class TargetConfig{
/** @param {TargetConfig} c */
constructor(c){
this.target = c.target;
this.sources = c.sources;
}
/** @type {string} */
target;
/** @type {SourceConfig[]} */
sources;
}