@kitschpatrol/mdat-config 8.1.0 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +5 -6
- package/init/.vscode/tasks.json +73 -0
- package/package.json +2 -2
- package/readme.md +32 -8
package/bin/cli.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{cosmiconfig as e}from"cosmiconfig";import{TypeScriptLoader as t}from"cosmiconfig-typescript-loader";import{execa as n}from"execa";import r from"fs-extra";import i from"node:fs";import a from"node:path";import{PassThrough as
|
|
3
|
-
`)
|
|
4
|
-
`)}})}function
|
|
5
|
-
`);
|
|
6
|
-
`)
|
|
7
|
-
`);for(let t of r)e.write(`${t}\n`);return 0}async function $(e){let t=k(),n=await Z(),r=[];for(let i of t)r.push({cwdOverride:i,name:`mdat`,optionFlags:n===void 0||n===``?[`--format`]:[`--config`,n,`--format`],subcommands:[e]});return r}await J({commands:{fix:{commands:await $(`expand`),description:`Expand all Mdat content placeholders in your readme.md file(s). ${X.packageRun} ${X.monorepoRun}`,positionalArgumentMode:`none`},init:{configFile:`mdat.config.ts`,configPackageJson:{mdat:{$import:`node_modules/@kitschpatrol/mdat-config/dist/index.js`}},locationOptionFlag:!0},lint:{commands:await $(`check`),description:`Validate that all Mdat content placeholders in your readme.md file(s) have been expanded and are up to date. ${X.packageRun} ${X.monorepoRun}`,positionalArgumentMode:`none`},printConfig:{commands:[{execute:Q,name:Q.name}],description:`Print the effective Mdat configuration. ${X.packageSearch}. ${X.monorepoSearch}.`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Mdat shared configuration tools.`,logColor:`green`,logPrefix:`[Mdat Config]`,name:`ksc-mdat`,order:2});export{};
|
|
2
|
+
import{cosmiconfig as e}from"cosmiconfig";import{TypeScriptLoader as t}from"cosmiconfig-typescript-loader";import{execa as n}from"execa";import r from"fs-extra";import i from"node:fs";import{availableParallelism as a}from"node:os";import o from"node:path";import{PassThrough as s,Transform as c}from"node:stream";import{fileURLToPath as l}from"node:url";import{packageUp as u,packageUpSync as d}from"package-up";import f from"yargs";import{hideBin as p}from"yargs/helpers";import m from"picocolors";import{stripVTControlCharacters as h}from"node:util";import g from"@pinojs/json-colorizer";import _ from"decircular";import v from"deepmerge";import y from"json-stringify-pretty-compact";import{findWorkspaces as b,findWorkspacesRoot as ee}from"find-workspaces";import x from"node:fs/promises";import{loadConfig as te}from"mdat";var ne=`8.3.0`;const S=[`json`,`machine`,`native`],re=S;function C(e){return typeof e==`string`&&S.includes(e)}function w(){let e=process.env.KSC_FORMAT;return C(e)?e:`native`}function ie(){let{argv:e}=process;for(let[t,n]of e.entries()){let r;n===`--format`?r=e[t+1]:n.startsWith(`--format=`)&&(r=n.slice(9)),C(r)&&(process.env.KSC_FORMAT=r)}}function ae(){let{env:e}=process;if(e.NO_COLOR!==void 0&&e.NO_COLOR!==``)return!1;if(e.FORCE_COLOR!==void 0)return e.FORCE_COLOR!==`0`&&e.FORCE_COLOR!==`false`;if(e.TERM===`dumb`)return!1}function T(e,{ciColor:t=!0}={}){let n=ae();return n===void 0?e.isTTY===!0||t&&!!process.env.CI:n}function E(){return w()===`json`?process.stderr:process.stdout}function D(){return w()===`machine`?m.createColors(!1):m.createColors(T(E()))}function O(e){if(!e)return{FORCE_COLOR:`0`,NO_COLOR:`1`};let t=process.env.FORCE_COLOR;return t===void 0||t===``?{FORCE_COLOR:`1`}:{}}const oe=/\s*\n\s*/gv,se=/\r?\n/v;function ce(e){let t=e.message.replaceAll(oe,` `),n=e.rule===void 0?e.tool:`${e.tool}/${e.rule}`;return e.file===void 0?`${e.severity}: ${t} [${n}]`:`${e.file}:${e.line??1}:${e.column??1}: ${e.severity}: ${t} [${n}]`}function le(e,t){let n=(e.file??``).localeCompare(t.file??``);if(n!==0)return n;let r=(e.line??0)-(t.line??0);return r===0?(e.column??0)-(t.column??0):r}function ue(e,t){let n=t.toSorted(le);return{cwd:process.cwd(),diagnostics:n,success:e.every(e=>e.exitCode===0),summary:{errors:n.filter(e=>e.severity===`error`).length,infos:n.filter(e=>e.severity===`info`).length,warnings:n.filter(e=>e.severity===`warning`).length},tools:e,version:1}}function k(e){return h(e).split(se).map(e=>e.trimEnd()).filter(e=>e.trim().length>0)}function A(e){return e instanceof Error&&`exitCode`in e&&typeof e.exitCode==`number`}function j(e){return T(process.stdout,{ciColor:!1})?fe(e):de(e)}function de(e){return y(_(e),{indent:2,replacer(e,t){return typeof t==`function`?t.name:t}})}function fe(e){return g(de(e),{colors:{BRACKET:`gray`}})}const pe=(e,t,n)=>{let r=[...e];for(let[i,a]of t.entries())r[i]===void 0?r[i]=n.cloneUnlessOtherwiseSpecified(a,n):n.isMergeableObject(a)?r[i]=M(e[i],a,n):e.includes(a)||r.push(a);return r};function M(e,t,n={arrayMerge:pe}){return v(e,t,n)}function N(e){let{tasks:t}=e;return Array.isArray(t)?t:[]}function me(e,t){let n=[...N(e)];for(let e of N(t)){let t=n.findIndex(t=>t.label!==void 0&&t.label===e.label);t===-1?n.push(e):n[t]=e}return{...e,...t,tasks:n}}function he(e,t){return e.startsWith(t+o.sep)}function ge(){let e=P(),t=new Set([e]),n=b();if(n!==null)for(let r of n){let n=o.resolve(r.location);he(n,e)&&t.add(n)}return[...t]}function P(){let e=d();if(e===void 0)throw Error(`No package.json found.`);return o.dirname(e)}function F(){let e=ee();return e===null?P():o.resolve(e.location)}function I(e){if(e===`workspace-root`)return F();if(e===`package-dir`)return P();if(typeof e==`string`){if(!r.pathExistsSync(e))throw Error(`Custom cwd directory does not exist: ${e}`);return e}return process.cwd()}async function _e(e,t){try{let{default:n}=await import(`prettier`),r=await n.resolveConfig(e),i=await n.format(t,{filepath:e,...r});await x.writeFile(e,i,`utf8`)}catch{console.warn(`Skipped formatting ${e} since Prettier is not installed.`)}}async function L(e){try{await _e(e,await x.readFile(e,`utf8`))}catch{}}const R=/\r?\n/v;function z(e){let t=``,n=t=>t.filter(t=>t.trim()!==``&&!e(h(t))).map(e=>`${e}\n`).join(``);return new c({flush(e){e(void 0,n([t]))},transform(e,r,i){let a=(t+e.toString()).split(R);t=a.pop()??``,i(void 0,n(a))}})}function B(e,t){let n=w()===`native`?e:void 0,r=n===void 0||n===``?``:t===void 0?n:D()[t](n),i=``,a=e=>e.filter(e=>e.trim().length>0).map(e=>r===``?`${e}\n`:`${r} ${e}\n`).join(``);return new c({flush(e){e(void 0,a([i]))},transform(e,t,n){let r=(i+e.toString()).split(R);i=r.pop()??``,n(void 0,a(r))}})}async function ve(e){let t=[];return new Promise((n,r)=>{e.on(`data`,e=>{t.push(e)}),e.on(`error`,e=>{r(e)}),e.on(`end`,()=>{n(Buffer.concat(t).toString(`utf8`))})})}function V(e,t){return t===1?e:e+`s`}async function H(e){return typeof e==`function`?e():e}async function ye(e,t,n,r,i){let a;if(r.logPrefix===void 0)a=e;else{let t=B(r.logPrefix,r.logColor);t.pipe(e),a=t}i&&a.write(D().bold(`Running: "${r.name}() with Positional arguments: ${String(t)} and Option flags: ${String(n)}"`)+`
|
|
3
|
+
`);try{return await r.execute(a,t,n)}catch(e){return console.error(String(e)),1}}function U(e,t,n,r,i){return[...e.subcommands??[],...e.receiveOptionFlags?n:[],...r??[],...i&&e.cache!==void 0?[...e.cache.flags,`--cache-location`,o.join(F(),`node_modules`,`.cache`,`ksc`,e.cache.name)]:[],...e.receivePositionalArguments?t:[],...e.positionalArguments??[]]}async function be(e,t,r,i,a,o){let c=1,l;if(i.logPrefix===void 0)l=e;else{let t=B(i.logPrefix,i.logColor);t.pipe(e),l=t}let u=U(i,t,r,i.optionFlags,a),d=I(i.cwdOverride);o&&l.write(`Running: "${i.name} ${u.join(` `)}"\n`);let f=i.prettyJsonOutput?new s:l,p=O(w()===`native`&&i.prettyJsonOutput!==!0&&T(E()));try{let e=n(i.name,u,{cwd:d,env:{...p},preferLocal:!0,reject:!1,stdin:`inherit`});if(i.outputFilter){let t=z(i.outputFilter),n=z(i.outputFilter);e.stdout.pipe(t).pipe(f,{end:!1}),e.stderr.pipe(n).pipe(f,{end:!1})}else e.stdout.pipe(f,{end:!1}),e.stderr.pipe(f,{end:!1});let t=await e;if(i.prettyJsonOutput){f.end();let e=await ve(f),t=j(JSON.parse(e)).split(`
|
|
4
|
+
`);for(let e of t)l.write(`${e}\n`)}c=t.exitCode??1}catch(e){console.error(`${i.name} failed with error:`),console.error(e),A(e)&&(c=typeof e.exitCode==`number`?e.exitCode:1)}return c}function W(e){return`execute`in e}function G(e){return`kind`in e}async function K(e,t,r,i,a){let o=U(r,e,t,r.collect?.optionFlags??r.optionFlags,i),s=I(r.cwdOverride);try{let e=n(r.name,o,{cwd:s,env:O(!1),preferLocal:!0,reject:!1,stdin:`inherit`});a!==void 0&&e.stderr.pipe(a,{end:!1});let t=await e;return{cwd:s,exitCode:t.exitCode??1,stderr:t.stderr,stdout:t.stdout}}catch(e){return console.error(`${r.name} failed with error:`),console.error(e),{cwd:s,exitCode:A(e)&&typeof e.exitCode==`number`?e.exitCode:1,stderr:``,stdout:``}}}function xe(e){return typeof e==`object`&&!!e&&`version`in e&&e.version===1&&`diagnostics`in e&&Array.isArray(e.diagnostics)&&`tools`in e&&Array.isArray(e.tools)}async function Se(e,t,n,r,i){let a=Date.now(),o=()=>Date.now()-a;if(W(r)){if(r.collect!==void 0)try{let{diagnostics:e,exitCode:i,unparsed:a}=await r.collect(t,n);return{diagnostics:e,exitCode:i,tools:[{durationMs:o(),exitCode:i,name:r.name,unparsed:a}]}}catch(e){return{diagnostics:[],exitCode:1,tools:[{durationMs:o(),exitCode:1,name:r.name,unparsed:[String(e)]}]}}let e=``,i=new s;i.on(`data`,t=>{e+=t.toString()});let a;try{a=await r.execute(i,t,n)}catch(t){e+=`\n${String(t)}`,a=1}return{diagnostics:[],exitCode:a,tools:[{durationMs:o(),exitCode:a,name:r.name,unparsed:k(e)}]}}if(G(r))throw Error(`Command groups must be expanded before collection`);if(r.outputFormatAware){let a=await K(t,n,r,i,e);try{let e=JSON.parse(a.stdout);if(!xe(e))throw Error(`Child output is not a lint report`);return{diagnostics:e.diagnostics,exitCode:a.exitCode,tools:e.tools}}catch{return{diagnostics:[],exitCode:a.exitCode,tools:[{durationMs:o(),exitCode:a.exitCode,name:r.name,unparsed:k(a.stdout)}]}}}let c=await K(t,n,r,i);if(r.collect!==void 0)try{let{diagnostics:e,unparsed:t}=r.collect.parse(c);return{diagnostics:e,exitCode:c.exitCode,tools:[{durationMs:o(),exitCode:c.exitCode,name:r.name,unparsed:t}]}}catch(e){return{diagnostics:[],exitCode:c.exitCode,tools:[{durationMs:o(),exitCode:c.exitCode,name:r.name,unparsed:[...k(c.stdout),...k(c.stderr),String(e)]}]}}return{diagnostics:[],exitCode:c.exitCode,tools:[{durationMs:o(),exitCode:c.exitCode,name:r.name,unparsed:[...k(c.stdout),...k(c.stderr)]}]}}const Ce=/^ksc-/v;function q(e){return e.replace(Ce,``)}function J(e){return e===void 0||e.length===0?[]:e.flatMap(e=>e.split(`,`)).map(e=>q(e.trim()))}function Y(e){return e.option(`skip`,{array:!0,describe:`Tool names to skip (with or without "ksc-" prefix).`,type:`string`})}function X(e){return e.option(`format`,{choices:re,default:`native`,describe:`Output format: "native" streams each tool's own output, "machine" prints one parseable line per issue for editor problem matchers, "json" prints an aggregate report.`})}function Z(e){return e.option(`cache`,{boolean:!0,default:!0,describe:`Use tool-native caches stored below node_modules/.cache/ksc at the workspace root. Disable with --no-cache.`})}function we(e,t){return t===`native`||t===`machine`&&!W(e)&&!G(e)&&e.outputFormatAware===!0}function Te(e,t){for(let n of t.diagnostics)e.write(`${ce(n)}\n`);for(let n of t.tools)for(let t of n.unparsed)e.write(`${t}\n`)}function Ee(){return Math.min(4,a())}var De=class{concurrency;active=0;queue=[];constructor(e){this.concurrency=e}async run(e){this.active>=this.concurrency&&await new Promise(e=>{this.queue.push(e)}),this.active+=1;try{return await e()}finally{--this.active,this.queue.shift()?.()}}};async function Oe(e){let t=e.cache??!1,n=e.concurrency??Ee();if(!Number.isInteger(n)||n<1)throw Error(`Concurrency must be a positive integer.`);return t&&await r.ensureDir(o.join(F(),`node_modules`,`.cache`,`ksc`)),{cache:t,scheduler:new De(n)}}function ke(e,t){return e.positionalArgumentMode===`none`?[]:t.length>0?t:e.positionalArgumentDefault===void 0?[]:[e.positionalArgumentDefault]}function Ae(e,t){if(t.logPrefix===void 0)return e;let n=B(t.logPrefix,t.logColor);return n.pipe(e),n}async function je(e,t){if(G(e)){if(t.nativeVerbose){let n=[e.subcommand,...t.positionalArguments].join(` `);t.logStream.write(`Running: "${e.name} ${n}"\n`)}let n=Ae(t.logStream,e);try{let r=await Me(await H(e.commands),{...t,logStream:n,nativeVerbose:e.verbose,positionalArguments:ke(e,t.positionalArguments)},e.parallel===!0);return{diagnostics:r.flatMap(({diagnostics:e})=>e),exitCode:+!r.every(({exitCode:e})=>e===0),machineOutcomes:r.flatMap(({machineOutcomes:e})=>e),name:e.name,tools:r.flatMap(({tools:e})=>e)}}catch(r){let i=String(r),a={durationMs:0,exitCode:1,name:e.name,unparsed:[i]};return t.format===`native`&&n.write(`${i}\n`),{diagnostics:[],exitCode:1,machineOutcomes:[{diagnostics:[],exitCode:1,tools:[a]}],name:e.name,tools:[a]}}}return t.scheduler.run(async()=>{if(we(e,t.format))return{diagnostics:[],exitCode:await(W(e)?ye(t.logStream,t.positionalArguments,t.optionFlags,e,t.nativeVerbose):be(t.logStream,t.positionalArguments,t.optionFlags,e,t.cache,t.nativeVerbose)),machineOutcomes:[],name:e.name,tools:[]};let n=await Se(t.logStream,t.positionalArguments,t.optionFlags,e,t.cache);return{diagnostics:n.diagnostics,exitCode:n.exitCode,machineOutcomes:[n],name:e.name,tools:n.tools}})}async function Me(e,t,n){if(!n||t.scheduler.concurrency===1){let n=[];for(let r of e)n.push(await je(r,t));return n}await Promise.resolve();let r=new Map;for(let[t,n]of e.entries()){let e=n.stage??0,i=r.get(e)??[];i.push({command:n,index:t}),r.set(e,i)}let i=Array.from({length:e.length}),a=r.keys().toArray().toSorted((e,t)=>e-t);for(let e of a){let n=r.get(e)??[],a=await Promise.all(n.map(async({command:e,index:n})=>({index:n,outcome:await je(e,t)})));for(let{index:e,outcome:t}of a)i[e]=t}return i.filter(e=>e!==void 0)}function Ne(e,t,n){let r=[],i=[];for(let e of t)n.length>0&&n.includes(q(e.name))?i.push(e):r.push(e);if(n.length>0){let r=new Set(i.map(e=>q(e.name))),a=n.filter(e=>!r.has(e));if(a.length>0){let n=t.map(e=>q(e.name)).join(`, `);e.write(`⚠️ ${D().yellow(`Unrecognized --skip ${V(`value`,a.length)}: ${a.join(`, `)}. Available: ${n}`)}\n`)}}return{commandsToRun:r,skippedCommands:i}}async function Q(e,t,n,r,i,a,o,s=`native`){let c=typeof s==`string`?{}:s,l=typeof s==`string`?s:c.format??`native`,{commandsToRun:u,skippedCommands:d}=Ne(e,r,o??[]),f=l===`native`&&i,{cache:p,scheduler:m}=await Oe(c),h=await Me(u,{cache:p,format:l,logStream:e,nativeVerbose:f,optionFlags:n,positionalArguments:t,scheduler:m},c.parallel===!0),g=h.map(({exitCode:e,name:t})=>({exitCode:e,name:t})),_=h.flatMap(({tools:e})=>e),v=h.flatMap(({diagnostics:e})=>e);if(l===`machine`)for(let t of h)for(let n of t.machineOutcomes)Te(e,n);let y=r.length,b=D();if(l===`native`&&d.length>0){let t=d.map(({name:e})=>e),n=b.bold(`${t.length} / ${y} ${V(`Command`,t.length)} Skipped:`);e.write(`⏭️ ${b.dim(n)} ${b.dim(t.join(`, `))}\n`)}if(l===`native`&&a){let t=g.filter(({exitCode:e})=>e===0).map(({name:e})=>e),n=g.filter(({exitCode:e})=>e!==0).map(({name:e})=>e);if(t.length>0){let n=b.bold(`${t.length} / ${y} ${V(`Command`,t.length)} Succeeded:`);e.write(`✅ ${b.green(n)} ${b.green(t.join(`, `))}\n`)}if(n.length>0){let t=b.bold(`${n.length} / ${y} ${V(`Command`,n.length)} Failed:`);e.write(`❌ ${b.red(t)} ${b.red(n.join(`, `))}\n`)}}return{exitCode:+!g.every(({exitCode:e})=>e===0),report:l===`json`?ue(_,v):void 0}}async function Pe(e,t,n,a){let s=await u();if(s===void 0)throw Error("The `init` command must be used in a directory with a package.json file");let c=await u({cwd:l(import.meta.url)});if(c===void 0)return e.write(`Error: The script being called was not in a package, weird.
|
|
5
|
+
`),1;let d=o.join(o.dirname(c),`init`),f=o.dirname(s),p=(t===`file`||t===`package`)&&n!==void 0&&a!==void 0;try{if(p){let n=Object.keys(a)[0],i=r.readJsonSync(s);if(t===`package`){e.write(`Merging: \nPackage config key "${n}" → "${f}" (Because --location is set to "package")\n`);let t=M(i,a);r.writeJSONSync(s,t,{spaces:` `}),await L(s)}else n!==void 0&&Object.keys(i).includes(n)&&(e.write(`Deleting: \nPackage config key "${n}" in "${f}" (Because --location is set to "file")\n`),delete i[n],r.writeJSONSync(s,i,{spaces:` `}),await L(s))}if(!await r.pathExists(d))return 0;if((await r.readdir(d)).length===0)return e.write(`Source directory "${d}" is empty.\n`),0;e.write(`Adding initial configuration files from:\n"${d}" → "${f}"\n`),await r.copy(d,f,{async filter(a,s){let c=i.statSync(a).isFile(),l=i.existsSync(s);if(c){if(p&&t===`package`&&a.includes(n))return l?(e.write(`Deleting: \n"${a}" → "${s}" (Because --location is set to "package")\n`),r.removeSync(s)):e.write(`Skipping: \n"${a}" → "${s}" (Because --location is set to "package")\n`),!1;if(l&&(s.includes(`.vscode/`)||s.includes(`package.json`))&&o.extname(s)===`.json`){e.write(`Merging: \n"${a}" → "${s}"\n`);let t=r.readJSONSync(a),n=r.readJSONSync(s),i=s.endsWith(`.vscode/tasks.json`)?me(n,t):M(n,t);return r.writeJSONSync(s,i,{spaces:` `}),await L(s),!1}return l?(e.write(`Overwriting: \n"${a}" → "${s}"\n`),await L(s),!0):(e.write(`Copying: \n"${a}" → "${s}"\n`),await L(s),!0)}return!0},overwrite:!0})}catch(e){return console.error(String(e)),1}return 0}async function Fe(e){let{commands:{fix:t,init:n,lint:r,printConfig:i},description:a,logColor:o,logPrefix:s,name:c,showSummary:l,verbose:u}=e;ie();let d=B(s,o);d.pipe(E());let m=f(p(process.argv)).scriptName(c).usage(`$0 <command>`,a);n!==void 0&&m.command({builder(e){let t=n.locationOptionFlag?e.option(`location`,{choices:[`file`,`package`],default:`file`,describe:`Where to store the configuration.`,type:`string`}):e;return l?Y(t):t},command:`init`,describe:n.description??`Initialize by copying starter config files to your project root${n.locationOptionFlag?` or to your package.json file.`:`.`}`,async handler(e){let t=n.locationOptionFlag?e.location:void 0,r=J(e.skip),{exitCode:i}=await Q(d,[],t===void 0?[]:[`--location`,t],[{async execute(e,t,r){return Pe(e,r.at(1),n.configFile,n.configPackageJson)},name:`copyAndMergeInitFiles`},...n.commands??[]],void 0,void 0,r);process.exitCode=i}}),r!==void 0&&m.command({builder(e){let t=Z(X(r.positionalArgumentMode===`none`?e:e.positional(`files`,{array:!0,...r.positionalArgumentDefault!==void 0&&{default:r.positionalArgumentDefault},describe:`Files or glob pattern to lint.`,type:`string`})));return l?Y(t):t},command:r.positionalArgumentMode===`none`?`lint`:r.positionalArgumentMode===`optional`?`lint [files..]`:`lint <files..>`,describe:r.description,async handler(e){let t=e.files??[],n=J(e.skip),i=w(),{exitCode:a,report:o}=await Q(d,t,[],await H(r.commands),u,l,n,{cache:e.cache,format:i,parallel:r.parallel});o!==void 0&&process.stdout.write(`${j(o)}\n`),process.exitCode=a}}),t!==void 0&&m.command({builder(e){let n=Z(X(t.positionalArgumentMode===`none`?e:e.positional(`files`,{array:!0,...t.positionalArgumentDefault!==void 0&&{default:t.positionalArgumentDefault},describe:`Files or glob pattern to fix.`,type:`string`})));return l?Y(n):n},command:t.positionalArgumentMode===`none`?`fix`:t.positionalArgumentMode===`optional`?`fix [files..]`:`fix <files..>`,describe:t.description,async handler(e){let n=e.files??[],r=J(e.skip),i=w(),{exitCode:a,report:o}=await Q(d,n,[],await H(t.commands),void 0,void 0,r,{cache:e.cache,format:i,parallel:t.parallel});o!==void 0&&process.stdout.write(`${j(o)}\n`),process.exitCode=a}}),i!==void 0&&m.command({builder(e){let t=i.positionalArgumentMode===`none`?e:e.positional(`file`,{...i.positionalArgumentDefault!==void 0&&{default:i.positionalArgumentDefault},describe:`File or glob pattern to print configuration for.`,type:`string`});return l?Y(t):t},command:i.positionalArgumentMode===`none`?`print-config`:i.positionalArgumentMode===`optional`?`print-config [file]`:`print-config <file>`,describe:i.description,async handler(e){let t=e.file??void 0,n=t===void 0?[]:[t],r=J(e.skip),{exitCode:a}=await Q(d,n,[],await H(i.commands),u,l,r);process.exitCode=a}}),m.alias(`h`,`help`),m.version(ne),m.alias(`v`,`version`),m.help(),m.wrap(process.stdout.isTTY?Math.min(120,m.terminalWidth()):0),await m.parseAsync()}async function Ie(n){let r=e(n,{loaders:{".ts":t()},searchStrategy:`project`});try{let e=await r.search();if(e===null){console.error(`No ${n} configuration found.`);return}return e}catch(e){console.error(`Error while searching for ${n} configuration:`,e);return}}const $={fileRun:`Matches files below the current working directory by default.`,monorepoRun:`In a monorepo, it will also run in all packages below the current working directory.`,monorepoSearch:`Searches up to the root of a monorepo if necessary.`,multiArgumentCaveat:`Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package scope.`,multiOptionCaveat:`Will use option flags where possible if provided, but some of the invoked tools will ignore them.`,optionalFileRun:`Package-scoped by default, file-scoped if a file argument is provided.`,packageRun:`Package-scoped.`,packageSearch:`Package-scoped.`};async function Le(){return(await Ie(`mdat`))?.filepath}async function Re(e){let t=`mdat`,n=await Ie(t);n!==void 0&&e.write(`Found ${t} readme configuration at "${n.filepath}"\n`);let r=j(await te({additionalConfig:await te()})).split(`
|
|
6
|
+
`);for(let t of r)e.write(`${t}\n`);return 0}async function ze(e){let t=ge(),n=await Le(),r=[];for(let i of t)r.push({cwdOverride:i,name:`mdat`,optionFlags:n===void 0||n===``?[`--format`]:[`--config`,n,`--format`],subcommands:[e]});return r}await Fe({commands:{fix:{commands:await ze(`expand`),description:`Expand all Mdat content placeholders in your readme.md file(s). ${$.packageRun} ${$.monorepoRun}`,parallel:!0,positionalArgumentMode:`none`},init:{configFile:`mdat.config.ts`,configPackageJson:{mdat:{$import:`node_modules/@kitschpatrol/mdat-config/dist/index.js`}},locationOptionFlag:!0},lint:{commands:await ze(`check`),description:`Validate that all Mdat content placeholders in your readme.md file(s) have been expanded and are up to date. ${$.packageRun} ${$.monorepoRun}`,parallel:!0,positionalArgumentMode:`none`},printConfig:{commands:[{execute:Re,name:`mdat-config`}],description:`Print the effective Mdat configuration. ${$.packageSearch}. ${$.monorepoSearch}.`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Mdat shared configuration tools.`,logColor:`green`,logPrefix:`[Mdat Config]`,name:`ksc-mdat`,order:2});export{};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0.0",
|
|
3
|
+
"tasks": [
|
|
4
|
+
{
|
|
5
|
+
"label": "ksc-mdat lint",
|
|
6
|
+
"detail": "Validate that all Mdat content placeholders in your readme.md file(s) have been expanded and are up to date.",
|
|
7
|
+
"type": "shell",
|
|
8
|
+
"command": "pnpm exec ksc-mdat lint --format machine",
|
|
9
|
+
"options": {
|
|
10
|
+
"cwd": "${workspaceFolder}"
|
|
11
|
+
},
|
|
12
|
+
"presentation": {
|
|
13
|
+
"clear": true,
|
|
14
|
+
"echo": true,
|
|
15
|
+
"focus": false,
|
|
16
|
+
"panel": "dedicated",
|
|
17
|
+
"reveal": "silent",
|
|
18
|
+
"revealProblems": "onProblem",
|
|
19
|
+
"showReuseMessage": false
|
|
20
|
+
},
|
|
21
|
+
"problemMatcher": [
|
|
22
|
+
{
|
|
23
|
+
"owner": "ksc",
|
|
24
|
+
"source": "ksc",
|
|
25
|
+
"fileLocation": ["relative", "${workspaceFolder}"],
|
|
26
|
+
"pattern": {
|
|
27
|
+
"regexp": "^(.+?):(\\d+):(\\d+): (error|warning|info): (.+) \\[([^\\]]+)\\]$",
|
|
28
|
+
"file": 1,
|
|
29
|
+
"line": 2,
|
|
30
|
+
"column": 3,
|
|
31
|
+
"severity": 4,
|
|
32
|
+
"message": 5,
|
|
33
|
+
"code": 6
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"label": "ksc-mdat fix",
|
|
40
|
+
"detail": "Expand all Mdat content placeholders in your readme.md file(s).",
|
|
41
|
+
"type": "shell",
|
|
42
|
+
"command": "pnpm exec ksc-mdat fix --format machine",
|
|
43
|
+
"options": {
|
|
44
|
+
"cwd": "${workspaceFolder}"
|
|
45
|
+
},
|
|
46
|
+
"presentation": {
|
|
47
|
+
"clear": true,
|
|
48
|
+
"echo": true,
|
|
49
|
+
"focus": false,
|
|
50
|
+
"panel": "dedicated",
|
|
51
|
+
"reveal": "silent",
|
|
52
|
+
"revealProblems": "onProblem",
|
|
53
|
+
"showReuseMessage": false
|
|
54
|
+
},
|
|
55
|
+
"problemMatcher": [
|
|
56
|
+
{
|
|
57
|
+
"owner": "ksc",
|
|
58
|
+
"source": "ksc",
|
|
59
|
+
"fileLocation": ["relative", "${workspaceFolder}"],
|
|
60
|
+
"pattern": {
|
|
61
|
+
"regexp": "^(.+?):(\\d+):(\\d+): (error|warning|info): (.+) \\[([^\\]]+)\\]$",
|
|
62
|
+
"file": 1,
|
|
63
|
+
"line": 2,
|
|
64
|
+
"column": 3,
|
|
65
|
+
"severity": 4,
|
|
66
|
+
"message": 5,
|
|
67
|
+
"code": 6
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitschpatrol/mdat-config",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.0",
|
|
4
4
|
"description": "MDAT configuration for @kitschpatrol/shared-config.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shared-config",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"cosmiconfig-typescript-loader": "^6.3.0",
|
|
50
50
|
"decircular": "^1.0.0",
|
|
51
51
|
"deepmerge": "^4.3.1",
|
|
52
|
-
"execa": "^
|
|
52
|
+
"execa": "^10.0.0",
|
|
53
53
|
"find-workspaces": "^0.3.1",
|
|
54
54
|
"fs-extra": "^11.3.6",
|
|
55
55
|
"json-stringify-pretty-compact": "^4.0.0",
|
package/readme.md
CHANGED
|
@@ -150,10 +150,12 @@ Usage:
|
|
|
150
150
|
ksc-mdat lint
|
|
151
151
|
```
|
|
152
152
|
|
|
153
|
-
| Option | Description
|
|
154
|
-
| ------------------- |
|
|
155
|
-
| `--
|
|
156
|
-
| `--
|
|
153
|
+
| Option | Description | Type | Default |
|
|
154
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ---------- |
|
|
155
|
+
| `--format` | Output format: "native" streams each tool's own output, "machine" prints one parseable line per issue for editor problem matchers, "json" prints an aggregate report. | `"json"` `"machine"` `"native"` | `"native"` |
|
|
156
|
+
| `--cache` | Use tool-native caches stored below node\_modules/.cache/ksc at the workspace root. Disable with --no-cache. | `boolean` | `true` |
|
|
157
|
+
| `--help`<br>`-h` | Show help | `boolean` | |
|
|
158
|
+
| `--version`<br>`-v` | Show version number | `boolean` | |
|
|
157
159
|
|
|
158
160
|
#### Subcommand: `ksc-mdat fix`
|
|
159
161
|
|
|
@@ -165,10 +167,12 @@ Usage:
|
|
|
165
167
|
ksc-mdat fix
|
|
166
168
|
```
|
|
167
169
|
|
|
168
|
-
| Option | Description
|
|
169
|
-
| ------------------- |
|
|
170
|
-
| `--
|
|
171
|
-
| `--
|
|
170
|
+
| Option | Description | Type | Default |
|
|
171
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ---------- |
|
|
172
|
+
| `--format` | Output format: "native" streams each tool's own output, "machine" prints one parseable line per issue for editor problem matchers, "json" prints an aggregate report. | `"json"` `"machine"` `"native"` | `"native"` |
|
|
173
|
+
| `--cache` | Use tool-native caches stored below node\_modules/.cache/ksc at the workspace root. Disable with --no-cache. | `boolean` | `true` |
|
|
174
|
+
| `--help`<br>`-h` | Show help | `boolean` | |
|
|
175
|
+
| `--version`<br>`-v` | Show version number | `boolean` | |
|
|
172
176
|
|
|
173
177
|
#### Subcommand: `ksc-mdat print-config`
|
|
174
178
|
|
|
@@ -187,6 +191,26 @@ ksc-mdat print-config
|
|
|
187
191
|
|
|
188
192
|
<!-- /cli-help -->
|
|
189
193
|
|
|
194
|
+
### VS Code tasks
|
|
195
|
+
|
|
196
|
+
`ksc-mdat init` adds a `.vscode/tasks.json` with two tasks:
|
|
197
|
+
|
|
198
|
+
- **`ksc-mdat lint`** runs `ksc-mdat lint --format machine`, validating that readme content placeholders are expanded and up to date
|
|
199
|
+
- **`ksc-mdat fix`** runs `ksc-mdat fix --format machine`, expanding readme content placeholders
|
|
200
|
+
|
|
201
|
+
If you're using the complete [@kitschpatrol/shared-config](https://github.com/kitschpatrol/shared-config) package, you'd more likely want to run:
|
|
202
|
+
|
|
203
|
+
- **`ksc lint`** runs `ksc lint --format machine`, which runs all `ksc lint` tools across the whole project
|
|
204
|
+
- **`ksc fix`** runs `ksc fix --format machine`, which applies all `ksc fix` auto-fixes and reports anything unfixable
|
|
205
|
+
|
|
206
|
+
Run them via the _Tasks: Run Task_ command (or the _Terminal → Run Task…_ menu item).
|
|
207
|
+
|
|
208
|
+
Each task's problem matcher parses the machine-format output and populates VS Code's [Problems panel](https://code.visualstudio.com/docs/debugtest/debugging#_errors-and-warnings) with every reported issue, pointing to the offending file, line, and column.
|
|
209
|
+
|
|
210
|
+
The tasks share a problem matcher owner with the other `@kitschpatrol/shared-config` tasks, so the panel reflects the most recent run rather than stacking duplicates.
|
|
211
|
+
|
|
212
|
+
If your project already has a `.vscode/tasks.json`, `init` merges by task label: your own tasks are left alone, and same-label tasks are replaced with the latest definitions.
|
|
213
|
+
|
|
190
214
|
### API
|
|
191
215
|
|
|
192
216
|
The package also exports `fix`, `fixFile` functions for expanding Mdat comment placeholders programmatically, pre-configured with the shared Mdat configuration. The [mdat](https://github.com/kitschpatrol/mdat) project already provides a robust TypeScript API and CLI for general use cases, but these proxies are provided for convenience in @kitschpatrol/shared-config projects.
|