{"version":3,"sources":["jsdelivr-header.js","/npm/mkjs-cli@0.3.0/build/index.js"],"names":[],"mappings":"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","file":"/npm/mkjs-cli@0.3.0/build/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/mkjs-cli@0.3.0/build/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","#!/usr/bin/env node\n\nconst fs = require('fs');\nconst cp = require('child_process');\nconst path = require('path');\nrequire('colors');\n\nconst targets = require('./targets/parser.js');\n\nconst debug = {\n\tlog: (s, ...a_args) => console.log(`| ${s}`, ...a_args),\n\twarn: (s, ...a_args) => console.warn(`# ${s}`, ...a_args),\n\terror: (s, ...a_args) => console.error(`* ${s}`, ...a_args),\n};\n\nconst gobble = (s_text) => {\n\tlet m_pad = /^(\\s+)/.exec(s_text.replace(/^\\n+/, ''));\n\tif(m_pad) {\n\t\treturn s_text.replace(new RegExp(`\\\\n${m_pad[1]}`, 'g'), '\\n\\t').trim();\n\t}\n\telse {\n\t\treturn s_text.trim();\n\t}\n};\n\n\nasync function load(p_mkfile, g_args) {\n\tlet z_mkfile;\n\ttry {\n\t\tz_mkfile = require(p_mkfile);\n\t}\n\tcatch(e_require) {\n\t\tthrow new Error(`error while trying to load mk.js file: ${e_require.message}\\n`.red+e_require.stack);\n\t}\n\n\tlet h_mkfile;\n\n\t// descriptor is callback\n\tif('function' === typeof z_mkfile) {\n\t\th_mkfile = z_mkfile(new helper_mkfile());\n\t}\n\t// descriptor is static\n\telse {\n\t\th_mkfile = z_mkfile;\n\t}\n\n\t// make mkfile object\n\tlet k_mkfile = new mkfile(h_mkfile);\n\n\t// mkfile mtime\n\tk_mkfile.mtime = fs.statSync(p_mkfile).mtime;\n\n\t// ref targets\n\tlet a_targets = g_args.targets || [];\n\n\t// default to 'all'\n\tif(!a_targets.length) a_targets = ['all'];\n\n\t// invoke targets\n\tlet hm_runners = new Map();\n\tlet a_makes = await k_mkfile.make(a_targets, hm_runners);\n\n\tif(g_args.watch) {\n\t\tlet h_listeners = {};\n\n\t\tfor(let g_make of a_makes) {\n\t\t\tfor(let s_file in g_make.files) {\n\t\t\t\tlet a_w_targets = g_make.files[s_file];\n\t\t\t\tlet f_listener = () => {\n\t\t\t\t\tdebug.log(`updated ${s_file}`.green);\n\t\t\t\t\tk_mkfile.make(a_w_targets, new Map());\n\t\t\t\t};\n\t\t\t\tfs.watchFile(s_file, f_listener);\n\t\t\t\th_listeners[s_file] = f_listener;\n\t\t\t}\n\t\t}\n\n\t\t// watch mkfile\n\t\tlet f_listener_mk = () => {\n\t\t\tdebug.log(`updated ${p_mkfile}`.green);\n\t\t\t// remove watch listeners\n\t\t\tfor(let s_file in h_listeners) {\n\t\t\t\tfs.unwatchFile(s_file, h_listeners[s_file]);\n\t\t\t}\n\n\t\t\t// unwatch self\n\t\t\tfs.unwatchFile(p_mkfile, f_listener_mk);\n\n\t\t\t// rerun mk\n\t\t\tload(p_mkfile, g_args);\n\t\t};\n\t\tfs.watchFile(p_mkfile, f_listener_mk);\n\n\t\t// print\n\t\tdebug.log(`watching files...`.blue);\n\t}\n}\n\nclass helper_mkfile {\n\tconstructor() {\n\n\t}\n\n\tpaths(a_files) {\n\t\tlet a_paths = [];\n\t\tfor(let z_file of a_files) {\n\t\t\tif('string' === typeof z_file) {\n\t\t\t\ta_paths.push(z_file);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfor(let s_dir in z_file) {\n\t\t\t\t\ta_paths.push(...this.paths(z_file[s_dir]).map(s => `${s_dir}/${s}`));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn a_paths;\n\t}\n}\n\nclass bash {\n\tstatic prepare(h_variables, a_args=[]) {\n\t\t// bash variables\n\t\treturn `set -- ${a_args.map(s => `\"${s.replace(/\"/g, '\\\\\"')}\"`).join(' ')}; `\n\t\t\t+Object.keys(h_variables).map((s_var) => {\n\t\t\t\tlet z_value = h_variables[s_var];\n\n\t\t\t\t// value is string\n\t\t\t\tif('string' === typeof z_value) {\n\t\t\t\t\treturn `${s_var}=\"${z_value.replace(/\"/g, '\\\\\"')}\"; `;\n\t\t\t\t}\n\t\t\t\t// value is array\n\t\t\t\telse if(Array.isArray(z_value)) {\n\t\t\t\t\treturn `${s_var}=(${z_value.map(z => `'${z}'`).join(' ')}); `;\n\t\t\t\t}\n\t\t\t\t// other\n\t\t\t\telse {\n\t\t\t\t\tthrow new Error(`unexpected value for variable '${s_var}': ${z_value}`);\n\t\t\t\t}\n\t\t\t}).join('');\n\t}\n\n\tstatic spawn_sync(s_cmds, h_variables, a_args) {\n\t\tlet s_exec = this.prepare(h_variables, a_args)+s_cmds.trim();\n\t\treturn cp.spawnSync('/bin/bash', ['-c', s_exec], {\n\t\t\tencoding: 'utf8',\n\t\t\ttimeout: 1000,\n\t\t});\n\t}\n\n\tstatic spawn(s_cmds, h_variables, a_args) {\n\t\tlet s_exec = this.prepare(h_variables, a_args)+s_cmds.trim();\n\t\treturn cp.spawn('/bin/bash', ['-c', s_exec], {\n\t\t\tencoding: 'utf8',\n\t\t});\n\t}\n}\n\n\nclass err_no_target extends Error {}\n\n\nclass mkfile {\n\tconstructor(h_mkfile) {\n\t\tlet b_phony_pattern = false;\n\t\tlet r_phony = /^[\\w-]+$/;\n\t\tlet a_phonies = [];\n\t\tlet h_patterns = {};\n\t\tlet h_recipes = {};\n\n\t\t// normalize mkfile\n\t\tfor(let s_key in h_mkfile) {\n\t\t\tlet z_value = h_mkfile[s_key];\n\n\t\t\t// pattern definition\n\t\t\tif('&' === s_key[0]) {\n\t\t\t\tlet s_value;\n\n\t\t\t\t// already a string\n\t\t\t\tif('string' === typeof z_value) {\n\t\t\t\t\ts_value = z_value;\n\t\t\t\t}\n\t\t\t\t// regex\n\t\t\t\telse if(z_value instanceof RegExp) {\n\t\t\t\t\ts_value = z_value.toString().slice(1, -1);\n\n\t\t\t\t\t// cannot use flags\n\t\t\t\t\tif(z_value.flags) {\n\t\t\t\t\t\tthrow new Error(`cannot use regex flags in pattern def since they are used in substitution`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// other\n\t\t\t\telse {\n\t\t\t\t\tthrow new TypeError(`unrecognized type for pattern def '${s_key}': ${z_value}`);\n\t\t\t\t}\n\n\t\t\t\t// save pattern\n\t\t\t\th_patterns[s_key.slice(1)] = s_value;\n\t\t\t}\n\t\t\t// phony override\n\t\t\telse if('.PHONY' === s_key) {\n\t\t\t\t// boolean; enable/disable default pattern\n\t\t\t\tif('boolean' === typeof z_value) {\n\t\t\t\t\tb_phony_pattern = z_value;\n\t\t\t\t}\n\t\t\t\t// regex\n\t\t\t\telse if(z_value instanceof RegExp) {\n\t\t\t\t\tb_phony_pattern = true;\n\t\t\t\t\tr_phony = z_value;\n\t\t\t\t}\n\t\t\t\t// targets in string\n\t\t\t\telse if('string' === typeof z_value) {\n\t\t\t\t\ta_phonies = z_value.trim().split(/\\s+/g);\n\t\t\t\t}\n\t\t\t\t// list of targets\n\t\t\t\telse if(Array.isArray(z_value)) {\n\t\t\t\t\ta_phonies = z_value;\n\t\t\t\t}\n\t\t\t\t// invalid\n\t\t\t\telse {\n\t\t\t\t\tthrow new TypeError('unrecognized type for .PHONY value');\n\t\t\t\t}\n\t\t\t}\n\t\t\t// otherwise it is a build recipe\n\t\t\telse {\n\t\t\t\t// assume phony target\n\t\t\t\tlet b_phony = true;\n\n\t\t\t\t// normalize recipe\n\t\t\t\tlet g_recipe = {deps:[]};\n\n\t\t\t\t// value is string\n\t\t\t\tif('string' === typeof z_value) {\n\t\t\t\t\t// dep targets in string\n\t\t\t\t\tg_recipe.deps = z_value.trim().split(/\\s+/g);\n\t\t\t\t}\n\t\t\t\t// value is function\n\t\t\t\telse if('function' === typeof z_value) {\n\t\t\t\t\t// runtime target\n\t\t\t\t\tg_recipe.deps = [z_value];\n\t\t\t\t}\n\t\t\t\t// value is array\n\t\t\t\telse if(Array.isArray(z_value)) {\n\t\t\t\t\t// list of targets\n\t\t\t\t\tg_recipe.deps = z_value;\n\t\t\t\t}\n\t\t\t\t// value is simple object\n\t\t\t\telse if('object' === typeof z_value && Object === z_value.constructor) {\n\t\t\t\t\t// phonyness made explicit\n\t\t\t\t\tif('phony' in z_value) {\n\t\t\t\t\t\tb_phony = !!z_value.phony;\n\t\t\t\t\t}\n\t\t\t\t\t// implicit; phony test is pattern\n\t\t\t\t\telse if(b_phony_pattern) {\n\t\t\t\t\t\t// set phony as result of regex test\n\t\t\t\t\t\tb_phony = r_phony.test(s_key);\n\t\t\t\t\t}\n\t\t\t\t\t// phony test is array and this is in list; mark as phony\n\t\t\t\t\telse if(a_phonies.includes(s_key)) {\n\t\t\t\t\t\tb_phony = true;\n\t\t\t\t\t}\n\t\t\t\t\t// otherwise, not phony\n\t\t\t\t\telse {\n\t\t\t\t\t\tb_phony = false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// copy properties from value onto recipe spec\n\t\t\t\t\tObject.assign(g_recipe, z_value);\n\t\t\t\t}\n\t\t\t\t// invalid value\n\t\t\t\telse {\n\t\t\t\t\tthrow new TypeError(`unrecognized value type for recipe '${s_key}': ${z_value}`);\n\t\t\t\t}\n\n\t\t\t\t// phony\n\t\t\t\tif(b_phony) {\n\t\t\t\t\tg_recipe.phony = true;\n\t\t\t\t}\n\t\t\t\t// not phony\n\t\t\t\telse {\n\t\t\t\t\t// but value has no .run property\n\t\t\t\t\tif('string' === typeof z_value || Array.isArray(z_value) || !('run' in z_value)) {\n\t\t\t\t\t\tthrow new Error(`non-phony recipe for '${s_key}' target has no '.run' property`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// normal; not phony\n\t\t\t\t\tObject.assign(g_recipe, z_value, {phony:false});\n\t\t\t\t}\n\n\t\t\t\t// save target\n\t\t\t\th_recipes[s_key] = Object.assign(g_recipe, {target:s_key});\n\t\t\t}\n\t\t}\n\n\t\t// save fields\n\t\tObject.assign(this, {\n\t\t\tpatterns: h_patterns,\n\t\t\trecipes: h_recipes,\n\t\t\tbash: new bash(),\n\t\t\tmtime: 0,\n\t\t});\n\t}\n\n\tasync make(a_targets, hm_runners) {\n\t\t// make distinct\n\t\ta_targets = [...new Set(a_targets)];\n\n\t\t// prep empty scope\n\t\tlet g_scope = {\n\t\t\tvariables: {},\n\t\t\tconcurrent: new Map(),\n\t\t\tencountered: new Map(),\n\t\t\trunners: hm_runners,\n\t\t};\n\n\t\tlet g_state = {};\n\n\t\t// run each make target\n\t\tlet a_makes = await Promise.all(a_targets.map((s_target) => {\n\t\t\t// print\n\t\t\tdebug.log(`mk ${s_target}`.white);\n\n\t\t\t// run\n\t\t\treturn this.run(s_target, Object.assign(g_scope, {stack:[]}), s_target, g_state);\n\t\t}));\n\n\t\t// each make target\n\t\tfor(let i_target=0; i_target<a_makes.length; i_target++) {\n\t\t\tif(!a_makes[i_target].mtimes[0]) {\n\t\t\t\tdebug.warn(`nothing to make for target: ${a_targets[i_target]}`.yellow);\n\t\t\t}\n\t\t}\n\n\t\treturn a_makes;\n\t}\n\n\tasync run(s_target, g_scope, s_tag, g_state) {\n\t\tlet {\n\t\t\trecipes: h_recipes,\n\t\t} = this;\n\n\t\tlet hm_runners = g_scope.runners;\n\n\t\t// debug\n\t\tdebug.log(`[${s_tag}]: run ${s_target}`.cyan);\n\n\t\t// already running\n\t\tif(hm_runners.has(s_target)) {\n\t\t\treturn await hm_runners.get(s_target);\n\t\t}\n\n\t\t// name of recipe\n\t\tlet s_recipe = s_target;\n\n\t\t// context for this run\n\t\tlet g_context = {\n\t\t\tfiles: {},\n\t\t\ttarget: s_target,\n\t\t\tvariables: Object.create(g_scope.variables),\n\t\t};\n\n\t\t// no exact matches\n\t\tif(!(h_recipes.hasOwnProperty(s_target))) {\n\t\t\t// the pattern to use\n\t\t\tlet g_pattern;\n\n\t\t\t// all patterns that match target\n\t\t\tlet a_matching_patterns = [];\n\n\t\t\t// test against all patterns\n\t\t\tfor(let s_key in h_recipes) {\n\t\t\t\tlet h_matches = this.matches(s_target, s_key);\n\n\t\t\t\t// positive match\n\t\t\t\tif(h_matches) {\n\t\t\t\t\ta_matching_patterns.push({\n\t\t\t\t\t\tkey: s_key,\n\t\t\t\t\t\tmatches: h_matches,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// number of matching patterns\n\t\t\tlet nl_matching_patterns = a_matching_patterns.length;\n\n\t\t\t// no patterns match\n\t\t\tif(!nl_matching_patterns) {\n\t\t\t\t// glob for all targets\n\t\t\t\tlet a_files = this.eval(/* syntax: bash */ `$(\n\t\t\t\t\t# remove space\n\t\t\t\t\tIFS=\"$(printf '\\\\n\\\\t')\"\n\n\t\t\t\t\t# glob target\n\t\t\t\t\t__target=\"${s_target}\"\n\n\t\t\t\t\t# use for-loop\n\t\t\t\t\tfor __file in $__target; do\n\t\t\t\t\t\techo \"$__file\"\n\t\t\t\t\tdone\n\t\t\t\t)`, g_context);\n\n\t\t\t\t// no targets\n\t\t\t\tif(!a_files.length) {\n\t\t\t\t\tthrow new err_no_target(`glob returned no files: '${s_target}'`);\n\t\t\t\t}\n\n\t\t\t\t// set file map\n\t\t\t\tlet h_files = {};\n\t\t\t\tfor(let s_file of a_files) {\n\t\t\t\t\th_files[s_file] = [];\n\t\t\t\t}\n\n\t\t\t\t// each target\n\t\t\t\treturn {\n\t\t\t\t\tfiles: h_files,\n\t\t\t\t\tmtimes: a_files.map((s_file) => {\n\t\t\t\t\t\tlet g_stat;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// stat file\n\t\t\t\t\t\t\tg_stat = fs.statSync(s_file);\n\n\t\t\t\t\t\t\t// directory\n\t\t\t\t\t\t\tif(g_stat.isDirectory()) {\n\t\t\t\t\t\t\t\treturn Infinity;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// regular file\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t// modification time\n\t\t\t\t\t\t\t\tlet xt_mtime = g_stat.mtimeMs;\n\n\t\t\t\t\t\t\t\t// return dependency struct\n\t\t\t\t\t\t\t\treturn xt_mtime;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// no such file\n\t\t\t\t\t\tcatch(e_stat) {\n\t\t\t\t\t\t\tthrow new err_no_target(`no recipe to make target, or dependency file not exists: '${s_target}'`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t}\n\t\t\t// multiple patterns match\n\t\t\telse if(nl_matching_patterns > 1) {\n\t\t\t\t// filter recipes that are not consensually a case\n\t\t\t\tlet a_nonconsual = a_matching_patterns\n\t\t\t\t\t.filter(g => !h_recipes[g.key].case)\n\t\t\t\t\t.map(g => ` '${g.key}'`);\n\n\t\t\t\t// there exist nonconsensual cases\n\t\t\t\tif(a_nonconsual.length) {\n\t\t\t\t\tthrow new Error(`multiple non-consensual patterns match target '${s_target}':${a_nonconsual}`\n\t\t\t\t\t\t+`\\n\tenable order-based matching by adding '.case' property to each candidate recipe and first matching recipe will be used`);\n\t\t\t\t}\n\n\t\t\t\t// okay, use first matching recipe\n\t\t\t\tg_pattern = a_matching_patterns[0];\n\t\t\t}\n\t\t\t// single match\n\t\t\telse {\n\t\t\t\tg_pattern = a_matching_patterns[0];\n\t\t\t}\n\n\t\t\t// set recipe name\n\t\t\ts_recipe = g_pattern.key;\n\n\t\t\t// set match variables\n\t\t\tObject.assign(g_context.variables, g_pattern.matches);\n\t\t}\n\n\t\t// ref recipe\n\t\tlet g_recipe = h_recipes[s_recipe];\n\n\t\t// save recipe name to context\n\t\tg_context.recipe = s_recipe;\n\n\t\t// not phony\n\t\tif(!g_recipe.phony) {\n\t\t\ttry {\n\t\t\t\t// stat file\n\t\t\t\tlet g_stat = fs.statSync(s_target);\n\n\t\t\t\t// is a directory\n\t\t\t\tif(g_stat.isDirectory()) {\n\t\t\t\t\t// set artificial modification time\n\t\t\t\t\tg_context.mtime = Infinity;\n\n\t\t\t\t\tdebug.log(`[${s_tag}] '${s_target}' is a directory that already exists`);\n\t\t\t\t}\n\t\t\t\t// regular file\n\t\t\t\telse {\n\t\t\t\t\t// fetch modification time\n\t\t\t\t\tg_context.mtime = g_stat.mtimeMs;\n\n\t\t\t\t\t// // save file\n\t\t\t\t\t// g_context.files[s_target] = [];\n\n\t\t\t\t\tdebug.log(`[${s_tag}] '${s_target}' modified ${new Date(g_context.mtime)}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// file not exists\n\t\t\tcatch(e_stat) {\n\t\t\t\t// always run this rule\n\t\t\t\tg_context.mtime = 0;\n\t\t\t}\n\t\t}\n\n\t\t// destructue scope object\n\t\tlet {\n\t\t\tstack: a_stack,\n\t\t\tconcurrent: hm_concurrent,\n\t\t\tencountered: hm_encountered,\n\t\t} = g_scope;\n\n\t\t// target already encountered in stack\n\t\tif(a_stack.includes(s_target)) {\n\t\t\t// avoid recursion\n\t\t\tthrow new Error(`infinite recusion detected at target '${s_target}'${s_recipe === s_target? '': ` applied to recipe pattern '${s_recipe}'`}`);\n\t\t}\n\n\t\t// target running concurrently\n\t\tif(hm_concurrent.has(s_target) && hm_concurrent.get(s_target).size) {\n\t\t\t// target does not allow for concurrency\n\t\t\tif(!g_recipe.concurrency) {\n\t\t\t\tthrow new Error(`target '${s_target}' is already running in another task stack:`\n\t\t\t\t\t+'\\n\t'+JSON.stringify(hm_concurrent.get(s_target), null, '\\t')\n\t\t\t\t\t+`\\n\tthis is usually a dangerous practice since it could cause race conditions, however you can explicitly allow this recipe to be run concurrently by adding a '.concurrency' property`);\n\t\t\t}\n\t\t}\n\n\t\t// target already encountered\n\t\tif(hm_encountered.has(s_target)) {\n\t\t\t// target does not allow for concurrency\n\t\t\tif(!g_recipe.concurrency) {\n\t\t\t\t// warn\n\t\t\t\tdebug.warn((`target '${s_target}' was already run in another task stack:`\n\t\t\t\t\t+'\\n\t'+JSON.stringify(hm_encountered.get(s_target), null, '\\t')\n\t\t\t\t\t+`\\n\tthis is usually a dangerous practice since it could cause race conditions, however you can explicitly allow this recipe to be run concurrently by adding a '.concurrency' property`).yellow);\n\t\t\t}\n\t\t}\n\n\t\t// add target to stack\n\t\ta_stack.push(s_target);\n\n\t\t// target is running elsewhere\n\t\tif(hm_concurrent.has(s_target)) {\n\t\t\t// add this stack to map\n\t\t\thm_concurrent.get(s_target).add(a_stack);\n\t\t}\n\t\t// target not running elsewhere\n\t\telse {\n\t\t\t// put stack into map\n\t\t\thm_concurrent.set(s_target, new Set([a_stack]));\n\t\t}\n\n\t\t// target was encountered elsewhere\n\t\tif(hm_encountered.has(s_target)) {\n\t\t\t// add this stack to map\n\t\t\thm_encountered.get(s_target).add(a_stack);\n\t\t}\n\t\t// target not seen elsewhere\n\t\telse {\n\t\t\t// put stack into map\n\t\t\thm_encountered.set(s_target, new Set([a_stack]));\n\t\t}\n\n\n\t\t// run recipe\n\t\tlet dp_runner = new Promise(async(fk_run) => {\n\t\t\t// run dependencies first\n\t\t\tlet a_deps = await Promise.all(\n\t\t\t\tg_recipe.deps.map(z_dep => Promise.all(\n\t\t\t\t\t// each resolved dependency target\n\t\t\t\t\tthis.resolve(z_dep, g_context).map((s_dep_target) => {\n\t\t\t\t\t\t// create new scope\n\t\t\t\t\t\tlet g_dep_scope = Object.assign({}, g_scope, {\n\t\t\t\t\t\t\t// stack needs to be cloned\n\t\t\t\t\t\t\tstack: [...g_scope.stack],\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// run dependency\n\t\t\t\t\t\treturn new Promise(async(fk_dep) => {\n\t\t\t\t\t\t\tlet a_runs = await this.run(s_dep_target, g_dep_scope, s_target, g_state)\n\t\t\t\t\t\t\t\t.catch((e_run) => {\n\t\t\t\t\t\t\t\t\t// allow no target exceptions\n\t\t\t\t\t\t\t\t\tif(!(e_run instanceof err_no_target)) {\n\t\t\t\t\t\t\t\t\t\tthrow e_run;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tlet h_files = {};\n\t\t\t\t\t\t\tif(a_runs) {\n\t\t\t\t\t\t\t\t// debugger;\n\t\t\t\t\t\t\t\tfor(let s_file in a_runs.files) {\n\t\t\t\t\t\t\t\t\tlet a_files = a_runs.files[s_file].length? a_runs.files[s_file]: [s_target];\n\n\t\t\t\t\t\t\t\t\tif(s_file in h_files) h_files[s_file].push(...a_files);\n\t\t\t\t\t\t\t\t\telse h_files[s_file] = a_files;\n\n\t\t\t\t\t\t\t\t\tif(s_file in g_context.files) g_context.files[s_file].push(...a_files);\n\t\t\t\t\t\t\t\t\telse g_context.files[s_file] = a_files;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn fk_dep(Object.assign(a_runs || {\n\t\t\t\t\t\t\t\tfiles: h_files,\n\t\t\t\t\t\t\t\tmtimes: [0],\n\t\t\t\t\t\t\t}, {target:s_dep_target}));\n\t\t\t\t\t\t});\n\t\t\t\t\t}))\n\t\t\t\t));\n\n\n\t\t\t// dependencies => variables $n (and update context deps)\n\t\t\tlet a_dep_targets = g_context.deps = a_deps.reduce((a_out, a_in) => [...a_out, ...a_in.map(g => g.target)], []);\n\n\t\t\t// only if target is newer than all dependencies and mkfile is older\n\t\t\tif(g_context.mtime && this.mtime < g_context.mtime && a_deps.every(a => a.every(g => g.mtimes.every(xt_mtime => g_context.mtime >= xt_mtime)))) {\n\t\t\t\t// skip build\n\t\t\t\tdebug.warn(`nothing to make for ${s_target}`.yellow);\n\t\t\t}\n\t\t\t// otherwise, build\n\t\t\telse {\n\t\t\t\t// run recipe\n\t\t\t\tif(g_recipe.run) {\n\t\t\t\t\tlet z_run = g_recipe.run;\n\n\t\t\t\t\tawait new Promise((fk_recipe) => {\n\t\t\t\t\t\tlet s_run = z_run;\n\n\t\t\t\t\t\t// run is a function\n\t\t\t\t\t\tif('function' === typeof z_run) {\n\t\t\t\t\t\t\ts_run = z_run(g_context.variables, g_context.deps);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// run is not a string\n\t\t\t\t\t\tif('string' !== typeof s_run) {\n\t\t\t\t\t\t\tthrow new TypeError(`invalid run type: ${s_run}`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet s_exec = this.special(s_run, g_context);\n\n\t\t\t\t\t\tdebug.log(`[${s_tag}] args: ${JSON.stringify(a_dep_targets)}`.blue);\n\t\t\t\t\t\tdebug.log(`[${s_tag}] vars: ${JSON.stringify(g_context.variables)}`.blue);\n\t\t\t\t\t\tdebug.log(`[${s_tag}] > ${gobble(s_exec)}`.green);\n\n\t\t\t\t\t\tlet u_run = bash.spawn(s_exec, g_context.variables, a_dep_targets);\n\n\t\t\t\t\t\tlet s_buffer_stdout = '';\n\t\t\t\t\t\tu_run.stdout.on('data', (s_data) => {\n\t\t\t\t\t\t\t// append to buffer\n\t\t\t\t\t\t\ts_buffer_stdout += s_data;\n\n\t\t\t\t\t\t\t// print each newline\n\t\t\t\t\t\t\tlet a_lines = s_buffer_stdout.split(/\\n/g);\n\t\t\t\t\t\t\tfor(let s_line of a_lines.slice(0, -1)) {\n\t\t\t\t\t\t\t\tdebug.log(`[[${s_target}]]:`.magenta+` ${s_line}`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// set to final un-terminated line\n\t\t\t\t\t\t\ts_buffer_stdout = a_lines[a_lines.length-1];\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tlet s_buffer_stderr = '';\n\t\t\t\t\t\tu_run.stderr.on('data', (s_data) => {\n\t\t\t\t\t\t\t// append to buffer\n\t\t\t\t\t\t\ts_buffer_stderr += s_data;\n\n\t\t\t\t\t\t\t// print each newline\n\t\t\t\t\t\t\tlet a_lines = s_buffer_stderr.split(/\\n/g);\n\t\t\t\t\t\t\tfor(let s_line of a_lines.slice(0, -1)) {\n\t\t\t\t\t\t\t\tdebug.error(`[[${s_target}]]:`.red+` ${s_line}`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// set to final un-terminated line\n\t\t\t\t\t\t\ts_buffer_stderr = a_lines[a_lines.length-1];\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tu_run.on('exit', (n_code) => {\n\t\t\t\t\t\t\t// print last of buffers\n\t\t\t\t\t\t\tif(s_buffer_stdout) {\n\t\t\t\t\t\t\t\tdebug.log(`[[${s_target}]]:`.magenta+` ${s_buffer_stdout}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(s_buffer_stderr) {\n\t\t\t\t\t\t\t\tdebug.error(`[[${s_target}]]:`.red+` ${s_buffer_stderr}`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// error\n\t\t\t\t\t\t\tif(n_code) {\n\t\t\t\t\t\t\t\t// let user know in case they are watching files\n\t\t\t\t\t\t\t\tprocess.stdout.write('\\x07');\n\t\t\t\t\t\t\t\tthrow new Error(`recipe commands resulted in non-zero exit code '${n_code}' for target '${s_target}'`);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// resolve\n\t\t\t\t\t\t\tfk_recipe();\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// update mtime\n\t\t\t\tg_context.mtime = Date.now();\n\t\t\t}\n\n\t\t\t// remove this invocation from concurrency\n\t\t\thm_concurrent.get(s_target).delete(a_stack);\n\n\t\t\t// done running task\n\t\t\tfk_run();\n\t\t});\n\n\t\t//\n\t\thm_runners.set(s_target, dp_runner);\n\n\t\t// done with task\n\t\tawait dp_runner;\n\n\t\t// mtime\n\t\treturn {\n\t\t\tfiles: g_context.files,\n\t\t\tmtimes: [g_context.mtime],\n\t\t};\n\t}\n\n\tmatches(s_target, s_pattern) {\n\t\treturn targets.parse(s_pattern)(s_target, this);\n\t}\n\n\tspecial(s_str, g_context) {\n\t\treturn s_str.replace(/(^|[^\\\\])\\$([@#$%^&*<])/g, (s_base, s_preceed, s_char) => {\n\t\t\tlet s_text = (() => {\n\t\t\t\tswitch(s_char) {\n\t\t\t\t\tcase '@': return g_context.target;\n\t\t\t\t\tcase '<': return g_context.deps[0];\n\t\t\t\t\tcase '*': return g_context.deps.join(' ');\n\t\t\t\t\tdefault: throw new Error(`special variable '$${s_char}' not supported`);\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn `${s_preceed}${s_text}`;\n\t\t});\n\t}\n\n\teval(s_str, g_context) {\n\t\t// ref variables\n\t\tlet h_variables = g_context.variables;\n\n\t\t// exec echo on string\n\t\tlet g_echo = bash.spawn_sync(`echo -e \"${this.special(s_str, g_context)}\"`, h_variables);\n\n\t\t// error\n\t\tif(g_echo.status) {\n\t\t\tthrow new Error(`invalid parameterized bash string: '${s_str}'.\\nbash said: ${g_echo.stderr}`);\n\t\t}\n\n\t\treturn g_echo.stdout\n\t\t\t.replace(/\\n$/, '')\n\t\t\t.match(/((?:\\\\ |[^ ])*(?: |$))/g)\n\t\t\t.slice(0, -1)\n\t\t\t.map(s => s.trim().replace(/\\\\ /g, ' '));\n\t}\n\n\tresolve(z_dep, g_context, b_avoid_recursion=false, as_family=new Set()) {\n\t\t// string dependency\n\t\tif('string' === typeof z_dep) {\n\t\t\tlet s_dep = z_dep;\n\n\t\t\t// eval string\n\t\t\treturn this.eval(s_dep, g_context);\n\t\t}\n\t\t// runtime dependency\n\t\telse if('function' === typeof z_dep) {\n\t\t\t// avoid recursion\n\t\t\tif(b_avoid_recursion) {\n\t\t\t\tthrow new Error(`detected dependency callback recursion`);\n\t\t\t}\n\n\t\t\t// fetch deps from callback\n\t\t\tlet z_deps = z_dep(g_context.variables);\n\n\t\t\t// resolve targets (avoiding recursion this time)\n\t\t\treturn this.resolve(z_deps, g_context, true);\n\t\t}\n\t\t// array\n\t\telse if(Array.isArray(z_dep)) {\n\t\t\t// already in family\n\t\t\tif(as_family.has(z_dep)) {\n\t\t\t\tthrow new Error(`detected cyclical array`);\n\t\t\t}\n\n\t\t\t// do not evaluate this object again\n\t\t\tas_family.add(z_dep);\n\n\t\t\t// each target\n\t\t\treturn z_dep.map(z => this.resolve(z, g_context, b_avoid_recursion, as_family));\n\t\t}\n\t\t// invalid type\n\t\telse {\n\t\t\tthrow new TypeError(`unrecognized type for dependency: '${z_dep}' under recipe '${g_context.recipe}'`);\n\t\t}\n\t}\n}\n\n\nif(module === require.main) {\n\tlet h_cli = require('commander')\n\t\t.version(require('../package.json').version, '-v, --version')\n\t\t.option('-n, --dry-run', 'show the targets and commands without executing them')\n\t\t.option('-s, --silent', 'do not echo commands')\n\t\t.option('-w, --watch', 'watch dependency files and re-mk targets')\n\t\t.option('-f, --file', 'use specified mkfile')\n\t\t.arguments('[targets...]')\n\t\t.parse(process.argv);\n\n\tlet g_args = {\n\t\ttargets: h_cli.args,\n\t\twatch: h_cli.watch,\n\t};\n\n\tlet s_mk_file = h_cli.file || 'mk.js';\n\n\tlet p_mkfile = path.join(process.cwd(), s_mk_file);\n\n\t(async() => {\n\t\ttry {\n\t\t\tawait load(p_mkfile, g_args);\n\t\t}\n\t\tcatch(e_mk) {\n\t\t\tconsole.error(`\\n\\nFatal error: ${e_mk.message}`.red+e_mk.stack);\n\t\t\tprocess.exit(1);\n\t\t}\n\t})();\n}\n\n"]}