@abw/badger 1.3.4 → 1.3.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"badger.esm.js","sources":["../src/Badger/Utils/Color.js","../src/Badger/Utils/Debug.js","../src/Badger/Component.js","../src/Badger/Utils/DataPath.js","../src/Badger/Config.js","../src/Badger/Library.js","../src/Badger/Utils/AppStatus.js","../src/Badger/Utils/Prompt.js","../src/Badger/Utils/CmdLine.js","../src/Badger/Utils/Dotenv.js","../src/Badger/Utils/Exit.js","../src/Badger/Utils/Misc.js","../src/Badger/Utils/Options.js","../src/Badger/Utils/Params.js","../src/Badger/Utils/Progress.js","../src/Badger/Utils/Setup.js","../src/Badger/Utils/Watch.js","../src/Badger/Workspace.js"],"sourcesContent":["import { isObject, splitList } from \"@abw/badger-utils\";\n\nconst ANSIStart = '\\u001B[';\nconst ANSIEnd = 'm';\nconst 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};\nconst ANSIRGB = {\n fg: rgb => `38;2;${rgb.r};${rgb.g};${rgb.b}`,\n bg: rgb => `48;2;${rgb.r};${rgb.g};${rgb.b}`,\n}\n\nconst isRGB = color => {\n const triple = splitList(color)\n return triple.length === 3\n ? { r: triple[0], g: triple[1], b: triple[2]}\n : null\n}\n\nconst isHex = color => {\n const match = color.match(/^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i)\n return match\n ? {\n r: parseInt(match[1], 16),\n g: parseInt(match[2], 16),\n b: parseInt(match[3], 16)\n }\n : null;\n}\n\nconst ANSIescapeCodes = (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\nconst ANSIRGBescapeCodes = (color, base='fg') =>\n ANSIStart + ANSIRGB[base](color) + ANSIEnd;\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 ANSIescapeCode = (color, base='fg') => {\n const rgb = isHex(color) || isRGB(color)\n return rgb\n ? ANSIRGBescapeCodes(rgb, base)\n : ANSIescapeCodes(color, base)\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 ANSIescape = (colors={}) => {\n const col = isObject(colors) ? colors : { fg: colors };\n let escapes = [ ];\n if (col.bg) {\n escapes.push(ANSIescapeCode(col.bg, 'bg'));\n }\n if (col.fg) {\n escapes.push(ANSIescapeCode(col.fg, 'fg'));\n }\n return escapes.join('');\n}\n\n/**\n * Returns an ANSI escape code to reset all colors.\n * @return {String} ANSI escape reset string\n */\nexport const ANSIresetCode = ANSIescapeCode('reset', false)\n\n\n/**\n * Returns an ANSI escape code to reset all colors.\n * @return {String} ANSI escape reset string\n */\nexport const ANSIreset = () => ANSIresetCode\n\n/**\n * Returns a function to display strings in a particular color.\n * @param {String} colors - color(s) to display string\n * @return {Function} function to display strings in the pre-defined color(s)\n */\nexport const color = (colors) =>\n (...text) => ANSIescape(colors) + text.join('') + ANSIresetCode;\n\n/**\n * Expand an object of color names into color functions.\n * @param {Object} palette - mapping arbitrary keys to color names\n * @return {Object} object mapping keys to color functions\n */\nexport const palette = palette =>\n Object.entries(palette).reduce(\n (palette, [key, value]) => {\n palette[key] = color(value)\n return palette\n },\n { }\n )\n\nexport const black = color('black');\nexport const red = color('red');\nexport const green = color('green');\nexport const yellow = color('yellow');\nexport const blue = color('blue');\nexport const magenta = color('magenta');\nexport const cyan = color('cyan');\nexport const grey = color('grey');\nexport const white = color('white');\nexport const brightBlack = color('bright black');\nexport const brightRed = color('bright red');\nexport const brightGreen = color('bright green');\nexport const brightYellow = color('bright yellow');\nexport const brightBlue = color('bright blue');\nexport const brightMagenta = color('bright magenta');\nexport const brightCyan = color('bright cyan');\nexport const brightGrey = color('bright grey');\nexport const brightWhite = color('bright white');\nexport const darkBlack = color('dark black');\nexport const darkRed = color('dark red');\nexport const darkGreen = color('dark green');\nexport const darkYellow = color('dark yellow');\nexport const darkBlue = color('dark blue');\nexport const darkMagenta = color('dark magenta');\nexport const darkCyan = color('dark cyan');\nexport const darkGrey = color('dark grey');\nexport const darkWhite = color('dark white');\n","import { ANSIescape, ANSIreset } from './Color.js'\nimport { doNothing } from '@abw/badger-utils';\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 ? ANSIescape(color) : '',\n ANSIreset(),\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","import { fail, isArray, noValue } from \"@abw/badger-utils\";\n\n/**\n * Characters that can be escaped in quoted strings.\n */\nconst quotedEscapes = {\n b: \"\\b\",\n f: \"\\f\",\n n: \"\\n\",\n r: \"\\r\",\n t: \"\\t\",\n v: \"\\v\",\n '\"': '\"',\n \"'\": \"'\",\n '\\\\': '\\\\',\n}\n\n/**\n * Match a double quoted string and expand escaped characters\n * @param {String} [string] - the string to match\n */\nexport const matchDoubleQuotedString = string => {\n const regex = /^\"((?:\\\\[\\\\\"bfnrtv]|.)*?)\"$/\n const match = string.match(regex);\n return match\n ? match[1].replace(/\\\\([\\\\\"bfnrtv])/g, (all, one) => quotedEscapes[one] || `\\\\${one}`)\n : null;\n}\n\n/**\n * Match a single quoted string and expand escaped characters\n * @param {String} [string] - the string to match\n */\nexport const matchSingleQuotedString = string => {\n const regex = /^'((?:\\\\[\\\\'bfnrtv]|.)*?)'$/\n const match = string.match(regex);\n return match\n ? match[1].replace(/\\\\([\\\\'bfnrtv])/g, (all, one) => quotedEscapes[one] || `\\\\${one}`)\n : null;\n}\n\n/**\n * Split a data path into component parts\n * @param {String} [path] - the path to split\n */\nexport const splitDataPath = path => {\n let parts = [ ];\n let part;\n let match;\n\n while (path.length) {\n let maybe;\n let optional;\n\n // match and ignore any slashes\n if ((match = path.match(/^(\\/+)/))) {\n path = path.slice(match[1].length)\n continue\n }\n\n // look for leading ?\n if (path.match(/^(\\?)/)) {\n path = path.slice(1)\n maybe = true;\n }\n\n if ((match = path.match(/^('((\\\\[\\\\'bfnrtv]|.)*?)')/))) {\n // matched a single quoted string\n path = path.slice(match[1].length)\n part = match[2].replace(/\\\\([\\\\'bfnrtv])/g, (all, one) => quotedEscapes[one] || `\\\\${one}`);\n }\n else if ((match = path.match(/^(\"((\\\\[\\\\\"bfnrtv]|.)*?)\")/))) {\n // matched a double quoted string\n path = path.slice(match[1].length)\n part = match[2].replace(/\\\\([\\\\\"bfnrtv])/g, (all, one) => quotedEscapes[one] || `\\\\${one}`);\n }\n else if ((match = path.match(/^([^/?]+)/))) {\n // matched an unquoted string\n part = match[1]\n path = path.slice(part.length)\n }\n else {\n fail(`Can't parse data path: ${path}`);\n }\n\n if (path.match(/^(\\?)/)) {\n path = path.slice(1)\n optional = true;\n }\n\n if (maybe) {\n parts.push([part, { maybe: true }])\n }\n else if (optional) {\n parts.push([part, { optional: true }])\n }\n else {\n parts.push(part)\n }\n }\n return parts;\n}\n\n/**\n * Traverse a data structure using a path.\n * @param {Object} [data] - the data to traverse\n * @param {String} [path] - the data path\n */\nexport const dataPath = (data, path) => {\n let root = data;\n let parts = splitDataPath(path);\n let done = [ ];\n // console.log('parts: ', parts);\n\n for (let part of parts) {\n const [word, opts] = isArray(part) ? part : [part, {}];\n const next = root[word]\n // root = root[word];\n done.push(word);\n if (noValue(next)) {\n if (opts.maybe) {\n return root;\n }\n if (opts.optional) {\n return undefined;\n }\n fail(\"No value for data at path: \", done.join('/'));\n }\n root = next\n }\n return root;\n}\n","import { DirPath } from '@abw/badger-filesystem';\nimport { addDebug } from './Utils/Debug.js';\nimport { dataPath } from '../Badger/Utils/DataPath.js';\nimport { doNothing, fail, splitList } from '@abw/badger-utils';\n\n/**\n * Default configuration options.\n */\nconst defaults = {\n codec: ['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 extends DirPath {\n /**\n * Constructor for Config object.\n * @param {String} dir - one or more directories that contain 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.codec='yaml json'] - Array or comma/whitespace delimited string of codec names\n * @return {Object} the Config object\n */\n constructor(dir, options={}) {\n super(dir);\n const params = { ...defaults, ...options };\n this.state.codec = splitList(params.codec),\n this.state.jsExt = splitList(params.jsExt),\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\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 const dirs = await this.dirs();\n\n for (let dir of dirs) {\n for (let ext of exts) {\n const path = uri + '.' + ext;\n const file = 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 }\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 `codec` 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.codec, (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 const [base, fragment] = uri.split('#', 2);\n let jsFile, file, data;\n\n // first look for a JS file, e.g. <uri>.js, <uri>.mjs\n if ((jsFile = await this.jsFile(base))) {\n data = await import(jsFile.path());\n }\n // then for a config file with a codec extension, e.g. <uri>.yaml, <uri>.yaml\n else if ((file = await this.file(base))) {\n data = await file.read();\n }\n // failing that use any default value\n else if (defaults) {\n data = defaults;\n }\n // anything else is a big pile of fail\n else {\n return fail(\"No configuration file for \" + base);\n }\n // resolve any data path in a #fragment\n return fragment\n ? dataPath(data, fragment)\n : data;\n }\n}\n\n/**\n * Function to create a new Config object\n * @param {String} dir - directory or directories 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.codec='yaml json'] - Array or comma/whitespace delimited string of codec names\n * @return {Object} the Config object\n */\nexport const config = (dir, options) => new Config(dir, options)\n\nexport default Config\n","import { DirPath } from \"@abw/badger-filesystem\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { dataPath } from \"./Utils/DataPath.js\";\nimport { fail, splitList } from \"@abw/badger-utils\";\n\n/**\n * Default configuration options.\n */\nconst defaults = {\n jsExt: 'js mjs',\n}\n\n/**\n * The Library class implements an object which can load Javascript files\n * from one or more library directories. Files can be Javascript files\n * (with `.js` or `.mjs` extensions by default)\n */\nexport class Library extends DirPath {\n /**\n * Constructor for Library object.\n * @param {String} dir - one or more directories that contain Javascript libraries\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 * @return {Object} the Library object\n */\n constructor(dir, options={}) {\n super(dir);\n const params = { ...defaults, ...options };\n const exts = splitList(params.jsExt).map( ext => ext.replace(/^\\./, '') ); // remove leading '.'\n this.state.exts = exts;\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\n this.debug(\"state: \", this.state)\n }\n\n /**\n * Method to load a Javascript library in one of the library directories and with one of the `jsExt` extensions (`.js` or `.mjs` by default).\n * Returns the exports from the library if found or throws an error if not.\n * @param {String} uri - base part of filename\n * @return {Object} the exports from the loaded libary\n */\n async library(uri) {\n const [base, fragment] = uri.split('#', 2);\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(base + '.' + ext);\n this.debug('looking for module %s as', base, 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 fragment\n ? dataPath(load, fragment)\n : load;\n }\n }\n }\n fail(\"Library not found: \", uri);\n }\n}\n\n/**\n * Function to create a new Library object\n * @param {String} dir - directory or directories 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 * @return {Object} the Library object\n */\nexport const library = (dir, options) => new Library(dir, options);\n\nexport default library;","import process from 'node:process'\nimport { brightGreen, brightRed } from './Color.js';\n\nexport const appStatus = app => async function(...args) {\n try {\n const message = await app(...args);\n if (message) {\n console.log(brightGreen(`✓ ${message}`));\n }\n return true;\n }\n catch (error) {\n console.log(\n process.env.DEBUG\n ? error\n : brightRed(`✗ ${error.message||error}`)\n )\n return false;\n }\n}\n\nexport default appStatus","import { isArray, isBoolean, isString } from '@abw/badger-utils';\nimport prompts from 'prompts'\n\n/**\n * Prompt user to enter a value.\n * @param {String} question - question to prompt user to answer\n * @param {Object} [options] - optional options\n * @param {String} [options.default] - default value returned if user presses RETURN\n * @return {Promise} fulfills with response to question or default value\n * @example\n * prompt(\"What is your name?\")\n * .then( name => console.log(`Hello ${name}`) );\n * @example\n * prompt(\"What is your name?\", { default: 'Mr.Badger' })\n * .then( name => console.log(`Hello ${name}`) );\n */\nexport const prompt = async (question, options={}) => {\n options = isString(options)\n ? { default: options }\n : options;\n\n const name = options.name || 'answer';\n const answers = await prompts([\n {\n name,\n type: options.type || 'text',\n message: question,\n initial: options.default,\n },\n ]);\n return answers[name];\n}\n\n/**\n * Prompt user to confirm a choice.\n * @param {String} question - question to prompt user to answer\n * @param {Object} [options] - optional options\n * @param {String} [options.default] - default value returned if user presses RETURN\n * @return {Promise} fulfills with response to question or default value\n * @example\n * confirm(\"Are you sure?\")\n * .then( yes => console.log('You said \"%s\"', yes ? 'YES' : 'NO') );\n */\nexport const confirm = async (question, options={}) => {\n options = isBoolean(options)\n ? { default: options }\n : options;\n return prompt(\n question,\n { ...options, type: 'confirm' });\n}\n\n/**\n * Prompt user to select an option.\n * @param {String} message - question to prompt user to answer\n * @param {Object} choices - array of title and value or object mapping value to title\n * @param {String} [initial] - initial value\n * @return {Promise} fulfills with selected option value\n * @example\n * select(\"Pick a colour\", { red: 'Red', green: 'Green', blue: 'Blue'})\n * .then( colour => console.log('You chose \"%s\"', colour) );\n * @example\n * select(\n * \"Pick a colour\",\n * [\n * { value: 'red': title: 'Red' },\n * { value: 'green', title: 'Green' },\n * { value: 'blue', title: 'Blue' },\n * ],\n * 0\n * ).then( colour => console.log('You chose \"%s\"', colour) );\n */\n\nexport const select = async (message, choices, initial) => {\n const choice = await prompts([\n {\n type: 'select',\n name: 'selected',\n message,\n initial,\n choices: isArray(choices)\n ? choices\n : Object.entries(choices).map(\n ([value, title]) => ({ value, title }),\n )\n }\n ]);\n return choice.selected;\n}\n","import { fail, hasValue, isArray, splitHash } from '@abw/badger-utils';\nimport process from 'node:process'\nimport { prompt } from './Prompt.js';\n\nexport const cmdLine = () => process.argv.slice(2);\n\nexport function cmdLineFlags(config, args) {\n // allow config and/or args to be undefined, and also allow an array of\n // arguments to be passed as the first argument\n if (! config) {\n config = { }\n }\n else if (isArray(config)) {\n args = config;\n config = { };\n }\n if (! args) {\n args ||= cmdLine()\n }\n\n const options = config.options ? splitHash(config.options) : false;\n const others = config.others || 'error';\n const short = config.short || { };\n const on = config.on || { }\n let done = false;\n let n = 0;\n let flags = { };\n\n while (n < args.length) {\n const match = args[n].match(/^-(-)?(.*)/);\n if (args[n] === '--') {\n done = true;\n args.splice(n, 1);\n }\n if (match && ! done) {\n const long = match[1] === '-';\n const name = (! long && hasValue(short[match[2]]))\n ? short[match[2]]\n : match[2];\n\n if (on[name]) {\n if (on[name](name, args.splice(n, 1)[0], args, flags)) {\n continue;\n }\n else {\n args.splice(n, 0, match[0]);\n }\n }\n\n if (options && ! options[name]) {\n switch (others) {\n case 'collect':\n break\n case 'remove':\n args.splice(n, 1)[0];\n // eslint-disable-next-line no-fallthrough\n case 'keep':\n n++;\n continue;\n case 'error':\n return fail(`Invalid command line flag: ${match[0]}`);\n default:\n return fail(`Invalid \"others\" option: ${others}`)\n }\n }\n\n args.splice(n, 1);\n flags[name] = true;\n }\n else {\n n++;\n }\n }\n return { flags, args }\n}\n\nexport async function cmdLineArg(argPrompt, args=cmdLine()) {\n if (args.length) {\n return args.shift();\n }\n else if (argPrompt) {\n return await prompt(argPrompt);\n }\n return undefined;\n}\n\nexport async function cmdLineArgs(argPrompts, args=cmdLine()) {\n let results = [ ];\n if (argPrompts) {\n for (let argPrompt of argPrompts) {\n const response = await cmdLineArg(argPrompt, args);\n if (! response?.length) {\n return undefined;\n }\n results.push(response);\n }\n return results;\n }\n else {\n return args;\n }\n}","// dotenv is still in the dark ages of using require() which causes problems\n// when you're in an ESM only environment. This is a modern async replacement\n// which is ESM-only and has some additional features:\n// * looks for the .env file in the directory in which the script is defined\n// * looks for the .env file in the current working directory\n// * walks up through parents of those directories to find it\n// * returns the loaded environment variables as an object\n// * adding to process.env van be disabled\n//\n\nimport { bin, cwd, dir, file } from '@abw/badger-filesystem'\nimport { fail } from '@abw/badger-utils'\nimport process from 'node:process'\n\nconst DOT_ENV = '.env'\nconst LINE = /(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg\n\nexport async function findDotenv({\n filename = DOT_ENV,\n dirs = [ bin(), cwd() ],\n walkup = true\n}) {\n const lookedIn = { }\n const search = dirs.map(\n d => dir(d)\n )\n\n while (search.length) {\n const d = search.shift()\n\n if (! lookedIn[d.path()]) {\n lookedIn[d.path()] = true\n const dotEnv = d.file(filename)\n const exists = await dotEnv.exists()\n if (exists) {\n return dotEnv.path()\n }\n if (walkup) {\n search.push(d.up())\n }\n }\n }\n fail(`Cannot locate ${DOT_ENV} file in any parent directory of ${dirs.join(', ')}`)\n}\n\nexport function parseDotenv(text) {\n const env = { }\n\n // Convert buffer to string and standardise line endings\n const lines = text.toString().replace(/\\r\\n?/mg, '\\n')\n let match\n\n while ((match = LINE.exec(lines)) != null) {\n const key = match[1]\n\n // Default undefined or null to empty string\n let value = (match[2] ?? '')\n value = value.trim()\n\n // Check if double quoted\n const maybeQuote = value[0]\n\n // Remove surrounding quotes\n value = value.replace(/^(['\"`])([\\s\\S]*)\\1$/mg, '$2')\n\n // Expand newlines if double quoted\n if (maybeQuote === '\"') {\n value = value.replace(/\\\\n/g, '\\n')\n value = value.replace(/\\\\r/g, '\\r')\n }\n\n // Add to object\n env[key] = value\n }\n\n return env\n}\n\n/**\n * Modern ESM and async version of the dotenv module. Looks for a .env\n * file in the source directory of the running script and/or the current\n * working directory, or the closest parent directory of either of those\n * that contains one.\n * @async\n * @function dotenv\n * @param {Object} [options] - configuration options\n * @param {String} [options.path] - explicit path to .env file\n * @param {String} [options.filename] - alternate name for .env file\n * @param {Array} [options.dirs] - array of directories to search in (default: bin() and cwd())\n * @param {Boolean} [options.walkup] - walkup from search directories to parent directories (default: true)\n * @param {Boolean} [options.addToProcessEnv] - add environment to process.env (default: true)\n * @param {Boolean} [options.debug] - enable debugging messages\n * @return {Object} the loaded environment variables\n * @example\n * dotenv()\n * @example\n * dotenv({ path: '/path/to/my/.env' })\n * @example\n * dotenv({ filename: '.env-local' })\n * @example\n * dotenv({ dirs: ['/dir/one', '/dir/two'] })\n * @example\n * dotenv({ dirs: ['/dir/one', '/dir/two'], walkup: false })\n * @example\n * const env = dotenv({ addToProcessEnv: false })\n */\nexport async function dotenv({\n path,\n filename,\n dirs,\n addToProcessEnv=true,\n debug=false\n} = { }) {\n path ||= await findDotenv({ filename, dirs })\n if (debug) {\n console.log(`Loading environment from ${path}`)\n }\n const f = file(path)\n if (! await f.exists()) {\n fail(`Specified environment file does not exist: ${path}`)\n }\n const text = await f.read()\n const env = parseDotenv(text)\n\n if (debug) {\n console.log(`Loaded environment:`, env)\n }\n\n if (addToProcessEnv) {\n Object.assign(process.env, env)\n if (debug) {\n console.log(`Added environment to process.env`)\n }\n }\n\n return env\n}\n\n","import process from 'node:process'\n\nexport function exit(value, message) {\n if (message) {\n console.log(message);\n }\n process.exit(value);\n}\n\nexport function quit(message) {\n exit(0, message);\n}\n\nexport function abort(message) {\n exit(1, message);\n}","import process from \"node:process\"\n\n/**\n * Returns an array of the `process.argv` array from offset 2 onwards,\n * i.e. removing the node path and script name.\n * @param {Array} argv - list of arguments, defaults to `process.argv`\n * @return {Array} array of arguments excluding the first two\n */\nexport function args(argv=process.argv) {\n return argv.slice(2);\n}\n","import process from 'node:process';\nimport prompter from 'prompts'\nimport { Command } from 'commander';\nimport { color } from './Color.js';\nimport { fail, hasValue, splitList } from '@abw/badger-utils';\n\nexport const defaults = {\n verboseColor: 'magenta',\n titleColor: 'bright yellow',\n underlineColor: 'dark yellow',\n infoColor: 'cyan',\n tickColor: 'green',\n questionColor: 'bright white',\n answerColor: 'bright green',\n sectionNewlines: true\n};\n\nexport const options = async config => {\n const vcol = color(options.verboseColor || defaults.verboseColor);\n const command = new Command;\n\n // set command name, description and version\n if (config.name) {\n command.name(config.name);\n }\n if (config.description) {\n command.description(config.description);\n }\n if (config.version) {\n command.version(config.version);\n }\n\n // define the -y / -yes and -v / --verbose options\n if (config.yes) {\n command.option('-y, --yes', 'Accept default answers')\n }\n if (config.verbose) {\n command.option('-v, --verbose', 'Verbose output')\n }\n if (config.quiet) {\n command.option('-q, --quiet', 'Quiet output')\n }\n\n // add in other command line options\n config.options\n ?.filter(\n option => {\n if (hasValue(option.arg) && ! option.arg) {\n // allow arg: false to indicate no command line argument\n return false;\n }\n if (option.title) {\n // section break\n return;\n }\n return hasValue(option.name);\n }\n )\n .forEach(\n option => {\n const name = option.name;\n const about = option.about;\n const deflt = option.default;\n const handler = option.handler;\n const short = option.short;\n const type = option.type;\n const pattern = option.pattern || (hasValue(type) ? `<${type}>` : undefined);\n let string = `--${name}`;\n let args = [];\n if (hasValue(short)) {\n string = `-${short}, ${string}`;\n }\n if (hasValue(pattern)) {\n string = `${string} ${pattern}`;\n }\n args.push(string);\n if (hasValue(about)) {\n args.push(about);\n }\n if (hasValue(handler)) {\n args.push(handler);\n }\n if (hasValue(deflt)) {\n args.push(deflt);\n }\n command.option(...args)\n }\n )\n\n let commands = { };\n\n config.commands?.forEach(\n option => {\n const name = option.name;\n const about = option.about;\n const type = option.type;\n const pattern = option.pattern || (hasValue(type) ? `<${type}>` : undefined);\n let args = [];\n let string = name;\n let cmd = command.command(string)\n if (hasValue(pattern)) {\n cmd.argument(pattern);\n }\n if (hasValue(about)) {\n cmd.description(about);\n }\n if (hasValue(option.arguments)) {\n splitList(option.arguments).forEach(\n argument => {\n args.push(matchArgName(argument));\n cmd.argument(argument)\n }\n )\n }\n cmd.action(\n (...values) => {\n commands[name] = args.length\n ? args.reduce(\n (opts, arg) => {\n opts[arg] = values.shift()\n return opts;\n },\n { }\n )\n : values[0]\n }\n )\n //console.log({ args });\n //command.command(...args)\n }\n )\n\n // parse the command line arguments\n command.parse();\n const cmdline = command.opts();\n\n // if the -y / --yes option has been specified then accept all\n // default answers automatically\n const yes = config.yes && cmdline.yes;\n const verbose = config.verbose && cmdline.verbose;\n const quiet = config.quiet && cmdline.quiet;\n\n if (yes) {\n if (verbose && ! quiet) {\n process.stdout.write(vcol('Accepting default answers (-y option is set)\\n'))\n }\n prompter.override(cmdline);\n }\n\n // build up the list of prompts for interactive questions\n let prompts = [ ];\n config.options?.forEach(\n option => {\n const type = option.type || 'text';\n const name = option.name;\n const prompt = option.prompt;\n const noArg = hasValue(option.arg) && ! option.arg;\n const validate = option.validate ||\n (option.required\n ? value => (hasValue(value) && value.toString().length)\n ? true\n : (options.invalid || `You must enter a value for ${name}`)\n : undefined\n )\n\n // special process for initial\n // - use cmdline[name]\n // - or if noArg, use option.default\n // - if a select list and not a number, find the index\n let initial = noArg ? option.default : cmdline[name];\n if (type === 'select' && hasValue(initial)) {\n if (! Number.isInteger(initial)) {\n // console.log('looking up select option for [%s]', initial);\n initial = option.choices?.findIndex( i => i.value === initial );\n if (initial < 0) {\n initial = 0;\n }\n }\n }\n\n if (hasValue(prompt)) {\n prompts.push(\n {\n ...option,\n type: (\n hasValue(initial)\n ? () => {\n yes && (quiet || answer({ question: prompt, answer: initial }));\n return type;\n }\n : type\n ),\n name,\n message: prompt,\n initial: initial,\n validate: validate,\n },\n )\n }\n else if (option.title || option.info) {\n prompts.push(\n {\n type: () => {\n quiet || section(option);\n return false;\n }\n }\n );\n }\n }\n );\n\n // prompt the user to answer/confirm questions\n let cancelled = false;\n const answers = await prompter(\n prompts,\n {\n onCancel: () => {\n cancelled = true;\n return false;\n }\n }\n );\n\n return cancelled\n ? undefined\n : {\n ...cmdline, ...answers, ...commands\n }\n}\n\nfunction matchArgName(argument) {\n const match = argument.match(/(\\w+)/);\n if (! match) {\n fail(\"Can't parse argument name: \", argument);\n }\n return match[1];\n}\n\nexport const section = option => {\n const title = option.title;\n const tcol = color(option.titleColor || defaults.titleColor);\n const ucol = color(option.underlineColor || defaults.underlineColor);\n const icol = color(option.infoColor || defaults.infoColor);\n const nl = (hasValue(option.newlines) ? option.newlines : defaults.sectionNewlines) ? \"\\n\" : \"\";\n\n if (title) {\n const uline = '-'.repeat(title.length);\n process.stdout.write(nl + tcol(title) + \"\\n\" + ucol(uline) + \"\\n\" + nl);\n }\n\n if (option.info) {\n process.stdout.write(icol(option.info) + \"\\n\" + nl);\n }\n}\n\nexport const answer = option => {\n const tcol = color(option.tickColor || defaults.tickColor);\n const qcol = color(option.questionColor || defaults.questionColor);\n const acol = color(option.answerColor || defaults.answerColor);\n process.stdout.write(tcol(\"✔ \") + qcol(option.question) + \" \" + acol(option.answer) + \"\\n\");\n}\n\n// export default options","import { joinListOr, splitList, hasValue, fail } from \"@abw/badger-utils\";\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 { now } from '@abw/badger-timestamp';\nimport { isInteger, isString } from '@abw/badger-utils';\nimport { addDebug } from './Debug.js';\nimport { color } from './Color.js';\nimport process from 'node:process';\n\nexport const charTypes = {\n border: '┌─┐│└─┘|-',\n background: '+∙',\n fill: '*',\n};\n\nexport const colours = {\n border: 'green',\n background: 'dark grey',\n foreground: 'blue',\n fill: 'bright yellow'\n};\n\nexport const picture = {\n charTypes,\n source: `\n┌────────────────────────────────────────────────────────────────┐\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙ ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ∙∙ │\n│ ∙∙ ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ∙∙ │\n│ ∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙ │\n│ ∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙ │\n│ ∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙ │\n│ ∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙ │\n│ ∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙ │\n│ ∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙ ●● *◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦* ●● ∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙ ●● **◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦** ●● ∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙ ●● *****◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦***** ●● ∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● *******◦◦◦◦◦◦◦◦◦◦******* ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ****************** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ************ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ****** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● **** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● **** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● **** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦****◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦****◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦****◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦******◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦********◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦************◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦******************◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦************************◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙ │\n│ ∙∙∙∙∙ ●● ◦◦◦◦◦◦◦******************************◦◦◦◦◦◦◦ ●● ∙∙∙∙∙ │\n│ ∙∙∙∙ ●● ◦◦◦◦◦************************************◦◦◦◦◦ ●● ∙∙∙∙ │\n│ ∙∙∙ ●● ◦◦◦◦****************************************◦◦◦◦ ●● ∙∙∙ │\n│ ∙∙ ●● ◦◦◦********************************************◦◦◦ ●● ∙∙ │\n│ ∙∙ ●● ◦◦**********************************************◦◦ ●● ∙∙ │\n│ ∙∙ ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ∙∙ │\n│ ∙∙ ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n└────────────────────────────────────────────────────────────────┘\n`\n};\n\nconst defaults = {\n size: 100,\n elapsed: false,\n picture,\n colours\n}\n\nexport function preparePicture(config) {\n const { source, charTypes={ background: '' } } = config\n const picture = source.trim() + \"\\n\";\n const length = picture.length;\n const charType = Object\n .entries(charTypes)\n .reduce(\n (types, [type, chars]) => {\n chars.split('').forEach(\n char => types[char] = type\n );\n return types\n },\n { }\n )\n const lineLength = source\n .split(\"\\n\")\n .reduce(\n (longest, line) => Math.max(longest, line.length),\n 0\n )\n return { picture, length, lineLength, charType };\n}\n\nexport function prepareColours(colours) {\n return Object.entries(colours).reduce(\n (formatters, [type, colour]) => {\n formatters[type] = color(colour);\n return formatters;\n },\n { }\n )\n}\n\nexport function formatPicture(config) {\n const { picture, charType={}, colours={} } = config;\n return picture\n .split('')\n .map(\n char => {\n const type = charType[char] || 'foreground'\n const col = colours[type];\n return col ? col(char) : char;\n }\n )\n .join('')\n}\n\nexport function formatElapsed(elapsed) {\n const s = elapsed % 60;\n const m = Math.floor(elapsed / 60);\n const h = Math.floor(elapsed / 3600);\n return [h, m, s].map( x => x.toString().padStart(2, '0') ).join(':');\n}\n\nexport class Progress {\n constructor(params={}) {\n const config = {\n ...defaults,\n ...(\n // you wouldn't believe the number of times I've tried to create a\n // progress object passing only the size as an argument instead of\n // { size: N } so this de-numpties my numptiness\n isInteger(params)\n ? { size: params }\n : params\n )\n };\n const { size, colours, colors, debug, elapsed } = config;\n const { picture, length, lineLength, charType } =\n preparePicture(\n isString(config.picture)\n ? { source: config.picture, charTypes }\n : config.picture\n );\n this.size = size;\n this.picture = picture;\n this.pixels = this.picture.split('');\n this.length = length;\n this.lineLength = lineLength;\n this.charType = charType;\n this.colours = prepareColours(colors || colours);\n this.count = 0;\n this.lastCount = 0;\n this.lastPixel = 0;\n this.startTime = now().epochSeconds();\n this.elapsed = 0;\n this.elapsedCol = color('dark grey');\n this.showElapsed = elapsed;\n this.debugging = debug;\n addDebug(this, debug, 'Progress > ', 'blue');\n }\n\n progress(n=1) {\n this.count += n;\n\n const time = now().epochSeconds();\n const elapsed = time - this.startTime;\n this.elapsed = elapsed;\n // const duration = elapsed - this.elapsed;\n\n const end = Math.floor(this.length * this.count / this.size);\n if (end > this.lastPixel) {\n const start = this.lastPixel;\n this.lastPixel = end;\n this.debug(`count: ${this.count}/${this.size} pixels from ${start} to ${end}`);\n return this.pictureSegment(start, end);\n }\n else {\n return '';\n }\n }\n\n remains() {\n this.count = this.size;\n const start = this.lastPixel;\n const end = this.length;\n if (end > start) {\n this.lastPixel = this.length;\n return this.pictureSegment(start, end);\n }\n else {\n return '';\n }\n }\n pictureSegment(start, end) {\n if (this.debugging) {\n return '';\n }\n\n let slice = formatPicture({\n picture: this.picture.substring(start, end),\n charType: this.charType,\n colours: this.colours,\n });\n\n // this.picture.substring(start, end);\n if (this.showElapsed && slice.match(\"\\n\")) {\n const lines = slice.split(\"\\n\");\n const last = lines.pop();\n slice = lines\n .map( line => line + ` ` + this.elapsedCol(formatElapsed(this.elapsed)) )\n .join(\"\\n\")\n .concat(\"\\n\", last)\n }\n return slice;\n }\n\n printProgress(n=1) {\n process.stdout.write(this.progress(n));\n }\n\n printRemains() {\n process.stdout.write(this.remains());\n }\n}\n\nexport const progress = config => new Progress(config);\n\nexport default progress\n","import process from 'node:process'\nimport { options } from './Options.js';\nimport { cwd, dir } from '@abw/badger-filesystem';\nimport { extract, fail, hasValue, isBoolean, splitLines, splitList } from '@abw/badger-utils';\nimport { brightGreen, brightRed } from './Color.js';\nimport { now } from '@abw/badger-timestamp';\nimport { quit } from './Exit.js';\nimport { appStatus } from './AppStatus.js';\nimport { dotenv } from './Dotenv.js';\n\nconst defaults = {\n description: 'Project setup script.',\n configFiles: [\n 'config/setup.yaml', 'config/setup.json',\n 'setup.yaml', 'setup.json',\n '.setup.yaml', '.setup.json'\n ],\n dataFile: '.env.yaml',\n envFile: '.env',\n envComments: true,\n envSections: true,\n writeData: true,\n writeEnv: false,\n compact: false,\n cancelled: 'Setup cancelled',\n allDone: 'All configuration options have been set',\n warning: config => `\n#=============================================================================\n# WARNING: This file is generated automatically when the ${config.scriptName}\n# script is run. Any changes made here may be lost.\n#\n# Generated: ${now()}\n#=============================================================================\n\n`\n}\n\nexport const setup = appStatus(\n async config => {\n await runSetup(config)\n }\n)\n\nexport async function runSetup(props) {\n const config = { ...defaults, ...props };\n const rootDir = config.rootDir\n ? dir(config.rootDir)\n : cwd();\n\n // read the environment file (.env) if it exists\n const envFile = rootDir.file(config.envFile);\n const env = dotenv({ path: envFile.path() });\n\n // read the data file (.env.yaml) if it exists\n const dataFile = rootDir.file(config.dataFile, { codec: 'auto' });\n const data = (await dataFile.exists())\n ? await dataFile.read()\n : { };\n\n // look for a setup file - if it's provided as configFile then it's treated\n // as definitive, otherwise we look for the first of configFiles\n const configFile = config.configFile\n ? rootDir.file(config.configFile, { codec: 'auto' })\n : await findFirstFile(rootDir, config.configFiles);\n\n // read the setup file\n const setup = await configFile.read();\n\n setup.name ||= config.name\n || process.argv[1].replace(rootDir.path() + '/', '');\n setup.version ||= config.version;\n setup.description ||= config.description;\n\n // hack to allow setup configuration to be pre-processed by a function\n if (props.preprocess) {\n await props.preprocess(setup)\n }\n\n // caller may have provided us with some values\n const values = {\n root: rootDir.path(),\n ...(config.values || { })\n };\n const nonsave = {\n quiet: true,\n verbose: true,\n yes: true\n }\n\n // process the options\n for (let option of setup.options) {\n const { name, save } = option;\n\n // make an index of options we don't want saved in .env or .env.yaml\n if (isBoolean(save) && ! save) {\n nonsave[name] = true\n }\n\n // section headings don't have names\n if (! name) {\n continue;\n }\n\n // if there's a pattern specified then the type can default to text\n if (option.pattern) {\n option.type ||= 'text';\n }\n\n // look to see if we've got a value in the environment or data file\n const envVar = option.envvar ||= name.toUpperCase();\n\n if (hasValue(env[envVar])) {\n // set the value from the environment\n option.default = env[envVar];\n }\n else if (hasValue(data[name])) {\n // set the value from the data file\n option.default = data[name];\n }\n else if (hasValue(values[name])) {\n // set the value from the provided values\n option.default = values[name];\n }\n else if (option.program) {\n // look for a program in the path\n option.default = await findProgram(option.program)\n option.pattern ||= '<path>'\n }\n }\n\n // Read command line arguments or prompt user to enter values\n const answers = await options(setup);\n if (! answers) {\n quit('\\n👎 ' + brightRed(config.cancelled));\n }\n\n // extract the options that shouldn't be preserved\n const { debug, verbose, quiet } = answers;\n\n if (config.writeData) {\n await dataFile.write(\n extract(\n answers,\n key => ! nonsave[key]\n )\n );\n if (verbose) {\n console.log(brightGreen(`✓ Wrote data file: ${dataFile}`));\n }\n }\n\n if (config.writeEnv) {\n await envFile.write(\n await envFileText(rootDir, config, setup, answers)\n )\n if (verbose) {\n console.log(brightGreen(`✓ Wrote .env file: ${envFile}`));\n }\n }\n\n if (debug) {\n console.log('\\nGenerated configuration:', answers);\n }\n if (config.allDone && ! quiet) {\n console.log('\\n👍 ', brightGreen(config.allDone), '\\n');\n }\n\n return answers;\n}\n\nexport async function findFirstFile(root, names=[]) {\n for (let name of names) {\n const file = root.file(name, { codec: 'auto' });\n if (await file.exists()) {\n return file;\n }\n }\n fail(\"Can't find a configFile: \", names.join(', '));\n}\n\nexport async function findProgram(names) {\n for (let name of splitList(names)) {\n for (let path of process.env.PATH.split(':')) {\n const file = dir(path).file(name);\n const exists = await file.exists();\n if (exists) {\n return file.path();\n }\n }\n }\n}\n\nasync function envFileText(rootDir, config, setup, answers) {\n const { compact, envComments, envSections, envPrefix='' } = config;\n const gap = compact ? '' : \"\\n\";\n let output = [\n comment(config.warning(config))\n ];\n const line = '#' + '-'.repeat(77)\n const line2 = '#' + '='.repeat(77)\n for (let option of setup.options) {\n const { name, envvar, title, about, save } = option\n // belt and braces - we remove these above but it's possible this function\n // is being called independently\n if (isBoolean(save) && ! save) {\n continue;\n }\n if (title && envSections) {\n output.push(\n `${gap}\\n${line}\\n${comment(title)}\\n${line}`\n )\n continue;\n }\n if (! compact) {\n output.push(\"\");\n }\n if (about && envComments) {\n output.push(`${comment(about)}`)\n }\n if (name) {\n const value = answers[name];\n if (hasValue(value)) {\n const safe = value.toString().match(/[#\\r\\n]/) ? `\"$value\"` : value;\n output.push(`${envPrefix}${envvar || name.toUpperCase()}=${safe}`)\n }\n else {\n output.push(comment(`No value for ${envvar || name.toUpperCase()}`))\n }\n }\n }\n if (config.envExtra) {\n const extraFile = rootDir.file(config.envExtra);\n if (! await extraFile.exists()) {\n fail(`Cannot find envExtra file: ${config.envExtra}`);\n }\n if (envSections) {\n output.push(\n \"\\n\",\n line2,\n comment(` Additional configuration copied from ${config.envExtra}`),\n line2,\n \"\",\n )\n }\n output.push(await extraFile.read())\n }\n return output.join(\"\\n\") + \"\\n\";\n}\n\nfunction comment(text) {\n return splitLines(text.trim())\n .map( line => line.match(/^#/) ? line : `# ${line}` )\n .join(\"\\n\");\n}","#!/usr/bin/env node\nimport chokidar from 'chokidar'\nimport process from 'node:process'\nimport kidproc from 'node:child_process'\nimport { file } from '@abw/badger-filesystem'\nimport { debounce, doNothing, sleep } from '@abw/badger-utils'\nimport { quit, abort, exit } from './Exit.js'\nimport { cmdLineFlags } from './CmdLine.js'\nimport { palette } from './Color.js'\n\nconst defaults = {\n script: process.argv[1].split('/').at(-1),\n prefix: 'watcher >',\n colors: {\n prefix: 'dark grey',\n error: 'bright red',\n watcher: 'bright yellow',\n section: 'bright white',\n program: 'bright green',\n arg: 'bright cyan',\n args: 'bright blue',\n debug: 'bright grey',\n command: 'yellow',\n scanning: 'cyan',\n watching: 'cyan',\n change: 'bright cyan',\n starting: 'bright green',\n stopping: 'bright red',\n stopped: 'green',\n failed: 'bright red',\n }\n};\n\nexport async function watch(options) {\n const { config, cmdLine } = watcherFunctions(options)\n const cmdOptions = await cmdLine()\n const { watch, restart, program, programArgs } = cmdOptions\n const {\n scanning, watching, starting, stopping, failed, stopped, change\n } = watcherStatus({ ...config, ...cmdOptions })\n\n let child\n let ready = false\n\n scanning()\n watching(watch)\n\n const start = () => {\n if (child) {\n return\n }\n starting()\n child = kidproc.spawn(\n program,\n programArgs,\n {\n stdio: 'inherit',\n }\n )\n child.on(\n 'exit',\n (code, signal) => {\n if (signal) {\n return\n }\n if (code) {\n failed(code)\n }\n else {\n stopped()\n }\n if (restart) {\n child = null\n sleep(500).then(start)\n }\n else {\n exit(code)\n }\n }\n )\n }\n\n const stop = () => {\n if (! child) {\n return\n }\n stopping()\n child.kill()\n child = null\n }\n\n const changed = debounce(\n () => {\n stop()\n start()\n },\n 300\n )\n\n chokidar.watch(\n watch\n ).on(\n 'ready',\n () => {\n start()\n ready = true\n }\n ).on(\n 'all',\n (event, path) => {\n if (ready) {\n change(event, path)\n changed()\n }\n }\n )\n}\n\nexport const watcherFunctions = (props) => {\n const config = { ...defaults, ...props };\n const colors = config.colors = palette({\n ...defaults.colors,\n ...config.colors\n })\n\n const helpText = watcherHelpText(config)\n\n const help = () => quit(\n helpText()\n )\n\n const barf = error => abort(\n helpText(error)\n )\n\n const cmdLine = async () => {\n const { flags, args } = cmdLineFlags(\n {\n options: 'watch restart verbose help',\n others: 'keep',\n short: {\n w: 'watch',\n r: 'restart',\n v: 'verbose',\n h: 'help',\n },\n on: {\n help,\n watch: (name, arg, args, flags) => {\n flags.watch ||= [ ]\n if (! args.length) {\n barf(`The -w option expects an argument!`)\n }\n flags.watch.push(args.shift())\n return true\n }\n }\n }\n )\n const [ program, ...programArgs ] = args\n const progText = args.join(' ')\n\n if (args.length < 1) {\n barf('No program specified to run!')\n }\n if (! flags.watch?.length) {\n barf('Nothing specified to watch!')\n }\n if (! await file(program).exists()) {\n barf(`Program not found: ${program}`)\n }\n\n return {\n ...flags, progText, program, programArgs\n }\n }\n\n return { config, colors, helpText, help, barf, cmdLine }\n}\n\nexport const watcherStatus = ({ verbose, colors, prefix, progText }) => {\n const scanning = () => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.scanning('scanning...')\n )\n : doNothing\n\n const watching = paths => verbose\n ? paths.forEach(\n path => console.log(\n colors.prefix(prefix),\n colors.watching('watching '),\n colors.command(path)\n )\n )\n : doNothing\n\n const change = (event, path) => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.change(`${event}`.padEnd(9)),\n colors.command(path)\n )\n : doNothing\n\n const starting = () => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.starting('starting '),\n colors.command(progText)\n )\n : doNothing\n\n const stopping = () => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.stopping('stopping '),\n colors.command(progText)\n )\n : doNothing\n\n const failed = code => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.failed(`failed ${code}`),\n colors.command(progText)\n )\n : doNothing\n\n const stopped = () => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.stopped(`stopped `),\n colors.command(progText)\n )\n : doNothing\n\n return {\n scanning, watching, change, starting,\n stopping, failed, stopped\n }\n\n}\n\nexport const watcherHelpText = ({ colors, script }) => {\n const { watcher, arg, section, program, args, error } = colors\n const name = watcher(script)\n return errMsg => `${name}\n${errMsg ? `\\n${error(errMsg)}\\n` : ''}\n${section('Usage')}\n\n $ ${name} [${arg('options')}] ${program('program')} [${args('arg1 arg2 ...')}]\n\n${section('Description')}\n\n This program will run another program and restart it if any files\n are added, deleted or modified in one or more watched locations.\n\n Paths to watch should be specified using the ${arg('-w')} (or ${arg('--watch')})\n option. You can specify this multiple times for different paths.\n\n The path to the ${program('program')} should follow, along with any additional\n ${args('arguments')} to be passed to it.\n\n If the ${arg('-r')} (or ${arg('--restart')}) option is specified then the\n program will be restarted when it exits.\n\n${section('Options')}\n\n ${arg('-w <path>')} / ${arg('--watch <path>')} Watch a path for changes\n ${arg('-r')} / ${arg('--restart')} Restart program on exit\n ${arg('-v')} / ${arg('--verbose')} Verbose mode\n ${arg('-h')} / ${arg('--help')} This help\n\n${section('Examples')}\n\n $ ${name} ${arg('-w .')} ${program('bin/foo.js')}\n $ ${name} ${arg('-w lib -w config')} ${program('bin/foo.js')}\n $ ${name} ${arg('-w lib -w config')} ${program('bin/foo.js')} ${args('bar baz')}\n $ ${name} ${arg('-w lib -w config -v')} ${program('bin/foo.js')} ${args('bar baz')}\n $ ${name} ${arg('-w lib -w config -v -r')} ${program('bin/foo.js')} ${args('bar baz')}\n`\n}\n","import { addDebug } from \"./Utils/Debug.js\";\nimport { Config } from \"./Config.js\";\nimport { Library } from \"./Library.js\";\nimport { dir as fsDir } from \"@abw/badger-filesystem\";\nimport { fail, hasValue, splitList } from \"@abw/badger-utils\";\n\n/**\n * Default configuration options.\n */\nconst defaults = {\n config: {\n dir: 'config',\n },\n library: {\n dir: 'lib library src components',\n },\n case: {\n // config and/or library case conversion functions\n }\n}\n\n/**\n * The Workspace class implements an object which acts as a central repository\n * for your project, providing access to directories, files, configuration files,\n * Javascript libraries and components.\n */\nexport class Workspace {\n /**\n * Constructor for Workspace object.\n * @param {String} dir - root directory for the workspace\n * @param {Object} [options] - configuration options\n * @param {Object} [options.config] - configuration options for a {@link Config} object\n * @param {Array|String} [options.config.dir] - configuration directory or directories relative to the workspace directory\n * @param {Object} [options.library] - configuration options for a {@link Config} object\n * @param {Array|String} [options.library.dir] - library directory or directories relative to the workspace directory\n * @return {Object} the Workspace object\n */\n constructor(dir, options={}) {\n const rootDir = fsDir(dir);\n const cfgDir = splitList(options.config?.dir || defaults.config.dir).map( dir => rootDir.dir(dir) );\n const cfgOpts = { ...defaults.config, ...(options.config||{}) };\n const config = new Config(cfgDir, cfgOpts);\n const libDirs = splitList(options.library?.dir || defaults.library.dir).map( dir => rootDir.dir(dir) );\n const libOpts = { ...defaults.library, ...(options.library||{}) };\n const library = new Library(libDirs, libOpts);\n\n this.case = {\n ...defaults.case,\n ...(options.case||{})\n };\n\n this.state = {\n rootDir,\n config,\n library\n }\n\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\n this.debug('root dir: ', rootDir.path());\n this.debug('config dir: ', cfgDir.map( d => d.path() ));\n this.debug('libDirs: ', libDirs);\n this.debug('libOpts: ', libOpts);\n }\n\n /**\n * Fetch a new {@link Directory} object for a sub-directory of the workspace directory.\n * @param {string} path - directory path relative to the workspace directory\n * @param {Object} [options] - directory configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object\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\n /**\n * Fetch a new {@link File} object for a file in the workspace.\n * @param {string} path - file path relative to the workspace directory\n * @param {Object} [options] - file configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @param {Boolean} [options.encoding=utf8] - character encoding for the file\n * @return {Object} a {@link File} object\n */\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return this.state.rootDir.file(path, options)\n }\n\n /**\n * Read the content of a file in the workspace.\n * @param {string} path - file path relative to the workspace directory\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @param {Boolean} [options.encoding=utf8] - character encoding for the file\n * @return {Promise} fulfills with the file content\n * @example\n * file('myfile.txt').read().then( text => console.log(text) );\n * @example\n * file('myfile.json', { codec: 'json' }).read().then( data => console.log(data) );\n * @example\n * file('myfile.json').read({ codec: 'json' }).then( data => console.log(data) );\n */\n read(path, options) {\n this.debug(\"read(%s, %o)\", path, options);\n return this.file(path, options).read();\n }\n\n /**\n * Writes content to a file. If a `codec` has been specified then the content will be encoded.\n * @param {string} path - file path relative to the workspace directory\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 * @param {Boolean} [options.encoding=utf8] - codec for encoding/decoding file data\n * @return {Promise} fulfills with the file object\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(path, data, options) {\n this.debug(\"write(%s, %o, %o)\", path, data, options);\n return this.file(path, options).write(data);\n }\n\n /**\n * Fetch the configuration directory or a directory relative to it\n * @param {string} [path] - file path relative to the configuration directory\n * @param {Object} [options] - directory configuration options\n * @param {String} [options.codec] - codec for encoding/decoding data for files in the directory\n * @param {Boolean} [options.encoding=utf8] - character encoding for files in the directory\n * @return {Object} a {@link Directory} object\n */\n configDir(path, options) {\n this.debug(\"configDir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.configDir.dir(path, options)\n : this.state.configDir;\n }\n\n /**\n * Fetches configuration data from a file in the configuration directory or returns the\n * {@link Config} object itself if no file uri is specified.\n * @param {string} [uri] - file path relative to the configuration directory\n * @param {Object} [defaults] - default configuration options if file isn't found\n * @return {Promise} fulfills to the configuration data read from the file\n * @example\n * workspace.config('myfile').then(\n * config => console.log(\"Loaded myfile config: \", config)\n * );\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\n /**\n * Loads a Javscript library from the library directory or returns the\n * {@link Library} object itself if no file uri is specified.\n * @param {string} [uri] - file path relative to the library directory\n * @return {Promise} fulfills to the configuration data read from the file\n * @example\n * workspace.library('mylib').then(\n * exports => console.log(\"Loaded mylib exports: \", exports)\n * );\n */\n async library(uri) {\n this.debug(\"library(%s, %o)\", uri);\n return hasValue(uri)\n ? this.state.library.library(uri)\n : this.state.library;\n }\n\n /**\n * Loads a Javscript library from the library directory and instantiates a\n * component.\n * @param {String} uri - component base name\n * @param {Object} [props] - optional configuration properties\n * @return {Promise} fulfills to a newly instantiated component\n * @example\n * workspace.component('mycomp').then(\n * component => console.log(\"Created component: \", component)\n * );\n */\n async component(uri, props) {\n const [base, fragment] = uri.split('#', 2);\n const cfgname = this.convertCase('config', base);\n const config = await this.config(cfgname, {});\n const libname = config.component?.library || this.convertCase('library', base);\n const lib = await this.library(libname);\n const exp = fragment || 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 return comp;\n }\n\n convertCase(type, uri) {\n const fn = this.case[type];\n return fn\n ? fn(uri)\n : uri;\n }\n}\n\nexport const workspace = (dir, options) => new Workspace(dir, options);\n\nexport default Workspace;"],"names":["ANSIColors","reset","bold","bright","dark","black","red","green","yellow","blue","magenta","cyan","grey","white","fg","bg","ANSIRGB","rgb","r","g","b","ANSIescapeCode","color","base","match","parseInt","isHex","triple","splitList","length","isRGB","ANSIRGBescapeCodes","codes","pair","split","hue","pop","code","push","shade","shift","join","ANSIescapeCodes","ANSIescape","colors","col","isObject","escapes","ANSIresetCode","ANSIreset","text","palette","Object","entries","reduce","key","value","brightBlack","brightRed","brightGreen","brightYellow","brightBlue","brightMagenta","brightCyan","brightGrey","brightWhite","darkBlack","darkRed","darkGreen","darkYellow","darkBlue","darkMagenta","darkCyan","darkGrey","darkWhite","Debugger","enabled","prefix","format","args","console","log","bind","doNothing","addDebug","obj","debug","Component","constructor","workspace","props","this","debugPrefix","debugColor","initComponent","quotedEscapes","f","n","t","v","matchDoubleQuotedString","string","replace","all","one","matchSingleQuotedString","splitDataPath","path","part","parts","maybe","optional","slice","fail","dataPath","data","root","done","word","opts","isArray","next","noValue","defaults","codec","jsExt","Config","DirPath","dir","options","super","params","state","firstFileWithExt","uri","exts","makeOptions","dirs","ext","file","exists","jsFile","config","fragment","import","read","Library","map","library","load","appStatus","app","async","message","error","process","env","DEBUG","prompt","question","name","isString","default","prompts","type","initial","confirm","isBoolean","select","choices","title","selected","cmdLine","argv","cmdLineFlags","splitHash","others","short","on","flags","splice","hasValue","cmdLineArg","argPrompt","cmdLineArgs","argPrompts","results","response","DOT_ENV","LINE","findDotenv","filename","bin","cwd","walkup","lookedIn","search","d","dotEnv","up","parseDotenv","lines","toString","exec","trim","maybeQuote","dotenv","addToProcessEnv","assign","exit","quit","abort","verboseColor","titleColor","underlineColor","infoColor","tickColor","questionColor","answerColor","sectionNewlines","vcol","command","Command","description","version","yes","option","verbose","quiet","filter","arg","forEach","about","deflt","handler","pattern","undefined","commands","cmd","argument","arguments","matchArgName","action","values","parse","cmdline","stdout","write","prompter","override","noArg","validate","required","invalid","Number","isInteger","findIndex","i","answer","info","section","cancelled","answers","onCancel","tcol","ucol","icol","nl","newlines","uline","repeat","qcol","acol","requiredParam","requiredParams","names","allParams","anyParams","found","nlist","joinListOr","charTypes","border","background","fill","colours","foreground","picture","source","size","elapsed","preparePicture","charType","types","chars","char","lineLength","longest","line","Math","max","prepareColours","formatters","colour","formatPicture","formatElapsed","s","m","floor","x","padStart","Progress","pixels","count","lastCount","lastPixel","startTime","now","epochSeconds","elapsedCol","showElapsed","debugging","progress","end","start","pictureSegment","remains","substring","last","concat","printProgress","printRemains","configFiles","dataFile","envFile","envComments","envSections","writeData","writeEnv","compact","allDone","warning","scriptName","setup","runSetup","rootDir","configFile","findFirstFile","preprocess","nonsave","save","envVar","envvar","toUpperCase","program","findProgram","extract","envPrefix","gap","output","comment","line2","safe","envExtra","extraFile","envFileText","PATH","splitLines","script","at","watcher","scanning","watching","change","starting","stopping","stopped","failed","watch","watcherFunctions","cmdOptions","restart","programArgs","watcherStatus","child","ready","kidproc","spawn","stdio","signal","sleep","then","changed","debounce","kill","chokidar","event","helpText","watcherHelpText","help","barf","w","h","progText","paths","padEnd","errMsg","Workspace","fsDir","cfgDir","cfgOpts","libDirs","libOpts","case","configDir","component","cfgname","convertCase","libname","lib","exp","export","fn"],"mappings":"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"}
1
+ {"version":3,"file":"badger.esm.js","sources":["../src/Badger/Utils/Color.js","../src/Badger/Utils/Debug.js","../src/Badger/Component.js","../src/Badger/Utils/DataPath.js","../src/Badger/Config.js","../src/Badger/Library.js","../src/Badger/Utils/AppStatus.js","../src/Badger/Utils/Prompt.js","../src/Badger/Utils/CmdLine.js","../src/Badger/Utils/Dotenv.js","../src/Badger/Utils/Exit.js","../src/Badger/Utils/Misc.js","../src/Badger/Utils/Options.js","../src/Badger/Utils/Params.js","../src/Badger/Utils/Progress.js","../src/Badger/Utils/Setup.js","../src/Badger/Utils/Watch.js","../src/Badger/Workspace.js"],"sourcesContent":["import { isObject, splitList } from \"@abw/badger-utils\";\n\nconst ANSIStart = '\\u001B[';\nconst ANSIEnd = 'm';\nconst 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};\nconst ANSIRGB = {\n fg: rgb => `38;2;${rgb.r};${rgb.g};${rgb.b}`,\n bg: rgb => `48;2;${rgb.r};${rgb.g};${rgb.b}`,\n}\n\nconst isRGB = color => {\n const triple = splitList(color)\n return triple.length === 3\n ? { r: triple[0], g: triple[1], b: triple[2]}\n : null\n}\n\nconst isHex = color => {\n const match = color.match(/^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i)\n return match\n ? {\n r: parseInt(match[1], 16),\n g: parseInt(match[2], 16),\n b: parseInt(match[3], 16)\n }\n : null;\n}\n\nconst ANSIescapeCodes = (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\nconst ANSIRGBescapeCodes = (color, base='fg') =>\n ANSIStart + ANSIRGB[base](color) + ANSIEnd;\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 ANSIescapeCode = (color, base='fg') => {\n const rgb = isHex(color) || isRGB(color)\n return rgb\n ? ANSIRGBescapeCodes(rgb, base)\n : ANSIescapeCodes(color, base)\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 ANSIescape = (colors={}) => {\n const col = isObject(colors) ? colors : { fg: colors };\n let escapes = [ ];\n if (col.bg) {\n escapes.push(ANSIescapeCode(col.bg, 'bg'));\n }\n if (col.fg) {\n escapes.push(ANSIescapeCode(col.fg, 'fg'));\n }\n return escapes.join('');\n}\n\n/**\n * Returns an ANSI escape code to reset all colors.\n * @return {String} ANSI escape reset string\n */\nexport const ANSIresetCode = ANSIescapeCode('reset', false)\n\n\n/**\n * Returns an ANSI escape code to reset all colors.\n * @return {String} ANSI escape reset string\n */\nexport const ANSIreset = () => ANSIresetCode\n\n/**\n * Returns a function to display strings in a particular color.\n * @param {String} colors - color(s) to display string\n * @return {Function} function to display strings in the pre-defined color(s)\n */\nexport const color = (colors) =>\n (...text) => ANSIescape(colors) + text.join('') + ANSIresetCode;\n\n/**\n * Expand an object of color names into color functions.\n * @param {Object} palette - mapping arbitrary keys to color names\n * @return {Object} object mapping keys to color functions\n */\nexport const palette = palette =>\n Object.entries(palette).reduce(\n (palette, [key, value]) => {\n palette[key] = color(value)\n return palette\n },\n { }\n )\n\nexport const black = color('black');\nexport const red = color('red');\nexport const green = color('green');\nexport const yellow = color('yellow');\nexport const blue = color('blue');\nexport const magenta = color('magenta');\nexport const cyan = color('cyan');\nexport const grey = color('grey');\nexport const white = color('white');\nexport const brightBlack = color('bright black');\nexport const brightRed = color('bright red');\nexport const brightGreen = color('bright green');\nexport const brightYellow = color('bright yellow');\nexport const brightBlue = color('bright blue');\nexport const brightMagenta = color('bright magenta');\nexport const brightCyan = color('bright cyan');\nexport const brightGrey = color('bright grey');\nexport const brightWhite = color('bright white');\nexport const darkBlack = color('dark black');\nexport const darkRed = color('dark red');\nexport const darkGreen = color('dark green');\nexport const darkYellow = color('dark yellow');\nexport const darkBlue = color('dark blue');\nexport const darkMagenta = color('dark magenta');\nexport const darkCyan = color('dark cyan');\nexport const darkGrey = color('dark grey');\nexport const darkWhite = color('dark white');\n","import { ANSIescape, ANSIreset } from './Color.js'\nimport { doNothing } from '@abw/badger-utils';\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 ? ANSIescape(color) : '',\n ANSIreset(),\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","import { fail, isArray, noValue } from \"@abw/badger-utils\";\n\n/**\n * Characters that can be escaped in quoted strings.\n */\nconst quotedEscapes = {\n b: \"\\b\",\n f: \"\\f\",\n n: \"\\n\",\n r: \"\\r\",\n t: \"\\t\",\n v: \"\\v\",\n '\"': '\"',\n \"'\": \"'\",\n '\\\\': '\\\\',\n}\n\n/**\n * Match a double quoted string and expand escaped characters\n * @param {String} [string] - the string to match\n */\nexport const matchDoubleQuotedString = string => {\n const regex = /^\"((?:\\\\[\\\\\"bfnrtv]|.)*?)\"$/\n const match = string.match(regex);\n return match\n ? match[1].replace(/\\\\([\\\\\"bfnrtv])/g, (all, one) => quotedEscapes[one] || `\\\\${one}`)\n : null;\n}\n\n/**\n * Match a single quoted string and expand escaped characters\n * @param {String} [string] - the string to match\n */\nexport const matchSingleQuotedString = string => {\n const regex = /^'((?:\\\\[\\\\'bfnrtv]|.)*?)'$/\n const match = string.match(regex);\n return match\n ? match[1].replace(/\\\\([\\\\'bfnrtv])/g, (all, one) => quotedEscapes[one] || `\\\\${one}`)\n : null;\n}\n\n/**\n * Split a data path into component parts\n * @param {String} [path] - the path to split\n */\nexport const splitDataPath = path => {\n let parts = [ ];\n let part;\n let match;\n\n while (path.length) {\n let maybe;\n let optional;\n\n // match and ignore any slashes\n if ((match = path.match(/^(\\/+)/))) {\n path = path.slice(match[1].length)\n continue\n }\n\n // look for leading ?\n if (path.match(/^(\\?)/)) {\n path = path.slice(1)\n maybe = true;\n }\n\n if ((match = path.match(/^('((\\\\[\\\\'bfnrtv]|.)*?)')/))) {\n // matched a single quoted string\n path = path.slice(match[1].length)\n part = match[2].replace(/\\\\([\\\\'bfnrtv])/g, (all, one) => quotedEscapes[one] || `\\\\${one}`);\n }\n else if ((match = path.match(/^(\"((\\\\[\\\\\"bfnrtv]|.)*?)\")/))) {\n // matched a double quoted string\n path = path.slice(match[1].length)\n part = match[2].replace(/\\\\([\\\\\"bfnrtv])/g, (all, one) => quotedEscapes[one] || `\\\\${one}`);\n }\n else if ((match = path.match(/^([^/?]+)/))) {\n // matched an unquoted string\n part = match[1]\n path = path.slice(part.length)\n }\n else {\n fail(`Can't parse data path: ${path}`);\n }\n\n if (path.match(/^(\\?)/)) {\n path = path.slice(1)\n optional = true;\n }\n\n if (maybe) {\n parts.push([part, { maybe: true }])\n }\n else if (optional) {\n parts.push([part, { optional: true }])\n }\n else {\n parts.push(part)\n }\n }\n return parts;\n}\n\n/**\n * Traverse a data structure using a path.\n * @param {Object} [data] - the data to traverse\n * @param {String} [path] - the data path\n */\nexport const dataPath = (data, path) => {\n let root = data;\n let parts = splitDataPath(path);\n let done = [ ];\n // console.log('parts: ', parts);\n\n for (let part of parts) {\n const [word, opts] = isArray(part) ? part : [part, {}];\n const next = root[word]\n // root = root[word];\n done.push(word);\n if (noValue(next)) {\n if (opts.maybe) {\n return root;\n }\n if (opts.optional) {\n return undefined;\n }\n fail(\"No value for data at path: \", done.join('/'));\n }\n root = next\n }\n return root;\n}\n","import { DirPath } from '@abw/badger-filesystem';\nimport { addDebug } from './Utils/Debug.js';\nimport { dataPath } from '../Badger/Utils/DataPath.js';\nimport { doNothing, fail, splitList } from '@abw/badger-utils';\n\n/**\n * Default configuration options.\n */\nconst defaults = {\n codec: ['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 extends DirPath {\n /**\n * Constructor for Config object.\n * @param {String} dir - one or more directories that contain 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.codec='yaml json'] - Array or comma/whitespace delimited string of codec names\n * @return {Object} the Config object\n */\n constructor(dir, options={}) {\n super(dir);\n const params = { ...defaults, ...options };\n this.state.codec = splitList(params.codec),\n this.state.jsExt = splitList(params.jsExt),\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\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 const dirs = await this.dirs();\n\n for (let dir of dirs) {\n for (let ext of exts) {\n const path = uri + '.' + ext;\n const file = 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 }\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 `codec` 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.codec, (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 const [base, fragment] = uri.split('#', 2);\n let jsFile, file, data;\n\n // first look for a JS file, e.g. <uri>.js, <uri>.mjs\n if ((jsFile = await this.jsFile(base))) {\n data = await import(jsFile.path());\n }\n // then for a config file with a codec extension, e.g. <uri>.yaml, <uri>.yaml\n else if ((file = await this.file(base))) {\n data = await file.read();\n }\n // failing that use any default value\n else if (defaults) {\n data = defaults;\n }\n // anything else is a big pile of fail\n else {\n return fail(\"No configuration file for \" + base);\n }\n // resolve any data path in a #fragment\n return fragment\n ? dataPath(data, fragment)\n : data;\n }\n}\n\n/**\n * Function to create a new Config object\n * @param {String} dir - directory or directories 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.codec='yaml json'] - Array or comma/whitespace delimited string of codec names\n * @return {Object} the Config object\n */\nexport const config = (dir, options) => new Config(dir, options)\n\nexport default Config\n","import { DirPath } from \"@abw/badger-filesystem\";\nimport { addDebug } from \"./Utils/Debug.js\";\nimport { dataPath } from \"./Utils/DataPath.js\";\nimport { fail, splitList } from \"@abw/badger-utils\";\n\n/**\n * Default configuration options.\n */\nconst defaults = {\n jsExt: 'js mjs',\n}\n\n/**\n * The Library class implements an object which can load Javascript files\n * from one or more library directories. Files can be Javascript files\n * (with `.js` or `.mjs` extensions by default)\n */\nexport class Library extends DirPath {\n /**\n * Constructor for Library object.\n * @param {String} dir - one or more directories that contain Javascript libraries\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 * @return {Object} the Library object\n */\n constructor(dir, options={}) {\n super(dir);\n const params = { ...defaults, ...options };\n const exts = splitList(params.jsExt).map( ext => ext.replace(/^\\./, '') ); // remove leading '.'\n this.state.exts = exts;\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\n this.debug(\"state: \", this.state)\n }\n\n /**\n * Method to load a Javascript library in one of the library directories and with one of the `jsExt` extensions (`.js` or `.mjs` by default).\n * Returns the exports from the library if found or throws an error if not.\n * @param {String} uri - base part of filename\n * @return {Object} the exports from the loaded libary\n */\n async library(uri) {\n const [base, fragment] = uri.split('#', 2);\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(base + '.' + ext);\n this.debug('looking for module %s as', base, 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 fragment\n ? dataPath(load, fragment)\n : load;\n }\n }\n }\n fail(\"Library not found: \", uri);\n }\n}\n\n/**\n * Function to create a new Library object\n * @param {String} dir - directory or directories 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 * @return {Object} the Library object\n */\nexport const library = (dir, options) => new Library(dir, options);\n\nexport default library;","import process from 'node:process'\nimport { brightGreen, brightRed } from './Color.js';\n\nexport const appStatus = app => async function(...args) {\n try {\n const message = await app(...args);\n if (message) {\n console.log(brightGreen(`✓ ${message}`));\n }\n return true;\n }\n catch (error) {\n console.log(\n process.env.DEBUG\n ? error\n : brightRed(`✗ ${error.message||error}`)\n )\n return false;\n }\n}\n\nexport default appStatus","import { isArray, isBoolean, isString } from '@abw/badger-utils';\nimport prompts from 'prompts'\n\n/**\n * Prompt user to enter a value.\n * @param {String} question - question to prompt user to answer\n * @param {Object} [options] - optional options\n * @param {String} [options.default] - default value returned if user presses RETURN\n * @return {Promise} fulfills with response to question or default value\n * @example\n * prompt(\"What is your name?\")\n * .then( name => console.log(`Hello ${name}`) );\n * @example\n * prompt(\"What is your name?\", { default: 'Mr.Badger' })\n * .then( name => console.log(`Hello ${name}`) );\n */\nexport const prompt = async (question, options={}) => {\n options = isString(options)\n ? { default: options }\n : options;\n\n const name = options.name || 'answer';\n const answers = await prompts([\n {\n name,\n type: options.type || 'text',\n message: question,\n initial: options.default,\n },\n ]);\n return answers[name];\n}\n\n/**\n * Prompt user to confirm a choice.\n * @param {String} question - question to prompt user to answer\n * @param {Object} [options] - optional options\n * @param {String} [options.default] - default value returned if user presses RETURN\n * @return {Promise} fulfills with response to question or default value\n * @example\n * confirm(\"Are you sure?\")\n * .then( yes => console.log('You said \"%s\"', yes ? 'YES' : 'NO') );\n */\nexport const confirm = async (question, options={}) => {\n options = isBoolean(options)\n ? { default: options }\n : options;\n return prompt(\n question,\n { ...options, type: 'confirm' });\n}\n\n/**\n * Prompt user to select an option.\n * @param {String} message - question to prompt user to answer\n * @param {Object} choices - array of title and value or object mapping value to title\n * @param {String} [initial] - initial value\n * @return {Promise} fulfills with selected option value\n * @example\n * select(\"Pick a colour\", { red: 'Red', green: 'Green', blue: 'Blue'})\n * .then( colour => console.log('You chose \"%s\"', colour) );\n * @example\n * select(\n * \"Pick a colour\",\n * [\n * { value: 'red': title: 'Red' },\n * { value: 'green', title: 'Green' },\n * { value: 'blue', title: 'Blue' },\n * ],\n * 0\n * ).then( colour => console.log('You chose \"%s\"', colour) );\n */\n\nexport const select = async (message, choices, initial) => {\n const choice = await prompts([\n {\n type: 'select',\n name: 'selected',\n message,\n initial,\n choices: isArray(choices)\n ? choices\n : Object.entries(choices).map(\n ([value, title]) => ({ value, title }),\n )\n }\n ]);\n return choice.selected;\n}\n","import { fail, hasValue, isArray, splitHash } from '@abw/badger-utils';\nimport process from 'node:process'\nimport { prompt } from './Prompt.js';\n\nexport const cmdLine = () => process.argv.slice(2);\n\nexport function cmdLineFlags(config, args) {\n // allow config and/or args to be undefined, and also allow an array of\n // arguments to be passed as the first argument\n if (! config) {\n config = { }\n }\n else if (isArray(config)) {\n args = config;\n config = { };\n }\n if (! args) {\n args ||= cmdLine()\n }\n\n const options = config.options ? splitHash(config.options) : false;\n const others = config.others || 'error';\n const short = config.short || { };\n const on = config.on || { }\n let done = false;\n let n = 0;\n let flags = { };\n\n while (n < args.length) {\n const match = args[n].match(/^-(-)?(.*)/);\n if (args[n] === '--') {\n done = true;\n args.splice(n, 1);\n }\n if (match && ! done) {\n const long = match[1] === '-';\n const name = (! long && hasValue(short[match[2]]))\n ? short[match[2]]\n : match[2];\n\n if (on[name]) {\n if (on[name](name, args.splice(n, 1)[0], args, flags)) {\n continue;\n }\n else {\n args.splice(n, 0, match[0]);\n }\n }\n\n if (options && ! options[name]) {\n switch (others) {\n case 'collect':\n break\n case 'remove':\n args.splice(n, 1)[0];\n // eslint-disable-next-line no-fallthrough\n case 'keep':\n n++;\n continue;\n case 'error':\n return fail(`Invalid command line flag: ${match[0]}`);\n default:\n return fail(`Invalid \"others\" option: ${others}`)\n }\n }\n\n args.splice(n, 1);\n flags[name] = true;\n }\n else {\n n++;\n }\n }\n return { flags, args }\n}\n\nexport async function cmdLineArg(argPrompt, args=cmdLine()) {\n if (args.length) {\n return args.shift();\n }\n else if (argPrompt) {\n return await prompt(argPrompt);\n }\n return undefined;\n}\n\nexport async function cmdLineArgs(argPrompts, args=cmdLine()) {\n let results = [ ];\n if (argPrompts) {\n for (let argPrompt of argPrompts) {\n const response = await cmdLineArg(argPrompt, args);\n if (! response?.length) {\n return undefined;\n }\n results.push(response);\n }\n return results;\n }\n else {\n return args;\n }\n}","// dotenv is still in the dark ages of using require() which causes problems\n// when you're in an ESM only environment. This is a modern async replacement\n// which is ESM-only and has some additional features:\n// * looks for the .env file in the directory in which the script is defined\n// * looks for the .env file in the current working directory\n// * walks up through parents of those directories to find it\n// * returns the loaded environment variables as an object\n// * adding to process.env van be disabled\n//\n\nimport { bin, cwd, dir, file } from '@abw/badger-filesystem'\nimport { fail } from '@abw/badger-utils'\nimport process from 'node:process'\n\nconst DOT_ENV = '.env'\nconst LINE = /(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg\n\nexport async function findDotenv({\n filename = DOT_ENV,\n dirs = [ bin(), cwd() ],\n walkup = true\n}) {\n const lookedIn = { }\n const search = dirs.map(\n d => dir(d)\n )\n\n while (search.length) {\n const d = search.shift()\n\n if (! lookedIn[d.path()]) {\n lookedIn[d.path()] = true\n const dotEnv = d.file(filename)\n const exists = await dotEnv.exists()\n if (exists) {\n return dotEnv.path()\n }\n if (walkup) {\n search.push(d.up())\n }\n }\n }\n fail(`Cannot locate ${DOT_ENV} file in any parent directory of ${dirs.join(', ')}`)\n}\n\nexport function parseDotenv(text) {\n const env = { }\n\n // Convert buffer to string and standardise line endings\n const lines = text.toString().replace(/\\r\\n?/mg, '\\n')\n let match\n\n while ((match = LINE.exec(lines)) != null) {\n const key = match[1]\n\n // Default undefined or null to empty string\n let value = (match[2] ?? '')\n value = value.trim()\n\n // Check if double quoted\n const maybeQuote = value[0]\n\n // Remove surrounding quotes\n value = value.replace(/^(['\"`])([\\s\\S]*)\\1$/mg, '$2')\n\n // Expand newlines if double quoted\n if (maybeQuote === '\"') {\n value = value.replace(/\\\\n/g, '\\n')\n value = value.replace(/\\\\r/g, '\\r')\n }\n\n // Add to object\n env[key] = value\n }\n\n return env\n}\n\n/**\n * Modern ESM and async version of the dotenv module. Looks for a .env\n * file in the source directory of the running script and/or the current\n * working directory, or the closest parent directory of either of those\n * that contains one.\n * @async\n * @function dotenv\n * @param {Object} [options] - configuration options\n * @param {String} [options.path] - explicit path to .env file\n * @param {String} [options.filename] - alternate name for .env file\n * @param {Array} [options.dirs] - array of directories to search in (default: bin() and cwd())\n * @param {Boolean} [options.walkup] - walkup from search directories to parent directories (default: true)\n * @param {Boolean} [options.addToProcessEnv] - add environment to process.env (default: true)\n * @param {Boolean} [options.debug] - enable debugging messages\n * @return {Object} the loaded environment variables\n * @example\n * dotenv()\n * @example\n * dotenv({ path: '/path/to/my/.env' })\n * @example\n * dotenv({ filename: '.env-local' })\n * @example\n * dotenv({ dirs: ['/dir/one', '/dir/two'] })\n * @example\n * dotenv({ dirs: ['/dir/one', '/dir/two'], walkup: false })\n * @example\n * const env = dotenv({ addToProcessEnv: false })\n */\nexport async function dotenv({\n path,\n filename,\n dirs,\n addToProcessEnv=true,\n debug=false\n} = { }) {\n path ||= await findDotenv({ filename, dirs })\n if (debug) {\n console.log(`Loading environment from ${path}`)\n }\n const f = file(path)\n if (! await f.exists()) {\n fail(`Specified environment file does not exist: ${path}`)\n }\n const text = await f.read()\n const env = parseDotenv(text)\n\n if (debug) {\n console.log(`Loaded environment:`, env)\n }\n\n if (addToProcessEnv) {\n Object.assign(process.env, env)\n if (debug) {\n console.log(`Added environment to process.env`)\n }\n }\n\n return env\n}\n\n","import process from 'node:process'\n\nexport function exit(value, message) {\n if (message) {\n console.log(message);\n }\n process.exit(value);\n}\n\nexport function quit(message) {\n exit(0, message);\n}\n\nexport function abort(message) {\n exit(1, message);\n}","import process from \"node:process\"\n\n/**\n * Returns an array of the `process.argv` array from offset 2 onwards,\n * i.e. removing the node path and script name.\n * @param {Array} argv - list of arguments, defaults to `process.argv`\n * @return {Array} array of arguments excluding the first two\n */\nexport function args(argv=process.argv) {\n return argv.slice(2);\n}\n","import process from 'node:process';\nimport prompter from 'prompts'\nimport { Command } from 'commander';\nimport { color } from './Color.js';\nimport { fail, hasValue, splitList } from '@abw/badger-utils';\n\nexport const defaults = {\n verboseColor: 'magenta',\n titleColor: 'bright yellow',\n underlineColor: 'dark yellow',\n infoColor: 'cyan',\n tickColor: 'green',\n questionColor: 'bright white',\n answerColor: 'bright green',\n sectionNewlines: true\n};\n\nexport const options = async config => {\n const vcol = color(options.verboseColor || defaults.verboseColor);\n const command = new Command;\n\n // set command name, description and version\n if (config.name) {\n command.name(config.name);\n }\n if (config.description) {\n command.description(config.description);\n }\n if (config.version) {\n command.version(config.version);\n }\n\n // define the -y / -yes and -v / --verbose options\n if (config.yes) {\n command.option('-y, --yes', 'Accept default answers')\n }\n if (config.verbose) {\n command.option('-v, --verbose', 'Verbose output')\n }\n if (config.quiet) {\n command.option('-q, --quiet', 'Quiet output')\n }\n\n // add in other command line options\n config.options\n ?.filter(\n option => {\n if (hasValue(option.arg) && ! option.arg) {\n // allow arg: false to indicate no command line argument\n return false;\n }\n if (option.title) {\n // section break\n return;\n }\n return hasValue(option.name);\n }\n )\n .forEach(\n option => {\n const name = option.name;\n const about = option.about;\n const deflt = option.default;\n const handler = option.handler;\n const short = option.short;\n const type = option.type;\n const pattern = option.pattern || (hasValue(type) ? `<${type}>` : undefined);\n let string = `--${name}`;\n let args = [];\n if (hasValue(short)) {\n string = `-${short}, ${string}`;\n }\n if (hasValue(pattern)) {\n string = `${string} ${pattern}`;\n }\n args.push(string);\n if (hasValue(about)) {\n args.push(about);\n }\n if (hasValue(handler)) {\n args.push(handler);\n }\n if (hasValue(deflt)) {\n args.push(deflt);\n }\n command.option(...args)\n }\n )\n\n let commands = { };\n\n config.commands?.forEach(\n option => {\n const name = option.name;\n const about = option.about;\n const type = option.type;\n const pattern = option.pattern || (hasValue(type) ? `<${type}>` : undefined);\n let args = [];\n let string = name;\n let cmd = command.command(string)\n if (hasValue(pattern)) {\n cmd.argument(pattern);\n }\n if (hasValue(about)) {\n cmd.description(about);\n }\n if (hasValue(option.arguments)) {\n splitList(option.arguments).forEach(\n argument => {\n args.push(matchArgName(argument));\n cmd.argument(argument)\n }\n )\n }\n cmd.action(\n (...values) => {\n commands[name] = args.length\n ? args.reduce(\n (opts, arg) => {\n opts[arg] = values.shift()\n return opts;\n },\n { }\n )\n : values[0]\n }\n )\n //console.log({ args });\n //command.command(...args)\n }\n )\n\n // parse the command line arguments\n command.parse();\n const cmdline = command.opts();\n\n // if the -y / --yes option has been specified then accept all\n // default answers automatically\n const yes = config.yes && cmdline.yes;\n const verbose = config.verbose && cmdline.verbose;\n const quiet = config.quiet && cmdline.quiet;\n\n if (yes) {\n if (verbose && ! quiet) {\n process.stdout.write(vcol('Accepting default answers (-y option is set)\\n'))\n }\n prompter.override(cmdline);\n }\n\n // build up the list of prompts for interactive questions\n let prompts = [ ];\n config.options?.forEach(\n option => {\n const type = option.type || 'text';\n const name = option.name;\n const prompt = option.prompt;\n const noArg = hasValue(option.arg) && ! option.arg;\n const validate = option.validate ||\n (option.required\n ? value => (hasValue(value) && value.toString().length)\n ? true\n : (options.invalid || `You must enter a value for ${name}`)\n : undefined\n )\n\n // special process for initial\n // - use cmdline[name]\n // - or if noArg, use option.default\n // - if a select list and not a number, find the index\n let initial = noArg ? option.default : cmdline[name];\n if (type === 'select' && hasValue(initial)) {\n if (! Number.isInteger(initial)) {\n // console.log('looking up select option for [%s]', initial);\n initial = option.choices?.findIndex( i => i.value === initial );\n if (initial < 0) {\n initial = 0;\n }\n }\n }\n\n if (hasValue(prompt)) {\n prompts.push(\n {\n ...option,\n type: (\n hasValue(initial)\n ? () => {\n yes && (quiet || answer({ question: prompt, answer: initial }));\n return type;\n }\n : type\n ),\n name,\n message: prompt,\n initial: initial,\n validate: validate,\n },\n )\n }\n else if (option.title || option.info) {\n prompts.push(\n {\n type: () => {\n quiet || section(option);\n return false;\n }\n }\n );\n }\n }\n );\n\n // prompt the user to answer/confirm questions\n let cancelled = false;\n const answers = await prompter(\n prompts,\n {\n onCancel: () => {\n cancelled = true;\n return false;\n }\n }\n );\n\n return cancelled\n ? undefined\n : {\n ...cmdline, ...answers, ...commands\n }\n}\n\nfunction matchArgName(argument) {\n const match = argument.match(/(\\w+)/);\n if (! match) {\n fail(\"Can't parse argument name: \", argument);\n }\n return match[1];\n}\n\nexport const section = option => {\n const title = option.title;\n const tcol = color(option.titleColor || defaults.titleColor);\n const ucol = color(option.underlineColor || defaults.underlineColor);\n const icol = color(option.infoColor || defaults.infoColor);\n const nl = (hasValue(option.newlines) ? option.newlines : defaults.sectionNewlines) ? \"\\n\" : \"\";\n\n if (title) {\n const uline = '-'.repeat(title.length);\n process.stdout.write(nl + tcol(title) + \"\\n\" + ucol(uline) + \"\\n\" + nl);\n }\n\n if (option.info) {\n process.stdout.write(icol(option.info) + \"\\n\" + nl);\n }\n}\n\nexport const answer = option => {\n const tcol = color(option.tickColor || defaults.tickColor);\n const qcol = color(option.questionColor || defaults.questionColor);\n const acol = color(option.answerColor || defaults.answerColor);\n process.stdout.write(tcol(\"✔ \") + qcol(option.question) + \" \" + acol(option.answer) + \"\\n\");\n}\n\n// export default options","import { joinListOr, splitList, hasValue, fail } from \"@abw/badger-utils\";\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 { now } from '@abw/badger-timestamp';\nimport { isInteger, isString } from '@abw/badger-utils';\nimport { addDebug } from './Debug.js';\nimport { color } from './Color.js';\nimport process from 'node:process';\n\nexport const charTypes = {\n border: '┌─┐│└─┘|-',\n background: '+∙',\n fill: '*',\n};\n\nexport const colours = {\n border: 'green',\n background: 'dark grey',\n foreground: 'blue',\n fill: 'bright yellow'\n};\n\nexport const picture = {\n charTypes,\n source: `\n┌────────────────────────────────────────────────────────────────┐\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙ ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ∙∙ │\n│ ∙∙ ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ∙∙ │\n│ ∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙ │\n│ ∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙ │\n│ ∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙ │\n│ ∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙ │\n│ ∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙ │\n│ ∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙ ●● *◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦* ●● ∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙ ●● **◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦** ●● ∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙ ●● *****◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦***** ●● ∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● *******◦◦◦◦◦◦◦◦◦◦******* ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ****************** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ************ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ****** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● **** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● **** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● **** ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦****◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦****◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦****◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦******◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦********◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦◦************◦◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦◦******************◦◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙∙∙ │\n│ ∙∙∙∙∙∙ ●● ◦◦◦◦◦◦◦◦◦************************◦◦◦◦◦◦◦◦◦ ●● ∙∙∙∙∙∙ │\n│ ∙∙∙∙∙ ●● ◦◦◦◦◦◦◦******************************◦◦◦◦◦◦◦ ●● ∙∙∙∙∙ │\n│ ∙∙∙∙ ●● ◦◦◦◦◦************************************◦◦◦◦◦ ●● ∙∙∙∙ │\n│ ∙∙∙ ●● ◦◦◦◦****************************************◦◦◦◦ ●● ∙∙∙ │\n│ ∙∙ ●● ◦◦◦********************************************◦◦◦ ●● ∙∙ │\n│ ∙∙ ●● ◦◦**********************************************◦◦ ●● ∙∙ │\n│ ∙∙ ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ∙∙ │\n│ ∙∙ ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ∙∙ │\n│ ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ │\n└────────────────────────────────────────────────────────────────┘\n`\n};\n\nconst defaults = {\n size: 100,\n elapsed: false,\n picture,\n colours\n}\n\nexport function preparePicture(config) {\n const { source, charTypes={ background: '' } } = config\n const picture = source.trim() + \"\\n\";\n const length = picture.length;\n const charType = Object\n .entries(charTypes)\n .reduce(\n (types, [type, chars]) => {\n chars.split('').forEach(\n char => types[char] = type\n );\n return types\n },\n { }\n )\n const lineLength = source\n .split(\"\\n\")\n .reduce(\n (longest, line) => Math.max(longest, line.length),\n 0\n )\n return { picture, length, lineLength, charType };\n}\n\nexport function prepareColours(colours) {\n return Object.entries(colours).reduce(\n (formatters, [type, colour]) => {\n formatters[type] = color(colour);\n return formatters;\n },\n { }\n )\n}\n\nexport function formatPicture(config) {\n const { picture, charType={}, colours={} } = config;\n return picture\n .split('')\n .map(\n char => {\n const type = charType[char] || 'foreground'\n const col = colours[type];\n return col ? col(char) : char;\n }\n )\n .join('')\n}\n\nexport function formatElapsed(elapsed) {\n const s = elapsed % 60;\n const m = Math.floor(elapsed / 60);\n const h = Math.floor(elapsed / 3600);\n return [h, m, s].map( x => x.toString().padStart(2, '0') ).join(':');\n}\n\nexport class Progress {\n constructor(params={}) {\n const config = {\n ...defaults,\n ...(\n // you wouldn't believe the number of times I've tried to create a\n // progress object passing only the size as an argument instead of\n // { size: N } so this de-numpties my numptiness\n isInteger(params)\n ? { size: params }\n : params\n )\n };\n const { size, colours, colors, debug, elapsed } = config;\n const { picture, length, lineLength, charType } =\n preparePicture(\n isString(config.picture)\n ? { source: config.picture, charTypes }\n : config.picture\n );\n this.size = size;\n this.picture = picture;\n this.pixels = this.picture.split('');\n this.length = length;\n this.lineLength = lineLength;\n this.charType = charType;\n this.colours = prepareColours(colors || colours);\n this.count = 0;\n this.lastCount = 0;\n this.lastPixel = 0;\n this.startTime = now().epochSeconds();\n this.elapsed = 0;\n this.elapsedCol = color('dark grey');\n this.showElapsed = elapsed;\n this.debugging = debug;\n addDebug(this, debug, 'Progress > ', 'blue');\n }\n\n progress(n=1) {\n this.count += n;\n\n const time = now().epochSeconds();\n const elapsed = time - this.startTime;\n this.elapsed = elapsed;\n // const duration = elapsed - this.elapsed;\n\n const end = Math.floor(this.length * this.count / this.size);\n if (end > this.lastPixel) {\n const start = this.lastPixel;\n this.lastPixel = end;\n this.debug(`count: ${this.count}/${this.size} pixels from ${start} to ${end}`);\n return this.pictureSegment(start, end);\n }\n else {\n return '';\n }\n }\n\n remains() {\n this.count = this.size;\n const start = this.lastPixel;\n const end = this.length;\n if (end > start) {\n this.lastPixel = this.length;\n return this.pictureSegment(start, end);\n }\n else {\n return '';\n }\n }\n pictureSegment(start, end) {\n if (this.debugging) {\n return '';\n }\n\n let slice = formatPicture({\n picture: this.picture.substring(start, end),\n charType: this.charType,\n colours: this.colours,\n });\n\n // this.picture.substring(start, end);\n if (this.showElapsed && slice.match(\"\\n\")) {\n const lines = slice.split(\"\\n\");\n const last = lines.pop();\n slice = lines\n .map( line => line + ` ` + this.elapsedCol(formatElapsed(this.elapsed)) )\n .join(\"\\n\")\n .concat(\"\\n\", last)\n }\n return slice;\n }\n\n printProgress(n=1) {\n process.stdout.write(this.progress(n));\n }\n\n printRemains() {\n process.stdout.write(this.remains());\n }\n}\n\nexport const progress = config => new Progress(config);\n\nexport default progress\n","import process from 'node:process'\nimport { options } from './Options.js';\nimport { cwd, dir } from '@abw/badger-filesystem';\nimport { extract, fail, hasValue, isBoolean, splitLines, splitList } from '@abw/badger-utils';\nimport { brightGreen, brightRed } from './Color.js';\nimport { now } from '@abw/badger-timestamp';\nimport { quit } from './Exit.js';\nimport { appStatus } from './AppStatus.js';\nimport { dotenv } from './Dotenv.js';\n\nconst defaults = {\n description: 'Project setup script.',\n configFiles: [\n 'config/setup.yaml', 'config/setup.json',\n 'setup.yaml', 'setup.json',\n '.setup.yaml', '.setup.json'\n ],\n dataFile: '.env.yaml',\n envFile: '.env',\n envComments: true,\n envSections: true,\n writeData: true,\n writeEnv: false,\n compact: false,\n scriptName: 'scaffolding',\n cancelled: 'Setup cancelled',\n allDone: 'All configuration options have been set',\n warning: config => `\n#=============================================================================\n# WARNING: This file is generated automatically when the ${config.scriptName}\n# script is run. Any changes made here may be lost.\n#\n# Generated: ${now()}\n#=============================================================================\n\n`\n}\n\nexport const setup = appStatus(\n async config => {\n await runSetup(config)\n }\n)\n\nexport async function runSetup(props) {\n const config = { ...defaults, ...props };\n const rootDir = config.rootDir\n ? dir(config.rootDir)\n : cwd();\n\n // read the environment file (.env) if it exists\n const envFile = rootDir.file(config.envFile);\n const env = dotenv({ path: envFile.path() });\n\n // read the data file (.env.yaml) if it exists\n const dataFile = rootDir.file(config.dataFile, { codec: 'auto' });\n const data = (await dataFile.exists())\n ? await dataFile.read()\n : { };\n\n // look for a setup file - if it's provided as configFile then it's treated\n // as definitive, otherwise we look for the first of configFiles\n const configFile = config.configFile\n ? rootDir.file(config.configFile, { codec: 'auto' })\n : await findFirstFile(rootDir, config.configFiles);\n\n // read the setup file\n const setup = await configFile.read();\n\n setup.name ||= config.name\n || process.argv[1].replace(rootDir.path() + '/', '');\n setup.version ||= config.version;\n setup.description ||= config.description;\n\n // hack to allow setup configuration to be pre-processed by a function\n if (props.preprocess) {\n await props.preprocess(setup)\n }\n\n // caller may have provided us with some values\n const values = {\n root: rootDir.path(),\n ...(config.values || { })\n };\n const nonsave = {\n quiet: true,\n verbose: true,\n yes: true\n }\n\n // process the options\n for (let option of setup.options) {\n const { name, save } = option;\n\n // make an index of options we don't want saved in .env or .env.yaml\n if (isBoolean(save) && ! save) {\n nonsave[name] = true\n }\n\n // section headings don't have names\n if (! name) {\n continue;\n }\n\n // if there's a pattern specified then the type can default to text\n if (option.pattern) {\n option.type ||= 'text';\n }\n\n // look to see if we've got a value in the environment or data file\n const noPrefix = option.no_prefix || (isBoolean(option.env_prefix) && ! option.env_prefix)\n const prefix = noPrefix\n ? ''\n : (option.env_prefix ?? config.envPrefix ?? '')\n const envVar = option.envvar ??= option.env_var ?? `${prefix}${name.toUpperCase()}`\n\n if (hasValue(env[envVar])) {\n // set the value from the environment\n option.default = env[envVar];\n }\n else if (hasValue(data[name])) {\n // set the value from the data file\n option.default = data[name];\n }\n else if (hasValue(values[name])) {\n // set the value from the provided values\n option.default = values[name];\n }\n else if (option.program) {\n // look for a program in the path\n option.default = await findProgram(option.program)\n option.pattern ||= '<path>'\n }\n }\n\n // Read command line arguments or prompt user to enter values\n const answers = await options(setup);\n if (! answers) {\n quit('\\n👎 ' + brightRed(config.cancelled));\n }\n\n // extract the options that shouldn't be preserved\n const { debug, verbose, quiet } = answers;\n\n if (config.writeData) {\n await dataFile.write(\n extract(\n answers,\n key => ! nonsave[key]\n )\n );\n if (verbose) {\n console.log(brightGreen(`✓ Wrote data file: ${dataFile}`));\n }\n }\n\n if (config.writeEnv) {\n await envFile.write(\n await envFileText(rootDir, config, setup, answers)\n )\n if (verbose) {\n console.log(brightGreen(`✓ Wrote .env file: ${envFile}`));\n }\n }\n\n if (debug) {\n console.log('\\nGenerated configuration:', answers);\n }\n if (config.allDone && ! quiet) {\n console.log('\\n👍 ', brightGreen(config.allDone), '\\n');\n }\n\n return answers;\n}\n\nexport async function findFirstFile(root, names=[]) {\n for (let name of names) {\n const file = root.file(name, { codec: 'auto' });\n if (await file.exists()) {\n return file;\n }\n }\n fail(\"Can't find a configFile: \", names.join(', '));\n}\n\nexport async function findProgram(names) {\n for (let name of splitList(names)) {\n for (let path of process.env.PATH.split(':')) {\n const file = dir(path).file(name);\n const exists = await file.exists();\n if (exists) {\n return file.path();\n }\n }\n }\n}\n\nasync function envFileText(rootDir, config, setup, answers) {\n const { compact, envComments, envSections, envPrefix='' } = config;\n const gap = compact ? '' : \"\\n\";\n let output = [\n comment(config.warning(config))\n ];\n const line = '#' + '-'.repeat(77)\n const line2 = '#' + '='.repeat(77)\n for (let option of setup.options) {\n const { name, envvar, env_var, title, about, save, save_env } = option\n // belt and braces - we remove these above but it's possible this function\n // is being called independently\n if (isBoolean(save) && ! save) {\n continue;\n }\n if (isBoolean(save_env) && ! save_env) {\n continue;\n }\n if (title && envSections) {\n output.push(\n `${gap}\\n${line}\\n${comment(title)}\\n${line}`\n )\n continue;\n }\n if (! compact) {\n output.push(\"\");\n }\n if (about && envComments) {\n output.push(`${comment(about)}`)\n }\n if (name) {\n const value = answers[name];\n if (hasValue(value)) {\n const safe = value.toString().match(/[#\\r\\n]/) ? `\"$value\"` : value;\n const no_prefix = option.no_prefix || (isBoolean(option.env_prefix) && ! option.env_prefix)\n const prefix = no_prefix\n ? ''\n : (option.env_prefix ?? envPrefix)\n const envName = envvar ?? env_var ?? `${prefix}${name.toUpperCase()}`\n output.push(`${envName}=${safe}`)\n }\n else {\n output.push(comment(`No value for ${envvar || name.toUpperCase()}`))\n }\n }\n }\n if (config.envExtra) {\n const extraFile = rootDir.file(config.envExtra);\n if (! await extraFile.exists()) {\n fail(`Cannot find envExtra file: ${config.envExtra}`);\n }\n if (envSections) {\n output.push(\n \"\\n\",\n line2,\n comment(` Additional configuration copied from ${config.envExtra}`),\n line2,\n \"\",\n )\n }\n output.push(await extraFile.read())\n }\n return output.join(\"\\n\") + \"\\n\";\n}\n\nfunction comment(text) {\n return splitLines(text.trim())\n .map( line => line.match(/^#/) ? line : `# ${line}` )\n .join(\"\\n\");\n}","#!/usr/bin/env node\nimport chokidar from 'chokidar'\nimport process from 'node:process'\nimport kidproc from 'node:child_process'\nimport { file } from '@abw/badger-filesystem'\nimport { debounce, doNothing, sleep } from '@abw/badger-utils'\nimport { quit, abort, exit } from './Exit.js'\nimport { cmdLineFlags } from './CmdLine.js'\nimport { palette } from './Color.js'\n\nconst defaults = {\n script: process.argv[1].split('/').at(-1),\n prefix: 'watcher >',\n colors: {\n prefix: 'dark grey',\n error: 'bright red',\n watcher: 'bright yellow',\n section: 'bright white',\n program: 'bright green',\n arg: 'bright cyan',\n args: 'bright blue',\n debug: 'bright grey',\n command: 'yellow',\n scanning: 'cyan',\n watching: 'cyan',\n change: 'bright cyan',\n starting: 'bright green',\n stopping: 'bright red',\n stopped: 'green',\n failed: 'bright red',\n }\n};\n\nexport async function watch(options) {\n const { config, cmdLine } = watcherFunctions(options)\n const cmdOptions = await cmdLine()\n const { watch, restart, program, programArgs } = cmdOptions\n const {\n scanning, watching, starting, stopping, failed, stopped, change\n } = watcherStatus({ ...config, ...cmdOptions })\n\n let child\n let ready = false\n\n scanning()\n watching(watch)\n\n const start = () => {\n if (child) {\n return\n }\n starting()\n child = kidproc.spawn(\n program,\n programArgs,\n {\n stdio: 'inherit',\n }\n )\n child.on(\n 'exit',\n (code, signal) => {\n if (signal) {\n return\n }\n if (code) {\n failed(code)\n }\n else {\n stopped()\n }\n if (restart) {\n child = null\n sleep(500).then(start)\n }\n else {\n exit(code)\n }\n }\n )\n }\n\n const stop = () => {\n if (! child) {\n return\n }\n stopping()\n child.kill()\n child = null\n }\n\n const changed = debounce(\n () => {\n stop()\n start()\n },\n 300\n )\n\n chokidar.watch(\n watch\n ).on(\n 'ready',\n () => {\n start()\n ready = true\n }\n ).on(\n 'all',\n (event, path) => {\n if (ready) {\n change(event, path)\n changed()\n }\n }\n )\n}\n\nexport const watcherFunctions = (props) => {\n const config = { ...defaults, ...props };\n const colors = config.colors = palette({\n ...defaults.colors,\n ...config.colors\n })\n\n const helpText = watcherHelpText(config)\n\n const help = () => quit(\n helpText()\n )\n\n const barf = error => abort(\n helpText(error)\n )\n\n const cmdLine = async () => {\n const { flags, args } = cmdLineFlags(\n {\n options: 'watch restart verbose help',\n others: 'keep',\n short: {\n w: 'watch',\n r: 'restart',\n v: 'verbose',\n h: 'help',\n },\n on: {\n help,\n watch: (name, arg, args, flags) => {\n flags.watch ||= [ ]\n if (! args.length) {\n barf(`The -w option expects an argument!`)\n }\n flags.watch.push(args.shift())\n return true\n }\n }\n }\n )\n const [ program, ...programArgs ] = args\n const progText = args.join(' ')\n\n if (args.length < 1) {\n barf('No program specified to run!')\n }\n if (! flags.watch?.length) {\n barf('Nothing specified to watch!')\n }\n if (! await file(program).exists()) {\n barf(`Program not found: ${program}`)\n }\n\n return {\n ...flags, progText, program, programArgs\n }\n }\n\n return { config, colors, helpText, help, barf, cmdLine }\n}\n\nexport const watcherStatus = ({ verbose, colors, prefix, progText }) => {\n const scanning = () => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.scanning('scanning...')\n )\n : doNothing\n\n const watching = paths => verbose\n ? paths.forEach(\n path => console.log(\n colors.prefix(prefix),\n colors.watching('watching '),\n colors.command(path)\n )\n )\n : doNothing\n\n const change = (event, path) => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.change(`${event}`.padEnd(9)),\n colors.command(path)\n )\n : doNothing\n\n const starting = () => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.starting('starting '),\n colors.command(progText)\n )\n : doNothing\n\n const stopping = () => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.stopping('stopping '),\n colors.command(progText)\n )\n : doNothing\n\n const failed = code => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.failed(`failed ${code}`),\n colors.command(progText)\n )\n : doNothing\n\n const stopped = () => verbose\n ? console.log(\n colors.prefix(prefix),\n colors.stopped(`stopped `),\n colors.command(progText)\n )\n : doNothing\n\n return {\n scanning, watching, change, starting,\n stopping, failed, stopped\n }\n\n}\n\nexport const watcherHelpText = ({ colors, script }) => {\n const { watcher, arg, section, program, args, error } = colors\n const name = watcher(script)\n return errMsg => `${name}\n${errMsg ? `\\n${error(errMsg)}\\n` : ''}\n${section('Usage')}\n\n $ ${name} [${arg('options')}] ${program('program')} [${args('arg1 arg2 ...')}]\n\n${section('Description')}\n\n This program will run another program and restart it if any files\n are added, deleted or modified in one or more watched locations.\n\n Paths to watch should be specified using the ${arg('-w')} (or ${arg('--watch')})\n option. You can specify this multiple times for different paths.\n\n The path to the ${program('program')} should follow, along with any additional\n ${args('arguments')} to be passed to it.\n\n If the ${arg('-r')} (or ${arg('--restart')}) option is specified then the\n program will be restarted when it exits.\n\n${section('Options')}\n\n ${arg('-w <path>')} / ${arg('--watch <path>')} Watch a path for changes\n ${arg('-r')} / ${arg('--restart')} Restart program on exit\n ${arg('-v')} / ${arg('--verbose')} Verbose mode\n ${arg('-h')} / ${arg('--help')} This help\n\n${section('Examples')}\n\n $ ${name} ${arg('-w .')} ${program('bin/foo.js')}\n $ ${name} ${arg('-w lib -w config')} ${program('bin/foo.js')}\n $ ${name} ${arg('-w lib -w config')} ${program('bin/foo.js')} ${args('bar baz')}\n $ ${name} ${arg('-w lib -w config -v')} ${program('bin/foo.js')} ${args('bar baz')}\n $ ${name} ${arg('-w lib -w config -v -r')} ${program('bin/foo.js')} ${args('bar baz')}\n`\n}\n","import { addDebug } from \"./Utils/Debug.js\";\nimport { Config } from \"./Config.js\";\nimport { Library } from \"./Library.js\";\nimport { dir as fsDir } from \"@abw/badger-filesystem\";\nimport { fail, hasValue, splitList } from \"@abw/badger-utils\";\n\n/**\n * Default configuration options.\n */\nconst defaults = {\n config: {\n dir: 'config',\n },\n library: {\n dir: 'lib library src components',\n },\n case: {\n // config and/or library case conversion functions\n }\n}\n\n/**\n * The Workspace class implements an object which acts as a central repository\n * for your project, providing access to directories, files, configuration files,\n * Javascript libraries and components.\n */\nexport class Workspace {\n /**\n * Constructor for Workspace object.\n * @param {String} dir - root directory for the workspace\n * @param {Object} [options] - configuration options\n * @param {Object} [options.config] - configuration options for a {@link Config} object\n * @param {Array|String} [options.config.dir] - configuration directory or directories relative to the workspace directory\n * @param {Object} [options.library] - configuration options for a {@link Config} object\n * @param {Array|String} [options.library.dir] - library directory or directories relative to the workspace directory\n * @return {Object} the Workspace object\n */\n constructor(dir, options={}) {\n const rootDir = fsDir(dir);\n const cfgDir = splitList(options.config?.dir || defaults.config.dir).map( dir => rootDir.dir(dir) );\n const cfgOpts = { ...defaults.config, ...(options.config||{}) };\n const config = new Config(cfgDir, cfgOpts);\n const libDirs = splitList(options.library?.dir || defaults.library.dir).map( dir => rootDir.dir(dir) );\n const libOpts = { ...defaults.library, ...(options.library||{}) };\n const library = new Library(libDirs, libOpts);\n\n this.case = {\n ...defaults.case,\n ...(options.case||{})\n };\n\n this.state = {\n rootDir,\n config,\n library\n }\n\n addDebug(this, options.debug, options.debugPrefix, options.debugColor);\n this.debug('root dir: ', rootDir.path());\n this.debug('config dir: ', cfgDir.map( d => d.path() ));\n this.debug('libDirs: ', libDirs);\n this.debug('libOpts: ', libOpts);\n }\n\n /**\n * Fetch a new {@link Directory} object for a sub-directory of the workspace directory.\n * @param {string} path - directory path relative to the workspace directory\n * @param {Object} [options] - directory configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @return {Object} a {@link Directory} object\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\n /**\n * Fetch a new {@link File} object for a file in the workspace.\n * @param {string} path - file path relative to the workspace directory\n * @param {Object} [options] - file configuration options\n * @param {String} [options.codec] - codec for encoding/decoding file data\n * @param {Boolean} [options.encoding=utf8] - character encoding for the file\n * @return {Object} a {@link File} object\n */\n file(path, options) {\n this.debug(\"file(%s, %o)\", path, options);\n return this.state.rootDir.file(path, options)\n }\n\n /**\n * Read the content of a file in the workspace.\n * @param {string} path - file path relative to the workspace directory\n * @param {Object} [options] - directory configuration options\n * @param {Boolean} [options.codec] - codec for encoding/decoding file data\n * @param {Boolean} [options.encoding=utf8] - character encoding for the file\n * @return {Promise} fulfills with the file content\n * @example\n * file('myfile.txt').read().then( text => console.log(text) );\n * @example\n * file('myfile.json', { codec: 'json' }).read().then( data => console.log(data) );\n * @example\n * file('myfile.json').read({ codec: 'json' }).then( data => console.log(data) );\n */\n read(path, options) {\n this.debug(\"read(%s, %o)\", path, options);\n return this.file(path, options).read();\n }\n\n /**\n * Writes content to a file. If a `codec` has been specified then the content will be encoded.\n * @param {string} path - file path relative to the workspace directory\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 * @param {Boolean} [options.encoding=utf8] - codec for encoding/decoding file data\n * @return {Promise} fulfills with the file object\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(path, data, options) {\n this.debug(\"write(%s, %o, %o)\", path, data, options);\n return this.file(path, options).write(data);\n }\n\n /**\n * Fetch the configuration directory or a directory relative to it\n * @param {string} [path] - file path relative to the configuration directory\n * @param {Object} [options] - directory configuration options\n * @param {String} [options.codec] - codec for encoding/decoding data for files in the directory\n * @param {Boolean} [options.encoding=utf8] - character encoding for files in the directory\n * @return {Object} a {@link Directory} object\n */\n configDir(path, options) {\n this.debug(\"configDir(%s, %o)\", path, options);\n return hasValue(path)\n ? this.state.configDir.dir(path, options)\n : this.state.configDir;\n }\n\n /**\n * Fetches configuration data from a file in the configuration directory or returns the\n * {@link Config} object itself if no file uri is specified.\n * @param {string} [uri] - file path relative to the configuration directory\n * @param {Object} [defaults] - default configuration options if file isn't found\n * @return {Promise} fulfills to the configuration data read from the file\n * @example\n * workspace.config('myfile').then(\n * config => console.log(\"Loaded myfile config: \", config)\n * );\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\n /**\n * Loads a Javscript library from the library directory or returns the\n * {@link Library} object itself if no file uri is specified.\n * @param {string} [uri] - file path relative to the library directory\n * @return {Promise} fulfills to the configuration data read from the file\n * @example\n * workspace.library('mylib').then(\n * exports => console.log(\"Loaded mylib exports: \", exports)\n * );\n */\n async library(uri) {\n this.debug(\"library(%s, %o)\", uri);\n return hasValue(uri)\n ? this.state.library.library(uri)\n : this.state.library;\n }\n\n /**\n * Loads a Javscript library from the library directory and instantiates a\n * component.\n * @param {String} uri - component base name\n * @param {Object} [props] - optional configuration properties\n * @return {Promise} fulfills to a newly instantiated component\n * @example\n * workspace.component('mycomp').then(\n * component => console.log(\"Created component: \", component)\n * );\n */\n async component(uri, props) {\n const [base, fragment] = uri.split('#', 2);\n const cfgname = this.convertCase('config', base);\n const config = await this.config(cfgname, {});\n const libname = config.component?.library || this.convertCase('library', base);\n const lib = await this.library(libname);\n const exp = fragment || 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 return comp;\n }\n\n convertCase(type, uri) {\n const fn = this.case[type];\n return fn\n ? fn(uri)\n : uri;\n }\n}\n\nexport const workspace = (dir, options) => new Workspace(dir, options);\n\nexport default Workspace;"],"names":["ANSIColors","reset","bold","bright","dark","black","red","green","yellow","blue","magenta","cyan","grey","white","fg","bg","ANSIRGB","rgb","r","g","b","ANSIescapeCode","color","base","match","parseInt","isHex","triple","splitList","length","isRGB","ANSIRGBescapeCodes","codes","pair","split","hue","pop","code","push","shade","shift","join","ANSIescapeCodes","ANSIescape","colors","col","isObject","escapes","ANSIresetCode","ANSIreset","text","palette","Object","entries","reduce","key","value","brightBlack","brightRed","brightGreen","brightYellow","brightBlue","brightMagenta","brightCyan","brightGrey","brightWhite","darkBlack","darkRed","darkGreen","darkYellow","darkBlue","darkMagenta","darkCyan","darkGrey","darkWhite","Debugger","enabled","prefix","format","args","console","log","bind","doNothing","addDebug","obj","debug","Component","constructor","workspace","props","this","debugPrefix","debugColor","initComponent","quotedEscapes","f","n","t","v","matchDoubleQuotedString","string","replace","all","one","matchSingleQuotedString","splitDataPath","path","part","parts","maybe","optional","slice","fail","dataPath","data","root","done","word","opts","isArray","next","noValue","defaults","codec","jsExt","Config","DirPath","dir","options","super","params","state","firstFileWithExt","uri","exts","makeOptions","dirs","ext","file","exists","jsFile","config","fragment","import","read","Library","map","library","load","appStatus","app","async","message","error","process","env","DEBUG","prompt","question","name","isString","default","prompts","type","initial","confirm","isBoolean","select","choices","title","selected","cmdLine","argv","cmdLineFlags","splitHash","others","short","on","flags","splice","hasValue","cmdLineArg","argPrompt","cmdLineArgs","argPrompts","results","response","DOT_ENV","LINE","findDotenv","filename","bin","cwd","walkup","lookedIn","search","d","dotEnv","up","parseDotenv","lines","toString","exec","trim","maybeQuote","dotenv","addToProcessEnv","assign","exit","quit","abort","verboseColor","titleColor","underlineColor","infoColor","tickColor","questionColor","answerColor","sectionNewlines","vcol","command","Command","description","version","yes","option","verbose","quiet","filter","arg","forEach","about","deflt","handler","pattern","undefined","commands","cmd","argument","arguments","matchArgName","action","values","parse","cmdline","stdout","write","prompter","override","noArg","validate","required","invalid","Number","isInteger","findIndex","i","answer","info","section","cancelled","answers","onCancel","tcol","ucol","icol","nl","newlines","uline","repeat","qcol","acol","requiredParam","requiredParams","names","allParams","anyParams","found","nlist","joinListOr","charTypes","border","background","fill","colours","foreground","picture","source","size","elapsed","preparePicture","charType","types","chars","char","lineLength","longest","line","Math","max","prepareColours","formatters","colour","formatPicture","formatElapsed","s","m","floor","x","padStart","Progress","pixels","count","lastCount","lastPixel","startTime","now","epochSeconds","elapsedCol","showElapsed","debugging","progress","end","start","pictureSegment","remains","substring","last","concat","printProgress","printRemains","configFiles","dataFile","envFile","envComments","envSections","writeData","writeEnv","compact","scriptName","allDone","warning","setup","runSetup","rootDir","configFile","findFirstFile","preprocess","nonsave","save","no_prefix","env_prefix","envPrefix","envVar","envvar","env_var","toUpperCase","program","findProgram","extract","gap","output","comment","line2","save_env","safe","envName","envExtra","extraFile","envFileText","PATH","splitLines","script","at","watcher","scanning","watching","change","starting","stopping","stopped","failed","watch","watcherFunctions","cmdOptions","restart","programArgs","watcherStatus","child","ready","kidproc","spawn","stdio","signal","sleep","then","changed","debounce","kill","chokidar","event","helpText","watcherHelpText","help","barf","w","h","progText","paths","padEnd","errMsg","Workspace","fsDir","cfgDir","cfgOpts","libDirs","libOpts","case","configDir","component","cfgname","convertCase","libname","lib","exp","export","fn"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abw/badger",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
4
4
  "description": "Component based framework and utility modules",
5
5
  "type": "module",
6
6
  "main": "dist/badger.cjs.js",