Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
name: tests
on:
- push

jobs:
build:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- 14.x
- 18.x
- 19.x
- 20.x
- 24.x
- latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
- run: npm install-test
Expand Down
49 changes: 49 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,55 @@ faucet-pipeline-core version history
====================================


v3.1.0
------

_2025-10-30_

no significant changes for end users

notable changes for developers:

* `faucetDispatch` now has a return value which reports completion of the
initial build


v3.0.0
------

_2025-03-02_

notable changes for end users:

* bumped Node requirement to v18 or later, dropping support for obsolete versions
* reduced number of dependencies

notable changes for developers:

* switched to named instead of default exports

this might affect users of utilities like `resolvePath` and `FileFinder`

* ensured dynamic imports are asynchronous

this might affect users of utilities like `loadExtension`

* `promisify` was removed entirely after being deprecated for a while


v2.1.0
------

_2025-10-26_

notable changes for end users:

* added support for faucet-pipeline-assets and faucet-pipeline-css
* dropped support for Node 19 and below

no significant changes for developers


v2.0.0
------

Expand Down
10 changes: 6 additions & 4 deletions bin/faucet
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env node
"use strict";

let faucet = require("../lib");
let parseCLI = require("../lib/cli");
let { faucetDispatch } = require("../lib");
let { parseCLI } = require("../lib/cli");

let { referenceDir, config, options } = parseCLI();
faucet(referenceDir, config, options);
parseCLI().
then(({ referenceDir, config, options }) => {
faucetDispatch(referenceDir, config, options);
});
64 changes: 46 additions & 18 deletions lib/cli.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use strict";

let readConfig = require("./config");
let { readConfig } = require("./config");
let { abort, repr } = require("./util");
let parseArgs = require("minimist");
let { parseArgs } = require("node:util");

let HELP = `
Usage:
Expand All @@ -27,27 +27,55 @@ Options:
serve generated files via HTTP with live reloading
`.trim();

module.exports = function parseCLI(argv = process.argv.slice(2), help = HELP) {
argv = parseArgs(argv, {
boolean: ["watch", "fingerprint", "sourcemaps", "compact"],
alias: {
c: "config",
w: "watch",
h: "help"
exports.parseCLI = async function parseCLI() {
let { values } = parseArgs({
options: {
help: {
type: "boolean",
short: "h",
default: false
},
config: {
type: "string",
short: "c"
},
watch: {
type: "boolean",
short: "w",
default: false
},
fingerprint: {
type: "boolean",
default: false
},
sourcemaps: {
type: "boolean",
default: false
},
compact: {
type: "boolean",
default: false
},
serve: {
type: "string"
},
liveserve: {
type: "string"
}
}
});

if(argv.help) {
abort(help, 0);
if(values.help) {
abort(HELP, 0);
}

let options = {
watch: argv.watch,
fingerprint: argv.fingerprint,
sourcemaps: argv.sourcemaps,
compact: argv.compact,
serve: argv.serve,
liveserve: argv.liveserve
watch: values.watch,
fingerprint: values.fingerprint,
sourcemaps: values.sourcemaps,
compact: values.compact,
serve: values.serve,
liveserve: values.liveserve
};

if(options.watch && options.fingerprint) { // for convenience
Expand All @@ -56,6 +84,6 @@ module.exports = function parseCLI(argv = process.argv.slice(2), help = HELP) {
}

let rootDir = process.cwd();
let { referenceDir, config } = readConfig(rootDir, argv.config);
let { referenceDir, config } = await readConfig(rootDir, values.config);
return { referenceDir, config, options };
};
4 changes: 2 additions & 2 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

let path = require("path");

module.exports = function readConfig(rootDir, filepath = "faucet.config.js") {
exports.readConfig = async function readConfig(rootDir, filepath = "faucet.config.js") {
let configPath = path.resolve(rootDir, filepath);
return {
referenceDir: path.dirname(configPath),
config: require(configPath)
config: await require(configPath)
};
};
24 changes: 14 additions & 10 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

let server = require("./server");
let { pluginsByBucket } = require("./plugins");
let AssetManager = require("./manager");
let resolvePath = require("./util/resolve");
let { AssetManager } = require("./manager");
let { resolvePath } = require("./util/resolve");
let { abort, repr } = require("./util");
let SerializedRunner = require("./util/runner");
let { SerializedRunner } = require("./util/runner");
let browserslist = require("browserslist");

module.exports = async function faucetDispatch(referenceDir, config,
exports.faucetDispatch = async function faucetDispatch(referenceDir, config,
{ watch, fingerprint, sourcemaps, compact, serve, liveserve }) {
config = await config;

Expand All @@ -22,7 +22,7 @@ module.exports = async function faucetDispatch(referenceDir, config,
browsers = [browsers];
}

let plugins = pluginsByBucket(config);
let plugins = await pluginsByBucket(config);
// initialize plugins with corresponding configuration
let buckets = Object.keys(plugins).reduce((memo, bucket) => {
memo[bucket] = plugins[bucket].map(({ plugin, config }) => {
Expand All @@ -36,12 +36,14 @@ module.exports = async function faucetDispatch(referenceDir, config,
then(buildStep(buckets.scripts.concat(buckets.styles))).
then(buildStep(buckets.markup));
});
runner.run();
let res = runner.run();

if(watch) {
makeWatcher(config.watchDirs, referenceDir).
on("edit", filepaths => {
runner.rerun(filepaths);
then(watcher => {
watcher.on("edit", filepaths => {
runner.rerun(filepaths);
});
});
}

Expand All @@ -53,15 +55,17 @@ module.exports = async function faucetDispatch(referenceDir, config,
} else if(liveserve) {
server.live(liveserve, assetManager.manifest.webRoot);
}

return res; // notifies consumers once the initial build has completed
};

function buildStep(plugins) {
return files => Promise.all(plugins.map(plugin => plugin(files))).
then(() => files);
}

function makeWatcher(watchDirs, referenceDir) {
let niteOwl = require("nite-owl");
async function makeWatcher(watchDirs, referenceDir) {
let niteOwl = await require("nite-owl");

if(watchDirs) {
watchDirs = watchDirs.map(dir => resolvePath(dir, referenceDir,
Expand Down
8 changes: 4 additions & 4 deletions lib/manager.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use strict";

let Manifest = require("./manifest");
let createFile = require("./util/files");
let resolvePath = require("./util/resolve");
let { Manifest } = require("./manifest");
let { createFile } = require("./util/files");
let { resolvePath } = require("./util/resolve");
let { reportFileStatus, abort, generateFingerprint } = require("./util");
let path = require("path");

module.exports = class AssetManager {
exports.AssetManager = class AssetManager {
constructor(referenceDir, { manifestConfig, fingerprint, exitOnError } = {}) {
this.referenceDir = referenceDir;
this.fingerprint = fingerprint;
Expand Down
6 changes: 3 additions & 3 deletions lib/manifest.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"use strict";

let createFile = require("./util/files");
let resolvePath = require("./util/resolve");
let { createFile } = require("./util/files");
let { resolvePath } = require("./util/resolve");
let { abort } = require("./util");
let path = require("path");

module.exports = class Manifest {
exports.Manifest = class Manifest {
constructor(referenceDir, { target, key, value, baseURI, webRoot } = {}) {
if(value && (baseURI || webRoot)) {
abort("ERROR: `value` must not be used with `baseURI` and/or `webRoot`");
Expand Down
Loading