Skip to content
Merged

2.1 #163

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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@ faucet-pipeline-core version history
====================================


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
4 changes: 2 additions & 2 deletions lib/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ module.exports = class AssetManager {
}

return createFile(filepath, data).
then(_ => this.manifest &&
then(() => this.manifest &&
this._updateManifest(originalPath, filepath, targetDir)).
then(_ => {
then(() => {
reportFileStatus(originalPath, this.referenceDir, error);
if(error && this.exitOnError) {
throw error;
Expand Down
8 changes: 8 additions & 0 deletions lib/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ let { loadExtension, abort, repr } = require("./util");

// common plugins included for convenience
let DEFAULTS = [{
key: "assets",
bucket: "static",
plugin: "faucet-pipeline-assets"
}, {
key: "js",
bucket: "scripts",
plugin: "faucet-pipeline-js"
}, {
key: "css",
bucket: "styles",
plugin: "faucet-pipeline-css"
}, {
key: "sass",
bucket: "styles",
Expand Down
8 changes: 2 additions & 6 deletions lib/util/files/finder.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
let fs = require("fs");
let { readdir, stat } = require("fs/promises");
let path = require("path");
let { promisify } = require("util");

let stat = promisify(fs.stat);
let readDir = promisify(fs.readdir);

module.exports = class FileFinder {
constructor(directory, { skipDotfiles, filter = () => true } = {}) {
Expand Down Expand Up @@ -36,7 +32,7 @@ function tree(filepath, referenceDir = filepath) {
return [path.relative(referenceDir, filepath)];
}

return readDir(filepath).
return readdir(filepath).
then(entries => {
let res = Promise.all(entries.map(entry => {
return tree(path.join(filepath, entry), referenceDir);
Expand Down
37 changes: 12 additions & 25 deletions lib/util/files/index.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,29 @@
"use strict";

let { abort, repr } = require("../");
let fs = require("fs");
let { writeFile } = require("fs/promises");
let { mkdirSync } = require("fs");
let path = require("path");
let { promisify } = require("util");

let KNOWN = {}; // avoids redundant `mkdirp` invocations
let LOCKS = {};

let writeFile = promisify(fs.writeFile);
let KNOWN = new Set(); // avoids redundant `mkdir` invocations
let LOCKS = new Map();

// avoids concurrent write operations and creates target directory if necessary
module.exports = function createFile(filepath, contents) {
let lock = LOCKS[filepath];
let lock = LOCKS.get(filepath);
if(lock) { // defer
return lock.then(_ => createFile(filepath, contents));
return lock.then(() => createFile(filepath, contents));
}

// create directory if necessary
if(!KNOWN[filepath]) {
KNOWN[filepath] = true;
if(!KNOWN.has(filepath)) {
KNOWN.add(filepath);
// NB: `sync` avoids race condition for subsequent operations
mkdirpSync(path.dirname(filepath));
mkdirSync(path.dirname(filepath), { recursive: true });
}

let prom = writeFile(filepath, contents);
LOCKS[filepath] = prom;
return prom.then(_ => {
delete LOCKS[filepath];
LOCKS.set(filepath, prom);
return prom.then(() => {
LOCKS.delete(filepath);
});
};

function mkdirpSync(directory) {
try {
// NB: `recursive` option was introduced in Node v10.12.0
fs.mkdirSync(directory, { recursive: true });
} catch(err) {
abort(`ERROR: auto-creating ${repr(directory)} requires ` +
"Node v10.12.0 or above");
}
}
2 changes: 0 additions & 2 deletions lib/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

let path = require("path");
let crypto = require("crypto");
let { promisify } = require("util");

exports.abort = abort;
exports.promisify = promisify; // deprecated
exports.repr = repr;

// reports success or failure for a given file path (typically regarding
Expand Down
6 changes: 3 additions & 3 deletions lib/util/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = class SerializedRunner {
run(...args) {
if(!this._pending) { // prevent concurrent execution
this._pending = augment(this.asyncOp(...args)).
finally(_ => {
finally(() => {
this._pending = null;
});
}
Expand All @@ -25,10 +25,10 @@ module.exports = class SerializedRunner {
let res = this.run(...args);
if(enqueue) {
this._queued = res = augment(res).
finally(_ => {
finally(() => {
this._queued = null;
}).
then(_ => this.run(...args));
then(() => this.run(...args));
}
return res;
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "faucet-pipeline-core",
"version": "2.0.0",
"version": "2.1.0",
"description": "faucet-pipeline's core library",
"author": "FND",
"contributors": [
Expand All @@ -25,7 +25,7 @@
"lint": "eslint --cache lib bin/* test test/bin/* && echo ✓"
},
"engines": {
"node": ">= 12"
"node": ">= 20"
},
"dependencies": {
"browserslist": "~4.21.4",
Expand Down
2 changes: 1 addition & 1 deletion test/test_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ let assert = require("assert");

let assertSame = assert.strictEqual;

describe("asset manager", _ => {
describe("asset manager", () => {
let root = path.resolve(__dirname, "fixtures");
let cwd;
let { exit } = process;
Expand Down
8 changes: 4 additions & 4 deletions test/test_manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ let assert = require("assert");

let assertSame = assert.strictEqual;

describe("manifest", _ => {
describe("manifest", () => {
let root = path.resolve(__dirname, "fixtures");
let cwd;

Expand All @@ -23,18 +23,18 @@ describe("manifest", _ => {
it("maps original to actual file names with deterministic serialization", () => {
let manifest = new Manifest(root);
return manifest.set("foo.png", "foo-abc123.png").
then(_ => {
then(() => {
assertSame(JSON.stringify(manifest), '{"foo.png":"/foo-abc123.png"}');

return manifest.set("bar.css", "bar-def456.css");
}).
then(_ => {
then(() => {
assertSame(JSON.stringify(manifest),
'{"bar.css":"/bar-def456.css","foo.png":"/foo-abc123.png"}');

return manifest.set("xox.js", "xox-ghi789.js");
}).
then(_ => {
then(() => {
assertSame(JSON.stringify(manifest), // eslint-disable-next-line max-len
'{"bar.css":"/bar-def456.css","foo.png":"/foo-abc123.png","xox.js":"/xox-ghi789.js"}');
});
Expand Down
12 changes: 10 additions & 2 deletions test/test_plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@ let { deepStrictEqual: assertDeep } = assert;

let ROOT = path.resolve(__dirname, "fixtures");
let DEFAULTS = {
assets: {
bucket: "static",
plugin: "faucet-pipeline-assets"
},
js: {
bucket: "scripts",
plugin: "faucet-pipeline-js"
},
css: {
bucket: "styles",
plugin: "faucet-pipeline-css"
},
sass: {
bucket: "styles",
plugin: "faucet-pipeline-sass"
Expand All @@ -30,7 +38,7 @@ let DEFAULTS = {
let { NODE_PATH } = process.env;
let CUSTOM_NODE_PATH = path.resolve(ROOT, "node_modules");

describe("plugin registration", _ => {
describe("plugin registration", () => {
before(() => {
updateNodePath(NODE_PATH, CUSTOM_NODE_PATH);
});
Expand Down Expand Up @@ -105,7 +113,7 @@ describe("plugin registration", _ => {
});
});

describe("plugin resolution", _ => {
describe("plugin resolution", () => {
let { exit } = process;

before(() => {
Expand Down
12 changes: 6 additions & 6 deletions test/test_runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
let SerializedRunner = require("../lib/util/runner");
let { strictEqual: assertSame, deepStrictEqual: assertDeep } = require("assert");

describe("watch mode", _ => {
describe("watch mode", () => {
it("avoids concurrent compilation, queueing recompilation", () => {
let bundle = new MockBundle();

Expand All @@ -13,7 +13,7 @@ describe("watch mode", _ => {
bundle.compile(); // skipped due to queue limit
let prevLog; // keeps track of compilation sequence
return bundle.compile(). // skipped due to queue limit
then(_ => {
then(() => {
let log = bundle.executionLog;
assertSame(log.length, 2); // compiled, then recompiled once
prevLog = [].concat(log);
Expand All @@ -23,15 +23,15 @@ describe("watch mode", _ => {
bundle.compile(); // skipped due to queue limit
return bundle.compile(); // skipped due to queue limit
}).
then(_ => {
then(() => {
let log = bundle.executionLog;
assertSame(log.length, 4); // compiled, then recompiled once
assertDeep(log.slice(0, prevLog.length), prevLog);
prevLog = [].concat(bundle.executionLog);

return bundle.compile(); // starts compilation
}).
then(_ => {
then(() => {
let log = bundle.executionLog;
assertSame(log.length, 5);
assertDeep(log.slice(0, prevLog.length), prevLog);
Expand All @@ -57,7 +57,7 @@ class MockBundle {

_compile(id) {
return wait(1).
then(_ => {
then(() => {
if(id) {
this.executionLog.push(id);
}
Expand All @@ -67,6 +67,6 @@ class MockBundle {

function wait(delay) {
return new Promise(resolve => {
setTimeout(_ => { resolve(); }, delay);
setTimeout(() => { resolve(); }, delay);
});
}
2 changes: 1 addition & 1 deletion test/test_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let assert = require("assert");

let assertSame = assert.strictEqual;

describe("server host parsing", _ => {
describe("server host parsing", () => {
let { exit } = process;

before(() => {
Expand Down
4 changes: 2 additions & 2 deletions test/test_util.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ let assertDeep = assert.deepStrictEqual;

let FIXTURES_PATH = path.resolve(__dirname, "fixtures");

describe("fingerprinting", _ => {
describe("fingerprinting", () => {
it("generates a content-dependent hash", () => {
let fingerprint = generateFingerprint("/path/to/foo.js", "lorem ipsum");
assertSame(fingerprint, "/path/to/foo-80a751fde577028640c419000e33eba6.js");
Expand All @@ -26,7 +26,7 @@ describe("fingerprinting", _ => {
});
});

describe("FileFinder", _ => {
describe("FileFinder", () => {
it("finds all files within a folder", () => {
let fileFinder = new FileFinder(FIXTURES_PATH);

Expand Down