You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.0 KiB
JavaScript
191 lines
4.0 KiB
JavaScript
"use strict";
|
|
|
|
const bluebird = require( "bluebird" );
|
|
const BundlerTarget = require( "@pegjs/bundler/target" );
|
|
const cp = require( "@futagoza/child-process" );
|
|
const fse = require( "fs-extra-plus" );
|
|
const isSourceNewer = require( "@tache/is-source-newer" );
|
|
const path = require( "path" );
|
|
|
|
/**
|
|
* This flag can be used to:
|
|
*
|
|
* 1. Force building content even if it hasn't changed.
|
|
* 2. Delete and write content instead of overwriting.
|
|
*/
|
|
|
|
const FRESH_BUILD = process.argv.includes( "--fresh" );
|
|
|
|
/**
|
|
* A conveniant object that has the following merged:
|
|
*
|
|
* - The `fs-extra-plus` module
|
|
* - The `path` module
|
|
* - Custom overwrides of the above 2 modules
|
|
*
|
|
* @type {path & fse}
|
|
*/
|
|
|
|
const fs = Object.assign( {}, path, fse, {
|
|
|
|
copy( source, target, opts ) {
|
|
|
|
return refresh( source, target, async () => {
|
|
|
|
if ( FRESH_BUILD ) await fse.remove( target );
|
|
|
|
await fse.copy( source, target, opts );
|
|
|
|
} );
|
|
|
|
},
|
|
|
|
} );
|
|
|
|
/**
|
|
* A bundler wrapper that simplfies bundler interaction across child process's via async functions.
|
|
*/
|
|
|
|
const Bundler = {
|
|
|
|
/**
|
|
* The CLI argument used to get/set a script that actually contains the bundles config.
|
|
*/
|
|
|
|
argv: "--get-config-from",
|
|
|
|
/**
|
|
* The CLI used to run the actual bundler.
|
|
*/
|
|
|
|
cli: require.resolve( "@pegjs/bundler/bundler.js" ),
|
|
|
|
/**
|
|
* The property exported from a script that contains the bundler's config.
|
|
*/
|
|
|
|
property: Symbol( "BundlerConfig" ),
|
|
|
|
/**
|
|
* This method must be called from a bundler's `*.js` config file to get the actual config.
|
|
*/
|
|
|
|
load() {
|
|
|
|
const { argv } = process;
|
|
|
|
return require( argv[ argv.indexOf( Bundler.argv ) + 1 ] )[ Bundler.property ];
|
|
|
|
},
|
|
|
|
/**
|
|
* This will create an async function that first executes the bundler if required, then calls `next`
|
|
*
|
|
* @template T
|
|
* @param {{check?: string, config: {}, cwd?: string, next: () => T, script: string, targets?: {}[]}} param0
|
|
*/
|
|
|
|
create( { check, config, cwd = __dirname, next, script, targets } ) {
|
|
|
|
if ( targets && ! config ) config = targets[ 0 ];
|
|
|
|
/** @returns {Promise<T>} */
|
|
|
|
async function executer() {
|
|
|
|
const run = () => cp.run( "node", [ Bundler.cli, Bundler.argv, script ], { cwd } );
|
|
|
|
await check ? refresh( check, config.output, run ) : run();
|
|
|
|
return bluebird.method( next )();
|
|
|
|
}
|
|
|
|
Object.defineProperty( executer, Bundler.property, {
|
|
get: () => targets || [ BundlerTarget( config ) ],
|
|
} );
|
|
|
|
return executer;
|
|
|
|
},
|
|
|
|
/**
|
|
* A wrapper function to help create a configuration for the bundler.
|
|
*/
|
|
|
|
target: BundlerTarget,
|
|
|
|
};
|
|
|
|
/**
|
|
* Helps to cleanly get the full filesystem path of `p`.
|
|
*
|
|
* @param {string} p The path to expand
|
|
* @param {string|string[]} cwd The current working directory (prepended to `p`)
|
|
*/
|
|
|
|
function expand( p = ".", cwd = [ __dirname, ".." ] ) {
|
|
|
|
let resolved = expand.cache[ p ];
|
|
|
|
if ( ! resolved ) {
|
|
|
|
if ( typeof cwd === "string" ) cwd = [ cwd ];
|
|
|
|
const right = p
|
|
.replace( "\\", "/" )
|
|
.split( "/" );
|
|
|
|
resolved = path.join( ...cwd, ...right );
|
|
|
|
expand.cache[ p ] = resolved;
|
|
|
|
}
|
|
|
|
return resolved;
|
|
|
|
}
|
|
|
|
/**
|
|
* A cache of the expaneded paths.
|
|
*
|
|
* @type {{ [key: string]: string }}
|
|
*/
|
|
|
|
expand.cache = {};
|
|
|
|
/**
|
|
* Will execute `cb` if `source` is newer then `target`. Can be used to only build changed files.
|
|
*
|
|
* _NOTE:_ If the `--fresh` flag is defined, this will always call `cb`
|
|
*
|
|
* @template T
|
|
* @param {string} source The source file or directory
|
|
* @param {string} target The generated output
|
|
* @param {(paths:{ source:string, target:string })=>Promise<T>} cb Called if `source` is newer.
|
|
*/
|
|
|
|
async function refresh( source, target, cb ) {
|
|
|
|
const paths = { source, target };
|
|
|
|
return FRESH_BUILD || await isSourceNewer( paths )
|
|
? cb( paths )
|
|
: Promise.resolve();
|
|
|
|
}
|
|
|
|
module.exports = {
|
|
|
|
FRESH_BUILD,
|
|
|
|
bluebird,
|
|
cp,
|
|
fs,
|
|
|
|
Bundler,
|
|
expand,
|
|
refresh,
|
|
|
|
};
|