@plugjs/plug
Version:
PlugJS Build System ===================
164 lines (162 loc) • 6.35 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// pipe.ts
var pipe_exports = {};
__export(pipe_exports, {
Context: () => Context,
ContextPromises: () => ContextPromises,
PipeImpl: () => PipeImpl,
install: () => install
});
module.exports = __toCommonJS(pipe_exports);
var import_node_path = require("node:path");
var import_asserts = require("./asserts.cjs");
var import_logging = require("./logging.cjs");
var import_paths = require("./paths.cjs");
var Context = class {
constructor(buildFile, taskName) {
this.buildFile = buildFile;
this.taskName = taskName;
this.buildDir = (0, import_paths.getAbsoluteParent)(buildFile);
this.log = (0, import_logging.getLogger)(taskName);
}
buildFile;
taskName;
/** The directory of the file where the task was defined (convenience). */
buildDir;
/** The {@link Logger} associated with this instance. */
log;
/**
* Resolve a (set of) path(s) in this {@link Context}.
*
* If the path (or first component thereof) starts with `@...`, then the
* resolved path will be relative to the directory containing the build file
* where the current task was defined, otherwise it will be relative to the
* current working directory.
*/
resolve(path, ...paths) {
if (path && path.startsWith("@")) {
const components = path.substring(1).split(import_node_path.sep).filter((s) => !!s);
return (0, import_paths.resolveAbsolutePath)(this.buildDir, ...components, ...paths);
}
if (!path) return (0, import_paths.getCurrentWorkingDirectory)();
return (0, import_paths.resolveAbsolutePath)((0, import_paths.getCurrentWorkingDirectory)(), path, ...paths);
}
};
var contextPromises = /* @__PURE__ */ new WeakMap();
var ContextPromises = class _ContextPromises {
/* Private constructor */
constructor(context) {
this.context = context;
}
context;
_cold = /* @__PURE__ */ new Set();
_hot = /* @__PURE__ */ new Set();
/** Track a {@link Promise} _hot_ (failure will fail the task) */
hot(promise) {
this._cold.delete(promise);
this._hot.add(promise);
}
/** Track a {@link Promise} _cold_ (failure will be ignored) */
cold(promise) {
this._hot.delete(promise);
this._cold.add(promise);
}
/**
* Await all tracked {@link Promise}s, triggering a build failure if any of
* the _hot_ ones is rejected.
*/
static async wait(context) {
const instance = contextPromises.get(context);
if (!instance) return;
await Promise.allSettled([...instance._cold]);
await (0, import_asserts.assertPromises)([...instance._hot]);
}
/** Get a {@link ContextPromises} instance for the given {@link Context} */
static get(context) {
let promises = contextPromises.get(context);
if (!promises) {
promises = new _ContextPromises(context);
contextPromises.set(context, promises);
}
return promises;
}
};
var PipeImpl = class _PipeImpl {
constructor(_context, _promise) {
this._context = _context;
this._promise = _promise;
ContextPromises.get(_context).hot(_promise);
}
_context;
_promise;
[Symbol.toStringTag] = "Pipe";
/* ------------------------------------------------------------------------ *
* Promise implementation *
* ------------------------------------------------------------------------ *
* From a _types_ point of view, the `Pipe` implements a `Promise<Files>` *
* (because only when plugging the correct `Plug` the correct value are *
* returned). *
* *
* Whether to return (as a type) another `Pipe` or a `Promise<undefined>` *
* is determined by the type of the `plug` parameter below. *
* *
* That said, in practice, a `Pipe` implements `Promise<Files | undefined>` *
* because the result of the plug is _eventually_ computed asynchronously *
* while `plug` returns immediately.
* *
* So, all those "as whatever" below are kind-of-legit... *
* ------------------------------------------------------------------------ */
then(onfulfilled, onrejected) {
ContextPromises.get(this._context).cold(this._promise);
return this._promise.then(onfulfilled, onrejected);
}
catch(onrejected) {
ContextPromises.get(this._context).cold(this._promise);
return this._promise.catch(onrejected);
}
finally(onfinally) {
ContextPromises.get(this._context).cold(this._promise);
return this._promise.finally(onfinally);
}
plug(arg) {
const plug = typeof arg === "function" ? { pipe: arg } : arg;
ContextPromises.get(this._context).cold(this._promise);
return new _PipeImpl(this._context, this._promise.then(async (result) => {
(0, import_asserts.assert)(result, "Unable to extend pipe");
const result2 = await plug.pipe(result, this._context);
return result2 || void 0;
}));
}
};
function install(name, ctor) {
function plug(...args) {
return this.plug(new ctor(...args));
}
Object.defineProperty(plug, "name", { value: name });
void Object.defineProperty(PipeImpl.prototype, name, { value: plug });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Context,
ContextPromises,
PipeImpl,
install
});
//# sourceMappingURL=pipe.cjs.map