UNPKG

@plugjs/plug

Version:
220 lines (218 loc) 8.34 kB
"use strict"; 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); // build.ts var build_exports = {}; __export(build_exports, { build: () => build, hookAfter: () => hookAfter, hookBefore: () => hookBefore, invokeTasks: () => invokeTasks, isBuild: () => isBuild, plugjs: () => plugjs }); module.exports = __toCommonJS(build_exports); var import_asserts = require("./asserts.cjs"); var import_async = require("./async.cjs"); var import_logging = require("./logging.cjs"); var import_pipe = require("./pipe.cjs"); var import_caller = require("./utils/caller.cjs"); var import_singleton = require("./utils/singleton.cjs"); var buildMarker = Symbol.for("plugjs:plug:types:Build"); var taskCallMarker = Symbol.for("plugjs:plug:types:TaskCall"); function isTaskCall(something) { return something[taskCallMarker] === taskCallMarker; } function merge(a, b) { return Object.assign(/* @__PURE__ */ Object.create(null), a, b); } function makeState(state) { const { cache = /* @__PURE__ */ new Map(), fails = /* @__PURE__ */ new Set(), stack = [], tasks = {}, props = {} } = state; return { cache, fails, stack, tasks, props }; } var lastIdKey = Symbol.for("plugjs:plug:singleton:taskId"); var taskId = (0, import_singleton.getSingleton)(lastIdKey, () => ({ id: 0 })); var TaskImpl = class { constructor(name, buildFile, _def, _tasks, _props) { this.name = name; this.buildFile = buildFile; this._def = _def; this.tasks = _tasks; this.props = _props; } before = []; after = []; id = ++taskId.id; props; tasks; async invoke(state, taskName) { (0, import_asserts.assert)(!state.stack.includes(this), `Recursion detected calling ${(0, import_logging.$t)(taskName)}`); const cached = state.cache.get(this); if (cached) return cached; state = makeState({ props: merge(this.props, state.props), tasks: merge(this.tasks, state.tasks), stack: [...state.stack, this], cache: state.cache, fails: state.fails }); const context = new import_pipe.Context(this.buildFile, taskName); const build2 = new Proxy({}, { get: (_, name) => { if (name in state.tasks) { return () => { const promise2 = state.tasks[name].invoke(state, name); return new import_pipe.PipeImpl(context, promise2); }; } else if (name in state.props) { return state.props[name]; } } }); for (const before of this.before) await before.invoke(state, before.name); context.log.info("Running..."); const now = Date.now(); const promise = (0, import_async.runAsync)(context, async () => { return await this._def.call(build2) || void 0; }).then(async (result) => { const level = taskName.startsWith("_") ? "info" : "notice"; context.log[level](`Success ${(0, import_logging.$ms)(Date.now() - now)}`); return result; }).catch((error) => { state.fails.add(this); context.log.error(`Failure ${(0, import_logging.$ms)(Date.now() - now)}`, error); throw import_asserts.BuildFailure.fail(); }).finally(async () => { await import_pipe.ContextPromises.wait(context); }).then(async (result) => { for (const after of this.after) await after.invoke(state, after.name); return result; }); state.cache.set(this, promise); return promise; } }; function plugjs(def) { const buildFile = (0, import_caller.findCaller)(plugjs); const tasks = {}; const props = {}; for (const [key, val] of Object.entries(def)) { let len = 0; if (isTaskCall(val)) { tasks[key] = val.task; len = key.length; } else if (typeof val === "string") { props[key] = val; } else if (typeof val === "function") { tasks[key] = new TaskImpl(key, buildFile, val, tasks, props); len = key.length; } if (import_logging.logOptions.level >= import_logging.NOTICE && key.startsWith("_")) continue; if (len > import_logging.logOptions.taskLength) import_logging.logOptions.taskLength = len; } const start = async function start2(callback, overrideProps = {}) { const state = makeState({ tasks, props: merge(props, overrideProps) }); const logger = (0, import_logging.getLogger)(); logger.notice("Starting..."); const now = Date.now(); try { const result = await callback(state); logger.notice(`Build successful ${(0, import_logging.$ms)(Date.now() - now)}`); return result; } catch (error) { if (state.fails.size) { logger.error(""); logger.error((0, import_logging.$plur)(state.fails.size, "task", "tasks"), "failed:"); state.fails.forEach((task) => logger.error((0, import_logging.$gry)("*"), (0, import_logging.$t)(task.name))); logger.error(""); } throw logger.fail(`Build failed ${(0, import_logging.$ms)(Date.now() - now)}`, error); } }; const invoke = async function invoke2(taskNames, overrideProps = {}) { await start(async (state) => { for (const name of taskNames) { const task = tasks[name]; (0, import_asserts.assert)(task, `Task ${(0, import_logging.$t)(name)} not found in build ${(0, import_logging.$p)(buildFile)}`); await task.invoke(state, name); } }, overrideProps); }; const callables = {}; for (const [name, task] of Object.entries(tasks)) { const callable = async (overrideProps) => start(async (state) => task.invoke(state, name), overrideProps); callables[name] = Object.defineProperties(callable, { [taskCallMarker]: { value: taskCallMarker }, "task": { value: task }, "name": { value: name } }); } const compiled = merge(props, callables); Object.defineProperty(compiled, buildMarker, { value: invoke }); return compiled; } var build = function(def) { import_logging.log.warn(`Use of deprecated ${(0, import_logging.$ylw)("build")} entry point, please use ${(0, import_logging.$grn)("plugjs")}`); return plugjs(def); }; function isBuild(build2) { return build2 && typeof build2[buildMarker] === "function"; } function invokeTasks(build2, tasks, props) { if (isBuild(build2)) { return build2[buildMarker](tasks, props); } else { throw new TypeError("Invalid build instance"); } } function hookBefore(build2, taskName, hooks) { const taskCall = build2[taskName]; (0, import_asserts.assert)(isTaskCall(taskCall), `Task "${(0, import_logging.$t)(taskName)}" not found in build`); for (const hook of hooks) { const beforeHook = build2[hook]; (0, import_asserts.assert)(isTaskCall(beforeHook), `Task "${(0, import_logging.$t)(hook)}" to hook before "${(0, import_logging.$t)(taskName)}" not found in build`); if (taskCall.task.before.includes(beforeHook.task)) continue; taskCall.task.before.push(beforeHook.task); } } function hookAfter(build2, taskName, hooks) { const taskCall = build2[taskName]; (0, import_asserts.assert)(isTaskCall(taskCall), `Task "${(0, import_logging.$t)(taskName)}" not found in build`); for (const hook of hooks) { const afterHook = build2[hook]; (0, import_asserts.assert)(isTaskCall(afterHook), `Task "${(0, import_logging.$t)(hook)}" to hook after "${(0, import_logging.$t)(taskName)}" not found in build`); if (taskCall.task.after.includes(afterHook.task)) continue; taskCall.task.after.push(afterHook.task); } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { build, hookAfter, hookBefore, invokeTasks, isBuild, plugjs }); //# sourceMappingURL=build.cjs.map