@abw/badger 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/badger.cjs.js +1 -1
- package/dist/badger.cjs.js.map +1 -1
- package/dist/badger.esm.js +1 -1
- package/dist/badger.esm.js.map +1 -1
- package/package.json +2 -2
package/dist/badger.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("js-yaml"),e=require("node:process"),r=require("node:path"),i=require("node:fs/promises");function s(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}function o(t){if(t&&t.__esModule)return t;var e=Object.create(null);return t&&Object.keys(t).forEach((function(r){if("default"!==r){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}})),e.default=t,Object.freeze(e)}var n=s(t),a=s(e),c=s(r);function u(t){return"string"==typeof t}function d(t){return Array.isArray(t)}function h(t){return"object"==typeof t&&!d(t)&&!f(t)}function p(t){return void 0===t}function f(t){return null===t}function l(t){return!(p(t)||f(t))}function g(...t){throw new Error(t.join(""))}function
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("js-yaml"),e=require("node:process"),r=require("node:path"),i=require("node:fs/promises");function s(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}function o(t){if(t&&t.__esModule)return t;var e=Object.create(null);return t&&Object.keys(t).forEach((function(r){if("default"!==r){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}})),e.default=t,Object.freeze(e)}var n=s(t),a=s(e),c=s(r);function u(t){return"string"==typeof t}function d(t){return Array.isArray(t)}function h(t){return"object"==typeof t&&!d(t)&&!f(t)}function p(t){return void 0===t}function f(t){return null===t}function l(t){return!(p(t)||f(t))}function g(t){return!l(t)}function b(...t){throw new Error(t.join(""))}function x(t){throw t}function y(){}const m={reset:0,bold:1,bright:1,dark:2,black:0,red:1,green:2,yellow:3,blue:4,magenta:5,cyan:6,grey:7,white:8,fg:30,bg:40},w=(t,e="fg")=>{let r=[],i=t.split(/ /,2);const s=i.pop(),o=(e?m[e]:0)+m[s];if(r.push(o),i.length){const t=i.length?i.shift():"dark";r.push(m[t])}return"["+r.join(";")+"m"};function j(t,e="",r){return t?e?(t,...i)=>console.log("%s"+e+"%s"+t,r?((t={})=>{const e=h(t)?t:{fg:t};let r=[];return e.bg&&r.push(w(e.bg,"bg")),e.fg&&r.push(w(e.fg,"fg")),r.join("")})(r):"",w("reset"),...i):console.log.bind(console):y}function E(t,e,r="",i){t.debug=j(e,r,i)}const v={json:{encode:t=>JSON.stringify(t),decode:t=>JSON.parse(t)},yaml:{encode:t=>n.default.dump(t),decode:t=>n.default.load(t)}},P=t=>v[t.toLowerCase()],k={encoding:"utf8"};class C{constructor(t,e={}){t instanceof C&&(t=t.path()),this.state={path:t,options:{...k,...e}},E(this,e.debug,e.debugPrefix||"Path",e.debugColor)}path(){return this.state.path}relativePath(...t){return c.default.join(this.state.path,...t)}options(t={}){return{...this.state.options,...t}}async exists(){try{return await this.stat(),!0}catch(t){return"ENOENT"!==t.code&&x(t)}}async stat(){const t=await i.stat(this.state.path);return this.state.stats=t}unstat(){return this.state.stats=void 0,this}}class O extends C{directory(t){return F(c.default.dirname(this.state.path),t)}dir(...t){return this.directory(...t)}read(t){const e=this.options(t),r=i.readFile(this.state.path,e);return e.codec?r.then((t=>P(e.codec).decode(t))):r}write(t,e){const r=this.options(e),s=r.codec?P(r.codec).encode(t):t;return i.writeFile(this.state.path,s,r).then((()=>this))}async delete(t){return await i.rm(this.state.path,t),this}}const D=(t,e)=>new O(t,e);class q extends C{file(t,e){return this.debug("file(%s, %o)",t,e),D(this.relativePath(t),this.options(e))}directory(t,e){return this.debug("directory(%s, %o)",t,e),F(this.relativePath(t),this.options(e))}dir(t,e){return this.debug("dir(%s, %o)",t,e),this.directory(t,e)}parent(t){return this.debug("parent()"),this.directory("..",t)}async read(){return this.debug("read()"),await i.readdir(this.path())}async isEmpty(){this.debug("isEmpty()");return 0===(await this.read()).length}async notEmpty(){this.debug("notEmpty()");return!await this.isEmpty()}async empty(t={}){return this.debug("empty(%o)",t),await this.exists()&&await this.notEmpty()&&await i.rm(this.path(),t),this}async mkdir(t={}){this.debug("mkdir(%o)",t);return await this.exists()||await i.mkdir(this.path(),t),this}async rmdir(t={}){return this.debug("rmdir(%o)",t),t.empty&&await this.empty(t),await this.exists()&&await i.rmdir(this.path()),this}create(t={recursive:!0}){return this.debug("create(%o)",t),this.mkdir(t)}destroy(t={empty:!0,recursive:!0,force:!0}){return this.debug("destroy(%o)",t),this.rmdir(t)}async mustExist(t={}){return this.debug("mustExist(%o)",t),await this.exists()?this:t.mkdir?this.mkdir(t):t.create?this.create():void b("Directory does not exist: ",this.path())}}const F=(t,e)=>new q(t,e);function L(t){return g(t)?[]:u(t)?t.length?t.split(/,\s*|\s+/):[]:d(t)?t:[t]}function N(t,e=" ",r=e){let i=[...t];const s=i.pop();return i.length?[i.join(e),s].join(r):s}function _(t,e=", ",r=" or "){return N(t,e,r)}function A(t){return t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()}const M={codecs:"yaml json",jsExt:"js mjs"};class S{constructor(t,e={}){const r={...M,...e};this.state={dir:F(t),codecs:L(r.codecs),jsExt:L(r.jsExt)},E(this,e.debug,e.debugPrefix,e.debugColor),this.debug("root dir: ",this.state.dir.path()),this.debug("codecs: ",this.state.codecs)}async firstFileWithExt(t,e,r=y){for(let i of e){const e=t+"."+i,s=this.state.dir.file(e,r(t,i));if(this.debug("looking for config file: ",s.path()),await s.exists())return this.debug("config file exists: ",s.path()),s}}async jsFile(t){return await this.firstFileWithExt(t,this.state.jsExt)}async file(t){return await this.firstFileWithExt(t,this.state.codecs,((t,e)=>({codec:e})))}async config(t,e){const r=await this.jsFile(t);if(r){return(await(i=r.path(),Promise.resolve().then((function(){return o(require(i))})))).default}var i;const s=await this.file(t);return s?await s.read():e||b("No configuration file for "+t)}}function W(t={},e){const r=t[e];if(l(r))return r;b("Missing value for required parameter: ",e)}function T(t={},e){return L(e).map((e=>W(t,e)))}const V=T;const J={dir:["lib","library","src","components"],ext:["js","mjs"]};class U{constructor(t={}){const e=F(W(t,"root")),r=t.directory||t.dir||t.dirs||J.dir,i=t.extension||t.ext||t.exts||J.ext,s=L(r).map((t=>e.dir(t))),o=L(i).map((t=>t.replace(/^\./,"")));this.state={dirs:s,exts:o},E(this,t.debug,t.debugPrefix,t.debugColor)}async dirs(){return this.state.dirsExist||(this.state.dirsExist=await this.dirsExist())}async dirsExist(){const t=this.state.dirs,e=await Promise.all(t.map((t=>t.exists())));return t.filter(((t,r)=>e[r]))}async lib(t){const e=await this.dirs(),r=this.state.exts;for(let i of e)for(let e of r){const r=i.file(t+"."+e);this.debug("looking for module %s as",t,r.path());if(await r.exists()){const t=await function(t){return Promise.resolve().then((function(){return o(require(t))}))}(r.path());return this.debug("loaded %s as",r.path()),t}}b("Library not found: ",t)}}const z={},B={dir:"config"};class G{constructor(t={}){const e=F(W(t,"dir")),r=e.dir(t.config?.dir||B.dir),i={...B,...t.config||{}},s=new S(r,i),o={...z,...t.library||{},root:e},n=new U(o);this.state={rootDir:e,config:s,library:n},E(this,t.debug,t.debugPrefix,t.debugColor),this.debug("root dir: ",e.path()),this.debug("config dir: ",r.path())}dir(t,e){return this.debug("dir(%s, %o)",t,e),l(t)?this.state.rootDir.dir(t,e):this.state.rootDir}file(t,e){return this.debug("file(%s, %o)",t,e),this.state.rootDir.file(t,e)}read(t,e){return this.debug("read(%s, %o)",t,e),this.file(t,e).read()}write(t,e,r){return this.debug("write(%s, %o, %o)",t,e,r),this.file(t,r).write(e)}configDir(t,e){return this.debug("configDir(%s, %o)",t,e),l(t)?this.state.configDir(t,e):this.state.configDir}async config(t,e){return this.debug("config(%s, %o)",t,e),l(t)?this.state.config.config(t,e):this.state.config}async lib(t){return this.state.library.lib(t)}async component(t,e){const r=await this.config(t,{}),i=await this.lib(r.component?.library||t),s=r.component?.export||"default";return new(i[s]||b("No '",s,"' export from component library: ",t))(this,{...r,...e})}}exports.Component=class{constructor(t,e={}){this.workspace=t,this.props=e,E(this,e.debug,e.debugPrefix,e.debugColor),this.initComponent(e)}initComponent(){}},exports.Config=S,exports.Library=U,exports.Path=C,exports.Workspace=G,exports.allParams=V,exports.anyParams=function(t,e){let r=!1;const i=L(e),s=i.map((e=>{const i=t[e];return l(i)&&(r=!0),i}));return r?s:b("Missing value for one of: ",_(i))},exports.bin=(t,e)=>F(c.default.dirname(t.replace(/^file:\/\//,"")),e),exports.capitalise=A,exports.codec=P,exports.codecs=v,exports.config=(t,e)=>new S(t,e),exports.cwd=t=>F(a.default.cwd(),t),exports.dir=F,exports.doNothing=y,exports.fail=b,exports.file=D,exports.hasValue=l,exports.haveValue=function(...t){return t.every((t=>l(t)))},exports.isArray=d,exports.isFunction=function(t){return"function"==typeof t},exports.isNull=f,exports.isObject=h,exports.isString=u,exports.isUndefined=p,exports.joinList=N,exports.joinListAnd=function(t,e=", ",r=" and "){return N(t,e,r)},exports.joinListOr=_,exports.library=t=>new U(t),exports.noValue=g,exports.requiredParam=W,exports.requiredParams=T,exports.rethrow=x,exports.snakeToCamel=function(t){return t.split("/").map((t=>t.split("_").map(((t,e)=>e?A(t):t)).join(""))).join("/")},exports.snakeToStudly=function(t){return t.split("/").map((t=>t.split("_").map(A).join(""))).join("/")},exports.splitList=L,exports.workspace=t=>new G(t);
|
|
2
2
|
//# sourceMappingURL=badger.cjs.js.map
|
package/dist/badger.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badger.cjs.js","sources":["../src/Badger/Utils/Misc.js","../src/Badger/Utils/Color.js","../src/Badger/Utils/Debug.js","../src/Badger/Codecs/Json.js","../src/Badger/Codecs/index.js","../src/Badger/Codecs/Yaml.js","../src/Badger/Filesystem/Path.js","../src/Badger/Filesystem/File.js","../src/Badger/Filesystem/Directory.js","../src/Badger/Utils/Text.js","../src/Badger/Utils/Params.js","../src/Badger/Config.js","../src/Badger/Library.js","../src/Badger/Workspace.js","../src/Badger/Component.js"],"sourcesContent":["/**\n * Determines if a value is a string\n * @param {String} value - value to test\n * @return {Boolean} true if `value` is a string or false if not\n */\nexport function isString(value) {\n return typeof value === 'string';\n}\n\n/**\n * Determines if a value is an array\n * @param {Array} value - value to test\n * @return {Boolean} true if `value` is an Array or false if not\n */\nexport function isArray(value) {\n return Array.isArray(value);\n}\n\n/**\n * Determines if a value is a Function\n * @param {Function} value - value to test\n * @return {Boolean} true if `value` is a Function or false if not\n */\nexport function isFunction(value) {\n return typeof value === 'function'\n}\n\n/**\n * Determines if a value is an Object (but not an Array)\n * @param {Object} value - value to test\n * @return {Boolean} true if `value` is an Object or false if not\n */\nexport function isObject(value) {\n return typeof value === \"object\"\n && ! isArray(value)\n && ! isNull(value);\n}\n\n/**\n * Determines if a value is `undefined`\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `undefined` or false if not\n */\nexport function isUndefined(value) {\n return typeof value === 'undefined';\n}\n\n/**\n * Determines if a value is `null`\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `null` or false if not\n */\nexport function isNull(value) {\n return value === null;\n}\n\n/**\n * Determines if a value is defined and not null\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is not `undefined` or `null`\n */\nexport function hasValue(value) {\n return ! (isUndefined(value) || isNull(value));\n}\n\n/**\n * Determines if all values are defined and not null\n * @param {any[]} values - values to test\n * @return {Boolean} true if all values are not `undefined` or `null`\n */\nexport function haveValue(...values) {\n return values.every( value => hasValue(value) );\n}\n\n/**\n * Determines if a value is undefined or null\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `undefined` or `null`\n */\nexport function noValue(value) {\n return ! hasValue(value);\n}\n\n/**\n * Throws a new Error object\n * @param {String[]} message - error message string(s)\n * @throws {Error}\n */\nexport function fail(...message) {\n throw new Error(message.join(''));\n}\n\n/**\n * Re-throw an existing Error object\n * @param {Error} error - error object\n * @throws {Error}\n */\nexport function rethrow(error) {\n throw error;\n}\n\n/**\n * Do nothing. Nothing at all.\n */\nexport function doNothing() {\n // speak again Cordelia\n}","import { isObject } from \"./Misc.js\";\n\nexport const ANSIStart = '\\u001B[';\nexport const ANSIEnd = 'm';\nexport const ANSIColors = {\n reset: 0,\n bold: 1,\n bright: 1,\n dark: 2,\n black: 0,\n red: 1,\n green: 2,\n yellow: 3,\n blue: 4,\n magenta: 5,\n cyan: 6,\n grey: 7,\n white: 8,\n fg: 30,\n bg: 40,\n};\n\n/**\n * Returns an ANSI escape code for a color string. This can be a single color\n * name, e.g. `red`, `green`, etc., or a color prefixed with `bright` or `dark`,\n * e.g. `bright red`, `dark green`, etc. An optional section argument can be\n * set to `fg` (default) to set a foreground color or `bg` for a background color.\n * @param {String} color - color name with optional modifier prefix\n * @param {String} [base='fg'] - `fg` or `bg` to set foreground or background color respectively\n * @return {String} ANSI escape code string\n * @example\n * const str = escapeCode('red')\n * @example\n * const str = escapeCode('bright red')\n * @example\n * const str = escapeCode('bright red', 'bg')\n */\nexport const escapeCode = (color, base='fg') => {\n let codes = [ ];\n let pair = color.split(/ /, 2);\n const hue = pair.pop();\n const code = (base ? ANSIColors[base] : 0) + ANSIColors[hue];\n codes.push(code);\n if (pair.length) {\n const shade = pair.length ? pair.shift() : 'dark';\n codes.push(ANSIColors[shade])\n }\n return ANSIStart + codes.join(';') + ANSIEnd;\n}\n\n/**\n * Returns an ANSI escape code for a color string or combination of foreground and\n * background colors.\n * @param {String|Object} colors - either a simple color name or object contain foreground and background colors\n * @param {String} [colors.fg] - foreground color\n * @param {String} [colors.fg] - background color\n * @return {String} ANSI escape code string\n * @example\n * const str = escape('red')\n * @example\n * const str = escape('bright red')\n * @example\n * const str = escape({ fg: 'bright yellow', bg: 'blue' })\n */\nexport const escape = (colors={}) => {\n const col = isObject(colors) ? colors : { fg: colors };\n let escapes = [ ];\n if (col.bg) {\n escapes.push(escapeCode(col.bg, 'bg'));\n }\n if (col.fg) {\n escapes.push(escapeCode(col.fg, 'fg'));\n }\n return escapes.join('');\n}\n\nexport const reset = () => escapeCode('reset')\n\n","import { escape, reset } from './Color.js'\nimport { doNothing } from './Misc.js';\n\n/**\n * Returns a debugging function which is enabled by the first `enabled` argument.\n * If this is `false` then it returns a function which does nothing. If it is\n * true then it returns a function that forwards all arguments to `console.log`.\n * An optional `prefix` be be specified to prefix each debugging line. The\n * optional third argument `color` can be used to specify a color for the prefix.\n * @param {Boolean} enabled - is debugging enabled?\n * @param {String} [prefix] - optional prefix for debugging messages\n * @param {String|Object} [color] - a color name or object (see {@link Badger/Utils/Color})\n * @param {String} [color.fg] - foreground color\n * @param {String} [color.bg] - background color\n * @return {Function} a debugging function\n * @example\n * const debug = Debugger(true)\n * @example\n * const debug = Debugger(true, 'Debug > ')\n * @example\n * const debug = Debugger(true, 'Debug > ', 'blue')\n * @example\n * const debug = Debugger(true, 'Debug > ', { bg: 'blue', fg: 'bright yellow' })\n */\nexport function Debugger(enabled, prefix='', color) {\n return enabled\n ? prefix\n ? (format, ...args) =>\n console.log(\n '%s' + prefix + '%s' + format,\n color ? escape(color) : '',\n reset(),\n ...args,\n )\n : console.log.bind(console)\n : doNothing;\n}\n\n/**\n * Creates a debugging function via {@link Debugger} and attaches it to the object\n * passed as the first argument as the `debug` function.\n * @param {Object} obj - the object to receive the `debug` function\n * @param {Boolean} enabled - is debugging enabled?\n * @param {String} [prefix] - optional prefix for debugging messages\n * @param {String|Object} [color] - a color name or object (see {@link Badger/Utils/Color})\n * @param {String} [color.fg] - foreground color\n * @param {String} [color.bg] - background color\n * @example\n * const debug = addDebug(myObject, true)\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ')\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ', 'blue')\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ', { bg: 'blue', fg: 'bright yellow' })\n */\nexport function addDebug(obj, enabled, prefix='', color) {\n obj.debug = Debugger(enabled, prefix, color);\n}\n","/**\n * Function to encode JSON\n * @param {Object} data - The data to encode as JSON text\n * @return {String} a JSON encoded string\n * @example\n * encode({ message: 'Hello World' })\n */\nexport const encode = data => JSON.stringify(data);\n\n/**\n * Function to decode JSON\n * @param {String} text - The JSON text to decode\n * @return {Object|Array} the decoded object or array\n * @example\n * decode(\"{ message: 'Hello World' }\")\n */\nexport const decode = text => JSON.parse(text);\n\n/**\n * An object containing the JSON `encode` and `decode` functions\n */\nexport const codec = { encode, decode };\n\nexport default codec\n","import json from './Json.js'\nimport yaml from './Yaml.js'\n\n/**\n * Codecs provide a consistent encode()/decode() interface for serialising\n * and de-serialising data. This standard naming convention makes it possible\n * for the ../Filesystem/File.js module to support a \"codec\" option for\n * files. When this option is set the file.read() and file.write() methods\n * automatically handle the translation to and from the serialised format\n * using a codec object returned by the codec() function below. The codec\n * name can be specified in any case, e.g. \"Yaml\", \"YAML\", \"yaml\", \"YaML\",\n * etc., and it will be converted to lower case.\n */\n\n/**\n * Lookup table for codecs\n */\nexport const codecs = {\n json, yaml\n};\n\n/**\n * Function to fetch a codec\n * @param {string} name - The title of the code, in any case, e.g. \"yaml\", \"YAML\", \"Yaml\"\n */\nexport const codec = name => codecs[\n name.toLowerCase()\n];\n\nexport default codecs\n","// simple wrapper around JSON load/dump\nimport yaml from 'js-yaml';\n\n/**\n * Function to encode YAML\n * @param {Object} data - The data to encode as YAML text\n * @return {String} a YAML encoded string\n * @example\n * encode({ message: 'Hello World' })\n */\nexport const encode = data => yaml.dump(data);\n\n/**\n * Function to decode YAML\n * @param {String} text - The YAML text to decode\n * @return {Object|Array} the decoded object or array\n * @example\n * decode(\"message: Hello World\")\n */\nexport const decode = text => yaml.load(text);\n\n/**\n * An object containing the YAML `encode` and `decode` functions\n */\nexport const codec = { encode, decode };\n\nexport default codec\n","import path from 'node:path';\nimport { stat } from 'node:fs/promises'\nimport { rethrow } from '../Utils/Misc.js';\nimport { addDebug } from '../Utils/Debug.js';\n\nconst defaultOptions = {\n encoding: 'utf8'\n}\n\nexport class Path {\n constructor(path, options={}) {\n // allow path/file/directory to be constructed from an existing object\n if (path instanceof Path) {\n path = path.path();\n }\n this.state = { path, options: { ...defaultOptions, ...options } };\n addDebug(this, options.debug, options.debugPrefix || 'Path', options.debugColor);\n }\n path() {\n return this.state.path;\n }\n relativePath(...parts) {\n return path.join(this.state.path, ...parts);\n }\n options(options={}) {\n return { ...this.state.options, ...options };\n }\n async exists() {\n try {\n await this.stat();\n return true;\n }\n catch (error) {\n return error.code === 'ENOENT'\n ? false\n : rethrow(error);\n }\n }\n async stat() {\n const stats = await stat(this.state.path);\n return this.state.stats = stats;\n }\n unstat() {\n this.state.stats = undefined;\n console.log('XXX unstat: ', this.state.stats);\n return this;\n }\n}\n\nexport default Path\n","import path from 'node:path'\nimport Path from './Path.js'\nimport { dir } from './Directory.js'\nimport { codec } from '../Codecs/index.js'\nimport { readFile, writeFile, rm } from 'node:fs/promises'\n\nclass File extends Path {\n /**\n * Returns a new {@link Directory} object for the parent directory of the file\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object for the parent\n */\n directory(options) {\n return dir(path.dirname(this.state.path), options);\n }\n\n /**\n * An alias for the {@link directory} method for lazy people\n * @return {Object} the parent {@link Directory} object\n */\n dir(...args) {\n return this.directory(...args);\n }\n\n /**\n * Reads the file content. If a `codec` has been specified then the content is decoded.\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {String|Object} the file content\n * @example\n * const text = file('myfile.txt').read();\n * @example\n * const data = file('myfile.json', { codec: 'json' }).read();\n * @example\n * const data = file('myfile.json').read({ codec: 'json' });\n */\n read(options) {\n const opts = this.options(options);\n const file = readFile(this.state.path, opts);\n return opts.codec\n ? file.then(text => codec(opts.codec).decode(text))\n : file;\n }\n\n /**\n * Writes the file content. If a `codec` has been specified then the content will be encoded.\n * @param {String|Object} data - directory configuration options\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @example\n * file('myfile.txt').write('Hello World');\n * @example\n * file('myfile.json', { codec: 'json' }).write({ message: 'Hello World' });\n * @example\n * file('myfile.json').write({ message: 'Hello World' }, { codec: 'json' });\n */\n write(data, options) {\n const opts = this.options(options);\n const text = opts.codec\n ? codec(opts.codec).encode(data)\n : data;\n return writeFile(this.state.path, text, opts).then( () => this );\n }\n\n async delete(options) {\n await rm(this.state.path, options);\n return this;\n }\n}\n\n/**\n * Function to create a new {@link File} object for a file\n * @param {String} path - file path\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link File} object\n */\nexport const file = (path, options) => {\n return new File(path, options);\n}\n\nexport default File\n","import process from 'node:process';\nimport path from 'node:path';\nimport Path from './Path.js'\nimport { file } from './File.js'\nimport { fail } from '../Utils/Misc.js';\nimport { rm, mkdir, rmdir, readdir } from 'node:fs/promises'\n\nclass Directory extends Path {\n /**\n * Fetch a new {@link File} object for a file in the directory.\n * @param {string} path - file path\n * @param {Object} [options] - file configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link File} object\n */\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return file(this.relativePath(path), this.options(options));\n }\n\n /**\n * Fetch a new {@link Directory} object for a sub-directory in the directory.\n * @param {string} path - directory path\n * @param {Object} [options] - directory configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link Directory} object\n */\n directory(path, options) {\n this.debug(\"directory(%s, %o)\", path, options);\n return dir(this.relativePath(path), this.options(options));\n }\n\n /**\n * An alias for the {@link directory} method for lazy people\n * @return {Object} the {@link Directory} object\n */\n dir(path, options) {\n this.debug(\"dir(%s, %o)\", path, options);\n return this.directory(path, options);\n }\n\n /**\n * Returns a new {@link Directory} object for the parent directory\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object for the parent\n */\n parent(options) {\n this.debug(\"parent()\");\n return this.directory('..', options);\n }\n\n /**\n * Returns the names of the files and sub-directories in the directory\n * @return {Promise} fulfills with an array of the file and directory names\n */\n async read() {\n this.debug(\"read()\");\n return await readdir(this.path());\n }\n\n /**\n * Determines if the directory is empty.\n * @return {Promise} fulfills with a boolean value true (empty) or false (not empty).\n */\n async isEmpty() {\n this.debug(\"isEmpty()\");\n const entries = await this.read();\n return entries.length === 0;\n }\n\n /**\n * Determines if the directory is not empty.\n * @return {Promise} fulfills with a boolean value true (not empty) or false (empty).\n */\n async notEmpty() {\n this.debug(\"notEmpty()\");\n const empty = await this.isEmpty();\n return !empty;\n }\n\n /**\n * Empty the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.force] - force removal of files and directories\n * @param {Boolean} [options.recursive] - recursively empty and delete sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async empty(options={}) {\n this.debug(\"empty(%o)\", options);\n if (await this.exists() && await this.notEmpty()) {\n await rm(this.path(), options);\n }\n return this;\n }\n\n /**\n * Make the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.recursive] - create intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async mkdir(options={}) {\n this.debug(\"mkdir(%o)\", options);\n const exists = await this.exists();\n if (! exists) {\n await mkdir(this.path(), options);\n }\n return this;\n }\n\n /**\n * Remove the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.empty] - delete items in directory\n * @param {Boolean} [options.force] - force delete files and directories\n * @param {Boolean} [options.recursive] - recursively delete sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async rmdir(options={}) {\n this.debug(\"rmdir(%o)\", options);\n if (options.empty) {\n await this.empty(options);\n }\n if (await this.exists()) {\n await rmdir(this.path());\n }\n return this;\n }\n\n /**\n * Create the directory and any intermediate directories.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.recursive=true] - recursively create intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n create(options={ recursive: true }) {\n this.debug(\"create(%o)\", options);\n return this.mkdir(options);\n }\n\n /**\n * Empty and delete the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.empty=true] - empty directory of any files and sub-directories\n * @param {Boolean} [options.recursive=true] - recursively delete sub-directories\n * @param {Boolean} [options.force=true] - force deletion of files and sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n destroy(options={ empty: true, recursive: true, force: true }) {\n this.debug(\"destroy(%o)\", options);\n return this.rmdir(options);\n }\n\n /**\n * Assert that a directory exists and optionally create it\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.create] - create the directory and any intermediate directories if it doesn't exist - equivalent to adding `mkdir` and `recursive` options or calling {@link create}\n * @param {Boolean} [options.mkdir] - create the directory, add the `recursive` option to create intermediate directories - equivalent to calling {@link mkdir}\n * @param {Boolean} [options.recursive] - when used with `mkdir`, creates any intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async mustExist(options={}) {\n this.debug(\"mustExist(%o)\", options);\n if (await this.exists()) {\n return this;\n }\n if (options.mkdir) {\n return this.mkdir(options);\n }\n if (options.create) {\n return this.create();\n }\n fail(\"Directory does not exist: \", this.path());\n }\n}\n\n/**\n * Function to create a new {@link Directory} object\n * @param {string} path - directory path\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const dir = (path, options) => {\n return new Directory(path, options);\n}\n\n/**\n * Function to create a new {@link Directory} object for the current working directory\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const cwd = options => {\n return dir(process.cwd(), options);\n}\n\n/**\n * Function to create a new {@link Directory} object for the directory of a JS source file\n * @param {string} url - module url - from `import.meta.url`\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const bin = (url, options) => {\n return dir(\n path.dirname(url.replace(/^file:\\/\\//, '')),\n options\n );\n}\n\nexport default Directory\n","import { isString, isArray } from \"./Misc.js\";\n\n/**\n * Split a comma/whitespace delimited string into an Array\n * @param {String} [value] - string to split\n * @return {Array} array of split strings\n * @example\n * const strings = splitList('one two three')\n * @example\n * const strings = splitList('one,two,three')\n * @example\n * const strings = splitList('one, two, three')\n */\nexport function splitList(value) {\n return isString(value)\n ? value.split(/,\\s*|\\s+/)\n : isArray(value)\n ? value\n : [value];\n}\n\n/**\n * Join an Array into a single string\n * @param {Array} [array] - array to join\n * @param {String} [joint=' '] - delimiter to join strings\n * @param {String} [lastJoint=joint] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinList(['one', 'two', 'three']); // one two three\n * @example\n * joinList(['one', 'two', 'three'], ', '); // one, two, three\n * @example\n * joinList(['one', 'two', 'three'], ', ', ' and '); // one, two and three\n */\nexport function joinList(array, joint=' ', lastJoint=joint) {\n let copy = [...array];\n const last = copy.pop();\n return copy.length\n ? [copy.join(joint), last].join(lastJoint)\n : last;\n}\n\n/**\n * Join an Array into a single string using commas for delimiters and ` and ` for the final item\n * @param {Array} [array] - array to join\n * @param {String} [joint=', '] - delimiter to join strings\n * @param {String} [lastJoint=' and '] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinListAnd(['one', 'two', 'three']); // one, two and three\n */\nexport function joinListAnd(array, joint=', ', lastJoint=' and ') {\n return joinList(array, joint, lastJoint);\n}\n\n/**\n * Join an Array into a single string using commas for delimiters and ` or ` for the final item\n * @param {Array} [array] - array to join\n * @param {String} [joint=', '] - delimiter to join strings\n * @param {String} [lastJoint=' or '] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinListOr(['one', 'two', 'three']); // one, two or three\n */\nexport function joinListOr(array, joint=', ', lastJoint=' or ') {\n return joinList(array, joint, lastJoint);\n}\n\n/**\n * Capitalise a string by converting the first character to upper case and other characters to lower case\n * @param {String} [word] - word to capitalise\n * @return {String} capitalised string\n * @example\n * capitalise('badger'); // Badger\n * @example\n * capitalise('BADGER'); // Badger\n */\nexport function capitalise(word) {\n return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\n}\n\n/**\n * Convert a snake case string to studly caps\n * @param {String} [snake] - word to capitalise\n * @return {String} capitalised string\n * @example\n * snakeToStudly('happy_badger_dance'); // HappyBadgerDance\n * @example\n * snakeToStudly('happy_badger/dance'); // HappyBadger/Dance\n */\nexport function snakeToStudly(snake) {\n return snake.split('/').map(\n // each segment can be like foo_bar which we convert to FooBar\n segment => segment.split('_').map(capitalise).join('')\n ).join('/');\n}\n\n/**\n * Convert a snake case string to camel case\n * @param {String} [snake] - word to capitalise\n * @return {String} capitalised string\n * @example\n * snakeToCamel('happy_badger_dance'); // happyBadgerDance\n * @example\n * snakeToCamel('happy_badger/dance'); // happyBadger/dance\n */\nexport function snakeToCamel(snake) {\n return snake.split('/').map(\n // each segment can be like foo_bar which we convert to fooBar\n segment => segment.split('_').map((i, n) => n ? capitalise(i) : i).join('')\n ).join('/');\n}\n","import { hasValue, fail } from \"./Misc.js\";\nimport { joinListOr, splitList } from \"./Text.js\";\n\n/**\n * Assert that a parameter object contains an item with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {String} name - parameter that must be included\n * @return {any} the parameter value\n * @throws {Error} if the parameter is not defined or null\n * @example\n * const foo = requiredParam({ foo: 10 }, 'foo');\n */\nexport function requiredParam(params={}, name) {\n const value = params[name];\n if (hasValue(value)) {\n return value;\n }\n else {\n fail(\"Missing value for required parameter: \", name);\n }\n}\n\n/**\n * Assert that a parameter object contains all specified item with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {Array|String} names - parameters that must be included, as an Array or whitespace/comma delimited string (see {@link splitList})\n * @return {Array} the parameter values\n * @throws {Error} if any parameter is not defined or null\n * @example\n * const [foo, bar] = requiredParams({ foo: 10, bar: 20 }, 'foo bar');\n */\nexport function requiredParams(params={}, names) {\n return splitList(names).map( name => requiredParam(params, name) );\n}\n\n/**\n * An alias for {@link requiredParams} for people who don't like typing long names (and for symmetry with {@link anyParams}))\n */\nexport const allParams=requiredParams;\n\n/**\n * Assert that a parameter object contains any of the specified items with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {Array|String} names - parameters of which at least one must be included, as an Array or whitespace/comma delimited string (see {@link splitList})\n * @return {Array} the parameter values\n * @throws {Error} if any parameter is not defined or null\n * @example\n * const [foo, bar] = anyParams({ foo: 10, wiz: 99 }, 'foo bar');\n */\nexport function anyParams(params, names) {\n let found = false;\n const nlist = splitList(names);\n const values = nlist.map(\n name => {\n const value = params[name];\n if (hasValue(value)) {\n found = true;\n }\n return value;\n }\n );\n return found\n ? values\n : fail(\"Missing value for one of: \", joinListOr(nlist));\n}\n","import { dir } from './Filesystem/Directory.js'\nimport { allParams, anyParams } from './Utils/Params.js'\nimport { splitList } from './Utils/Text.js'\nimport { fail } from './Utils/Misc.js';\nimport { addDebug } from './Utils/Debug.js';\n\nconst defaults = {\n codecs: 'yaml json',\n};\n\nexport class Config {\n constructor(params={}) {\n const options = { ...defaults, ...params };\n const [rootDir] = allParams(options, 'dir');\n const [codec, codecs] = anyParams(options, 'codec codecs');\n\n this.state = {\n dir: dir(rootDir),\n codecs: splitList(codecs) || [codec],\n }\n\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\n this.debug('root dir: ', this.state.dir.path());\n this.debug('codecs: ', this.state.codecs);\n }\n async file(uri) {\n for (let codec of this.state.codecs) {\n const path = uri + '.' + codec;\n const file = this.state.dir.file(path, { codec });\n this.debug('looking for config file: ', file.path());\n if (await file.exists()) {\n this.debug('config file exists: ', file.path());\n return file;\n }\n }\n return undefined;\n }\n async config(uri, defaults) {\n const file = await this.file(uri);\n return file\n ? await file.read()\n : (defaults || fail(\"No configuration file for \" + uri))\n }\n}\n\nexport const config = options => new Config(options)\n\nexport default Config\n","import { dir as fsdir } from \"./Filesystem/Directory.js\";\nimport { requiredParam } from \"./Utils/Params.js\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { splitList } from \"./Utils/Text.js\";\nimport { fail } from \"./Utils/Misc.js\";\n\nconst defaults = {\n dir: ['lib','library','src','components'],\n ext: ['js', 'mjs'],\n}\n\nexport class Library {\n constructor(props={}) {\n const root = fsdir(requiredParam(props, 'root'));\n const dir = props.directory || props.dir || props.dirs || defaults.dir;\n const ext = props.extension || props.ext || props.exts || defaults.ext;\n const dirs = splitList(dir).map( dir => root.dir(dir) ); // resolve to root dir\n const exts = splitList(ext).map( ext => ext.replace(/^\\./, '') ); // remove leading '.'\n this.state = {\n dirs, exts\n }\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n }\n async dirs() {\n return this.state.dirsExist\n || ( this.state.dirsExist = await this.dirsExist() );\n }\n async dirsExist() {\n const dirs = this.state.dirs;\n const exists = await Promise.all(\n dirs.map( d => d.exists() )\n );\n return dirs.filter((value, index) => exists[index]);\n }\n async lib(uri) {\n const dirs = await this.dirs();\n const exts = this.state.exts;\n for (let dir of dirs) {\n for (let ext of exts) {\n const file = dir.file(uri + '.' + ext);\n this.debug('looking for module %s as', uri, file.path());\n const exists = await file.exists();\n if (exists) {\n const load = await import(file.path());\n this.debug('loaded %s as', file.path());\n return load;\n }\n }\n }\n fail(\"Library not found: \", uri);\n }\n}\n\nexport const library = props => new Library(props);\n\nexport default library;","import { dir } from \"./Filesystem/Directory.js\";\nimport { requiredParam } from \"./Utils/Params.js\";\nimport { fail, hasValue } from \"./Utils/Misc.js\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { Config } from \"./Config.js\";\nimport { Library } from \"./Library.js\";\n\nconst defaults = {\n library: {\n },\n config: {\n dir: 'config',\n }\n}\nexport class Workspace {\n constructor(props={}) {\n const rootDir = dir(requiredParam(props, 'dir'));\n const cfgDir = rootDir.dir(props.config?.dir || defaults.config.dir);\n const cfgOpts = { ...defaults.config, ...(props.config||{}), dir: cfgDir };\n const config = new Config(cfgOpts);\n const libOpts = { ...defaults.library, ...(props.library||{}), root: rootDir };\n const library = new Library(libOpts);\n\n this.state = {\n rootDir,\n config,\n library\n }\n\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n this.debug('root dir: ', rootDir.path());\n this.debug('config dir: ', cfgDir.path());\n }\n dir(path, options) {\n this.debug(\"dir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.rootDir.dir(path, options)\n : this.state.rootDir;\n }\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return this.state.rootDir.file(path, options)\n }\n read(path, options) {\n this.debug(\"read(%s, %o)\", path, options);\n return this.file(path, options).read();\n }\n write(path, data, options) {\n this.debug(\"write(%s, %o, %o)\", path, data, options);\n return this.file(path, options).write(data);\n }\n configDir(path, options) {\n this.debug(\"configDir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.configDir(path, options)\n : this.state.configDir;\n }\n async config(uri, defaults) {\n this.debug(\"config(%s, %o)\", uri, defaults);\n return hasValue(uri)\n ? this.state.config.config(uri, defaults)\n : this.state.config;\n }\n async lib(uri) {\n return this.state.library.lib(uri);\n }\n async component(uri, props) {\n const config = await this.config(uri, {});\n const lib = await this.lib(config.component?.library || uri);\n const exp = config.component?.export || 'default';\n const compcls = lib[exp] || fail(\"No '\", exp, \"' export from component library: \", uri);\n const comp = new compcls(this, { ...config, ...props });\n // this.debug(\"created component \", uri)\n return comp;\n }\n}\n\nexport const workspace = props => new Workspace(props);\n\nexport default Workspace;","import { addDebug } from \"./Utils/Debug.js\";\n\nexport class Component {\n constructor(workspace, props={}) {\n this.workspace = workspace;\n this.props = props;\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n this.initComponent(props);\n }\n initComponent() {\n // stub for subclasses\n }\n}\n\nexport default Component"],"names":["isString","value","isArray","Array","isObject","isNull","isUndefined","hasValue","fail","message","Error","join","rethrow","error","doNothing","ANSIColors","reset","bold","bright","dark","black","red","green","yellow","blue","magenta","cyan","grey","white","fg","bg","escapeCode","color","base","codes","pair","split","hue","pop","code","push","length","shade","shift","Debugger","enabled","prefix","format","args","console","log","colors","col","escapes","escape","bind","addDebug","obj","debug","codecs","json","encode","data","JSON","stringify","decode","text","parse","yaml","dump","load","codec","name","toLowerCase","defaultOptions","encoding","Path","constructor","path","options","this","state","debugPrefix","debugColor","relativePath","parts","async","stat","stats","unstat","undefined","File","directory","dir","dirname","read","opts","file","readFile","then","write","writeFile","rm","Directory","parent","readdir","isEmpty","exists","notEmpty","mkdir","empty","rmdir","create","recursive","destroy","force","splitList","joinList","array","joint","lastJoint","copy","last","joinListOr","capitalise","word","charAt","toUpperCase","slice","requiredParam","params","requiredParams","names","map","allParams","anyParams","found","nlist","values","defaults","Config","rootDir","uri","ext","Library","props","root","fsdir","dirs","extension","exts","replace","dirsExist","Promise","all","d","filter","index","t","resolve","_interopNamespace","require","Workspace","cfgDir","config","cfgOpts","libOpts","library","configDir","lib","component","exp","export","workspace","initComponent","url","process","cwd","every","snake","segment","i","n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"badger.cjs.js","sources":["../src/Badger/Utils/Misc.js","../src/Badger/Utils/Color.js","../src/Badger/Utils/Debug.js","../src/Badger/Codecs/Json.js","../src/Badger/Codecs/index.js","../src/Badger/Codecs/Yaml.js","../src/Badger/Filesystem/Path.js","../src/Badger/Filesystem/File.js","../src/Badger/Filesystem/Directory.js","../src/Badger/Utils/Text.js","../src/Badger/Config.js","../src/Badger/Utils/Params.js","../src/Badger/Library.js","../src/Badger/Workspace.js","../src/Badger/Component.js"],"sourcesContent":["/**\n * Determines if a value is a string\n * @param {String} value - value to test\n * @return {Boolean} true if `value` is a string or false if not\n */\nexport function isString(value) {\n return typeof value === 'string';\n}\n\n/**\n * Determines if a value is an array\n * @param {Array} value - value to test\n * @return {Boolean} true if `value` is an Array or false if not\n */\nexport function isArray(value) {\n return Array.isArray(value);\n}\n\n/**\n * Determines if a value is a Function\n * @param {Function} value - value to test\n * @return {Boolean} true if `value` is a Function or false if not\n */\nexport function isFunction(value) {\n return typeof value === 'function'\n}\n\n/**\n * Determines if a value is an Object (but not an Array)\n * @param {Object} value - value to test\n * @return {Boolean} true if `value` is an Object or false if not\n */\nexport function isObject(value) {\n return typeof value === \"object\"\n && ! isArray(value)\n && ! isNull(value);\n}\n\n/**\n * Determines if a value is `undefined`\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `undefined` or false if not\n */\nexport function isUndefined(value) {\n return typeof value === 'undefined';\n}\n\n/**\n * Determines if a value is `null`\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `null` or false if not\n */\nexport function isNull(value) {\n return value === null;\n}\n\n/**\n * Determines if a value is defined and not null\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is not `undefined` or `null`\n */\nexport function hasValue(value) {\n return ! (isUndefined(value) || isNull(value));\n}\n\n/**\n * Determines if all values are defined and not null\n * @param {any[]} values - values to test\n * @return {Boolean} true if all values are not `undefined` or `null`\n */\nexport function haveValue(...values) {\n return values.every( value => hasValue(value) );\n}\n\n/**\n * Determines if a value is undefined or null\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `undefined` or `null`\n */\nexport function noValue(value) {\n return ! hasValue(value);\n}\n\n/**\n * Throws a new Error object\n * @param {String[]} message - error message string(s)\n * @throws {Error}\n */\nexport function fail(...message) {\n throw new Error(message.join(''));\n}\n\n/**\n * Re-throw an existing Error object\n * @param {Error} error - error object\n * @throws {Error}\n */\nexport function rethrow(error) {\n throw error;\n}\n\n/**\n * Do nothing. Nothing at all.\n */\nexport function doNothing() {\n // speak again Cordelia\n}","import { isObject } from \"./Misc.js\";\n\nexport const ANSIStart = '\\u001B[';\nexport const ANSIEnd = 'm';\nexport const ANSIColors = {\n reset: 0,\n bold: 1,\n bright: 1,\n dark: 2,\n black: 0,\n red: 1,\n green: 2,\n yellow: 3,\n blue: 4,\n magenta: 5,\n cyan: 6,\n grey: 7,\n white: 8,\n fg: 30,\n bg: 40,\n};\n\n/**\n * Returns an ANSI escape code for a color string. This can be a single color\n * name, e.g. `red`, `green`, etc., or a color prefixed with `bright` or `dark`,\n * e.g. `bright red`, `dark green`, etc. An optional section argument can be\n * set to `fg` (default) to set a foreground color or `bg` for a background color.\n * @param {String} color - color name with optional modifier prefix\n * @param {String} [base='fg'] - `fg` or `bg` to set foreground or background color respectively\n * @return {String} ANSI escape code string\n * @example\n * const str = escapeCode('red')\n * @example\n * const str = escapeCode('bright red')\n * @example\n * const str = escapeCode('bright red', 'bg')\n */\nexport const escapeCode = (color, base='fg') => {\n let codes = [ ];\n let pair = color.split(/ /, 2);\n const hue = pair.pop();\n const code = (base ? ANSIColors[base] : 0) + ANSIColors[hue];\n codes.push(code);\n if (pair.length) {\n const shade = pair.length ? pair.shift() : 'dark';\n codes.push(ANSIColors[shade])\n }\n return ANSIStart + codes.join(';') + ANSIEnd;\n}\n\n/**\n * Returns an ANSI escape code for a color string or combination of foreground and\n * background colors.\n * @param {String|Object} colors - either a simple color name or object contain foreground and background colors\n * @param {String} [colors.fg] - foreground color\n * @param {String} [colors.fg] - background color\n * @return {String} ANSI escape code string\n * @example\n * const str = escape('red')\n * @example\n * const str = escape('bright red')\n * @example\n * const str = escape({ fg: 'bright yellow', bg: 'blue' })\n */\nexport const escape = (colors={}) => {\n const col = isObject(colors) ? colors : { fg: colors };\n let escapes = [ ];\n if (col.bg) {\n escapes.push(escapeCode(col.bg, 'bg'));\n }\n if (col.fg) {\n escapes.push(escapeCode(col.fg, 'fg'));\n }\n return escapes.join('');\n}\n\nexport const reset = () => escapeCode('reset')\n\n","import { escape, reset } from './Color.js'\nimport { doNothing } from './Misc.js';\n\n/**\n * Returns a debugging function which is enabled by the first `enabled` argument.\n * If this is `false` then it returns a function which does nothing. If it is\n * true then it returns a function that forwards all arguments to `console.log`.\n * An optional `prefix` be be specified to prefix each debugging line. The\n * optional third argument `color` can be used to specify a color for the prefix.\n * @param {Boolean} enabled - is debugging enabled?\n * @param {String} [prefix] - optional prefix for debugging messages\n * @param {String|Object} [color] - a color name or object (see {@link Badger/Utils/Color})\n * @param {String} [color.fg] - foreground color\n * @param {String} [color.bg] - background color\n * @return {Function} a debugging function\n * @example\n * const debug = Debugger(true)\n * @example\n * const debug = Debugger(true, 'Debug > ')\n * @example\n * const debug = Debugger(true, 'Debug > ', 'blue')\n * @example\n * const debug = Debugger(true, 'Debug > ', { bg: 'blue', fg: 'bright yellow' })\n */\nexport function Debugger(enabled, prefix='', color) {\n return enabled\n ? prefix\n ? (format, ...args) =>\n console.log(\n '%s' + prefix + '%s' + format,\n color ? escape(color) : '',\n reset(),\n ...args,\n )\n : console.log.bind(console)\n : doNothing;\n}\n\n/**\n * Creates a debugging function via {@link Debugger} and attaches it to the object\n * passed as the first argument as the `debug` function.\n * @param {Object} obj - the object to receive the `debug` function\n * @param {Boolean} enabled - is debugging enabled?\n * @param {String} [prefix] - optional prefix for debugging messages\n * @param {String|Object} [color] - a color name or object (see {@link Badger/Utils/Color})\n * @param {String} [color.fg] - foreground color\n * @param {String} [color.bg] - background color\n * @example\n * const debug = addDebug(myObject, true)\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ')\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ', 'blue')\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ', { bg: 'blue', fg: 'bright yellow' })\n */\nexport function addDebug(obj, enabled, prefix='', color) {\n obj.debug = Debugger(enabled, prefix, color);\n}\n","/**\n * Function to encode JSON\n * @param {Object} data - The data to encode as JSON text\n * @return {String} a JSON encoded string\n * @example\n * encode({ message: 'Hello World' })\n */\nexport const encode = data => JSON.stringify(data);\n\n/**\n * Function to decode JSON\n * @param {String} text - The JSON text to decode\n * @return {Object|Array} the decoded object or array\n * @example\n * decode(\"{ message: 'Hello World' }\")\n */\nexport const decode = text => JSON.parse(text);\n\n/**\n * An object containing the JSON `encode` and `decode` functions\n */\nexport const codec = { encode, decode };\n\nexport default codec\n","import json from './Json.js'\nimport yaml from './Yaml.js'\n\n/**\n * Codecs provide a consistent encode()/decode() interface for serialising\n * and de-serialising data. This standard naming convention makes it possible\n * for the ../Filesystem/File.js module to support a \"codec\" option for\n * files. When this option is set the file.read() and file.write() methods\n * automatically handle the translation to and from the serialised format\n * using a codec object returned by the codec() function below. The codec\n * name can be specified in any case, e.g. \"Yaml\", \"YAML\", \"yaml\", \"YaML\",\n * etc., and it will be converted to lower case.\n */\n\n/**\n * Lookup table for codecs\n */\nexport const codecs = {\n json, yaml\n};\n\n/**\n * Function to fetch a codec\n * @param {string} name - The title of the code, in any case, e.g. \"yaml\", \"YAML\", \"Yaml\"\n */\nexport const codec = name => codecs[\n name.toLowerCase()\n];\n\nexport default codecs\n","// simple wrapper around JSON load/dump\nimport yaml from 'js-yaml';\n\n/**\n * Function to encode YAML\n * @param {Object} data - The data to encode as YAML text\n * @return {String} a YAML encoded string\n * @example\n * encode({ message: 'Hello World' })\n */\nexport const encode = data => yaml.dump(data);\n\n/**\n * Function to decode YAML\n * @param {String} text - The YAML text to decode\n * @return {Object|Array} the decoded object or array\n * @example\n * decode(\"message: Hello World\")\n */\nexport const decode = text => yaml.load(text);\n\n/**\n * An object containing the YAML `encode` and `decode` functions\n */\nexport const codec = { encode, decode };\n\nexport default codec\n","import path from 'node:path';\nimport { stat } from 'node:fs/promises'\nimport { rethrow } from '../Utils/Misc.js';\nimport { addDebug } from '../Utils/Debug.js';\n\nconst defaultOptions = {\n encoding: 'utf8'\n}\n\n/**\n * The Path class implements a base class for the {@link File} and {@link Directory}\n * classes. It implements the common functionality for representing a filesystem path.\n */\nexport class Path {\n /**\n * Constructor for filesystem paths.\n * @param {string} path - file path\n * @param {Object} [options] - configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link Path} object\n */\n constructor(path, options={}) {\n // allow path/file/directory to be constructed from an existing object\n if (path instanceof Path) {\n path = path.path();\n }\n this.state = { path, options: { ...defaultOptions, ...options } };\n addDebug(this, options.debug, options.debugPrefix || 'Path', options.debugColor);\n }\n\n /**\n * Accessor method to return the filesystem path.\n * @return {String} the filesystem path\n */\n path() {\n return this.state.path;\n }\n\n /**\n * Create a path relative to the current path.\n * @param {String[]} parts - part(s) of the filesystem path\n * @return {String} the new path\n * @example\n * const p = new Path('/path/to/here')\n * const q = p.relativePath('there') // -> /path/to/here/there\n * const r = p.relativePath('and', 'there') // -> /path/to/here/and/there\n */\n relativePath(...parts) {\n return path.join(this.state.path, ...parts);\n }\n\n /**\n * Internal method to merge any options with the pre-defined options passed to the\n * constructor. Options passed as arguments will take precedence.\n * @param {Object} options - new options\n * @return {Object} the merged options\n * @example\n * const p = new Path('/path/to/here', { option1: 'hello' })\n * const q = p.options({ option2: 'world' }) // -> { option1: 'hello', options2: 'world' }\n */\n options(options={}) {\n return { ...this.state.options, ...options };\n }\n\n /**\n * Method to assert that the path exists.\n * @return {Promise} fulfills with `true` if the path exists or rejects if the path doesn't\n * @example\n * const p = new Path('/path/to/here')\n * p.exists()\n * .then( console.log('path exists') )\n * .catch( console.log('path does not exist') )\n */\n async exists() {\n try {\n await this.stat();\n return true;\n }\n catch (error) {\n return error.code === 'ENOENT'\n ? false\n : rethrow(error);\n }\n }\n\n /**\n * Method to fetch stats for the path. Uses the `stat` function from `node:fs/promises`.\n * Stats are cached internally (subject to change)\n * @return {Promise} fulfills with path stats returned from the `stat` function\n * @example\n * const p = new Path('/path/to/here')\n * p.stat()\n * .then( stats => console.log('path stats:', stats) )\n * .catch( console.log('path does not exist') )\n */\n async stat() {\n const stats = await stat(this.state.path);\n return this.state.stats = stats;\n }\n\n /**\n * Method to clear internal cache of path stats (subject to change)\n */\n unstat() {\n this.state.stats = undefined;\n return this;\n }\n}\n\nexport default Path\n","import path from 'node:path'\nimport Path from './Path.js'\nimport { dir } from './Directory.js'\nimport { codec } from '../Codecs/index.js'\nimport { readFile, writeFile, rm } from 'node:fs/promises'\n\n/**\n * The File class implements a wrapper around a filesystem\n * file.\n */\nclass File extends Path {\n /**\n * Returns a new {@link Directory} object for the parent directory of the file\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object for the parent\n */\n directory(options) {\n return dir(path.dirname(this.state.path), options);\n }\n\n /**\n * An alias for the {@link directory} method for lazy people\n * @return {Object} the parent {@link Directory} object\n */\n dir(...args) {\n return this.directory(...args);\n }\n\n /**\n * Reads the file content. If a `codec` has been specified then the content is decoded.\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {String|Object} the file content\n * @example\n * const text = file('myfile.txt').read();\n * @example\n * const data = file('myfile.json', { codec: 'json' }).read();\n * @example\n * const data = file('myfile.json').read({ codec: 'json' });\n */\n read(options) {\n const opts = this.options(options);\n const file = readFile(this.state.path, opts);\n return opts.codec\n ? file.then(text => codec(opts.codec).decode(text))\n : file;\n }\n\n /**\n * Writes the file content. If a `codec` has been specified then the content will be encoded.\n * @param {String|Object} data - directory configuration options\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @example\n * file('myfile.txt').write('Hello World');\n * @example\n * file('myfile.json', { codec: 'json' }).write({ message: 'Hello World' });\n * @example\n * file('myfile.json').write({ message: 'Hello World' }, { codec: 'json' });\n */\n write(data, options) {\n const opts = this.options(options);\n const text = opts.codec\n ? codec(opts.codec).encode(data)\n : data;\n return writeFile(this.state.path, text, opts).then( () => this );\n }\n\n async delete(options) {\n await rm(this.state.path, options);\n return this;\n }\n}\n\n/**\n * Function to create a new {@link File} object for a file\n * @param {String} path - file path\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link File} object\n */\nexport const file = (path, options) => {\n return new File(path, options);\n}\n\nexport default File\n","import process from 'node:process';\nimport path from 'node:path';\nimport Path from './Path.js'\nimport { file } from './File.js'\nimport { fail } from '../Utils/Misc.js';\nimport { rm, mkdir, rmdir, readdir } from 'node:fs/promises'\n\n/**\n * The Directory class implements a wrapper around a filesystem\n * directory.\n */\nclass Directory extends Path {\n /**\n * Fetch a new {@link File} object for a file in the directory.\n * @param {string} path - file path\n * @param {Object} [options] - file configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link File} object\n */\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return file(this.relativePath(path), this.options(options));\n }\n\n /**\n * Fetch a new {@link Directory} object for a sub-directory in the directory.\n * @param {string} path - directory path\n * @param {Object} [options] - directory configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link Directory} object\n */\n directory(path, options) {\n this.debug(\"directory(%s, %o)\", path, options);\n return dir(this.relativePath(path), this.options(options));\n }\n\n /**\n * An alias for the {@link directory} method for lazy people\n * @return {Object} the {@link Directory} object\n */\n dir(path, options) {\n this.debug(\"dir(%s, %o)\", path, options);\n return this.directory(path, options);\n }\n\n /**\n * Returns a new {@link Directory} object for the parent directory\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object for the parent\n */\n parent(options) {\n this.debug(\"parent()\");\n return this.directory('..', options);\n }\n\n /**\n * Returns the names of the files and sub-directories in the directory\n * @return {Promise} fulfills with an array of the file and directory names\n */\n async read() {\n this.debug(\"read()\");\n return await readdir(this.path());\n }\n\n /**\n * Determines if the directory is empty.\n * @return {Promise} fulfills with a boolean value true (empty) or false (not empty).\n */\n async isEmpty() {\n this.debug(\"isEmpty()\");\n const entries = await this.read();\n return entries.length === 0;\n }\n\n /**\n * Determines if the directory is not empty.\n * @return {Promise} fulfills with a boolean value true (not empty) or false (empty).\n */\n async notEmpty() {\n this.debug(\"notEmpty()\");\n const empty = await this.isEmpty();\n return !empty;\n }\n\n /**\n * Empty the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.force] - force removal of files and directories\n * @param {Boolean} [options.recursive] - recursively empty and delete sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async empty(options={}) {\n this.debug(\"empty(%o)\", options);\n if (await this.exists() && await this.notEmpty()) {\n await rm(this.path(), options);\n }\n return this;\n }\n\n /**\n * Make the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.recursive] - create intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async mkdir(options={}) {\n this.debug(\"mkdir(%o)\", options);\n const exists = await this.exists();\n if (! exists) {\n await mkdir(this.path(), options);\n }\n return this;\n }\n\n /**\n * Remove the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.empty] - delete items in directory\n * @param {Boolean} [options.force] - force delete files and directories\n * @param {Boolean} [options.recursive] - recursively delete sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async rmdir(options={}) {\n this.debug(\"rmdir(%o)\", options);\n if (options.empty) {\n await this.empty(options);\n }\n if (await this.exists()) {\n await rmdir(this.path());\n }\n return this;\n }\n\n /**\n * Create the directory and any intermediate directories.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.recursive=true] - recursively create intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n create(options={ recursive: true }) {\n this.debug(\"create(%o)\", options);\n return this.mkdir(options);\n }\n\n /**\n * Empty and delete the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.empty=true] - empty directory of any files and sub-directories\n * @param {Boolean} [options.recursive=true] - recursively delete sub-directories\n * @param {Boolean} [options.force=true] - force deletion of files and sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n destroy(options={ empty: true, recursive: true, force: true }) {\n this.debug(\"destroy(%o)\", options);\n return this.rmdir(options);\n }\n\n /**\n * Assert that a directory exists and optionally create it\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.create] - create the directory and any intermediate directories if it doesn't exist - equivalent to adding `mkdir` and `recursive` options or calling {@link create}\n * @param {Boolean} [options.mkdir] - create the directory, add the `recursive` option to create intermediate directories - equivalent to calling {@link mkdir}\n * @param {Boolean} [options.recursive] - when used with `mkdir`, creates any intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async mustExist(options={}) {\n this.debug(\"mustExist(%o)\", options);\n if (await this.exists()) {\n return this;\n }\n if (options.mkdir) {\n return this.mkdir(options);\n }\n if (options.create) {\n return this.create();\n }\n fail(\"Directory does not exist: \", this.path());\n }\n}\n\n/**\n * Function to create a new {@link Directory} object\n * @param {string} path - directory path\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const dir = (path, options) => {\n return new Directory(path, options);\n}\n\n/**\n * Function to create a new {@link Directory} object for the current working directory\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const cwd = options => {\n return dir(process.cwd(), options);\n}\n\n/**\n * Function to create a new {@link Directory} object for the directory of a JS source file\n * @param {string} url - module url - from `import.meta.url`\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const bin = (url, options) => {\n return dir(\n path.dirname(url.replace(/^file:\\/\\//, '')),\n options\n );\n}\n\nexport default Directory\n","import { isString, isArray, noValue } from \"./Misc.js\";\n\n/**\n * Split a comma/whitespace delimited string into an Array\n * @param {String} [value] - string to split\n * @return {Array} array of split strings\n * @example\n * const strings = splitList('one two three')\n * @example\n * const strings = splitList('one,two,three')\n * @example\n * const strings = splitList('one, two, three')\n */\nexport function splitList(value) {\n if (noValue(value)) {\n return [ ];\n }\n else if (isString(value)) {\n return value.length\n ? value.split(/,\\s*|\\s+/)\n : [ ]\n }\n else if (isArray(value)) {\n return value;\n }\n return [value];\n}\n\n/**\n * Join an Array into a single string\n * @param {Array} [array] - array to join\n * @param {String} [joint=' '] - delimiter to join strings\n * @param {String} [lastJoint=joint] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinList(['one', 'two', 'three']); // one two three\n * @example\n * joinList(['one', 'two', 'three'], ', '); // one, two, three\n * @example\n * joinList(['one', 'two', 'three'], ', ', ' and '); // one, two and three\n */\nexport function joinList(array, joint=' ', lastJoint=joint) {\n let copy = [...array];\n const last = copy.pop();\n return copy.length\n ? [copy.join(joint), last].join(lastJoint)\n : last;\n}\n\n/**\n * Join an Array into a single string using commas for delimiters and ` and ` for the final item\n * @param {Array} [array] - array to join\n * @param {String} [joint=', '] - delimiter to join strings\n * @param {String} [lastJoint=' and '] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinListAnd(['one', 'two', 'three']); // one, two and three\n */\nexport function joinListAnd(array, joint=', ', lastJoint=' and ') {\n return joinList(array, joint, lastJoint);\n}\n\n/**\n * Join an Array into a single string using commas for delimiters and ` or ` for the final item\n * @param {Array} [array] - array to join\n * @param {String} [joint=', '] - delimiter to join strings\n * @param {String} [lastJoint=' or '] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinListOr(['one', 'two', 'three']); // one, two or three\n */\nexport function joinListOr(array, joint=', ', lastJoint=' or ') {\n return joinList(array, joint, lastJoint);\n}\n\n/**\n * Capitalise a string by converting the first character to upper case and other characters to lower case\n * @param {String} [word] - word to capitalise\n * @return {String} capitalised string\n * @example\n * capitalise('badger'); // Badger\n * @example\n * capitalise('BADGER'); // Badger\n */\nexport function capitalise(word) {\n return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\n}\n\n/**\n * Convert a snake case string to studly caps\n * @param {String} [snake] - word to capitalise\n * @return {String} capitalised string\n * @example\n * snakeToStudly('happy_badger_dance'); // HappyBadgerDance\n * @example\n * snakeToStudly('happy_badger/dance'); // HappyBadger/Dance\n */\nexport function snakeToStudly(snake) {\n return snake.split('/').map(\n // each segment can be like foo_bar which we convert to FooBar\n segment => segment.split('_').map(capitalise).join('')\n ).join('/');\n}\n\n/**\n * Convert a snake case string to camel case\n * @param {String} [snake] - word to capitalise\n * @return {String} capitalised string\n * @example\n * snakeToCamel('happy_badger_dance'); // happyBadgerDance\n * @example\n * snakeToCamel('happy_badger/dance'); // happyBadger/dance\n */\nexport function snakeToCamel(snake) {\n return snake.split('/').map(\n // each segment can be like foo_bar which we convert to fooBar\n segment => segment.split('_').map((i, n) => n ? capitalise(i) : i).join('')\n ).join('/');\n}\n","import { dir as fsDir } from './Filesystem/Directory.js'\nimport { splitList } from './Utils/Text.js'\nimport { doNothing, fail } from './Utils/Misc.js';\nimport { addDebug } from './Utils/Debug.js';\n\nconst defaults = {\n codecs: 'yaml json',\n jsExt: 'js mjs',\n};\n\n/**\n * The Config class implements an object which can load configuration\n * files from a configuration directory. Files can be Javascript files\n * (with `.js` or `.mjs` extensions by default) or data files using any\n * of the standard codecs (`.yaml` or `.json` by default).\n */\nexport class Config {\n /**\n * Constructor for Config object.\n * @param {String} dir - directory containing configuration files\n * @param {Object} [options] - configuration options\n * @param {Array|String} [options.jsExt='js mjs'] - Array or comma/whitespace delimited string of Javascript file extensions\n * @param {Array|String} [options.codecs='yaml json'] - Array or comma/whitespace delimited string of codec names\n * @return {Object} the {@link Config} object\n */\n constructor(dir, options={}) {\n const params = { ...defaults, ...options };\n this.state = {\n dir: fsDir(dir),\n codecs: splitList(params.codecs),\n jsExt: splitList(params.jsExt),\n }\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\n this.debug('root dir: ', this.state.dir.path());\n this.debug('codecs: ', this.state.codecs);\n }\n\n /**\n * Internal method to locate the first config file with one of a number of file extensions.\n * @param {String} uri - base part of filename\n * @param {Array} [exts] - array of possible extensions\n * @param {Function} [makeOptions] - optional function to generate options for a {@link File} object\n * @return {Object} the {@link File} object if it exists or `undefined` if not\n */\n async firstFileWithExt(uri, exts, makeOptions=doNothing) {\n for (let ext of exts) {\n const path = uri + '.' + ext;\n const file = this.state.dir.file(path, makeOptions(uri, ext));\n this.debug('looking for config file: ', file.path());\n if (await file.exists()) {\n this.debug('config file exists: ', file.path());\n return file;\n }\n }\n return undefined;\n }\n\n /**\n * Internal method to locate a Javascript configuration file with one of the `jsExt` extensions (`.js` or `.mjs` by default)\n * @param {String} uri - base part of filename\n * @return {Object} the {@link File} object if it exists or `undefined` if not\n */\n async jsFile(uri) {\n return await this.firstFileWithExt(uri, this.state.jsExt);\n }\n\n /**\n * Internal method to locate a configuration file with one of the `codecs` extensions (`.yaml` or `.json` by default)\n * @param {String} uri - base part of filename\n * @return {Object} the {@link File} object if it exists or `undefined` if not\n */\n async file(uri) {\n return await this.firstFileWithExt(uri, this.state.codecs, (uri, codec) => ({ codec }));\n }\n\n /**\n * Method to fetch configuration data from a file. The file can be a Javascript file which should\n * return the configuration data as the default export, or a YAML (`.yaml`) or JSON (`.json`) file.\n * If the file isn't found then the method returns the `defaults` data if provided, or throws an\n * error if not.\n * @param {String} uri - base part of filename\n * @param {Object} [defaults] - default configuration options to be used if a file isn't found\n * @return {Object} the configuration data loaded from the file\n */\n async config(uri, defaults) {\n // first look for a JS file, e.g. <uri>.js, <uri>.mjs\n const jsFile = await this.jsFile(uri);\n if (jsFile) {\n const load = await import(jsFile.path());\n return load.default;\n }\n // then for a config file with a codec extension, e.g. <uri>.yaml, <uri>.yaml\n const file = await this.file(uri);\n if (file) {\n return await file.read();\n }\n return defaults || fail(\"No configuration file for \" + uri);\n }\n}\n\n/**\n * Function to create a new {@link Config} object for a file\n * @param {String} dir - directory containing configuration files\n * @param {Object} [options] - configuration options\n * @param {Array|String} [options.jsExt='js mjs'] - Array or comma/whitespace delimited string of Javascript file extensions\n * @param {Array|String} [options.codecs='yaml json'] - Array or comma/whitespace delimited string of codec names\n * @return {Object} the {@link Config} object\n */\nexport const config = (dir, options) => new Config(dir, options)\n\nexport default Config\n","import { hasValue, fail } from \"./Misc.js\";\nimport { joinListOr, splitList } from \"./Text.js\";\n\n/**\n * Assert that a parameter object contains an item with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {String} name - parameter that must be included\n * @return {any} the parameter value\n * @throws {Error} if the parameter is not defined or null\n * @example\n * const foo = requiredParam({ foo: 10 }, 'foo');\n */\nexport function requiredParam(params={}, name) {\n const value = params[name];\n if (hasValue(value)) {\n return value;\n }\n else {\n fail(\"Missing value for required parameter: \", name);\n }\n}\n\n/**\n * Assert that a parameter object contains all specified item with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {Array|String} names - parameters that must be included, as an Array or whitespace/comma delimited string (see {@link splitList})\n * @return {Array} the parameter values\n * @throws {Error} if any parameter is not defined or null\n * @example\n * const [foo, bar] = requiredParams({ foo: 10, bar: 20 }, 'foo bar');\n */\nexport function requiredParams(params={}, names) {\n return splitList(names).map( name => requiredParam(params, name) );\n}\n\n/**\n * An alias for {@link requiredParams} for people who don't like typing long names (and for symmetry with {@link anyParams}))\n */\nexport const allParams=requiredParams;\n\n/**\n * Assert that a parameter object contains any of the specified items with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {Array|String} names - parameters of which at least one must be included, as an Array or whitespace/comma delimited string (see {@link splitList})\n * @return {Array} the parameter values\n * @throws {Error} if any parameter is not defined or null\n * @example\n * const [foo, bar] = anyParams({ foo: 10, wiz: 99 }, 'foo bar');\n */\nexport function anyParams(params, names) {\n let found = false;\n const nlist = splitList(names);\n const values = nlist.map(\n name => {\n const value = params[name];\n if (hasValue(value)) {\n found = true;\n }\n return value;\n }\n );\n return found\n ? values\n : fail(\"Missing value for one of: \", joinListOr(nlist));\n}\n","import { dir as fsdir } from \"./Filesystem/Directory.js\";\nimport { requiredParam } from \"./Utils/Params.js\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { splitList } from \"./Utils/Text.js\";\nimport { fail } from \"./Utils/Misc.js\";\n\nconst defaults = {\n dir: ['lib','library','src','components'],\n ext: ['js', 'mjs'],\n}\n\nexport class Library {\n constructor(props={}) {\n const root = fsdir(requiredParam(props, 'root'));\n const dir = props.directory || props.dir || props.dirs || defaults.dir;\n const ext = props.extension || props.ext || props.exts || defaults.ext;\n const dirs = splitList(dir).map( dir => root.dir(dir) ); // resolve to root dir\n const exts = splitList(ext).map( ext => ext.replace(/^\\./, '') ); // remove leading '.'\n this.state = {\n dirs, exts\n }\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n }\n async dirs() {\n return this.state.dirsExist\n || ( this.state.dirsExist = await this.dirsExist() );\n }\n async dirsExist() {\n const dirs = this.state.dirs;\n const exists = await Promise.all(\n dirs.map( d => d.exists() )\n );\n return dirs.filter((value, index) => exists[index]);\n }\n async lib(uri) {\n const dirs = await this.dirs();\n const exts = this.state.exts;\n for (let dir of dirs) {\n for (let ext of exts) {\n const file = dir.file(uri + '.' + ext);\n this.debug('looking for module %s as', uri, file.path());\n const exists = await file.exists();\n if (exists) {\n const load = await import(file.path());\n this.debug('loaded %s as', file.path());\n return load;\n }\n }\n }\n fail(\"Library not found: \", uri);\n }\n}\n\nexport const library = props => new Library(props);\n\nexport default library;","import { dir } from \"./Filesystem/Directory.js\";\nimport { requiredParam } from \"./Utils/Params.js\";\nimport { fail, hasValue } from \"./Utils/Misc.js\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { Config } from \"./Config.js\";\nimport { Library } from \"./Library.js\";\n\nconst defaults = {\n library: {\n },\n config: {\n dir: 'config',\n }\n}\nexport class Workspace {\n constructor(props={}) {\n const rootDir = dir(requiredParam(props, 'dir'));\n const cfgDir = rootDir.dir(props.config?.dir || defaults.config.dir);\n const cfgOpts = { ...defaults.config, ...(props.config||{}) };\n const config = new Config(cfgDir, cfgOpts);\n const libOpts = { ...defaults.library, ...(props.library||{}), root: rootDir };\n const library = new Library(libOpts);\n\n this.state = {\n rootDir,\n config,\n library\n }\n\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n this.debug('root dir: ', rootDir.path());\n this.debug('config dir: ', cfgDir.path());\n }\n dir(path, options) {\n this.debug(\"dir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.rootDir.dir(path, options)\n : this.state.rootDir;\n }\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return this.state.rootDir.file(path, options)\n }\n read(path, options) {\n this.debug(\"read(%s, %o)\", path, options);\n return this.file(path, options).read();\n }\n write(path, data, options) {\n this.debug(\"write(%s, %o, %o)\", path, data, options);\n return this.file(path, options).write(data);\n }\n configDir(path, options) {\n this.debug(\"configDir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.configDir(path, options)\n : this.state.configDir;\n }\n async config(uri, defaults) {\n this.debug(\"config(%s, %o)\", uri, defaults);\n return hasValue(uri)\n ? this.state.config.config(uri, defaults)\n : this.state.config;\n }\n async lib(uri) {\n return this.state.library.lib(uri);\n }\n async component(uri, props) {\n const config = await this.config(uri, {});\n const lib = await this.lib(config.component?.library || uri);\n const exp = config.component?.export || 'default';\n const compcls = lib[exp] || fail(\"No '\", exp, \"' export from component library: \", uri);\n const comp = new compcls(this, { ...config, ...props });\n // this.debug(\"created component \", uri)\n return comp;\n }\n}\n\nexport const workspace = props => new Workspace(props);\n\nexport default Workspace;","import { addDebug } from \"./Utils/Debug.js\";\n\nexport class Component {\n constructor(workspace, props={}) {\n this.workspace = workspace;\n this.props = props;\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n this.initComponent(props);\n }\n initComponent() {\n // stub for subclasses\n }\n}\n\nexport default Component"],"names":["isString","value","isArray","Array","isObject","isNull","isUndefined","hasValue","noValue","fail","message","Error","join","rethrow","error","doNothing","ANSIColors","reset","bold","bright","dark","black","red","green","yellow","blue","magenta","cyan","grey","white","fg","bg","escapeCode","color","base","codes","pair","split","hue","pop","code","push","length","shade","shift","Debugger","enabled","prefix","format","args","console","log","colors","col","escapes","escape","bind","addDebug","obj","debug","codecs","json","encode","data","JSON","stringify","decode","text","parse","yaml","dump","load","codec","name","toLowerCase","defaultOptions","encoding","Path","constructor","path","options","this","state","debugPrefix","debugColor","relativePath","parts","async","stat","stats","unstat","undefined","File","directory","dir","dirname","read","opts","file","readFile","then","write","writeFile","rm","Directory","parent","readdir","isEmpty","exists","notEmpty","mkdir","empty","rmdir","create","recursive","destroy","force","splitList","joinList","array","joint","lastJoint","copy","last","joinListOr","capitalise","word","charAt","toUpperCase","slice","defaults","jsExt","Config","params","fsDir","uri","exts","makeOptions","ext","firstFileWithExt","jsFile","t","Promise","resolve","_interopNamespace","require","default","requiredParam","requiredParams","names","map","allParams","Library","props","root","fsdir","dirs","extension","replace","dirsExist","all","d","filter","index","Workspace","rootDir","cfgDir","config","cfgOpts","libOpts","library","configDir","lib","component","exp","export","workspace","initComponent","found","nlist","values","url","process","cwd","every","snake","segment","i","n"],"mappings":"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"}
|
package/dist/badger.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t from"js-yaml";import i from"node:process";import
|
|
1
|
+
import t from"js-yaml";import i from"node:process";import s from"node:path";import{stat as e,readFile as r,writeFile as n,rm as o,readdir as a,mkdir as c,rmdir as h}from"node:fs/promises";function u(t){return"string"==typeof t}function d(t){return Array.isArray(t)}function f(t){return"function"==typeof t}function p(t){return"object"==typeof t&&!d(t)&&!g(t)}function l(t){return void 0===t}function g(t){return null===t}function b(t){return!(l(t)||g(t))}function m(...t){return t.every((t=>b(t)))}function y(t){return!b(t)}function w(...t){throw new Error(t.join(""))}function x(t){throw t}function j(){}const E={reset:0,bold:1,bright:1,dark:2,black:0,red:1,green:2,yellow:3,blue:4,magenta:5,cyan:6,grey:7,white:8,fg:30,bg:40},k=(t,i="fg")=>{let s=[],e=t.split(/ /,2);const r=e.pop(),n=(i?E[i]:0)+E[r];if(s.push(n),e.length){const t=e.length?e.shift():"dark";s.push(E[t])}return"["+s.join(";")+"m"};function v(t,i="",s){return t?i?(t,...e)=>console.log("%s"+i+"%s"+t,s?((t={})=>{const i=p(t)?t:{fg:t};let s=[];return i.bg&&s.push(k(i.bg,"bg")),i.fg&&s.push(k(i.fg,"fg")),s.join("")})(s):"",k("reset"),...e):console.log.bind(console):j}function C(t,i,s="",e){t.debug=v(i,s,e)}class P{constructor(t,i={}){this.workspace=t,this.props=i,C(this,i.debug,i.debugPrefix,i.debugColor),this.initComponent(i)}initComponent(){}}const D={json:{encode:t=>JSON.stringify(t),decode:t=>JSON.parse(t)},yaml:{encode:i=>t.dump(i),decode:i=>t.load(i)}},N=t=>D[t.toLowerCase()],F={encoding:"utf8"};class A{constructor(t,i={}){t instanceof A&&(t=t.path()),this.state={path:t,options:{...F,...i}},C(this,i.debug,i.debugPrefix||"Path",i.debugColor)}path(){return this.state.path}relativePath(...t){return s.join(this.state.path,...t)}options(t={}){return{...this.state.options,...t}}async exists(){try{return await this.stat(),!0}catch(t){return"ENOENT"!==t.code&&x(t)}}async stat(){const t=await e(this.state.path);return this.state.stats=t}unstat(){return this.state.stats=void 0,this}}class L extends A{directory(t){return J(s.dirname(this.state.path),t)}dir(...t){return this.directory(...t)}read(t){const i=this.options(t),s=r(this.state.path,i);return i.codec?s.then((t=>N(i.codec).decode(t))):s}write(t,i){const s=this.options(i),e=s.codec?N(s.codec).encode(t):t;return n(this.state.path,e,s).then((()=>this))}async delete(t){return await o(this.state.path,t),this}}const O=(t,i)=>new L(t,i);class W extends A{file(t,i){return this.debug("file(%s, %o)",t,i),O(this.relativePath(t),this.options(i))}directory(t,i){return this.debug("directory(%s, %o)",t,i),J(this.relativePath(t),this.options(i))}dir(t,i){return this.debug("dir(%s, %o)",t,i),this.directory(t,i)}parent(t){return this.debug("parent()"),this.directory("..",t)}async read(){return this.debug("read()"),await a(this.path())}async isEmpty(){this.debug("isEmpty()");return 0===(await this.read()).length}async notEmpty(){this.debug("notEmpty()");return!await this.isEmpty()}async empty(t={}){return this.debug("empty(%o)",t),await this.exists()&&await this.notEmpty()&&await o(this.path(),t),this}async mkdir(t={}){this.debug("mkdir(%o)",t);return await this.exists()||await c(this.path(),t),this}async rmdir(t={}){return this.debug("rmdir(%o)",t),t.empty&&await this.empty(t),await this.exists()&&await h(this.path()),this}create(t={recursive:!0}){return this.debug("create(%o)",t),this.mkdir(t)}destroy(t={empty:!0,recursive:!0,force:!0}){return this.debug("destroy(%o)",t),this.rmdir(t)}async mustExist(t={}){return this.debug("mustExist(%o)",t),await this.exists()?this:t.mkdir?this.mkdir(t):t.create?this.create():void w("Directory does not exist: ",this.path())}}const J=(t,i)=>new W(t,i),M=t=>J(i.cwd(),t),S=(t,i)=>J(s.dirname(t.replace(/^file:\/\//,"")),i);function _(t){return y(t)?[]:u(t)?t.length?t.split(/,\s*|\s+/):[]:d(t)?t:[t]}function q(t,i=" ",s=i){let e=[...t];const r=e.pop();return e.length?[e.join(i),r].join(s):r}function T(t,i=", ",s=" and "){return q(t,i,s)}function U(t,i=", ",s=" or "){return q(t,i,s)}function z(t){return t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()}function B(t){return t.split("/").map((t=>t.split("_").map(z).join(""))).join("/")}function G(t){return t.split("/").map((t=>t.split("_").map(((t,i)=>i?z(t):t)).join(""))).join("/")}const H={codecs:"yaml json",jsExt:"js mjs"};class I{constructor(t,i={}){const s={...H,...i};this.state={dir:J(t),codecs:_(s.codecs),jsExt:_(s.jsExt)},C(this,i.debug,i.debugPrefix,i.debugColor),this.debug("root dir: ",this.state.dir.path()),this.debug("codecs: ",this.state.codecs)}async firstFileWithExt(t,i,s=j){for(let e of i){const i=t+"."+e,r=this.state.dir.file(i,s(t,e));if(this.debug("looking for config file: ",r.path()),await r.exists())return this.debug("config file exists: ",r.path()),r}}async jsFile(t){return await this.firstFileWithExt(t,this.state.jsExt)}async file(t){return await this.firstFileWithExt(t,this.state.codecs,((t,i)=>({codec:i})))}async config(t,i){const s=await this.jsFile(t);if(s){return(await import(s.path())).default}const e=await this.file(t);return e?await e.read():i||w("No configuration file for "+t)}}const K=(t,i)=>new I(t,i);function Q(t={},i){const s=t[i];if(b(s))return s;w("Missing value for required parameter: ",i)}function R(t={},i){return _(i).map((i=>Q(t,i)))}const V=R;function X(t,i){let s=!1;const e=_(i),r=e.map((i=>{const e=t[i];return b(e)&&(s=!0),e}));return s?r:w("Missing value for one of: ",U(e))}const Y={dir:["lib","library","src","components"],ext:["js","mjs"]};class Z{constructor(t={}){const i=J(Q(t,"root")),s=t.directory||t.dir||t.dirs||Y.dir,e=t.extension||t.ext||t.exts||Y.ext,r=_(s).map((t=>i.dir(t))),n=_(e).map((t=>t.replace(/^\./,"")));this.state={dirs:r,exts:n},C(this,t.debug,t.debugPrefix,t.debugColor)}async dirs(){return this.state.dirsExist||(this.state.dirsExist=await this.dirsExist())}async dirsExist(){const t=this.state.dirs,i=await Promise.all(t.map((t=>t.exists())));return t.filter(((t,s)=>i[s]))}async lib(t){const i=await this.dirs(),s=this.state.exts;for(let e of i)for(let i of s){const s=e.file(t+"."+i);this.debug("looking for module %s as",t,s.path());if(await s.exists()){const t=await import(s.path());return this.debug("loaded %s as",s.path()),t}}w("Library not found: ",t)}}const $=t=>new Z(t),tt={},it={dir:"config"};class st{constructor(t={}){const i=J(Q(t,"dir")),s=i.dir(t.config?.dir||it.dir),e={...it,...t.config||{}},r=new I(s,e),n={...tt,...t.library||{},root:i},o=new Z(n);this.state={rootDir:i,config:r,library:o},C(this,t.debug,t.debugPrefix,t.debugColor),this.debug("root dir: ",i.path()),this.debug("config dir: ",s.path())}dir(t,i){return this.debug("dir(%s, %o)",t,i),b(t)?this.state.rootDir.dir(t,i):this.state.rootDir}file(t,i){return this.debug("file(%s, %o)",t,i),this.state.rootDir.file(t,i)}read(t,i){return this.debug("read(%s, %o)",t,i),this.file(t,i).read()}write(t,i,s){return this.debug("write(%s, %o, %o)",t,i,s),this.file(t,s).write(i)}configDir(t,i){return this.debug("configDir(%s, %o)",t,i),b(t)?this.state.configDir(t,i):this.state.configDir}async config(t,i){return this.debug("config(%s, %o)",t,i),b(t)?this.state.config.config(t,i):this.state.config}async lib(t){return this.state.library.lib(t)}async component(t,i){const s=await this.config(t,{}),e=await this.lib(s.component?.library||t),r=s.component?.export||"default";return new(e[r]||w("No '",r,"' export from component library: ",t))(this,{...s,...i})}}const et=t=>new st(t);export{P as Component,I as Config,Z as Library,A as Path,st as Workspace,V as allParams,X as anyParams,S as bin,z as capitalise,N as codec,D as codecs,K as config,M as cwd,J as dir,j as doNothing,w as fail,O as file,b as hasValue,m as haveValue,d as isArray,f as isFunction,g as isNull,p as isObject,u as isString,l as isUndefined,q as joinList,T as joinListAnd,U as joinListOr,$ as library,y as noValue,Q as requiredParam,R as requiredParams,x as rethrow,G as snakeToCamel,B as snakeToStudly,_ as splitList,et as workspace};
|
|
2
2
|
//# sourceMappingURL=badger.esm.js.map
|
package/dist/badger.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badger.esm.js","sources":["../src/Badger/Utils/Misc.js","../src/Badger/Utils/Color.js","../src/Badger/Utils/Debug.js","../src/Badger/Component.js","../src/Badger/Codecs/Json.js","../src/Badger/Codecs/index.js","../src/Badger/Codecs/Yaml.js","../src/Badger/Filesystem/Path.js","../src/Badger/Filesystem/File.js","../src/Badger/Filesystem/Directory.js","../src/Badger/Utils/Text.js","../src/Badger/Utils/Params.js","../src/Badger/Config.js","../src/Badger/Library.js","../src/Badger/Workspace.js"],"sourcesContent":["/**\n * Determines if a value is a string\n * @param {String} value - value to test\n * @return {Boolean} true if `value` is a string or false if not\n */\nexport function isString(value) {\n return typeof value === 'string';\n}\n\n/**\n * Determines if a value is an array\n * @param {Array} value - value to test\n * @return {Boolean} true if `value` is an Array or false if not\n */\nexport function isArray(value) {\n return Array.isArray(value);\n}\n\n/**\n * Determines if a value is a Function\n * @param {Function} value - value to test\n * @return {Boolean} true if `value` is a Function or false if not\n */\nexport function isFunction(value) {\n return typeof value === 'function'\n}\n\n/**\n * Determines if a value is an Object (but not an Array)\n * @param {Object} value - value to test\n * @return {Boolean} true if `value` is an Object or false if not\n */\nexport function isObject(value) {\n return typeof value === \"object\"\n && ! isArray(value)\n && ! isNull(value);\n}\n\n/**\n * Determines if a value is `undefined`\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `undefined` or false if not\n */\nexport function isUndefined(value) {\n return typeof value === 'undefined';\n}\n\n/**\n * Determines if a value is `null`\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `null` or false if not\n */\nexport function isNull(value) {\n return value === null;\n}\n\n/**\n * Determines if a value is defined and not null\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is not `undefined` or `null`\n */\nexport function hasValue(value) {\n return ! (isUndefined(value) || isNull(value));\n}\n\n/**\n * Determines if all values are defined and not null\n * @param {any[]} values - values to test\n * @return {Boolean} true if all values are not `undefined` or `null`\n */\nexport function haveValue(...values) {\n return values.every( value => hasValue(value) );\n}\n\n/**\n * Determines if a value is undefined or null\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `undefined` or `null`\n */\nexport function noValue(value) {\n return ! hasValue(value);\n}\n\n/**\n * Throws a new Error object\n * @param {String[]} message - error message string(s)\n * @throws {Error}\n */\nexport function fail(...message) {\n throw new Error(message.join(''));\n}\n\n/**\n * Re-throw an existing Error object\n * @param {Error} error - error object\n * @throws {Error}\n */\nexport function rethrow(error) {\n throw error;\n}\n\n/**\n * Do nothing. Nothing at all.\n */\nexport function doNothing() {\n // speak again Cordelia\n}","import { isObject } from \"./Misc.js\";\n\nexport const ANSIStart = '\\u001B[';\nexport const ANSIEnd = 'm';\nexport const ANSIColors = {\n reset: 0,\n bold: 1,\n bright: 1,\n dark: 2,\n black: 0,\n red: 1,\n green: 2,\n yellow: 3,\n blue: 4,\n magenta: 5,\n cyan: 6,\n grey: 7,\n white: 8,\n fg: 30,\n bg: 40,\n};\n\n/**\n * Returns an ANSI escape code for a color string. This can be a single color\n * name, e.g. `red`, `green`, etc., or a color prefixed with `bright` or `dark`,\n * e.g. `bright red`, `dark green`, etc. An optional section argument can be\n * set to `fg` (default) to set a foreground color or `bg` for a background color.\n * @param {String} color - color name with optional modifier prefix\n * @param {String} [base='fg'] - `fg` or `bg` to set foreground or background color respectively\n * @return {String} ANSI escape code string\n * @example\n * const str = escapeCode('red')\n * @example\n * const str = escapeCode('bright red')\n * @example\n * const str = escapeCode('bright red', 'bg')\n */\nexport const escapeCode = (color, base='fg') => {\n let codes = [ ];\n let pair = color.split(/ /, 2);\n const hue = pair.pop();\n const code = (base ? ANSIColors[base] : 0) + ANSIColors[hue];\n codes.push(code);\n if (pair.length) {\n const shade = pair.length ? pair.shift() : 'dark';\n codes.push(ANSIColors[shade])\n }\n return ANSIStart + codes.join(';') + ANSIEnd;\n}\n\n/**\n * Returns an ANSI escape code for a color string or combination of foreground and\n * background colors.\n * @param {String|Object} colors - either a simple color name or object contain foreground and background colors\n * @param {String} [colors.fg] - foreground color\n * @param {String} [colors.fg] - background color\n * @return {String} ANSI escape code string\n * @example\n * const str = escape('red')\n * @example\n * const str = escape('bright red')\n * @example\n * const str = escape({ fg: 'bright yellow', bg: 'blue' })\n */\nexport const escape = (colors={}) => {\n const col = isObject(colors) ? colors : { fg: colors };\n let escapes = [ ];\n if (col.bg) {\n escapes.push(escapeCode(col.bg, 'bg'));\n }\n if (col.fg) {\n escapes.push(escapeCode(col.fg, 'fg'));\n }\n return escapes.join('');\n}\n\nexport const reset = () => escapeCode('reset')\n\n","import { escape, reset } from './Color.js'\nimport { doNothing } from './Misc.js';\n\n/**\n * Returns a debugging function which is enabled by the first `enabled` argument.\n * If this is `false` then it returns a function which does nothing. If it is\n * true then it returns a function that forwards all arguments to `console.log`.\n * An optional `prefix` be be specified to prefix each debugging line. The\n * optional third argument `color` can be used to specify a color for the prefix.\n * @param {Boolean} enabled - is debugging enabled?\n * @param {String} [prefix] - optional prefix for debugging messages\n * @param {String|Object} [color] - a color name or object (see {@link Badger/Utils/Color})\n * @param {String} [color.fg] - foreground color\n * @param {String} [color.bg] - background color\n * @return {Function} a debugging function\n * @example\n * const debug = Debugger(true)\n * @example\n * const debug = Debugger(true, 'Debug > ')\n * @example\n * const debug = Debugger(true, 'Debug > ', 'blue')\n * @example\n * const debug = Debugger(true, 'Debug > ', { bg: 'blue', fg: 'bright yellow' })\n */\nexport function Debugger(enabled, prefix='', color) {\n return enabled\n ? prefix\n ? (format, ...args) =>\n console.log(\n '%s' + prefix + '%s' + format,\n color ? escape(color) : '',\n reset(),\n ...args,\n )\n : console.log.bind(console)\n : doNothing;\n}\n\n/**\n * Creates a debugging function via {@link Debugger} and attaches it to the object\n * passed as the first argument as the `debug` function.\n * @param {Object} obj - the object to receive the `debug` function\n * @param {Boolean} enabled - is debugging enabled?\n * @param {String} [prefix] - optional prefix for debugging messages\n * @param {String|Object} [color] - a color name or object (see {@link Badger/Utils/Color})\n * @param {String} [color.fg] - foreground color\n * @param {String} [color.bg] - background color\n * @example\n * const debug = addDebug(myObject, true)\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ')\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ', 'blue')\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ', { bg: 'blue', fg: 'bright yellow' })\n */\nexport function addDebug(obj, enabled, prefix='', color) {\n obj.debug = Debugger(enabled, prefix, color);\n}\n","import { addDebug } from \"./Utils/Debug.js\";\n\nexport class Component {\n constructor(workspace, props={}) {\n this.workspace = workspace;\n this.props = props;\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n this.initComponent(props);\n }\n initComponent() {\n // stub for subclasses\n }\n}\n\nexport default Component","/**\n * Function to encode JSON\n * @param {Object} data - The data to encode as JSON text\n * @return {String} a JSON encoded string\n * @example\n * encode({ message: 'Hello World' })\n */\nexport const encode = data => JSON.stringify(data);\n\n/**\n * Function to decode JSON\n * @param {String} text - The JSON text to decode\n * @return {Object|Array} the decoded object or array\n * @example\n * decode(\"{ message: 'Hello World' }\")\n */\nexport const decode = text => JSON.parse(text);\n\n/**\n * An object containing the JSON `encode` and `decode` functions\n */\nexport const codec = { encode, decode };\n\nexport default codec\n","import json from './Json.js'\nimport yaml from './Yaml.js'\n\n/**\n * Codecs provide a consistent encode()/decode() interface for serialising\n * and de-serialising data. This standard naming convention makes it possible\n * for the ../Filesystem/File.js module to support a \"codec\" option for\n * files. When this option is set the file.read() and file.write() methods\n * automatically handle the translation to and from the serialised format\n * using a codec object returned by the codec() function below. The codec\n * name can be specified in any case, e.g. \"Yaml\", \"YAML\", \"yaml\", \"YaML\",\n * etc., and it will be converted to lower case.\n */\n\n/**\n * Lookup table for codecs\n */\nexport const codecs = {\n json, yaml\n};\n\n/**\n * Function to fetch a codec\n * @param {string} name - The title of the code, in any case, e.g. \"yaml\", \"YAML\", \"Yaml\"\n */\nexport const codec = name => codecs[\n name.toLowerCase()\n];\n\nexport default codecs\n","// simple wrapper around JSON load/dump\nimport yaml from 'js-yaml';\n\n/**\n * Function to encode YAML\n * @param {Object} data - The data to encode as YAML text\n * @return {String} a YAML encoded string\n * @example\n * encode({ message: 'Hello World' })\n */\nexport const encode = data => yaml.dump(data);\n\n/**\n * Function to decode YAML\n * @param {String} text - The YAML text to decode\n * @return {Object|Array} the decoded object or array\n * @example\n * decode(\"message: Hello World\")\n */\nexport const decode = text => yaml.load(text);\n\n/**\n * An object containing the YAML `encode` and `decode` functions\n */\nexport const codec = { encode, decode };\n\nexport default codec\n","import path from 'node:path';\nimport { stat } from 'node:fs/promises'\nimport { rethrow } from '../Utils/Misc.js';\nimport { addDebug } from '../Utils/Debug.js';\n\nconst defaultOptions = {\n encoding: 'utf8'\n}\n\nexport class Path {\n constructor(path, options={}) {\n // allow path/file/directory to be constructed from an existing object\n if (path instanceof Path) {\n path = path.path();\n }\n this.state = { path, options: { ...defaultOptions, ...options } };\n addDebug(this, options.debug, options.debugPrefix || 'Path', options.debugColor);\n }\n path() {\n return this.state.path;\n }\n relativePath(...parts) {\n return path.join(this.state.path, ...parts);\n }\n options(options={}) {\n return { ...this.state.options, ...options };\n }\n async exists() {\n try {\n await this.stat();\n return true;\n }\n catch (error) {\n return error.code === 'ENOENT'\n ? false\n : rethrow(error);\n }\n }\n async stat() {\n const stats = await stat(this.state.path);\n return this.state.stats = stats;\n }\n unstat() {\n this.state.stats = undefined;\n console.log('XXX unstat: ', this.state.stats);\n return this;\n }\n}\n\nexport default Path\n","import path from 'node:path'\nimport Path from './Path.js'\nimport { dir } from './Directory.js'\nimport { codec } from '../Codecs/index.js'\nimport { readFile, writeFile, rm } from 'node:fs/promises'\n\nclass File extends Path {\n /**\n * Returns a new {@link Directory} object for the parent directory of the file\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object for the parent\n */\n directory(options) {\n return dir(path.dirname(this.state.path), options);\n }\n\n /**\n * An alias for the {@link directory} method for lazy people\n * @return {Object} the parent {@link Directory} object\n */\n dir(...args) {\n return this.directory(...args);\n }\n\n /**\n * Reads the file content. If a `codec` has been specified then the content is decoded.\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {String|Object} the file content\n * @example\n * const text = file('myfile.txt').read();\n * @example\n * const data = file('myfile.json', { codec: 'json' }).read();\n * @example\n * const data = file('myfile.json').read({ codec: 'json' });\n */\n read(options) {\n const opts = this.options(options);\n const file = readFile(this.state.path, opts);\n return opts.codec\n ? file.then(text => codec(opts.codec).decode(text))\n : file;\n }\n\n /**\n * Writes the file content. If a `codec` has been specified then the content will be encoded.\n * @param {String|Object} data - directory configuration options\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @example\n * file('myfile.txt').write('Hello World');\n * @example\n * file('myfile.json', { codec: 'json' }).write({ message: 'Hello World' });\n * @example\n * file('myfile.json').write({ message: 'Hello World' }, { codec: 'json' });\n */\n write(data, options) {\n const opts = this.options(options);\n const text = opts.codec\n ? codec(opts.codec).encode(data)\n : data;\n return writeFile(this.state.path, text, opts).then( () => this );\n }\n\n async delete(options) {\n await rm(this.state.path, options);\n return this;\n }\n}\n\n/**\n * Function to create a new {@link File} object for a file\n * @param {String} path - file path\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link File} object\n */\nexport const file = (path, options) => {\n return new File(path, options);\n}\n\nexport default File\n","import process from 'node:process';\nimport path from 'node:path';\nimport Path from './Path.js'\nimport { file } from './File.js'\nimport { fail } from '../Utils/Misc.js';\nimport { rm, mkdir, rmdir, readdir } from 'node:fs/promises'\n\nclass Directory extends Path {\n /**\n * Fetch a new {@link File} object for a file in the directory.\n * @param {string} path - file path\n * @param {Object} [options] - file configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link File} object\n */\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return file(this.relativePath(path), this.options(options));\n }\n\n /**\n * Fetch a new {@link Directory} object for a sub-directory in the directory.\n * @param {string} path - directory path\n * @param {Object} [options] - directory configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link Directory} object\n */\n directory(path, options) {\n this.debug(\"directory(%s, %o)\", path, options);\n return dir(this.relativePath(path), this.options(options));\n }\n\n /**\n * An alias for the {@link directory} method for lazy people\n * @return {Object} the {@link Directory} object\n */\n dir(path, options) {\n this.debug(\"dir(%s, %o)\", path, options);\n return this.directory(path, options);\n }\n\n /**\n * Returns a new {@link Directory} object for the parent directory\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object for the parent\n */\n parent(options) {\n this.debug(\"parent()\");\n return this.directory('..', options);\n }\n\n /**\n * Returns the names of the files and sub-directories in the directory\n * @return {Promise} fulfills with an array of the file and directory names\n */\n async read() {\n this.debug(\"read()\");\n return await readdir(this.path());\n }\n\n /**\n * Determines if the directory is empty.\n * @return {Promise} fulfills with a boolean value true (empty) or false (not empty).\n */\n async isEmpty() {\n this.debug(\"isEmpty()\");\n const entries = await this.read();\n return entries.length === 0;\n }\n\n /**\n * Determines if the directory is not empty.\n * @return {Promise} fulfills with a boolean value true (not empty) or false (empty).\n */\n async notEmpty() {\n this.debug(\"notEmpty()\");\n const empty = await this.isEmpty();\n return !empty;\n }\n\n /**\n * Empty the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.force] - force removal of files and directories\n * @param {Boolean} [options.recursive] - recursively empty and delete sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async empty(options={}) {\n this.debug(\"empty(%o)\", options);\n if (await this.exists() && await this.notEmpty()) {\n await rm(this.path(), options);\n }\n return this;\n }\n\n /**\n * Make the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.recursive] - create intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async mkdir(options={}) {\n this.debug(\"mkdir(%o)\", options);\n const exists = await this.exists();\n if (! exists) {\n await mkdir(this.path(), options);\n }\n return this;\n }\n\n /**\n * Remove the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.empty] - delete items in directory\n * @param {Boolean} [options.force] - force delete files and directories\n * @param {Boolean} [options.recursive] - recursively delete sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async rmdir(options={}) {\n this.debug(\"rmdir(%o)\", options);\n if (options.empty) {\n await this.empty(options);\n }\n if (await this.exists()) {\n await rmdir(this.path());\n }\n return this;\n }\n\n /**\n * Create the directory and any intermediate directories.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.recursive=true] - recursively create intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n create(options={ recursive: true }) {\n this.debug(\"create(%o)\", options);\n return this.mkdir(options);\n }\n\n /**\n * Empty and delete the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.empty=true] - empty directory of any files and sub-directories\n * @param {Boolean} [options.recursive=true] - recursively delete sub-directories\n * @param {Boolean} [options.force=true] - force deletion of files and sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n destroy(options={ empty: true, recursive: true, force: true }) {\n this.debug(\"destroy(%o)\", options);\n return this.rmdir(options);\n }\n\n /**\n * Assert that a directory exists and optionally create it\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.create] - create the directory and any intermediate directories if it doesn't exist - equivalent to adding `mkdir` and `recursive` options or calling {@link create}\n * @param {Boolean} [options.mkdir] - create the directory, add the `recursive` option to create intermediate directories - equivalent to calling {@link mkdir}\n * @param {Boolean} [options.recursive] - when used with `mkdir`, creates any intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async mustExist(options={}) {\n this.debug(\"mustExist(%o)\", options);\n if (await this.exists()) {\n return this;\n }\n if (options.mkdir) {\n return this.mkdir(options);\n }\n if (options.create) {\n return this.create();\n }\n fail(\"Directory does not exist: \", this.path());\n }\n}\n\n/**\n * Function to create a new {@link Directory} object\n * @param {string} path - directory path\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const dir = (path, options) => {\n return new Directory(path, options);\n}\n\n/**\n * Function to create a new {@link Directory} object for the current working directory\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const cwd = options => {\n return dir(process.cwd(), options);\n}\n\n/**\n * Function to create a new {@link Directory} object for the directory of a JS source file\n * @param {string} url - module url - from `import.meta.url`\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const bin = (url, options) => {\n return dir(\n path.dirname(url.replace(/^file:\\/\\//, '')),\n options\n );\n}\n\nexport default Directory\n","import { isString, isArray } from \"./Misc.js\";\n\n/**\n * Split a comma/whitespace delimited string into an Array\n * @param {String} [value] - string to split\n * @return {Array} array of split strings\n * @example\n * const strings = splitList('one two three')\n * @example\n * const strings = splitList('one,two,three')\n * @example\n * const strings = splitList('one, two, three')\n */\nexport function splitList(value) {\n return isString(value)\n ? value.split(/,\\s*|\\s+/)\n : isArray(value)\n ? value\n : [value];\n}\n\n/**\n * Join an Array into a single string\n * @param {Array} [array] - array to join\n * @param {String} [joint=' '] - delimiter to join strings\n * @param {String} [lastJoint=joint] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinList(['one', 'two', 'three']); // one two three\n * @example\n * joinList(['one', 'two', 'three'], ', '); // one, two, three\n * @example\n * joinList(['one', 'two', 'three'], ', ', ' and '); // one, two and three\n */\nexport function joinList(array, joint=' ', lastJoint=joint) {\n let copy = [...array];\n const last = copy.pop();\n return copy.length\n ? [copy.join(joint), last].join(lastJoint)\n : last;\n}\n\n/**\n * Join an Array into a single string using commas for delimiters and ` and ` for the final item\n * @param {Array} [array] - array to join\n * @param {String} [joint=', '] - delimiter to join strings\n * @param {String} [lastJoint=' and '] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinListAnd(['one', 'two', 'three']); // one, two and three\n */\nexport function joinListAnd(array, joint=', ', lastJoint=' and ') {\n return joinList(array, joint, lastJoint);\n}\n\n/**\n * Join an Array into a single string using commas for delimiters and ` or ` for the final item\n * @param {Array} [array] - array to join\n * @param {String} [joint=', '] - delimiter to join strings\n * @param {String} [lastJoint=' or '] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinListOr(['one', 'two', 'three']); // one, two or three\n */\nexport function joinListOr(array, joint=', ', lastJoint=' or ') {\n return joinList(array, joint, lastJoint);\n}\n\n/**\n * Capitalise a string by converting the first character to upper case and other characters to lower case\n * @param {String} [word] - word to capitalise\n * @return {String} capitalised string\n * @example\n * capitalise('badger'); // Badger\n * @example\n * capitalise('BADGER'); // Badger\n */\nexport function capitalise(word) {\n return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\n}\n\n/**\n * Convert a snake case string to studly caps\n * @param {String} [snake] - word to capitalise\n * @return {String} capitalised string\n * @example\n * snakeToStudly('happy_badger_dance'); // HappyBadgerDance\n * @example\n * snakeToStudly('happy_badger/dance'); // HappyBadger/Dance\n */\nexport function snakeToStudly(snake) {\n return snake.split('/').map(\n // each segment can be like foo_bar which we convert to FooBar\n segment => segment.split('_').map(capitalise).join('')\n ).join('/');\n}\n\n/**\n * Convert a snake case string to camel case\n * @param {String} [snake] - word to capitalise\n * @return {String} capitalised string\n * @example\n * snakeToCamel('happy_badger_dance'); // happyBadgerDance\n * @example\n * snakeToCamel('happy_badger/dance'); // happyBadger/dance\n */\nexport function snakeToCamel(snake) {\n return snake.split('/').map(\n // each segment can be like foo_bar which we convert to fooBar\n segment => segment.split('_').map((i, n) => n ? capitalise(i) : i).join('')\n ).join('/');\n}\n","import { hasValue, fail } from \"./Misc.js\";\nimport { joinListOr, splitList } from \"./Text.js\";\n\n/**\n * Assert that a parameter object contains an item with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {String} name - parameter that must be included\n * @return {any} the parameter value\n * @throws {Error} if the parameter is not defined or null\n * @example\n * const foo = requiredParam({ foo: 10 }, 'foo');\n */\nexport function requiredParam(params={}, name) {\n const value = params[name];\n if (hasValue(value)) {\n return value;\n }\n else {\n fail(\"Missing value for required parameter: \", name);\n }\n}\n\n/**\n * Assert that a parameter object contains all specified item with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {Array|String} names - parameters that must be included, as an Array or whitespace/comma delimited string (see {@link splitList})\n * @return {Array} the parameter values\n * @throws {Error} if any parameter is not defined or null\n * @example\n * const [foo, bar] = requiredParams({ foo: 10, bar: 20 }, 'foo bar');\n */\nexport function requiredParams(params={}, names) {\n return splitList(names).map( name => requiredParam(params, name) );\n}\n\n/**\n * An alias for {@link requiredParams} for people who don't like typing long names (and for symmetry with {@link anyParams}))\n */\nexport const allParams=requiredParams;\n\n/**\n * Assert that a parameter object contains any of the specified items with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {Array|String} names - parameters of which at least one must be included, as an Array or whitespace/comma delimited string (see {@link splitList})\n * @return {Array} the parameter values\n * @throws {Error} if any parameter is not defined or null\n * @example\n * const [foo, bar] = anyParams({ foo: 10, wiz: 99 }, 'foo bar');\n */\nexport function anyParams(params, names) {\n let found = false;\n const nlist = splitList(names);\n const values = nlist.map(\n name => {\n const value = params[name];\n if (hasValue(value)) {\n found = true;\n }\n return value;\n }\n );\n return found\n ? values\n : fail(\"Missing value for one of: \", joinListOr(nlist));\n}\n","import { dir } from './Filesystem/Directory.js'\nimport { allParams, anyParams } from './Utils/Params.js'\nimport { splitList } from './Utils/Text.js'\nimport { fail } from './Utils/Misc.js';\nimport { addDebug } from './Utils/Debug.js';\n\nconst defaults = {\n codecs: 'yaml json',\n};\n\nexport class Config {\n constructor(params={}) {\n const options = { ...defaults, ...params };\n const [rootDir] = allParams(options, 'dir');\n const [codec, codecs] = anyParams(options, 'codec codecs');\n\n this.state = {\n dir: dir(rootDir),\n codecs: splitList(codecs) || [codec],\n }\n\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\n this.debug('root dir: ', this.state.dir.path());\n this.debug('codecs: ', this.state.codecs);\n }\n async file(uri) {\n for (let codec of this.state.codecs) {\n const path = uri + '.' + codec;\n const file = this.state.dir.file(path, { codec });\n this.debug('looking for config file: ', file.path());\n if (await file.exists()) {\n this.debug('config file exists: ', file.path());\n return file;\n }\n }\n return undefined;\n }\n async config(uri, defaults) {\n const file = await this.file(uri);\n return file\n ? await file.read()\n : (defaults || fail(\"No configuration file for \" + uri))\n }\n}\n\nexport const config = options => new Config(options)\n\nexport default Config\n","import { dir as fsdir } from \"./Filesystem/Directory.js\";\nimport { requiredParam } from \"./Utils/Params.js\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { splitList } from \"./Utils/Text.js\";\nimport { fail } from \"./Utils/Misc.js\";\n\nconst defaults = {\n dir: ['lib','library','src','components'],\n ext: ['js', 'mjs'],\n}\n\nexport class Library {\n constructor(props={}) {\n const root = fsdir(requiredParam(props, 'root'));\n const dir = props.directory || props.dir || props.dirs || defaults.dir;\n const ext = props.extension || props.ext || props.exts || defaults.ext;\n const dirs = splitList(dir).map( dir => root.dir(dir) ); // resolve to root dir\n const exts = splitList(ext).map( ext => ext.replace(/^\\./, '') ); // remove leading '.'\n this.state = {\n dirs, exts\n }\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n }\n async dirs() {\n return this.state.dirsExist\n || ( this.state.dirsExist = await this.dirsExist() );\n }\n async dirsExist() {\n const dirs = this.state.dirs;\n const exists = await Promise.all(\n dirs.map( d => d.exists() )\n );\n return dirs.filter((value, index) => exists[index]);\n }\n async lib(uri) {\n const dirs = await this.dirs();\n const exts = this.state.exts;\n for (let dir of dirs) {\n for (let ext of exts) {\n const file = dir.file(uri + '.' + ext);\n this.debug('looking for module %s as', uri, file.path());\n const exists = await file.exists();\n if (exists) {\n const load = await import(file.path());\n this.debug('loaded %s as', file.path());\n return load;\n }\n }\n }\n fail(\"Library not found: \", uri);\n }\n}\n\nexport const library = props => new Library(props);\n\nexport default library;","import { dir } from \"./Filesystem/Directory.js\";\nimport { requiredParam } from \"./Utils/Params.js\";\nimport { fail, hasValue } from \"./Utils/Misc.js\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { Config } from \"./Config.js\";\nimport { Library } from \"./Library.js\";\n\nconst defaults = {\n library: {\n },\n config: {\n dir: 'config',\n }\n}\nexport class Workspace {\n constructor(props={}) {\n const rootDir = dir(requiredParam(props, 'dir'));\n const cfgDir = rootDir.dir(props.config?.dir || defaults.config.dir);\n const cfgOpts = { ...defaults.config, ...(props.config||{}), dir: cfgDir };\n const config = new Config(cfgOpts);\n const libOpts = { ...defaults.library, ...(props.library||{}), root: rootDir };\n const library = new Library(libOpts);\n\n this.state = {\n rootDir,\n config,\n library\n }\n\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n this.debug('root dir: ', rootDir.path());\n this.debug('config dir: ', cfgDir.path());\n }\n dir(path, options) {\n this.debug(\"dir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.rootDir.dir(path, options)\n : this.state.rootDir;\n }\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return this.state.rootDir.file(path, options)\n }\n read(path, options) {\n this.debug(\"read(%s, %o)\", path, options);\n return this.file(path, options).read();\n }\n write(path, data, options) {\n this.debug(\"write(%s, %o, %o)\", path, data, options);\n return this.file(path, options).write(data);\n }\n configDir(path, options) {\n this.debug(\"configDir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.configDir(path, options)\n : this.state.configDir;\n }\n async config(uri, defaults) {\n this.debug(\"config(%s, %o)\", uri, defaults);\n return hasValue(uri)\n ? this.state.config.config(uri, defaults)\n : this.state.config;\n }\n async lib(uri) {\n return this.state.library.lib(uri);\n }\n async component(uri, props) {\n const config = await this.config(uri, {});\n const lib = await this.lib(config.component?.library || uri);\n const exp = config.component?.export || 'default';\n const compcls = lib[exp] || fail(\"No '\", exp, \"' export from component library: \", uri);\n const comp = new compcls(this, { ...config, ...props });\n // this.debug(\"created component \", uri)\n return comp;\n }\n}\n\nexport const workspace = props => new Workspace(props);\n\nexport default Workspace;"],"names":["isString","value","isArray","Array","isFunction","isObject","isNull","isUndefined","hasValue","haveValue","values","every","noValue","fail","message","Error","join","rethrow","error","doNothing","ANSIColors","reset","bold","bright","dark","black","red","green","yellow","blue","magenta","cyan","grey","white","fg","bg","escapeCode","color","base","codes","pair","split","hue","pop","code","push","length","shade","shift","Debugger","enabled","prefix","format","args","console","log","colors","col","escapes","escape","bind","addDebug","obj","debug","Component","constructor","workspace","props","this","debugPrefix","debugColor","initComponent","codecs","json","encode","data","JSON","stringify","decode","text","parse","yaml","dump","load","codec","name","toLowerCase","defaultOptions","encoding","Path","path","options","state","relativePath","parts","async","stat","stats","unstat","undefined","File","directory","dir","dirname","read","opts","file","readFile","then","write","writeFile","rm","Directory","parent","readdir","isEmpty","exists","notEmpty","mkdir","empty","rmdir","create","recursive","destroy","force","cwd","process","bin","url","replace","splitList","joinList","array","joint","lastJoint","copy","last","joinListAnd","joinListOr","capitalise","word","charAt","toUpperCase","slice","snakeToStudly","snake","map","segment","snakeToCamel","i","n","requiredParam","params","requiredParams","names","allParams","anyParams","found","nlist","defaults","Config","rootDir","uri","config","ext","Library","root","fsdir","dirs","extension","exts","dirsExist","Promise","all","d","filter","index","import","library","Workspace","cfgDir","cfgOpts","libOpts","configDir","lib","component","exp","export"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"badger.esm.js","sources":["../src/Badger/Utils/Misc.js","../src/Badger/Utils/Color.js","../src/Badger/Utils/Debug.js","../src/Badger/Component.js","../src/Badger/Codecs/Json.js","../src/Badger/Codecs/index.js","../src/Badger/Codecs/Yaml.js","../src/Badger/Filesystem/Path.js","../src/Badger/Filesystem/File.js","../src/Badger/Filesystem/Directory.js","../src/Badger/Utils/Text.js","../src/Badger/Config.js","../src/Badger/Utils/Params.js","../src/Badger/Library.js","../src/Badger/Workspace.js"],"sourcesContent":["/**\n * Determines if a value is a string\n * @param {String} value - value to test\n * @return {Boolean} true if `value` is a string or false if not\n */\nexport function isString(value) {\n return typeof value === 'string';\n}\n\n/**\n * Determines if a value is an array\n * @param {Array} value - value to test\n * @return {Boolean} true if `value` is an Array or false if not\n */\nexport function isArray(value) {\n return Array.isArray(value);\n}\n\n/**\n * Determines if a value is a Function\n * @param {Function} value - value to test\n * @return {Boolean} true if `value` is a Function or false if not\n */\nexport function isFunction(value) {\n return typeof value === 'function'\n}\n\n/**\n * Determines if a value is an Object (but not an Array)\n * @param {Object} value - value to test\n * @return {Boolean} true if `value` is an Object or false if not\n */\nexport function isObject(value) {\n return typeof value === \"object\"\n && ! isArray(value)\n && ! isNull(value);\n}\n\n/**\n * Determines if a value is `undefined`\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `undefined` or false if not\n */\nexport function isUndefined(value) {\n return typeof value === 'undefined';\n}\n\n/**\n * Determines if a value is `null`\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `null` or false if not\n */\nexport function isNull(value) {\n return value === null;\n}\n\n/**\n * Determines if a value is defined and not null\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is not `undefined` or `null`\n */\nexport function hasValue(value) {\n return ! (isUndefined(value) || isNull(value));\n}\n\n/**\n * Determines if all values are defined and not null\n * @param {any[]} values - values to test\n * @return {Boolean} true if all values are not `undefined` or `null`\n */\nexport function haveValue(...values) {\n return values.every( value => hasValue(value) );\n}\n\n/**\n * Determines if a value is undefined or null\n * @param {any} value - value to test\n * @return {Boolean} true if `value` is `undefined` or `null`\n */\nexport function noValue(value) {\n return ! hasValue(value);\n}\n\n/**\n * Throws a new Error object\n * @param {String[]} message - error message string(s)\n * @throws {Error}\n */\nexport function fail(...message) {\n throw new Error(message.join(''));\n}\n\n/**\n * Re-throw an existing Error object\n * @param {Error} error - error object\n * @throws {Error}\n */\nexport function rethrow(error) {\n throw error;\n}\n\n/**\n * Do nothing. Nothing at all.\n */\nexport function doNothing() {\n // speak again Cordelia\n}","import { isObject } from \"./Misc.js\";\n\nexport const ANSIStart = '\\u001B[';\nexport const ANSIEnd = 'm';\nexport const ANSIColors = {\n reset: 0,\n bold: 1,\n bright: 1,\n dark: 2,\n black: 0,\n red: 1,\n green: 2,\n yellow: 3,\n blue: 4,\n magenta: 5,\n cyan: 6,\n grey: 7,\n white: 8,\n fg: 30,\n bg: 40,\n};\n\n/**\n * Returns an ANSI escape code for a color string. This can be a single color\n * name, e.g. `red`, `green`, etc., or a color prefixed with `bright` or `dark`,\n * e.g. `bright red`, `dark green`, etc. An optional section argument can be\n * set to `fg` (default) to set a foreground color or `bg` for a background color.\n * @param {String} color - color name with optional modifier prefix\n * @param {String} [base='fg'] - `fg` or `bg` to set foreground or background color respectively\n * @return {String} ANSI escape code string\n * @example\n * const str = escapeCode('red')\n * @example\n * const str = escapeCode('bright red')\n * @example\n * const str = escapeCode('bright red', 'bg')\n */\nexport const escapeCode = (color, base='fg') => {\n let codes = [ ];\n let pair = color.split(/ /, 2);\n const hue = pair.pop();\n const code = (base ? ANSIColors[base] : 0) + ANSIColors[hue];\n codes.push(code);\n if (pair.length) {\n const shade = pair.length ? pair.shift() : 'dark';\n codes.push(ANSIColors[shade])\n }\n return ANSIStart + codes.join(';') + ANSIEnd;\n}\n\n/**\n * Returns an ANSI escape code for a color string or combination of foreground and\n * background colors.\n * @param {String|Object} colors - either a simple color name or object contain foreground and background colors\n * @param {String} [colors.fg] - foreground color\n * @param {String} [colors.fg] - background color\n * @return {String} ANSI escape code string\n * @example\n * const str = escape('red')\n * @example\n * const str = escape('bright red')\n * @example\n * const str = escape({ fg: 'bright yellow', bg: 'blue' })\n */\nexport const escape = (colors={}) => {\n const col = isObject(colors) ? colors : { fg: colors };\n let escapes = [ ];\n if (col.bg) {\n escapes.push(escapeCode(col.bg, 'bg'));\n }\n if (col.fg) {\n escapes.push(escapeCode(col.fg, 'fg'));\n }\n return escapes.join('');\n}\n\nexport const reset = () => escapeCode('reset')\n\n","import { escape, reset } from './Color.js'\nimport { doNothing } from './Misc.js';\n\n/**\n * Returns a debugging function which is enabled by the first `enabled` argument.\n * If this is `false` then it returns a function which does nothing. If it is\n * true then it returns a function that forwards all arguments to `console.log`.\n * An optional `prefix` be be specified to prefix each debugging line. The\n * optional third argument `color` can be used to specify a color for the prefix.\n * @param {Boolean} enabled - is debugging enabled?\n * @param {String} [prefix] - optional prefix for debugging messages\n * @param {String|Object} [color] - a color name or object (see {@link Badger/Utils/Color})\n * @param {String} [color.fg] - foreground color\n * @param {String} [color.bg] - background color\n * @return {Function} a debugging function\n * @example\n * const debug = Debugger(true)\n * @example\n * const debug = Debugger(true, 'Debug > ')\n * @example\n * const debug = Debugger(true, 'Debug > ', 'blue')\n * @example\n * const debug = Debugger(true, 'Debug > ', { bg: 'blue', fg: 'bright yellow' })\n */\nexport function Debugger(enabled, prefix='', color) {\n return enabled\n ? prefix\n ? (format, ...args) =>\n console.log(\n '%s' + prefix + '%s' + format,\n color ? escape(color) : '',\n reset(),\n ...args,\n )\n : console.log.bind(console)\n : doNothing;\n}\n\n/**\n * Creates a debugging function via {@link Debugger} and attaches it to the object\n * passed as the first argument as the `debug` function.\n * @param {Object} obj - the object to receive the `debug` function\n * @param {Boolean} enabled - is debugging enabled?\n * @param {String} [prefix] - optional prefix for debugging messages\n * @param {String|Object} [color] - a color name or object (see {@link Badger/Utils/Color})\n * @param {String} [color.fg] - foreground color\n * @param {String} [color.bg] - background color\n * @example\n * const debug = addDebug(myObject, true)\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ')\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ', 'blue')\n * @example\n * const debug = addDebug(myObject, true, 'Debug > ', { bg: 'blue', fg: 'bright yellow' })\n */\nexport function addDebug(obj, enabled, prefix='', color) {\n obj.debug = Debugger(enabled, prefix, color);\n}\n","import { addDebug } from \"./Utils/Debug.js\";\n\nexport class Component {\n constructor(workspace, props={}) {\n this.workspace = workspace;\n this.props = props;\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n this.initComponent(props);\n }\n initComponent() {\n // stub for subclasses\n }\n}\n\nexport default Component","/**\n * Function to encode JSON\n * @param {Object} data - The data to encode as JSON text\n * @return {String} a JSON encoded string\n * @example\n * encode({ message: 'Hello World' })\n */\nexport const encode = data => JSON.stringify(data);\n\n/**\n * Function to decode JSON\n * @param {String} text - The JSON text to decode\n * @return {Object|Array} the decoded object or array\n * @example\n * decode(\"{ message: 'Hello World' }\")\n */\nexport const decode = text => JSON.parse(text);\n\n/**\n * An object containing the JSON `encode` and `decode` functions\n */\nexport const codec = { encode, decode };\n\nexport default codec\n","import json from './Json.js'\nimport yaml from './Yaml.js'\n\n/**\n * Codecs provide a consistent encode()/decode() interface for serialising\n * and de-serialising data. This standard naming convention makes it possible\n * for the ../Filesystem/File.js module to support a \"codec\" option for\n * files. When this option is set the file.read() and file.write() methods\n * automatically handle the translation to and from the serialised format\n * using a codec object returned by the codec() function below. The codec\n * name can be specified in any case, e.g. \"Yaml\", \"YAML\", \"yaml\", \"YaML\",\n * etc., and it will be converted to lower case.\n */\n\n/**\n * Lookup table for codecs\n */\nexport const codecs = {\n json, yaml\n};\n\n/**\n * Function to fetch a codec\n * @param {string} name - The title of the code, in any case, e.g. \"yaml\", \"YAML\", \"Yaml\"\n */\nexport const codec = name => codecs[\n name.toLowerCase()\n];\n\nexport default codecs\n","// simple wrapper around JSON load/dump\nimport yaml from 'js-yaml';\n\n/**\n * Function to encode YAML\n * @param {Object} data - The data to encode as YAML text\n * @return {String} a YAML encoded string\n * @example\n * encode({ message: 'Hello World' })\n */\nexport const encode = data => yaml.dump(data);\n\n/**\n * Function to decode YAML\n * @param {String} text - The YAML text to decode\n * @return {Object|Array} the decoded object or array\n * @example\n * decode(\"message: Hello World\")\n */\nexport const decode = text => yaml.load(text);\n\n/**\n * An object containing the YAML `encode` and `decode` functions\n */\nexport const codec = { encode, decode };\n\nexport default codec\n","import path from 'node:path';\nimport { stat } from 'node:fs/promises'\nimport { rethrow } from '../Utils/Misc.js';\nimport { addDebug } from '../Utils/Debug.js';\n\nconst defaultOptions = {\n encoding: 'utf8'\n}\n\n/**\n * The Path class implements a base class for the {@link File} and {@link Directory}\n * classes. It implements the common functionality for representing a filesystem path.\n */\nexport class Path {\n /**\n * Constructor for filesystem paths.\n * @param {string} path - file path\n * @param {Object} [options] - configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link Path} object\n */\n constructor(path, options={}) {\n // allow path/file/directory to be constructed from an existing object\n if (path instanceof Path) {\n path = path.path();\n }\n this.state = { path, options: { ...defaultOptions, ...options } };\n addDebug(this, options.debug, options.debugPrefix || 'Path', options.debugColor);\n }\n\n /**\n * Accessor method to return the filesystem path.\n * @return {String} the filesystem path\n */\n path() {\n return this.state.path;\n }\n\n /**\n * Create a path relative to the current path.\n * @param {String[]} parts - part(s) of the filesystem path\n * @return {String} the new path\n * @example\n * const p = new Path('/path/to/here')\n * const q = p.relativePath('there') // -> /path/to/here/there\n * const r = p.relativePath('and', 'there') // -> /path/to/here/and/there\n */\n relativePath(...parts) {\n return path.join(this.state.path, ...parts);\n }\n\n /**\n * Internal method to merge any options with the pre-defined options passed to the\n * constructor. Options passed as arguments will take precedence.\n * @param {Object} options - new options\n * @return {Object} the merged options\n * @example\n * const p = new Path('/path/to/here', { option1: 'hello' })\n * const q = p.options({ option2: 'world' }) // -> { option1: 'hello', options2: 'world' }\n */\n options(options={}) {\n return { ...this.state.options, ...options };\n }\n\n /**\n * Method to assert that the path exists.\n * @return {Promise} fulfills with `true` if the path exists or rejects if the path doesn't\n * @example\n * const p = new Path('/path/to/here')\n * p.exists()\n * .then( console.log('path exists') )\n * .catch( console.log('path does not exist') )\n */\n async exists() {\n try {\n await this.stat();\n return true;\n }\n catch (error) {\n return error.code === 'ENOENT'\n ? false\n : rethrow(error);\n }\n }\n\n /**\n * Method to fetch stats for the path. Uses the `stat` function from `node:fs/promises`.\n * Stats are cached internally (subject to change)\n * @return {Promise} fulfills with path stats returned from the `stat` function\n * @example\n * const p = new Path('/path/to/here')\n * p.stat()\n * .then( stats => console.log('path stats:', stats) )\n * .catch( console.log('path does not exist') )\n */\n async stat() {\n const stats = await stat(this.state.path);\n return this.state.stats = stats;\n }\n\n /**\n * Method to clear internal cache of path stats (subject to change)\n */\n unstat() {\n this.state.stats = undefined;\n return this;\n }\n}\n\nexport default Path\n","import path from 'node:path'\nimport Path from './Path.js'\nimport { dir } from './Directory.js'\nimport { codec } from '../Codecs/index.js'\nimport { readFile, writeFile, rm } from 'node:fs/promises'\n\n/**\n * The File class implements a wrapper around a filesystem\n * file.\n */\nclass File extends Path {\n /**\n * Returns a new {@link Directory} object for the parent directory of the file\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object for the parent\n */\n directory(options) {\n return dir(path.dirname(this.state.path), options);\n }\n\n /**\n * An alias for the {@link directory} method for lazy people\n * @return {Object} the parent {@link Directory} object\n */\n dir(...args) {\n return this.directory(...args);\n }\n\n /**\n * Reads the file content. If a `codec` has been specified then the content is decoded.\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {String|Object} the file content\n * @example\n * const text = file('myfile.txt').read();\n * @example\n * const data = file('myfile.json', { codec: 'json' }).read();\n * @example\n * const data = file('myfile.json').read({ codec: 'json' });\n */\n read(options) {\n const opts = this.options(options);\n const file = readFile(this.state.path, opts);\n return opts.codec\n ? file.then(text => codec(opts.codec).decode(text))\n : file;\n }\n\n /**\n * Writes the file content. If a `codec` has been specified then the content will be encoded.\n * @param {String|Object} data - directory configuration options\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @example\n * file('myfile.txt').write('Hello World');\n * @example\n * file('myfile.json', { codec: 'json' }).write({ message: 'Hello World' });\n * @example\n * file('myfile.json').write({ message: 'Hello World' }, { codec: 'json' });\n */\n write(data, options) {\n const opts = this.options(options);\n const text = opts.codec\n ? codec(opts.codec).encode(data)\n : data;\n return writeFile(this.state.path, text, opts).then( () => this );\n }\n\n async delete(options) {\n await rm(this.state.path, options);\n return this;\n }\n}\n\n/**\n * Function to create a new {@link File} object for a file\n * @param {String} path - file path\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link File} object\n */\nexport const file = (path, options) => {\n return new File(path, options);\n}\n\nexport default File\n","import process from 'node:process';\nimport path from 'node:path';\nimport Path from './Path.js'\nimport { file } from './File.js'\nimport { fail } from '../Utils/Misc.js';\nimport { rm, mkdir, rmdir, readdir } from 'node:fs/promises'\n\n/**\n * The Directory class implements a wrapper around a filesystem\n * directory.\n */\nclass Directory extends Path {\n /**\n * Fetch a new {@link File} object for a file in the directory.\n * @param {string} path - file path\n * @param {Object} [options] - file configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link File} object\n */\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return file(this.relativePath(path), this.options(options));\n }\n\n /**\n * Fetch a new {@link Directory} object for a sub-directory in the directory.\n * @param {string} path - directory path\n * @param {Object} [options] - directory configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} the {@link Directory} object\n */\n directory(path, options) {\n this.debug(\"directory(%s, %o)\", path, options);\n return dir(this.relativePath(path), this.options(options));\n }\n\n /**\n * An alias for the {@link directory} method for lazy people\n * @return {Object} the {@link Directory} object\n */\n dir(path, options) {\n this.debug(\"dir(%s, %o)\", path, options);\n return this.directory(path, options);\n }\n\n /**\n * Returns a new {@link Directory} object for the parent directory\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object for the parent\n */\n parent(options) {\n this.debug(\"parent()\");\n return this.directory('..', options);\n }\n\n /**\n * Returns the names of the files and sub-directories in the directory\n * @return {Promise} fulfills with an array of the file and directory names\n */\n async read() {\n this.debug(\"read()\");\n return await readdir(this.path());\n }\n\n /**\n * Determines if the directory is empty.\n * @return {Promise} fulfills with a boolean value true (empty) or false (not empty).\n */\n async isEmpty() {\n this.debug(\"isEmpty()\");\n const entries = await this.read();\n return entries.length === 0;\n }\n\n /**\n * Determines if the directory is not empty.\n * @return {Promise} fulfills with a boolean value true (not empty) or false (empty).\n */\n async notEmpty() {\n this.debug(\"notEmpty()\");\n const empty = await this.isEmpty();\n return !empty;\n }\n\n /**\n * Empty the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.force] - force removal of files and directories\n * @param {Boolean} [options.recursive] - recursively empty and delete sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async empty(options={}) {\n this.debug(\"empty(%o)\", options);\n if (await this.exists() && await this.notEmpty()) {\n await rm(this.path(), options);\n }\n return this;\n }\n\n /**\n * Make the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.recursive] - create intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async mkdir(options={}) {\n this.debug(\"mkdir(%o)\", options);\n const exists = await this.exists();\n if (! exists) {\n await mkdir(this.path(), options);\n }\n return this;\n }\n\n /**\n * Remove the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.empty] - delete items in directory\n * @param {Boolean} [options.force] - force delete files and directories\n * @param {Boolean} [options.recursive] - recursively delete sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async rmdir(options={}) {\n this.debug(\"rmdir(%o)\", options);\n if (options.empty) {\n await this.empty(options);\n }\n if (await this.exists()) {\n await rmdir(this.path());\n }\n return this;\n }\n\n /**\n * Create the directory and any intermediate directories.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.recursive=true] - recursively create intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n create(options={ recursive: true }) {\n this.debug(\"create(%o)\", options);\n return this.mkdir(options);\n }\n\n /**\n * Empty and delete the directory.\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.empty=true] - empty directory of any files and sub-directories\n * @param {Boolean} [options.recursive=true] - recursively delete sub-directories\n * @param {Boolean} [options.force=true] - force deletion of files and sub-directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n destroy(options={ empty: true, recursive: true, force: true }) {\n this.debug(\"destroy(%o)\", options);\n return this.rmdir(options);\n }\n\n /**\n * Assert that a directory exists and optionally create it\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.create] - create the directory and any intermediate directories if it doesn't exist - equivalent to adding `mkdir` and `recursive` options or calling {@link create}\n * @param {Boolean} [options.mkdir] - create the directory, add the `recursive` option to create intermediate directories - equivalent to calling {@link mkdir}\n * @param {Boolean} [options.recursive] - when used with `mkdir`, creates any intermediate directories\n * @return {Promise} fulfills to the {@link Directory} object\n */\n async mustExist(options={}) {\n this.debug(\"mustExist(%o)\", options);\n if (await this.exists()) {\n return this;\n }\n if (options.mkdir) {\n return this.mkdir(options);\n }\n if (options.create) {\n return this.create();\n }\n fail(\"Directory does not exist: \", this.path());\n }\n}\n\n/**\n * Function to create a new {@link Directory} object\n * @param {string} path - directory path\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const dir = (path, options) => {\n return new Directory(path, options);\n}\n\n/**\n * Function to create a new {@link Directory} object for the current working directory\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const cwd = options => {\n return dir(process.cwd(), options);\n}\n\n/**\n * Function to create a new {@link Directory} object for the directory of a JS source file\n * @param {string} url - module url - from `import.meta.url`\n * @param {Object} [options] - configuration options\n * @param {Boolean} [options.codec] - a codec for encoding/decoding files\n * @return {Object} the {@link Directory} object\n */\nexport const bin = (url, options) => {\n return dir(\n path.dirname(url.replace(/^file:\\/\\//, '')),\n options\n );\n}\n\nexport default Directory\n","import { isString, isArray, noValue } from \"./Misc.js\";\n\n/**\n * Split a comma/whitespace delimited string into an Array\n * @param {String} [value] - string to split\n * @return {Array} array of split strings\n * @example\n * const strings = splitList('one two three')\n * @example\n * const strings = splitList('one,two,three')\n * @example\n * const strings = splitList('one, two, three')\n */\nexport function splitList(value) {\n if (noValue(value)) {\n return [ ];\n }\n else if (isString(value)) {\n return value.length\n ? value.split(/,\\s*|\\s+/)\n : [ ]\n }\n else if (isArray(value)) {\n return value;\n }\n return [value];\n}\n\n/**\n * Join an Array into a single string\n * @param {Array} [array] - array to join\n * @param {String} [joint=' '] - delimiter to join strings\n * @param {String} [lastJoint=joint] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinList(['one', 'two', 'three']); // one two three\n * @example\n * joinList(['one', 'two', 'three'], ', '); // one, two, three\n * @example\n * joinList(['one', 'two', 'three'], ', ', ' and '); // one, two and three\n */\nexport function joinList(array, joint=' ', lastJoint=joint) {\n let copy = [...array];\n const last = copy.pop();\n return copy.length\n ? [copy.join(joint), last].join(lastJoint)\n : last;\n}\n\n/**\n * Join an Array into a single string using commas for delimiters and ` and ` for the final item\n * @param {Array} [array] - array to join\n * @param {String} [joint=', '] - delimiter to join strings\n * @param {String} [lastJoint=' and '] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinListAnd(['one', 'two', 'three']); // one, two and three\n */\nexport function joinListAnd(array, joint=', ', lastJoint=' and ') {\n return joinList(array, joint, lastJoint);\n}\n\n/**\n * Join an Array into a single string using commas for delimiters and ` or ` for the final item\n * @param {Array} [array] - array to join\n * @param {String} [joint=', '] - delimiter to join strings\n * @param {String} [lastJoint=' or '] - delimiter for final item\n * @return {String} joined string\n * @example\n * joinListOr(['one', 'two', 'three']); // one, two or three\n */\nexport function joinListOr(array, joint=', ', lastJoint=' or ') {\n return joinList(array, joint, lastJoint);\n}\n\n/**\n * Capitalise a string by converting the first character to upper case and other characters to lower case\n * @param {String} [word] - word to capitalise\n * @return {String} capitalised string\n * @example\n * capitalise('badger'); // Badger\n * @example\n * capitalise('BADGER'); // Badger\n */\nexport function capitalise(word) {\n return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\n}\n\n/**\n * Convert a snake case string to studly caps\n * @param {String} [snake] - word to capitalise\n * @return {String} capitalised string\n * @example\n * snakeToStudly('happy_badger_dance'); // HappyBadgerDance\n * @example\n * snakeToStudly('happy_badger/dance'); // HappyBadger/Dance\n */\nexport function snakeToStudly(snake) {\n return snake.split('/').map(\n // each segment can be like foo_bar which we convert to FooBar\n segment => segment.split('_').map(capitalise).join('')\n ).join('/');\n}\n\n/**\n * Convert a snake case string to camel case\n * @param {String} [snake] - word to capitalise\n * @return {String} capitalised string\n * @example\n * snakeToCamel('happy_badger_dance'); // happyBadgerDance\n * @example\n * snakeToCamel('happy_badger/dance'); // happyBadger/dance\n */\nexport function snakeToCamel(snake) {\n return snake.split('/').map(\n // each segment can be like foo_bar which we convert to fooBar\n segment => segment.split('_').map((i, n) => n ? capitalise(i) : i).join('')\n ).join('/');\n}\n","import { dir as fsDir } from './Filesystem/Directory.js'\nimport { splitList } from './Utils/Text.js'\nimport { doNothing, fail } from './Utils/Misc.js';\nimport { addDebug } from './Utils/Debug.js';\n\nconst defaults = {\n codecs: 'yaml json',\n jsExt: 'js mjs',\n};\n\n/**\n * The Config class implements an object which can load configuration\n * files from a configuration directory. Files can be Javascript files\n * (with `.js` or `.mjs` extensions by default) or data files using any\n * of the standard codecs (`.yaml` or `.json` by default).\n */\nexport class Config {\n /**\n * Constructor for Config object.\n * @param {String} dir - directory containing configuration files\n * @param {Object} [options] - configuration options\n * @param {Array|String} [options.jsExt='js mjs'] - Array or comma/whitespace delimited string of Javascript file extensions\n * @param {Array|String} [options.codecs='yaml json'] - Array or comma/whitespace delimited string of codec names\n * @return {Object} the {@link Config} object\n */\n constructor(dir, options={}) {\n const params = { ...defaults, ...options };\n this.state = {\n dir: fsDir(dir),\n codecs: splitList(params.codecs),\n jsExt: splitList(params.jsExt),\n }\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\n this.debug('root dir: ', this.state.dir.path());\n this.debug('codecs: ', this.state.codecs);\n }\n\n /**\n * Internal method to locate the first config file with one of a number of file extensions.\n * @param {String} uri - base part of filename\n * @param {Array} [exts] - array of possible extensions\n * @param {Function} [makeOptions] - optional function to generate options for a {@link File} object\n * @return {Object} the {@link File} object if it exists or `undefined` if not\n */\n async firstFileWithExt(uri, exts, makeOptions=doNothing) {\n for (let ext of exts) {\n const path = uri + '.' + ext;\n const file = this.state.dir.file(path, makeOptions(uri, ext));\n this.debug('looking for config file: ', file.path());\n if (await file.exists()) {\n this.debug('config file exists: ', file.path());\n return file;\n }\n }\n return undefined;\n }\n\n /**\n * Internal method to locate a Javascript configuration file with one of the `jsExt` extensions (`.js` or `.mjs` by default)\n * @param {String} uri - base part of filename\n * @return {Object} the {@link File} object if it exists or `undefined` if not\n */\n async jsFile(uri) {\n return await this.firstFileWithExt(uri, this.state.jsExt);\n }\n\n /**\n * Internal method to locate a configuration file with one of the `codecs` extensions (`.yaml` or `.json` by default)\n * @param {String} uri - base part of filename\n * @return {Object} the {@link File} object if it exists or `undefined` if not\n */\n async file(uri) {\n return await this.firstFileWithExt(uri, this.state.codecs, (uri, codec) => ({ codec }));\n }\n\n /**\n * Method to fetch configuration data from a file. The file can be a Javascript file which should\n * return the configuration data as the default export, or a YAML (`.yaml`) or JSON (`.json`) file.\n * If the file isn't found then the method returns the `defaults` data if provided, or throws an\n * error if not.\n * @param {String} uri - base part of filename\n * @param {Object} [defaults] - default configuration options to be used if a file isn't found\n * @return {Object} the configuration data loaded from the file\n */\n async config(uri, defaults) {\n // first look for a JS file, e.g. <uri>.js, <uri>.mjs\n const jsFile = await this.jsFile(uri);\n if (jsFile) {\n const load = await import(jsFile.path());\n return load.default;\n }\n // then for a config file with a codec extension, e.g. <uri>.yaml, <uri>.yaml\n const file = await this.file(uri);\n if (file) {\n return await file.read();\n }\n return defaults || fail(\"No configuration file for \" + uri);\n }\n}\n\n/**\n * Function to create a new {@link Config} object for a file\n * @param {String} dir - directory containing configuration files\n * @param {Object} [options] - configuration options\n * @param {Array|String} [options.jsExt='js mjs'] - Array or comma/whitespace delimited string of Javascript file extensions\n * @param {Array|String} [options.codecs='yaml json'] - Array or comma/whitespace delimited string of codec names\n * @return {Object} the {@link Config} object\n */\nexport const config = (dir, options) => new Config(dir, options)\n\nexport default Config\n","import { hasValue, fail } from \"./Misc.js\";\nimport { joinListOr, splitList } from \"./Text.js\";\n\n/**\n * Assert that a parameter object contains an item with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {String} name - parameter that must be included\n * @return {any} the parameter value\n * @throws {Error} if the parameter is not defined or null\n * @example\n * const foo = requiredParam({ foo: 10 }, 'foo');\n */\nexport function requiredParam(params={}, name) {\n const value = params[name];\n if (hasValue(value)) {\n return value;\n }\n else {\n fail(\"Missing value for required parameter: \", name);\n }\n}\n\n/**\n * Assert that a parameter object contains all specified item with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {Array|String} names - parameters that must be included, as an Array or whitespace/comma delimited string (see {@link splitList})\n * @return {Array} the parameter values\n * @throws {Error} if any parameter is not defined or null\n * @example\n * const [foo, bar] = requiredParams({ foo: 10, bar: 20 }, 'foo bar');\n */\nexport function requiredParams(params={}, names) {\n return splitList(names).map( name => requiredParam(params, name) );\n}\n\n/**\n * An alias for {@link requiredParams} for people who don't like typing long names (and for symmetry with {@link anyParams}))\n */\nexport const allParams=requiredParams;\n\n/**\n * Assert that a parameter object contains any of the specified items with a defined/non-null value\n * @param {Object} params={} - parameters object\n * @param {Array|String} names - parameters of which at least one must be included, as an Array or whitespace/comma delimited string (see {@link splitList})\n * @return {Array} the parameter values\n * @throws {Error} if any parameter is not defined or null\n * @example\n * const [foo, bar] = anyParams({ foo: 10, wiz: 99 }, 'foo bar');\n */\nexport function anyParams(params, names) {\n let found = false;\n const nlist = splitList(names);\n const values = nlist.map(\n name => {\n const value = params[name];\n if (hasValue(value)) {\n found = true;\n }\n return value;\n }\n );\n return found\n ? values\n : fail(\"Missing value for one of: \", joinListOr(nlist));\n}\n","import { dir as fsdir } from \"./Filesystem/Directory.js\";\nimport { requiredParam } from \"./Utils/Params.js\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { splitList } from \"./Utils/Text.js\";\nimport { fail } from \"./Utils/Misc.js\";\n\nconst defaults = {\n dir: ['lib','library','src','components'],\n ext: ['js', 'mjs'],\n}\n\nexport class Library {\n constructor(props={}) {\n const root = fsdir(requiredParam(props, 'root'));\n const dir = props.directory || props.dir || props.dirs || defaults.dir;\n const ext = props.extension || props.ext || props.exts || defaults.ext;\n const dirs = splitList(dir).map( dir => root.dir(dir) ); // resolve to root dir\n const exts = splitList(ext).map( ext => ext.replace(/^\\./, '') ); // remove leading '.'\n this.state = {\n dirs, exts\n }\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n }\n async dirs() {\n return this.state.dirsExist\n || ( this.state.dirsExist = await this.dirsExist() );\n }\n async dirsExist() {\n const dirs = this.state.dirs;\n const exists = await Promise.all(\n dirs.map( d => d.exists() )\n );\n return dirs.filter((value, index) => exists[index]);\n }\n async lib(uri) {\n const dirs = await this.dirs();\n const exts = this.state.exts;\n for (let dir of dirs) {\n for (let ext of exts) {\n const file = dir.file(uri + '.' + ext);\n this.debug('looking for module %s as', uri, file.path());\n const exists = await file.exists();\n if (exists) {\n const load = await import(file.path());\n this.debug('loaded %s as', file.path());\n return load;\n }\n }\n }\n fail(\"Library not found: \", uri);\n }\n}\n\nexport const library = props => new Library(props);\n\nexport default library;","import { dir } from \"./Filesystem/Directory.js\";\nimport { requiredParam } from \"./Utils/Params.js\";\nimport { fail, hasValue } from \"./Utils/Misc.js\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { Config } from \"./Config.js\";\nimport { Library } from \"./Library.js\";\n\nconst defaults = {\n library: {\n },\n config: {\n dir: 'config',\n }\n}\nexport class Workspace {\n constructor(props={}) {\n const rootDir = dir(requiredParam(props, 'dir'));\n const cfgDir = rootDir.dir(props.config?.dir || defaults.config.dir);\n const cfgOpts = { ...defaults.config, ...(props.config||{}) };\n const config = new Config(cfgDir, cfgOpts);\n const libOpts = { ...defaults.library, ...(props.library||{}), root: rootDir };\n const library = new Library(libOpts);\n\n this.state = {\n rootDir,\n config,\n library\n }\n\n addDebug(this, props.debug, props.debugPrefix, props.debugColor);\n this.debug('root dir: ', rootDir.path());\n this.debug('config dir: ', cfgDir.path());\n }\n dir(path, options) {\n this.debug(\"dir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.rootDir.dir(path, options)\n : this.state.rootDir;\n }\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return this.state.rootDir.file(path, options)\n }\n read(path, options) {\n this.debug(\"read(%s, %o)\", path, options);\n return this.file(path, options).read();\n }\n write(path, data, options) {\n this.debug(\"write(%s, %o, %o)\", path, data, options);\n return this.file(path, options).write(data);\n }\n configDir(path, options) {\n this.debug(\"configDir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.configDir(path, options)\n : this.state.configDir;\n }\n async config(uri, defaults) {\n this.debug(\"config(%s, %o)\", uri, defaults);\n return hasValue(uri)\n ? this.state.config.config(uri, defaults)\n : this.state.config;\n }\n async lib(uri) {\n return this.state.library.lib(uri);\n }\n async component(uri, props) {\n const config = await this.config(uri, {});\n const lib = await this.lib(config.component?.library || uri);\n const exp = config.component?.export || 'default';\n const compcls = lib[exp] || fail(\"No '\", exp, \"' export from component library: \", uri);\n const comp = new compcls(this, { ...config, ...props });\n // this.debug(\"created component \", uri)\n return comp;\n }\n}\n\nexport const workspace = props => new Workspace(props);\n\nexport default Workspace;"],"names":["isString","value","isArray","Array","isFunction","isObject","isNull","isUndefined","hasValue","haveValue","values","every","noValue","fail","message","Error","join","rethrow","error","doNothing","ANSIColors","reset","bold","bright","dark","black","red","green","yellow","blue","magenta","cyan","grey","white","fg","bg","escapeCode","color","base","codes","pair","split","hue","pop","code","push","length","shade","shift","Debugger","enabled","prefix","format","args","console","log","colors","col","escapes","escape","bind","addDebug","obj","debug","Component","constructor","workspace","props","this","debugPrefix","debugColor","initComponent","codecs","json","encode","data","JSON","stringify","decode","text","parse","yaml","dump","load","codec","name","toLowerCase","defaultOptions","encoding","Path","path","options","state","relativePath","parts","async","stat","stats","unstat","undefined","File","directory","dir","dirname","read","opts","file","readFile","then","write","writeFile","rm","Directory","parent","readdir","isEmpty","exists","notEmpty","mkdir","empty","rmdir","create","recursive","destroy","force","cwd","process","bin","url","replace","splitList","joinList","array","joint","lastJoint","copy","last","joinListAnd","joinListOr","capitalise","word","charAt","toUpperCase","slice","snakeToStudly","snake","map","segment","snakeToCamel","i","n","defaults","jsExt","Config","params","fsDir","uri","exts","makeOptions","ext","firstFileWithExt","jsFile","import","default","config","requiredParam","requiredParams","names","allParams","anyParams","found","nlist","Library","root","fsdir","dirs","extension","dirsExist","Promise","all","d","filter","index","library","Workspace","rootDir","cfgDir","cfgOpts","libOpts","configDir","lib","component","exp","export"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abw/badger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Component based framework and utility modules",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/badger.cjs.js",
|
|
7
7
|
"module": "dist/badger.esm.js",
|
|
8
|
-
"exports": "./
|
|
8
|
+
"exports": "./dist/badger.esm.js",
|
|
9
9
|
"author": "Andy Wardley",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"files": [
|