// @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, 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; }