@kitschpatrol/shared-config 8.10.1 → 8.11.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 +10 -10
- package/package.json +18 -17
- package/readme.md +33 -0
- package/skills/ksc/SKILL.md +113 -0
package/bin/cli.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
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,{constants as a}from"node:fs";import{availableParallelism as o}from"node:os";import s from"node:path";import{PassThrough as c,Transform as l}from"node:stream";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 ee from"decircular";import te from"deepmerge";import _ from"json-stringify-pretty-compact";import{findWorkspaces as v,findWorkspacesRoot as ne}from"find-workspaces";import y,{access as re}from"node:fs/promises";import{getDefaultConfigLoader as b,resolveConfigFileImports as ie}from"cspell-lib";import{fileURLToPath as x}from"node:url";import{createReaderWriter as ae}from"cspell-config-lib";import{loadFile as oe,writeFile as se}from"magicast";import{getDefaultExportOptions as ce}from"magicast/helpers";import{lint as le}from"cspell";import"deepmerge-ts";import{loadConfig as ue}from"mdat";import{globby as de}from"globby";import S,{gt as fe,minVersion as pe}from"semver";import{readWantedLockfile as me}from"@pnpm/lockfile.fs";import he from"stylelint";var ge=`8.
|
|
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,{constants as a}from"node:fs";import{availableParallelism as o}from"node:os";import s from"node:path";import{PassThrough as c,Transform as l}from"node:stream";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 ee from"decircular";import te from"deepmerge";import _ from"json-stringify-pretty-compact";import{findWorkspaces as v,findWorkspacesRoot as ne}from"find-workspaces";import y,{access as re}from"node:fs/promises";import{getDefaultConfigLoader as b,resolveConfigFileImports as ie}from"cspell-lib";import{fileURLToPath as x}from"node:url";import{createReaderWriter as ae}from"cspell-config-lib";import{loadFile as oe,writeFile as se}from"magicast";import{getDefaultExportOptions as ce}from"magicast/helpers";import{lint as le}from"cspell";import"deepmerge-ts";import{loadConfig as ue}from"mdat";import{globby as de}from"globby";import S,{gt as fe,minVersion as pe}from"semver";import{readWantedLockfile as me}from"@pnpm/lockfile.fs";import he from"stylelint";var ge=`8.11.0`;const _e=[`json`,`machine`,`native`],ve=_e;function ye(e){return typeof e==`string`&&_e.includes(e)}function C(){let e=process.env.KSC_FORMAT;return ye(e)?e:`native`}function be(){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)),ye(r)&&(process.env.KSC_FORMAT=r)}}function xe(){let{env:e}=process;return e.NO_COLOR!==void 0&&e.NO_COLOR!==``?!1:e.FORCE_COLOR===void 0?e.TERM!==`dumb`&&void 0:e.FORCE_COLOR!==`0`&&e.FORCE_COLOR!==`false`}function w(e,{ciColor:t=!0}={}){return xe()??(e.isTTY===!0||t&&!!process.env.CI)}function Se(){return C()===`json`?process.stderr:process.stdout}function T(){return C()===`machine`?m.createColors(!1):m.createColors(w(Se()))}function Ce(e){if(!e)return{FORCE_COLOR:`0`,NO_COLOR:`1`};let t=process.env.FORCE_COLOR;return t===void 0||t===``?{FORCE_COLOR:`1`}:{}}function E(e,t){let n=s.isAbsolute(e)?e:s.resolve(t,e),r=s.relative(process.cwd(),n);return r===``?`.`:r}const we=/\s*\n\s*/gv,Te=/\r?\n/v;function Ee(e){let t=e.message.replaceAll(we,` `),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 De(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 Oe(e,t){let n=t.toSorted(De);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 D(e){return h(e).split(Te).map(e=>e.trimEnd()).filter(e=>e.trim().length>0)}function ke(e){return e instanceof Error&&`exitCode`in e&&typeof e.exitCode==`number`}function O(e){return w(process.stdout,{ciColor:!1})?je(e):Ae(e)}function Ae(e){return _(ee(e),{indent:2,replacer(e,t){return typeof t==`function`?t.name:t}})}function je(e){return g(Ae(e),{colors:{BRACKET:`gray`}})}const Me=(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]=k(e[i],a,n):e.includes(a)||r.push(a);return r};function k(e,t,n={arrayMerge:Me}){return te(e,t,n)}function Ne(e){let{tasks:t}=e;return Array.isArray(t)?t:[]}function Pe(e,t){let n=[...Ne(e)];for(let e of Ne(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 Fe(e,t){return e.startsWith(t+s.sep)}function A(){let e=j(),t=/* @__PURE__ */ new Set([e]),n=v();if(n!==null)for(let r of n){let n=s.resolve(r.location);Fe(n,e)&&t.add(n)}return[...t]}function j(){let e=d();if(e===void 0)throw Error(`No package.json found.`);return s.dirname(e)}function Ie(){return ne()!==null}function M(){let e=ne();return e===null?j():s.resolve(e.location)}function Le(e){let t=s.join(M(),e);return r.existsSync(t)?t:void 0}function Re(e){if(e===`workspace-root`)return M();if(e===`package-dir`)return j();if(typeof e==`string`){if(!r.pathExistsSync(e))throw Error(`Custom cwd directory does not exist: ${e}`);return e}return process.cwd()}async function ze(e,t){try{let{default:n}=await import(`prettier`),r=await n.resolveConfig(e),i=await n.format(t,{filepath:e,...r});await y.writeFile(e,i,`utf8`)}catch{console.warn(`Skipped formatting ${e} since Prettier is not installed.`)}}async function N(e){try{await ze(e,await y.readFile(e,`utf8`))}catch{}}const Be=/\r?\n/v;function Ve(e){let t=``,n=t=>t.filter(t=>{let n=h(t);return n.trim()!==``&&!e(n)}).map(e=>`${e}\n`).join(``);return new l({flush(e){e(void 0,n([t]))},transform(e,r,i){let a=(t+e.toString()).split(Be);t=a.pop()??``,i(void 0,n(a))}})}function P(e,t){let n=C()===`native`?e:void 0,r=n===void 0||n===``?``:t===void 0?n:T()[t](n),i=``,a=e=>e.filter(e=>e.trim().length>0).map(e=>r===``?`${e}\n`:`${r} ${e}\n`).join(``);return new l({flush(e){e(void 0,a([i]))},transform(e,t,n){let r=(i+e.toString()).split(Be);i=r.pop()??``,n(void 0,a(r))}})}async function He(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 Ue(e){return e.replaceAll(/[A-Z\u{C0}-\u{D6}\u{D8}-\u{DE}]/gv,e=>`-`+e.toLowerCase())}function F(e,t){return t===1?e:e+`s`}async function I(e){return typeof e==`function`?e():e}async function We(e,t,n,r,i){let a;if(r.logPrefix===void 0)a=e;else{let t=P(r.logPrefix,r.logColor);t.pipe(e),a=t}i&&a.write(T().bold(`Running: "${r.name}() with Positional arguments: ${String(t)} and Option flags: ${String(n)}"`)+`
|
|
3
3
|
`);try{return await r.execute(a,t,n)}catch(e){return console.error(String(e)),1}}function Ge(e,t,n,r,i){return[...e.subcommands??[],...e.receiveOptionFlags?n:[],...r??[],...i&&e.cache!==void 0?[...e.cache.flags,`--cache-location`,s.join(M(),`node_modules`,`.cache`,`ksc`,e.cache.name)]:[],...e.receivePositionalArguments?t:[],...e.positionalArguments??[]]}async function Ke(e,t,r,i,a,o){let s=1,l;if(i.logPrefix===void 0)l=e;else{let t=P(i.logPrefix,i.logColor);t.pipe(e),l=t}let u=Ge(i,t,r,i.optionFlags,a),d=Re(i.cwdOverride);o&&l.write(`Running: "${i.name} ${u.join(` `)}"\n`);let f=i.prettyJsonOutput?new c:void 0,p=f??l,m=Ce(C()===`native`&&i.prettyJsonOutput!==!0&&w(Se()));try{let e=n(i.name,u,{cwd:d,env:m,preferLocal:!0,reject:!1,stdin:`inherit`});if(i.outputFilter){let t=Ve(i.outputFilter),n=Ve(i.outputFilter);e.stdout.pipe(t).pipe(p,{end:!1}),e.stderr.pipe(n).pipe(p,{end:!1})}else e.stdout.pipe(p,{end:!1}),e.stderr.pipe(p,{end:!1});let t=await e;if(f!==void 0){f.end();let e=await He(f),t=O(JSON.parse(e)).split(`
|
|
4
|
-
`);for(let e of t)l.write(`${e}\n`)}s=t.exitCode??1}catch(e){console.error(`${i.name} failed with error:`),console.error(e),ke(e)&&(s=typeof e.exitCode==`number`?e.exitCode:1)}return s}function L(e){return`execute`in e}function R(e){return`kind`in e}async function qe(e,t,r,i,a){let o=Ge(r,e,t,r.collect?.optionFlags??r.optionFlags,i),s=Re(r.cwdOverride);try{let e=n(r.name,o,{cwd:s,env:Ce(!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:ke(e)&&typeof e.exitCode==`number`?e.exitCode:1,stderr:``,stdout:``}}}function Je(e){return typeof e==`object`&&!!e&&`version`in e&&e.version===1&&`diagnostics`in e&&Array.isArray(e.diagnostics)&&`success`in e&&typeof e.success==`boolean`&&`tools`in e&&Array.isArray(e.tools)}function Ye(e,t){return e===0&&t.some(({severity:e})=>e===`error`)?1:e}async function Xe(e,t,n,r,i){let a=Date.now(),o=()=>Date.now()-a;if(L(r)){if(r.collect!==void 0)try{let e=await r.collect(t,n),i=Ye(e.exitCode,e.diagnostics);return{diagnostics:e.diagnostics,exitCode:i,tools:[{durationMs:o(),exitCode:i,name:r.name,unparsed:e.unparsed}]}}catch(e){return{diagnostics:[],exitCode:1,tools:[{durationMs:o(),exitCode:1,name:r.name,unparsed:[String(e)]}]}}let e=``,i=new c;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:D(e)}]}}if(R(r))throw Error(`Command groups must be expanded before collection`);if(r.outputFormatAware){let a=await qe(t,n,r,i,e);try{let e=JSON.parse(a.stdout);if(!Je(e))throw Error(`Child output is not a lint report`);return{diagnostics:e.diagnostics,exitCode:a.exitCode===0&&e.success&&e.diagnostics.every(({severity:e})=>e!==`error`)?0:1,tools:e.tools}}catch{return{diagnostics:[],exitCode:a.exitCode,tools:[{durationMs:o(),exitCode:a.exitCode,name:r.name,unparsed:D(a.stdout)}]}}}let s=await qe(t,n,r,i);if(r.collect!==void 0)try{let{diagnostics:e,unparsed:t}=r.collect.parse(s),n=Ye(s.exitCode,e);return{diagnostics:e,exitCode:n,tools:[{durationMs:o(),exitCode:n,name:r.name,unparsed:t}]}}catch(e){return{diagnostics:[],exitCode:s.exitCode,tools:[{durationMs:o(),exitCode:s.exitCode,name:r.name,unparsed:[...D(s.stdout),...D(s.stderr),String(e)]}]}}return{diagnostics:[],exitCode:s.exitCode,tools:[{durationMs:o(),exitCode:s.exitCode,name:r.name,unparsed:[...D(s.stdout),...D(s.stderr)]}]}}const Ze=/^ksc-/v;function z(e){return e.replace(Ze,``)}function B(e){return e===void 0||e.length===0?[]:e.flatMap(e=>e.split(`,`)).map(e=>z(e.trim()))}function V(e){return e.option(`skip`,{array:!0,describe:`Tool names to skip (with or without "ksc-" prefix).`,type:`string`})}function Qe(e){return e.option(`format`,{choices:ve,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 $e(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 et(e,t){return t===`native`||t===`machine`&&!L(e)&&!R(e)&&e.outputFormatAware===!0}function tt(e,t){for(let n of t.diagnostics)e.write(`${Ee(n)}\n`);for(let n of t.tools)for(let t of n.unparsed)e.write(`${t}\n`)}function nt(){return Math.min(4,o())}var rt=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 it(e){let t=e.cache??!1,n=e.concurrency??nt();if(!Number.isInteger(n)||n<1)throw Error(`Concurrency must be a positive integer.`);return t&&await r.ensureDir(s.join(M(),`node_modules`,`.cache`,`ksc`)),{cache:t,scheduler:new rt(n)}}const at=/[*?\[\]\{\}]/v;function
|
|
5
|
-
`),1;let l=s.dirname(o),d=(t===`file`||t===`package`)&&n!==void 0&&a!==void 0;try{if(d){let n=Object.keys(a)[0],i=r.readJsonSync(o);if(t===`package`){e.write(`Merging: \nPackage config key "${n}" → "${l}" (Because --location is set to "package")\n`);let t=k(i,a);r.writeJSONSync(o,t,{spaces:` `}),await N(o)}else n!==void 0&&Object.keys(i).includes(n)&&(e.write(`Deleting: \nPackage config key "${n}" in "${l}" (Because --location is set to "file")\n`),delete i[n],r.writeJSONSync(o,i,{spaces:` `}),await N(o))}if(!await r.pathExists(c))return 0;if((await r.readdir(c)).length===0)return e.write(`Source directory "${c}" is empty.\n`),0;e.write(`Adding initial configuration files from:\n"${c}" → "${l}"\n`),await r.copy(c,l,{async filter(a,o){let c=i.statSync(a).isFile(),l=i.existsSync(o);if(c){if(d&&t===`package`&&a.includes(n))return l?(e.write(`Deleting: \n"${a}" → "${o}" (Because --location is set to "package")\n`),r.removeSync(o)):e.write(`Skipping: \n"${a}" → "${o}" (Because --location is set to "package")\n`),!1;if(l&&(o.includes(`.vscode/`)||o.includes(`package.json`))&&s.extname(o)===`.json`){e.write(`Merging: \n"${a}" → "${o}"\n`);let t=r.readJSONSync(a),n=r.readJSONSync(o),i=o.endsWith(`.vscode/tasks.json`)?Pe(n,t):k(n,t);return r.writeJSONSync(o,i,{spaces:` `}),await N(o),!1}return l?(e.write(`Overwriting: \n"${a}" → "${o}"\n`),await N(o),!0):(e.write(`Copying: \n"${a}" → "${o}"\n`),await N(o),!0)}return!0},overwrite:!0})}catch(e){return console.error(String(e)),1}return 0}async function
|
|
4
|
+
`);for(let e of t)l.write(`${e}\n`)}s=t.exitCode??1}catch(e){console.error(`${i.name} failed with error:`),console.error(e),ke(e)&&(s=typeof e.exitCode==`number`?e.exitCode:1)}return s}function L(e){return`execute`in e}function R(e){return`kind`in e}async function qe(e,t,r,i,a){let o=Ge(r,e,t,r.collect?.optionFlags??r.optionFlags,i),s=Re(r.cwdOverride);try{let e=n(r.name,o,{cwd:s,env:Ce(!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:ke(e)&&typeof e.exitCode==`number`?e.exitCode:1,stderr:``,stdout:``}}}function Je(e){return typeof e==`object`&&!!e&&`version`in e&&e.version===1&&`diagnostics`in e&&Array.isArray(e.diagnostics)&&`success`in e&&typeof e.success==`boolean`&&`tools`in e&&Array.isArray(e.tools)}function Ye(e,t){return e===0&&t.some(({severity:e})=>e===`error`)?1:e}async function Xe(e,t,n,r,i){let a=Date.now(),o=()=>Date.now()-a;if(L(r)){if(r.collect!==void 0)try{let e=await r.collect(t,n),i=Ye(e.exitCode,e.diagnostics);return{diagnostics:e.diagnostics,exitCode:i,tools:[{durationMs:o(),exitCode:i,name:r.name,unparsed:e.unparsed}]}}catch(e){return{diagnostics:[],exitCode:1,tools:[{durationMs:o(),exitCode:1,name:r.name,unparsed:[String(e)]}]}}let e=``,i=new c;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:D(e)}]}}if(R(r))throw Error(`Command groups must be expanded before collection`);if(r.outputFormatAware){let a=await qe(t,n,r,i,e);try{let e=JSON.parse(a.stdout);if(!Je(e))throw Error(`Child output is not a lint report`);return{diagnostics:e.diagnostics,exitCode:a.exitCode===0&&e.success&&e.diagnostics.every(({severity:e})=>e!==`error`)?0:1,tools:e.tools}}catch{return{diagnostics:[],exitCode:a.exitCode,tools:[{durationMs:o(),exitCode:a.exitCode,name:r.name,unparsed:D(a.stdout)}]}}}let s=await qe(t,n,r,i);if(r.collect!==void 0)try{let{diagnostics:e,unparsed:t}=r.collect.parse(s),n=Ye(s.exitCode,e);return{diagnostics:e,exitCode:n,tools:[{durationMs:o(),exitCode:n,name:r.name,unparsed:t}]}}catch(e){return{diagnostics:[],exitCode:s.exitCode,tools:[{durationMs:o(),exitCode:s.exitCode,name:r.name,unparsed:[...D(s.stdout),...D(s.stderr),String(e)]}]}}return{diagnostics:[],exitCode:s.exitCode,tools:[{durationMs:o(),exitCode:s.exitCode,name:r.name,unparsed:[...D(s.stdout),...D(s.stderr)]}]}}const Ze=/^ksc-/v;function z(e){return e.replace(Ze,``)}function B(e){return e===void 0||e.length===0?[]:e.flatMap(e=>e.split(`,`)).map(e=>z(e.trim()))}function V(e){return e.option(`skip`,{array:!0,describe:`Tool names to skip (with or without "ksc-" prefix).`,type:`string`})}function Qe(e){return e.option(`format`,{choices:ve,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 $e(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 et(e,t){return t===`native`||t===`machine`&&!L(e)&&!R(e)&&e.outputFormatAware===!0}function tt(e,t){for(let n of t.diagnostics)e.write(`${Ee(n)}\n`);for(let n of t.tools)for(let t of n.unparsed)e.write(`${t}\n`)}function nt(){return Math.min(4,o())}var rt=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 it(e){let t=e.cache??!1,n=e.concurrency??nt();if(!Number.isInteger(n)||n<1)throw Error(`Concurrency must be a positive integer.`);return t&&await r.ensureDir(s.join(M(),`node_modules`,`.cache`,`ksc`)),{cache:t,scheduler:new rt(n)}}const at=/[*?\[\]\{\}]/v;function H(e,t){return t===void 0?e:e.filter(e=>at.test(e)||i.statSync(e,{throwIfNoEntry:!1})?.isDirectory()===!0||t.includes(s.extname(e).slice(1).toLowerCase()))}function ot(e,t){return e.length===0||H(e,t).length>0}function st(e,t){return e.positionalArgumentMode===`none`?[]:t.length>0?H(t,e.positionalArgumentExtensions):e.positionalArgumentDefault===void 0?[]:[e.positionalArgumentDefault]}function ct(e,t){if(t.logPrefix===void 0)return e;let n=P(t.logPrefix,t.logColor);return n.pipe(e),n}function lt(e){return R(e)?`${e.name} ${e.subcommand}`:!L(e)&&e.subcommands!==void 0?[e.name,...e.subcommands].join(` `):e.name}async function ut(e,t){if(R(e)){let n=ct(t.logStream,e);try{let r=await I(e.commands);if(t.nativeVerbose){let n=[e.subcommand,...t.positionalArguments].join(` `),i=e.showResolvedCommands?` (${r.map(e=>lt(e)).join(`, `)})`:``;t.logStream.write(`Running: "${e.name} ${n}"${i}\n`)}let i=await dt(r,{...t,logStream:n,nativeVerbose:e.verbose,positionalArguments:st(e,t.positionalArguments)},e.parallel===!0);return{diagnostics:i.flatMap(({diagnostics:e})=>e),exitCode:+!i.every(({exitCode:e})=>e===0),machineOutcomes:i.flatMap(({machineOutcomes:e})=>e),name:e.name,tools:i.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(et(e,t.format))return{diagnostics:[],exitCode:await(L(e)?We(t.logStream,t.positionalArguments,t.optionFlags,e,t.nativeVerbose):Ke(t.logStream,t.positionalArguments,t.optionFlags,e,t.cache,t.nativeVerbose)),machineOutcomes:[],name:e.name,tools:[]};let n=await Xe(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 dt(e,t,n){if(!n||t.scheduler.concurrency===1){let n=[];for(let r of e)n.push(await ut(r,t));return n}await Promise.resolve();let r=/* @__PURE__ */ 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 ut(e,t)})));for(let{index:e,outcome:t}of a)i[e]=t}return i.filter(e=>e!==void 0)}function ft(e,t,n,r,i){let a=[],o=[],s=ot(r,i);for(let e of t){let t=!R(e)||ot(r,e.positionalArgumentExtensions);!s||!t||n.includes(z(e.name))?o.push(e):a.push(e)}if(n.length>0){let r=new Set(o.map(e=>z(e.name))),i=n.filter(e=>!r.has(e));if(i.length>0){let n=t.map(e=>z(e.name)).join(`, `);e.write(`⚠️ ${T().yellow(`Unrecognized --skip ${F(`value`,i.length)}: ${i.join(`, `)}. Available: ${n}`)}\n`)}}return{commandsToRun:a,skippedCommands:o}}async function U(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}=ft(e,r,o??[],t,c.positionalArgumentExtensions),f=l===`native`&&i,{cache:p,scheduler:m}=await it(c),h=await dt(u,{cache:p,format:l,logStream:e,nativeVerbose:f,optionFlags:n,positionalArguments:H(t,c.positionalArgumentExtensions),scheduler:m},c.parallel===!0),g=h.map(({exitCode:e,name:t})=>({exitCode:e,name:t})),ee=h.flatMap(({tools:e})=>e),te=h.flatMap(({diagnostics:e})=>e);if(l===`machine`)for(let t of h)for(let n of t.machineOutcomes)tt(e,n);let _=r.length,v=T();if(l===`native`&&d.length>0){let t=d.map(({name:e})=>e),n=v.bold(`${t.length} / ${_} ${F(`Command`,t.length)} Skipped:`);e.write(`⏭️ ${v.dim(n)} ${v.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=v.bold(`${t.length} / ${_} ${F(`Command`,t.length)} Succeeded:`);e.write(`✅ ${v.green(n)} ${v.green(t.join(`, `))}\n`)}if(n.length>0){let t=v.bold(`${n.length} / ${_} ${F(`Command`,n.length)} Failed:`);e.write(`❌ ${v.red(t)} ${v.red(n.join(`, `))}\n`)}}return{exitCode:+!g.every(({exitCode:e})=>e===0),report:l===`json`?Oe(ee,te):void 0}}async function pt(e){let t=await u({cwd:e});return t===void 0?void 0:s.join(s.dirname(t),`init`)}async function mt(e,t,n,a){let o=await u();if(o===void 0)throw Error("The `init` command must be used in a directory with a package.json file");let c=await pt(import.meta.dirname);if(c===void 0)return e.write(`Error: Could not locate the package containing this CLI.
|
|
5
|
+
`),1;let l=s.dirname(o),d=(t===`file`||t===`package`)&&n!==void 0&&a!==void 0;try{if(d){let n=Object.keys(a)[0],i=r.readJsonSync(o);if(t===`package`){e.write(`Merging: \nPackage config key "${n}" → "${l}" (Because --location is set to "package")\n`);let t=k(i,a);r.writeJSONSync(o,t,{spaces:` `}),await N(o)}else n!==void 0&&Object.keys(i).includes(n)&&(e.write(`Deleting: \nPackage config key "${n}" in "${l}" (Because --location is set to "file")\n`),delete i[n],r.writeJSONSync(o,i,{spaces:` `}),await N(o))}if(!await r.pathExists(c))return 0;if((await r.readdir(c)).length===0)return e.write(`Source directory "${c}" is empty.\n`),0;e.write(`Adding initial configuration files from:\n"${c}" → "${l}"\n`),await r.copy(c,l,{async filter(a,o){let c=i.statSync(a).isFile(),l=i.existsSync(o);if(c){if(d&&t===`package`&&a.includes(n))return l?(e.write(`Deleting: \n"${a}" → "${o}" (Because --location is set to "package")\n`),r.removeSync(o)):e.write(`Skipping: \n"${a}" → "${o}" (Because --location is set to "package")\n`),!1;if(l&&(o.includes(`.vscode/`)||o.includes(`package.json`))&&s.extname(o)===`.json`){e.write(`Merging: \n"${a}" → "${o}"\n`);let t=r.readJSONSync(a),n=r.readJSONSync(o),i=o.endsWith(`.vscode/tasks.json`)?Pe(n,t):k(n,t);return r.writeJSONSync(o,i,{spaces:` `}),await N(o),!1}return l?(e.write(`Overwriting: \n"${a}" → "${o}"\n`),await N(o),!0):(e.write(`Copying: \n"${a}" → "${o}"\n`),await N(o),!0)}return!0},overwrite:!0})}catch(e){return console.error(String(e)),1}return 0}async function ht(e){let{commands:{fix:t,init:n,lint:r,printConfig:i},description:a,logColor:o,logPrefix:s,name:c,showSummary:l,verbose:u}=e;be();let d=P(s,o);d.pipe(Se());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?V(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=B(e.skip),{exitCode:i}=await U(d,[],t===void 0?[]:[`--location`,t],[{async execute(e,t,r){return mt(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=$e(Qe(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?V(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=B(e.skip),i=C(),{exitCode:a,report:o}=await U(d,t,[],await I(r.commands),u,l,n,{cache:e.cache,format:i,parallel:r.parallel,positionalArgumentExtensions:r.positionalArgumentExtensions});o!==void 0&&process.stdout.write(`${O(o)}\n`),process.exitCode=a}}),t!==void 0&&m.command({builder(e){let n=$e(Qe(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?V(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=B(e.skip),i=C(),{exitCode:a,report:o}=await U(d,n,[],await I(t.commands),void 0,void 0,r,{cache:e.cache,format:i,parallel:t.parallel,positionalArgumentExtensions:t.positionalArgumentExtensions});o!==void 0&&process.stdout.write(`${O(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?V(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=B(e.skip),{exitCode:a}=await U(d,n,[],await I(i.commands),u,l,r);process.exitCode=a}}),m.alias(`h`,`help`),m.version(ge),m.alias(`v`,`version`),m.help(),m.wrap(process.stdout.isTTY?Math.min(120,m.terminalWidth()):0),await m.parseAsync()}function W(e){return{async execute(t){let n=await G(e);if(n===void 0)return 1;let{config:r,filepath:i,isEmpty:a}=n;if(t.write(`Found ${e} configuration at "${i}"\n`),a)return t.write(`Configuration is empty.
|
|
6
6
|
`),0;let o=O(r).split(`
|
|
7
|
-
`);for(let e of o)t.write(`${e}\n`);return 0},name:`Cosmiconfig ${e}`}}async function
|
|
8
|
-
`),0;let r=await
|
|
9
|
-
`),0}async function
|
|
10
|
-
`);for(let t of n)e.write(`${t}\n`);return 0}const
|
|
11
|
-
`);for(let t of r)e.write(`${t}\n`);return 0}async function Zt(e){let t=A(),n=await Yt(),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}const Qt={commands:{fix:{commands:await Zt(`expand`),description:`Expand all Mdat content placeholders in your readme.md file(s). ${G.packageRun} ${G.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 Zt(`check`),description:`Validate that all Mdat content placeholders in your readme.md file(s) have been expanded and are up to date. ${G.packageRun} ${G.monorepoRun}`,parallel:!0,positionalArgumentMode:`none`},printConfig:{commands:[{execute:Xt,name:`mdat-config`}],description:`Print the effective Mdat configuration. ${G.packageSearch}. ${G.monorepoSearch}.`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Mdat shared configuration tools.`,logColor:`green`,logPrefix:`[Mdat Config]`,name:`ksc-mdat`,order:2},$t=/^\[warn\] (?<file>\S+)$/v,en=/^\[error\] (?<message>.+)$/v;function tn(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=$t.exec(r);if(i?.groups?.file!==void 0){t.push({file:E(i.groups.file,e.cwd),message:`File is not formatted with Prettier`,severity:`warning`,tool:`prettier`});continue}if(r.startsWith(`[warn] Code style issues found`))continue;let a=en.exec(r);if(a?.groups?.message!==void 0){t.push({message:a.groups.message,severity:`error`,tool:`prettier`});continue}n.push(r)}return{diagnostics:t,unparsed:n}}const nn=[`--log-level=warn`,`--ignore-unknown`,`--plugin=prettier-plugin-astro`,`--plugin=@prettier/plugin-php`,`--plugin=@prettier/plugin-ruby`,`--plugin=@prettier/plugin-xml`,`--plugin=prettier-plugin-jsdoc`,`--plugin=prettier-plugin-packagejson`,`--plugin=prettier-plugin-sh`,`--plugin=prettier-plugin-svelte`,`--plugin=prettier-plugin-toml`,`--plugin=prettier-plugin-tailwindcss`,`--ignore-path=${Le(`.gitignore`)??`.gitignore`}`,`--ignore-path=${Le(`.prettierignore`)??`.prettierignore`}`],rn={commands:{fix:{commands:[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`prettier`},collect:{parse:tn},name:`prettier`,optionFlags:[...nn,`--write`],receivePositionalArguments:!0}],description:`Format files according to your Prettier configuration. ${G.fileRun}`,positionalArgumentDefault:`.`,positionalArgumentMode:`optional`},init:{configFile:`prettier.config.ts`,configPackageJson:{prettier:`@kitschpatrol/prettier-config`},locationOptionFlag:!0},lint:{commands:[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`prettier`},collect:{parse:tn},name:`prettier`,optionFlags:[...nn,`--check`],receivePositionalArguments:!0}],description:`Check that files are formatted according to your Prettier configuration. ${G.fileRun}`,positionalArgumentDefault:`.`,positionalArgumentMode:`optional`},printConfig:{commands:[U(`prettier`)],description:`Print the effective Prettier configuration. ${G.packageSearch}. ${G.monorepoSearch}.`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Prettier shared configuration tools.`,logColor:`blue`,logPrefix:`[Prettier]`,name:`ksc-prettier`,order:9},an={commands:{init:{configFile:`.remarkrc.js`,configPackageJson:{remarkConfig:{plugins:[`@kitschpatrol/remark-config`]}},locationOptionFlag:!0},printConfig:{commands:[U(`remark`)],description:`Print the effective Remark configuration. ${G.packageSearch} ${G.monorepoSearch}`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Remark and Remark Lint shared configuration tools. (Actual linting and fixing is managed through @kitschpatrol/eslint-config.)`,logColor:`blue`,logPrefix:`[remarklint]`,name:`ksc-remark`,order:8},on=[/Version 2\.0,?\s*January 2004/gv,/Version 1,?\s*February 1989/gv,/Version 2,?\s*June 1991/gv,/Version 3,?\s*29 June 2007/gv,/Version 2\.1,?\s*February 1999/gv,/Version 3,?\s*19 November 2007/gv,/Version 1\.0\s*-\s*August 17th,?\s*2003/gv,/Version 1\.1,?\s*March 2000/gv,/Version 1\.2,?\s*November 2002/gv,/Version 1\.3,?\s*3 November 2008/gv,/Version 1\.0\s*-\s*22 November 2005/gv,/Version 1\.1\s*-\s*26 February 2007/gv,/Version 2,?\s*December 2004/gv,/20 December 1996/gv,/December 20,?\s*1996/gv,/11 March 1996/gv,/28 March 2007/gv,/November 1,?\s*2008/gv,/August 1,?\s*2009/gv,/1 April 19\d{2}/gv,/Copyright \(c\) 2000-2006,?\s*The Perl Foundation/giv,/Copyright \(C\) (?:\d{4},?\s*)+Free Software Foundation/gv],sn=[`node_modules/**`,`test/**`];function cn(e){let t=e;for(let e of on)e.lastIndex=0,t=t.replace(e,e=>e.replaceAll(/\d/gv,`X`));return t}const ln=/(\d{4})\s*-\s*(\d{4})/v,un=/(\d{4})/v;function dn(e,t){let n=cn(e),r=ln,i=r.exec(n);if(i){let[,n,a]=i;if(Number(a)!==t){let a=`${n}-${t}`;return e.slice(0,i.index)+e.slice(i.index).replace(r,()=>a)}return e}let a=un,o=a.exec(n);if(o){let[,n]=o;if(Number(n)!==t){let r=`${n}-${t}`;return e.slice(0,o.index)+e.slice(o.index).replace(a,()=>r)}return e}return e}async function fn(e){let t=(/* @__PURE__ */ new Date()).getFullYear(),n=[`**/license.txt`,`**/license`,...sn.map(e=>`!${e}`)],r=await de(n,{caseSensitiveMatch:!1,cwd:j(),followSymbolicLinks:!1,gitignore:!0}),i=[];for(let n of r)try{let r=await y.readFile(n,`utf8`),a=dn(r,t);a!==r&&(i.push(n),e&&await y.writeFile(n,a,`utf8`))}catch(e){console.error(`Failed to process ${n}:`,e)}return i}async function pn(e,t=!1){let n=await fn(t);if(n.length>0){e.write(`${t?`Fixed`:`Found`} ${n.length} license ${F(`file`,n.length)} with outdated copyright year:\n`);for(let t of n)e.write(` - ${t}\n`);return+!t}return 0}async function mn(e){return pn(e,!1)}async function hn(){let e=await fn(!1);return{diagnostics:e.map(e=>({file:E(e,j()),message:`License file has an outdated copyright year`,severity:`error`,tool:`copyright-year`})),exitCode:+(e.length>0),unparsed:[]}}async function gn(e){return pn(e,!0)}const _n=`pnpm-lock.yaml`;function vn(e){let t=M(),n=s.resolve(e);for(;;){if(r.existsSync(s.join(n,_n)))return n;if(n===t)break;let e=s.dirname(n);if(e===n)break;n=e}}function yn(e,t,n){let r=`${e}@${t}`;return Object.hasOwn(n,r)?r:Object.hasOwn(n,t)?t:void 0}function bn(e,t){return e===void 0||e===``?t===void 0||t===``?void 0:t:t===void 0||t===``||fe(e,t)?e:t}async function xn(e){let t=vn(e);if(t===void 0||t===``)throw Error(`${_n} not found at or above "${e}".`);let n=s.join(t,_n),r=await me(t,{ignoreIncompatible:!1});if(!r?.importers)throw Error(`Lockfile at "${n}" is unreadable or missing importers.`);let i=r.packages??{},a,o,c={},l={};function u(e,t){let n,r=/* @__PURE__ */ new Set;function a(e,t){if(t.startsWith(`link:`))return;let o=yn(e,t,i);if(o===void 0||o===``||r.has(o))return;r.add(o);let s=i[o];if(s===void 0)return;let c=s.engines?.node;if(c!==void 0&&c!==``){let e=pe(c)?.version;e!==void 0&&e!==``&&(n===void 0||n===``||fe(e,n))&&(n=e)}if(s.dependencies)for(let[e,t]of Object.entries(s.dependencies))a(e,t)}return a(e,t),n}function d(e,t){for(let[n,r]of Object.entries(e)){let e=u(n,typeof r==`string`?r:r.version);if(e===void 0||e===``)continue;let i=t?l:c;i[e]??=/* @__PURE__ */ new Set,i[e].add(n);let s=t?o:a;(s===void 0||s===``||fe(e,s))&&(t?o=e:a=e)}}let f=s.relative(t,e),p=f===``?`.`:f,m=r.importers[p];m!==void 0&&(m.dependencies&&d(m.dependencies,!1),m.devDependencies&&d(m.devDependencies,!0));let h=bn(a,o),g=h===void 0?void 0:`>=${h}`;return{dependencies:a!==void 0&&a!==``?{topLevelCauses:[...c[a]??[]],version:`>=${a}`}:void 0,devDependencies:o!==void 0&&o!==``?{topLevelCauses:[...l[o]??[]],version:`>=${o}`}:void 0,lockfile:n,version:g}}function Sn(e){let t=e.devEngines;if(t?.runtime)return(Array.isArray(t.runtime)?t.runtime:[t.runtime]).find(e=>e.name===`node`)?.version}function Cn(e,t){let n=e.devEngines??{};if(n.runtime){if(Array.isArray(n.runtime)){let e=n.runtime.find(e=>e.name===`node`);e===void 0?n.runtime.push({name:`node`,version:t}):e.version=t}else n.runtime.name===`node`?n.runtime.version=t:n.runtime=[n.runtime,{name:`node`,version:t}]}else n.runtime={name:`node`,version:t};e.devEngines=n}function wn(e){let t=e.devEngines;if(t?.runtime){if(Array.isArray(t.runtime)){t.runtime=t.runtime.filter(e=>e.name!==`node`);let[e]=t.runtime;e===void 0?delete t.runtime:t.runtime.length===1&&(t.runtime=e)}else t.runtime.name===`node`&&delete t.runtime;Object.keys(t).length===0&&delete e.devEngines}}function q(e){return e.length===0?``:` (from ${e.join(`, `)})`}async function Tn(e,t){let n=s.join(t,`package.json`);if(!r.existsSync(n))return{issues:[],packageJsonPath:n};let i=r.readJsonSync(n),a=i.engines?.node,o=Sn(i),c=await xn(t),l=c.dependencies?.version,u=c.dependencies?.topLevelCauses??[],d=c.version,f=c.devDependencies?.topLevelCauses??[],p=[];if(l!==void 0){if(a===void 0){if(p.push(`Missing engines.node — suggest setting to "${l}"${q(u)}`),e){let e=i.engines??{};e.node=l,i.engines=e}}else{let t=S.minVersion(a),n=S.minVersion(l);t&&n&&S.lt(t,n)&&(p.push(`engines.node is "${a}" but production dependencies require at least "${l}"${q(u)}`),e&&(i.engines.node=l))}}let m=(()=>{if(l!==void 0&&l!==``&&a!==void 0&&a!==``){let e=S.minVersion(l),t=S.minVersion(a);if(e&&t)return S.gt(e,t)?l:a}return l??a})(),h=m!==void 0&&m!==``?S.minVersion(m):void 0,g=d!==void 0&&d!==``?S.minVersion(d):void 0,ee=g&&h&&S.gt(g,h);if(d!==void 0&&ee){if(o===void 0)p.push(`devDependencies require a higher Node.js minimum (${d}) than engines.node (${m??`none`}) — suggest adding devEngines.runtime for node with version "${d}"${q(f)}`),e&&Cn(i,d);else{let t=S.minVersion(o);t&&S.lt(t,g)&&(p.push(`devEngines.runtime.version for node is "${o}" but all dependencies require at least "${d}"${q(f)}`),e&&Cn(i,d))}}else if(o!==void 0){let t=S.minVersion(o);t&&h&&S.lte(t,h)&&(p.push(`devEngines.runtime.version for node is redundant (engines.node already covers the requirement) — suggest removing`),e&&wn(i))}return e&&p.length>0&&(r.writeJsonSync(n,i,{spaces:` `}),await N(n)),{issues:p,packageJsonPath:n}}async function En(e,t){let n=A(),r=0;for(let i of n){let{issues:n,packageJsonPath:a}=await Tn(t,i);if(n.length!==0){e.write(`${t?`Fixed`:`Found`} ${n.length} Node.js version ${F(`issue`,n.length)} in ${a}:\n`);for(let t of n)e.write(` - ${t}\n`);t||(r=1)}}return r}async function Dn(){let e=A(),t=[];for(let n of e){let{issues:e,packageJsonPath:r}=await Tn(!1,n);for(let n of e)t.push({file:E(r,process.cwd()),message:n,severity:`error`,tool:`node-version`})}return{diagnostics:t,exitCode:+(t.length>0),unparsed:[]}}async function On(e){let t=O(await xn(j())).split(`
|
|
12
|
-
`);for(let n of t)e.write(`${n}\n`);return 0}async function
|
|
7
|
+
`);for(let e of o)t.write(`${e}\n`);return 0},name:`Cosmiconfig ${e}`}}async function G(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 K={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.`},gt=/['\u{2019}\u{2018}]s$/v;async function _t(e=[`.`]){let t=await b().searchForConfigFile(void 0);if(t===void 0)throw Error(`No CSpell configuration found.`);let{settings:n,url:r}=t;if(n.words===void 0||n.words.length===0)return{errors:0,filesChecked:0,unusedWords:[]};let i=[...n.words];delete n.words;let a=await le(e,{config:{settings:n,url:r},progress:!1,unique:!0,wordsOnly:!0},{issue({text:e,uri:t}){i=i.filter(n=>n.toLowerCase()!==e.toLowerCase().replace(gt,``)||t===r.href)}});return{errors:a.errors,filesChecked:a.files,unusedWords:i}}const vt=/* @__PURE__ */ new Set([`.cjs`,`.cts`,`.js`,`.mjs`,`.mts`,`.ts`]);async function yt(e=[`**/*`]){let t=await b().searchForConfigFile(void 0);if(t===void 0)throw Error(`No CSpell configuration found.`);let n=x(t.url),r=[...t.settings.words??[]];if(r.length===0)return;let{errors:i,filesChecked:a,unusedWords:o}=await _t(e);if(a===0||i>0)throw Error(`Refusing to modify "${n}": CSpell checked ${a} files with ${i} errors, so word usage can't be determined. Check your file globs and configuration.`);let s=new Set(o),c=r.filter(e=>!s.has(e)),l=bt([...new Set(c)]);return xt(l,r)?{configFilePath:n,removedWords:[],reordered:!1}:(await St(t.url,l),{configFilePath:n,removedWords:[...s],reordered:!xt(l,c)})}function bt(e){return e.toSorted((e,t)=>{let n=e.toLowerCase().localeCompare(t.toLowerCase());return n===0?e.localeCompare(t):n})}function xt(e,t){return e.length===t.length&&e.every((e,n)=>e===t[n])}async function St(e,t){let n=x(e),r=s.extname(n).toLowerCase();if(vt.has(r)){let e=await oe(n),r=ce(e);r.words=t,await se(e,n),await N(n);return}let i=ae(),a=await i.readConfig(e);if(a.readonly)throw Error(`CSpell configuration file "${n}" can't be modified automatically. Please update the words list manually.`);a.setValue(`words`,t),await i.writeConfig(a)}const Ct=`**/*`;function wt(e){return e.length===0||e.length===1&&e[0]===Ct}async function Tt(){let e=await b().searchForConfigFile(void 0);return e===void 0?void 0:x(e.url)}async function Et(){let e=await b().searchForConfigFile(void 0);if(e===void 0)throw Error(`No CSpell configuration found.`);let t=await ie(e);return t.ignorePaths===void 0?``:Array.from(t.ignorePaths,e=>typeof e==`string`?e:e.glob).join(`,`)}const Dt=/^(?<file>.+?):(?<line>\d+):(?<column>\d+) - (?<message>.+)$/v,Ot=/ fix: \((?<suggestion>[^\)]+)\)$/v;function kt(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=Dt.exec(r);if(i?.groups===void 0){n.push(r);continue}let{column:a,file:o=``,line:s,message:c=``}=i.groups,l=Ot.exec(c),u=l?.groups?.suggestion;t.push({column:Number(a),file:E(o,e.cwd),line:Number(s),message:l===null?c:c.slice(0,-l[0].length),...u!==void 0&&{suggestion:u},severity:`warning`,tool:`cspell`})}return{diagnostics:t,unparsed:n}}async function At(e,t){if(!wt(t))return 0;let{errors:n,filesChecked:r,unusedWords:i}=await _t(t);if(n>0||r===0&&i.length>0){let t=P(`[Unused Words]`,`cyanBright`);return t.pipe(e),t.write(`Could not check for unused words: CSpell checked ${r} files with ${n} errors.\n`),1}if(i.length>0){let t=P(`[Unused Words]`,`cyanBright`);t.pipe(e);for(let e of i)t.write(`${e}\n`);return 1}return 0}async function jt(e){if(!wt(e))return{diagnostics:[],exitCode:0,unparsed:[]};let{errors:t,filesChecked:n,unusedWords:r}=await _t(e);if(t>0||n===0&&r.length>0)return{diagnostics:[{message:`Could not check for unused words: CSpell checked ${n} files with ${t} errors`,severity:`error`,tool:`unused-words`}],exitCode:1,unparsed:[]};let i=await Tt(),a=i===void 0?{}:{file:E(i,process.cwd())};return{diagnostics:r.map(e=>({...a,message:`Unused word in CSpell config "words" array: ${e}`,severity:`warning`,tool:`unused-words`})),exitCode:+(r.length>0),unparsed:[]}}async function Mt(e,t){let n=P(`[Words]`,`cyanBright`);if(n.pipe(e),!wt(t))return n.write(`Skipping unused word removal because file arguments were provided. Run without file arguments to remove unused words.
|
|
8
|
+
`),0;let r=await yt(t);if(r===void 0)return 0;for(let e of r.removedWords)n.write(`Removed unused word: ${e}\n`);return r.reordered&&n.write(`Sorted the "words" array alphabetically.
|
|
9
|
+
`),0}async function Nt(){let e=import.meta.resolve(`@kitschpatrol/cspell-config`),t=await u({cwd:s.dirname(x(e))});if(t===void 0)throw Error(`Could not find Case Police dictionary parent package.`);let n=s.join(s.dirname(t),`dictionaries`,`case-police.json`);try{await re(n,a.F_OK)}catch{throw Error(`Case Police dictionary file "${n}" does not exist.`)}return n}const Pt=/^(?<from>\S+) → (?<to>\S+)\s+(?<file>\S+):(?<line>\d+):(?<column>\d+)$/v;function Ft(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){if(!r.includes(`→`))continue;let i=Pt.exec(r);if(i?.groups===void 0){n.push(r);continue}let{column:a,file:o=``,from:s,line:c,to:l}=i.groups;t.push({column:Number(a),file:E(o,e.cwd),line:Number(c),message:`Case error: "${s}" should be "${l}"`,severity:`warning`,...l!==void 0&&{suggestion:l},tool:`case-police`})}return{diagnostics:t,unparsed:n}}async function It(e){let t=await b().searchForConfigFile(void 0);if(t===void 0)throw Error(`No CSpell configuration found.`);e.write(`Found cspell readme configuration at "${x(t.url)}"\n`);let n=O(await ie(t)).split(`
|
|
10
|
+
`);for(let t of n)e.write(`${t}\n`);return 0}const Lt={commands:{fix:{async commands(){return[{collect:{parse:Ft},logColor:`cyanBright`,logPrefix:`[Case Police]`,name:`case-police`,optionFlags:[`--fix`,`--dict`,await Nt(),`--ignore`,await Et()],outputFilter:e=>!e.includes(`→`),receivePositionalArguments:!0},{execute:Mt,name:`words`},{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`cspell`},collect:{parse:kt},name:`cspell`,optionFlags:[`--quiet`],receivePositionalArguments:!0}]},description:`Fix letter casing issues, remove unused words from the local CSpell configuration's "words" array, and report remaining (unfixable) spelling errors. ${K.fileRun} Unused words are only removed when no file arguments are given, since detecting them requires checking every file.`,positionalArgumentDefault:Ct,positionalArgumentMode:`optional`},init:{configFile:`cspell.config.ts`,configPackageJson:{cspell:{import:`@kitschpatrol/cspell-config`}},locationOptionFlag:!0},lint:{async commands(){return[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`cspell`},collect:{parse:kt},name:`cspell`,optionFlags:[`--quiet`],receivePositionalArguments:!0},{collect:jt,execute:At,name:`unused-words`},{collect:{parse:Ft},logColor:`cyanBright`,logPrefix:`[Case Police]`,name:`case-police`,optionFlags:[`--dict`,await Nt(),`--ignore`,await Et()],outputFilter:e=>!e.includes(`→`),receivePositionalArguments:!0}]},description:`Check for spelling mistakes. ${K.fileRun} Unused words in the configuration's "words" array are only reported when no file arguments are given, since detecting them requires checking every file.`,positionalArgumentDefault:Ct,positionalArgumentMode:`optional`},printConfig:{commands:[{execute:It,name:`cspell-config`}],description:`Print the resolved CSpell configuration. ${K.packageSearch} ${K.monorepoSearch}`,positionalArgumentMode:`none`}},description:`Kitschpatrol's CSpell shared configuration tools.`,logColor:`cyan`,logPrefix:`[CSpell]`,name:`ksc-cspell`,order:6};async function Rt(e,t){let n,[r]=t;if(r===void 0)n=W(`eslint`);else{let t=s.join(process.cwd(),r);e.write(`Showing configuration for file: ${t}\n`),n={name:`eslint`,optionFlags:[`--print-config`],receivePositionalArguments:!0}}let{exitCode:i}=await U(e,t,[],[n]);return i}function zt(e){let t;try{t=JSON.parse(e.stdout)}catch{return{diagnostics:[],unparsed:[...D(e.stdout),...D(e.stderr)]}}let n=[];for(let r of t)for(let t of r.messages)n.push({column:t.column,endColumn:t.endColumn,endLine:t.endLine,file:E(r.filePath,e.cwd),line:t.line,message:t.message,rule:t.ruleId??void 0,severity:t.fatal===!0||t.severity===2?`error`:`warning`,tool:`eslint`});return{diagnostics:n,unparsed:D(e.stderr)}}const q=[`--max-warnings`,`0`,`--no-warn-ignored`],Bt={commands:{fix:{commands:[{collect:{optionFlags:[`--fix`,...q,`--format`,`json`],parse:zt},name:`eslint`,optionFlags:[`--fix`,...q],receivePositionalArguments:!0}],description:`Fix your project with ESLint. ${K.fileRun}`,positionalArgumentDefault:`.`,positionalArgumentMode:`optional`},init:{locationOptionFlag:!1},lint:{commands:[{collect:{optionFlags:[...q,`--format`,`json`],parse:zt},name:`eslint`,optionFlags:q,receivePositionalArguments:!0}],description:`Lint your project with ESLint. ${K.fileRun}`,positionalArgumentDefault:`.`,positionalArgumentMode:`optional`},printConfig:{commands:[{execute:Rt,name:`eslint-config`}],description:`Print the effective ESLint configuration. ${K.optionalFileRun} Use \`@eslint/config-inspector\` for a more detailed view.`,positionalArgumentMode:`optional`}},description:`Kitschpatrol's ESLint shared configuration tools.`,logColor:`magenta`,logPrefix:`[ESLint]`,name:`ksc-eslint`,order:4},Vt={entry:[`{index,cli,main}.{js,mjs,cjs,jsx,ts,tsx,mts,cts}!`,`src/{index,cli,main}.{js,mjs,cjs,jsx,ts,tsx,mts,cts}!`,`src/{bin,lib,cli}/{index,cli,main}.{js,mjs,cjs,jsx,ts,tsx,mts,cts}!`,`scripts/**/*.{js,mjs,cjs,ts,mts,cts}`,`skills/*/scripts/**/*.{js,mjs,cjs,ts,mts,cts}`,`.remarkrc.{js,mjs,cjs,ts,mts,cts}`,`cspell.config.{js,mjs,cjs,ts,mts,cts}`,`eslint.config.{js,mjs,cjs,ts,mts,cts}`,`mdat.config.{js,mjs,cjs,ts,mts,cts}`,`prettier.config.{js,mjs,cjs,ts,mts,cts}`,`stylelint.config.{js,mjs,cjs,ts,mts,cts}`],ignoreBinaries:[`gh`,`ksc-cspell`,`ksc-eslint`,`ksc-knip`,`ksc-mdat`,`ksc-prettier`,`ksc-remark`,`ksc-repo`,`ksc-stylelint`,`ksc-typescript`,`op`],ignoreDependencies:[`@astrojs/check`,`@kitschpatrol/cspell-config`,`@kitschpatrol/dict-en-wiktionary`,`@kitschpatrol/eslint-config`,`@kitschpatrol/knip-config`,`@kitschpatrol/mdat-config`,`@kitschpatrol/prettier-config`,`@kitschpatrol/remark-config`,`@kitschpatrol/repo-config`,`@kitschpatrol/stylelint-config`,`@kitschpatrol/typescript-config`,`@prettier/plugin-php`,`@prettier/plugin-ruby`,`@prettier/plugin-xml`,`node-addon-api`,`node-gyp`,`prettier-plugin-packagejson`,`prettier-plugin-sh`,`prettier-plugin-tailwindcss`,`prettier-plugin-toml`,`remark-attribute-list`,`remark-directive`,`sharp`,`svelte-check`]},Ht={binaries:`Unlisted binary`,catalog:`Unused catalog entry`,classMembers:`Unused class member`,dependencies:`Unused dependency`,devDependencies:`Unused devDependency`,duplicates:`Duplicate export`,enumMembers:`Unused enum member`,exports:`Unused export`,files:`Unused file`,namespaceMembers:`Unused namespace member`,nsExports:`Unused namespace export`,nsTypes:`Unused namespace type`,optionalPeerDependencies:`Unused optional peer dependency`,types:`Unused exported type`,unlisted:`Unlisted dependency`,unresolved:`Unresolved import`};function Ut(e){return Array.isArray(e)?e.flatMap(e=>Array.isArray(e)?e:[e]):[]}function Wt(e){let t;try{t=JSON.parse(e.stdout)}catch{return{diagnostics:[],unparsed:[...D(e.stdout),...D(e.stderr)]}}let n=[],r=t.issues??[];for(let t of r){let r=E(t.file,e.cwd);for(let[e,i]of Object.entries(t)){let t=Ht[e];if(t!==void 0)for(let a of Ut(i)){let i=typeof a==`string`?a:a.name,o=typeof a==`string`?{}:{column:a.col,line:a.line};n.push({...o,file:r,message:e===`files`?t:`${t}: ${i}`,rule:e,severity:`warning`,tool:`knip`})}}}return{diagnostics:n,unparsed:D(e.stderr)}}function Gt(){if(Ie()){let e=j(),t=M();if(e!==t){let n=s.relative(t,e);if(n!==``)return[`--workspace`,n.split(s.sep).join(`/`)]}}return[]}function Kt(){return{knip:Vt}}const qt={commands:{init:{configFile:`knip.config.ts`,configPackageJson:Kt(),locationOptionFlag:!0},lint:{commands:[{collect:{optionFlags:[`--no-progress`,`--no-config-hints`,...Gt(),`--reporter`,`json`],parse:Wt},cwdOverride:`workspace-root`,name:`knip`,optionFlags:[`--no-progress`,`--no-config-hints`,...Gt()]}],description:`Check for unused code and dependencies. ${K.packageRun} ${K.monorepoRun}`,positionalArgumentMode:`none`},printConfig:{commands:[W(`knip`)],description:`Print the effective Knip configuration. ${K.packageSearch} ${K.monorepoSearch}`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Knip shared configuration tools.`,logColor:`cyan`,logPrefix:`[Knip]`,name:`ksc-knip`,order:7};async function Jt(){return(await G(`mdat`))?.filepath}async function Yt(e){let t=`mdat`,n=await G(t);n!==void 0&&e.write(`Found ${t} readme configuration at "${n.filepath}"\n`);let r=O(await ue()).split(`
|
|
11
|
+
`);for(let t of r)e.write(`${t}\n`);return 0}async function Xt(e){let t=A(),n=await Jt(),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}const Zt={commands:{fix:{commands:await Xt(`expand`),description:`Expand all Mdat content placeholders in your readme.md file(s). ${K.packageRun} ${K.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 Xt(`check`),description:`Validate that all Mdat content placeholders in your readme.md file(s) have been expanded and are up to date. ${K.packageRun} ${K.monorepoRun}`,parallel:!0,positionalArgumentMode:`none`},printConfig:{commands:[{execute:Yt,name:`mdat-config`}],description:`Print the effective Mdat configuration. ${K.packageSearch}. ${K.monorepoSearch}.`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Mdat shared configuration tools.`,logColor:`green`,logPrefix:`[Mdat Config]`,name:`ksc-mdat`,order:2},Qt=/^\[warn\] (?<file>\S+)$/v,$t=/^\[error\] (?<message>.+)$/v;function en(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=Qt.exec(r);if(i?.groups?.file!==void 0){t.push({file:E(i.groups.file,e.cwd),message:`File is not formatted with Prettier`,severity:`warning`,tool:`prettier`});continue}if(r.startsWith(`[warn] Code style issues found`))continue;let a=$t.exec(r);if(a?.groups?.message!==void 0){t.push({message:a.groups.message,severity:`error`,tool:`prettier`});continue}n.push(r)}return{diagnostics:t,unparsed:n}}const tn=[`--log-level=warn`,`--ignore-unknown`,`--plugin=prettier-plugin-astro`,`--plugin=@prettier/plugin-php`,`--plugin=@prettier/plugin-ruby`,`--plugin=@prettier/plugin-xml`,`--plugin=prettier-plugin-jsdoc`,`--plugin=prettier-plugin-packagejson`,`--plugin=prettier-plugin-sh`,`--plugin=prettier-plugin-svelte`,`--plugin=prettier-plugin-toml`,`--plugin=prettier-plugin-tailwindcss`,`--ignore-path=${Le(`.gitignore`)??`.gitignore`}`,`--ignore-path=${Le(`.prettierignore`)??`.prettierignore`}`],nn={commands:{fix:{commands:[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`prettier`},collect:{parse:en},name:`prettier`,optionFlags:[...tn,`--write`],receivePositionalArguments:!0}],description:`Format files according to your Prettier configuration. ${K.fileRun}`,positionalArgumentDefault:`.`,positionalArgumentMode:`optional`},init:{configFile:`prettier.config.ts`,configPackageJson:{prettier:`@kitschpatrol/prettier-config`},locationOptionFlag:!0},lint:{commands:[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`prettier`},collect:{parse:en},name:`prettier`,optionFlags:[...tn,`--check`],receivePositionalArguments:!0}],description:`Check that files are formatted according to your Prettier configuration. ${K.fileRun}`,positionalArgumentDefault:`.`,positionalArgumentMode:`optional`},printConfig:{commands:[W(`prettier`)],description:`Print the effective Prettier configuration. ${K.packageSearch}. ${K.monorepoSearch}.`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Prettier shared configuration tools.`,logColor:`blue`,logPrefix:`[Prettier]`,name:`ksc-prettier`,order:9},rn={commands:{init:{configFile:`.remarkrc.js`,configPackageJson:{remarkConfig:{plugins:[`@kitschpatrol/remark-config`]}},locationOptionFlag:!0},printConfig:{commands:[W(`remark`)],description:`Print the effective Remark configuration. ${K.packageSearch} ${K.monorepoSearch}`,positionalArgumentMode:`none`}},description:`Kitschpatrol's Remark and Remark Lint shared configuration tools. (Actual linting and fixing is managed through @kitschpatrol/eslint-config.)`,logColor:`blue`,logPrefix:`[remarklint]`,name:`ksc-remark`,order:8},an=[/Version 2\.0,?\s*January 2004/gv,/Version 1,?\s*February 1989/gv,/Version 2,?\s*June 1991/gv,/Version 3,?\s*29 June 2007/gv,/Version 2\.1,?\s*February 1999/gv,/Version 3,?\s*19 November 2007/gv,/Version 1\.0\s*-\s*August 17th,?\s*2003/gv,/Version 1\.1,?\s*March 2000/gv,/Version 1\.2,?\s*November 2002/gv,/Version 1\.3,?\s*3 November 2008/gv,/Version 1\.0\s*-\s*22 November 2005/gv,/Version 1\.1\s*-\s*26 February 2007/gv,/Version 2,?\s*December 2004/gv,/20 December 1996/gv,/December 20,?\s*1996/gv,/11 March 1996/gv,/28 March 2007/gv,/November 1,?\s*2008/gv,/August 1,?\s*2009/gv,/1 April 19\d{2}/gv,/Copyright \(c\) 2000-2006,?\s*The Perl Foundation/giv,/Copyright \(C\) (?:\d{4},?\s*)+Free Software Foundation/gv],on=[`node_modules/**`,`test/**`];function sn(e){let t=e;for(let e of an)e.lastIndex=0,t=t.replace(e,e=>e.replaceAll(/\d/gv,`X`));return t}const cn=/(\d{4})\s*-\s*(\d{4})/v,ln=/(\d{4})/v;function un(e,t){let n=sn(e),r=cn,i=r.exec(n);if(i){let[,n,a]=i;if(Number(a)!==t){let a=`${n}-${t}`;return e.slice(0,i.index)+e.slice(i.index).replace(r,()=>a)}return e}let a=ln,o=a.exec(n);if(o){let[,n]=o;if(Number(n)!==t){let r=`${n}-${t}`;return e.slice(0,o.index)+e.slice(o.index).replace(a,()=>r)}return e}return e}async function dn(e){let t=(/* @__PURE__ */ new Date()).getFullYear(),n=[`**/license.txt`,`**/license`,...on.map(e=>`!${e}`)],r=await de(n,{caseSensitiveMatch:!1,cwd:j(),followSymbolicLinks:!1,gitignore:!0}),i=[];for(let n of r)try{let r=await y.readFile(n,`utf8`),a=un(r,t);a!==r&&(i.push(n),e&&await y.writeFile(n,a,`utf8`))}catch(e){console.error(`Failed to process ${n}:`,e)}return i}async function fn(e,t=!1){let n=await dn(t);if(n.length>0){e.write(`${t?`Fixed`:`Found`} ${n.length} license ${F(`file`,n.length)} with outdated copyright year:\n`);for(let t of n)e.write(` - ${t}\n`);return+!t}return 0}async function pn(e){return fn(e,!1)}async function mn(){let e=await dn(!1);return{diagnostics:e.map(e=>({file:E(e,j()),message:`License file has an outdated copyright year`,severity:`error`,tool:`copyright-year`})),exitCode:+(e.length>0),unparsed:[]}}async function hn(e){return fn(e,!0)}const gn=`pnpm-lock.yaml`;function _n(e){let t=M(),n=s.resolve(e);for(;;){if(r.existsSync(s.join(n,gn)))return n;if(n===t)break;let e=s.dirname(n);if(e===n)break;n=e}}function vn(e,t,n){let r=`${e}@${t}`;return Object.hasOwn(n,r)?r:Object.hasOwn(n,t)?t:void 0}function yn(e,t){return e===void 0||e===``?t===void 0||t===``?void 0:t:t===void 0||t===``||fe(e,t)?e:t}async function bn(e){let t=_n(e);if(t===void 0||t===``)throw Error(`${gn} not found at or above "${e}".`);let n=s.join(t,gn),r=await me(t,{ignoreIncompatible:!1});if(!r?.importers)throw Error(`Lockfile at "${n}" is unreadable or missing importers.`);let i=r.packages??{},a,o,c={},l={};function u(e,t){let n,r=/* @__PURE__ */ new Set;function a(e,t){if(t.startsWith(`link:`))return;let o=vn(e,t,i);if(o===void 0||o===``||r.has(o))return;r.add(o);let s=i[o];if(s===void 0)return;let c=s.engines?.node;if(c!==void 0&&c!==``){let e=pe(c)?.version;e!==void 0&&e!==``&&(n===void 0||n===``||fe(e,n))&&(n=e)}if(s.dependencies)for(let[e,t]of Object.entries(s.dependencies))a(e,t)}return a(e,t),n}function d(e,t){for(let[n,r]of Object.entries(e)){let e=u(n,typeof r==`string`?r:r.version);if(e===void 0||e===``)continue;let i=t?l:c;i[e]??=/* @__PURE__ */ new Set,i[e].add(n);let s=t?o:a;(s===void 0||s===``||fe(e,s))&&(t?o=e:a=e)}}let f=s.relative(t,e),p=f===``?`.`:f,m=r.importers[p];m!==void 0&&(m.dependencies&&d(m.dependencies,!1),m.devDependencies&&d(m.devDependencies,!0));let h=yn(a,o),g=h===void 0?void 0:`>=${h}`;return{dependencies:a!==void 0&&a!==``?{topLevelCauses:[...c[a]??[]],version:`>=${a}`}:void 0,devDependencies:o!==void 0&&o!==``?{topLevelCauses:[...l[o]??[]],version:`>=${o}`}:void 0,lockfile:n,version:g}}function xn(e){let t=e.devEngines;if(t?.runtime)return(Array.isArray(t.runtime)?t.runtime:[t.runtime]).find(e=>e.name===`node`)?.version}function Sn(e,t){let n=e.devEngines??{};if(n.runtime){if(Array.isArray(n.runtime)){let e=n.runtime.find(e=>e.name===`node`);e===void 0?n.runtime.push({name:`node`,version:t}):e.version=t}else n.runtime.name===`node`?n.runtime.version=t:n.runtime=[n.runtime,{name:`node`,version:t}]}else n.runtime={name:`node`,version:t};e.devEngines=n}function Cn(e){let t=e.devEngines;if(t?.runtime){if(Array.isArray(t.runtime)){t.runtime=t.runtime.filter(e=>e.name!==`node`);let[e]=t.runtime;e===void 0?delete t.runtime:t.runtime.length===1&&(t.runtime=e)}else t.runtime.name===`node`&&delete t.runtime;Object.keys(t).length===0&&delete e.devEngines}}function J(e){return e.length===0?``:` (from ${e.join(`, `)})`}async function wn(e,t){let n=s.join(t,`package.json`);if(!r.existsSync(n))return{issues:[],packageJsonPath:n};let i=r.readJsonSync(n),a=i.engines?.node,o=xn(i),c=await bn(t),l=c.dependencies?.version,u=c.dependencies?.topLevelCauses??[],d=c.version,f=c.devDependencies?.topLevelCauses??[],p=[];if(l!==void 0){if(a===void 0){if(p.push(`Missing engines.node — suggest setting to "${l}"${J(u)}`),e){let e=i.engines??{};e.node=l,i.engines=e}}else{let t=S.minVersion(a),n=S.minVersion(l);t&&n&&S.lt(t,n)&&(p.push(`engines.node is "${a}" but production dependencies require at least "${l}"${J(u)}`),e&&(i.engines.node=l))}}let m=(()=>{if(l!==void 0&&l!==``&&a!==void 0&&a!==``){let e=S.minVersion(l),t=S.minVersion(a);if(e&&t)return S.gt(e,t)?l:a}return l??a})(),h=m!==void 0&&m!==``?S.minVersion(m):void 0,g=d!==void 0&&d!==``?S.minVersion(d):void 0,ee=g&&h&&S.gt(g,h);if(d!==void 0&&ee){if(o===void 0)p.push(`devDependencies require a higher Node.js minimum (${d}) than engines.node (${m??`none`}) — suggest adding devEngines.runtime for node with version "${d}"${J(f)}`),e&&Sn(i,d);else{let t=S.minVersion(o);t&&S.lt(t,g)&&(p.push(`devEngines.runtime.version for node is "${o}" but all dependencies require at least "${d}"${J(f)}`),e&&Sn(i,d))}}else if(o!==void 0){let t=S.minVersion(o);t&&h&&S.lte(t,h)&&(p.push(`devEngines.runtime.version for node is redundant (engines.node already covers the requirement) — suggest removing`),e&&Cn(i))}return e&&p.length>0&&(r.writeJsonSync(n,i,{spaces:` `}),await N(n)),{issues:p,packageJsonPath:n}}async function Tn(e,t){let n=A(),r=0;for(let i of n){let{issues:n,packageJsonPath:a}=await wn(t,i);if(n.length!==0){e.write(`${t?`Fixed`:`Found`} ${n.length} Node.js version ${F(`issue`,n.length)} in ${a}:\n`);for(let t of n)e.write(` - ${t}\n`);t||(r=1)}}return r}async function En(){let e=A(),t=[];for(let n of e){let{issues:e,packageJsonPath:r}=await wn(!1,n);for(let n of e)t.push({file:E(r,process.cwd()),message:n,severity:`error`,tool:`node-version`})}return{diagnostics:t,exitCode:+(t.length>0),unparsed:[]}}async function Dn(e){let t=O(await bn(j())).split(`
|
|
12
|
+
`);for(let n of t)e.write(`${n}\n`);return 0}async function On(e){return Tn(e,!1)}async function kn(e){return Tn(e,!0)}const An={commands:{fix:{commands:[{execute:hn,name:`copyright-year`},{execute:kn,name:`node-version`}],description:`Fix common issues like outdated copyright years in license files. ${K.packageRun} ${K.monorepoRun}`,positionalArgumentMode:`none`},init:{locationOptionFlag:!1},lint:{commands:[{collect:mn,execute:pn,name:`copyright-year`},{collect:En,execute:On,name:`node-version`}],description:`Check the repo for common issues. ${K.packageRun} ${K.monorepoRun}`,positionalArgumentMode:`none`},printConfig:{commands:[{execute:Dn,name:`node-version`}],description:`Print minimum Node.js version constraints from the pnpm lockfile.`,positionalArgumentMode:`none`}},description:`Kitschpatrol's repository-related shared configuration tools.`,logColor:`gray`,logPrefix:`[Repo Config]`,name:`ksc-repo`,order:1},Y=[`--ignore-path`,Le(`.gitignore`)??`.gitignore`,`--allow-empty-input`],jn=[`css`,`scss`,`sass`,`svelte`,`html`,`astro`,`tsx`,`jsx`,`php`,`vue`],Mn=`**/*.{${jn.join(`,`)}}`;function Nn(e){let t;try{t=JSON.parse(e.stderr)}catch{return{diagnostics:[],unparsed:[...D(e.stdout),...D(e.stderr)]}}let n=[];for(let r of t){let t=E(r.source,e.cwd);for(let e of r.warnings){let r=e.rule===void 0?void 0:` (${e.rule})`,i=r!==void 0&&e.text.endsWith(r)?e.text.slice(0,-r.length):e.text;n.push({column:e.column,endColumn:e.endColumn,endLine:e.endLine,file:t,line:e.line,message:i,rule:e.rule,severity:e.severity===`warning`?`warning`:`error`,tool:`stylelint`})}let i=r.parseErrors??[];for(let e of i)n.push({column:e.column,file:t,line:e.line,message:e.text,rule:`parse-error`,severity:`error`,tool:`stylelint`})}return{diagnostics:n,unparsed:D(e.stdout)}}async function Pn(e,t){let n=`stylelint`,r=await G(n);if(r===void 0)return 1;let{filepath:i,isEmpty:a}=r;if(a)return e.write(`Configuration is empty.
|
|
13
13
|
`),0;e.write(`Found ${n} configuration at "${i}"\n`);let o,[c]=t;c===void 0?o=Re(`package-dir`):(o=s.join(process.cwd(),c),e.write(`Showing config for file at "${o}"\n`));let l=O(await he.resolveConfig(o)).split(`
|
|
14
|
-
`);for(let t of l)e.write(`${t}\n`);return 0}const In={commands:{fix:{commands:[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`stylelint`},collect:{optionFlags:[...J,`--fix`,`--formatter`,`json`],parse:Pn},name:`stylelint`,optionFlags:[...J,`--fix`],receivePositionalArguments:!0}],description:`Fix your project with Stylelint. ${G.fileRun}`,positionalArgumentDefault:Nn,positionalArgumentExtensions:Mn,positionalArgumentMode:`optional`},init:{configFile:`stylelint.config.js`,configPackageJson:{stylelint:{extends:`@kitschpatrol/stylelint-config`}},locationOptionFlag:!0},lint:{commands:[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`stylelint`},collect:{optionFlags:[...J,`--formatter`,`json`],parse:Pn},name:`stylelint`,optionFlags:J,receivePositionalArguments:!0}],description:`Lint your project with Stylelint. ${G.fileRun}`,positionalArgumentDefault:Nn,positionalArgumentExtensions:Mn,positionalArgumentMode:`optional`},printConfig:{commands:[{execute:Fn,name:`stylelint-config`}],description:`Print the effective Stylelint configuration. ${G.optionalFileRun}.`,positionalArgumentMode:`optional`}},description:`Kitschpatrol's Stylelint shared configuration tools.`,logColor:`greenBright`,logPrefix:`[Stylelint]`,name:`ksc-stylelint`,order:5},Ln=/^\s/v,Rn=/\berror\b|\bfailed\b|\bfailure\b/iv;function Y(e,t,n,r){return e.exitCode!==0&&t.every(({severity:e})=>e!==`error`)&&t.push({message:r.find(e=>Rn.test(e))??`${n} exited with code ${e.exitCode} without a parseable error.`,severity:`error`,tool:n}),{diagnostics:t,unparsed:r}}function zn(e){return Ln.test(e)}function X(e){return typeof e==`object`&&!!e}function Z(e){try{let t=JSON.parse(e);return typeof t==`string`?t:void 0}catch{return}}const Bn=/^(?<file>.+?):(?<line>\d+):(?<column>\d+) - (?<severity>error|warning|hint) (?<rule>[^:]+): (?<message>.*)$/v,Vn=/^(?:\d{2}:\d{2}:\d{2} )?(?:✘ )?\[(?<severity>ERROR|WARN)\](?: \[(?<label>[^\]]+)\])? (?<message>.*)$/v,Hn=/^\d{2}:\d{2}:\d{2}\s+\[(?!ERROR\]|WARN\])[^\]]+\]\s+/v,Un=/^(?:Result \(\d+ files?\):|- \d+ (?:errors?|warnings?|hints?))$/v,Wn=/^(?:\d+\s.*|\s*[~^]+)$/v;function Gn(e){try{let t=JSON.parse(e);return!X(t)||typeof t.message!=`string`||t.level!==`debug`&&t.level!==`error`&&t.level!==`info`&&t.level!==`warn`?void 0:{...typeof t.label==`string`&&t.label.length>0&&{label:t.label},level:t.level,message:t.message}}catch{return}}function Kn(e){return e.level!==`error`&&e.level!==`warn`?void 0:{...e.label!==void 0&&{rule:e.label},message:e.message,severity:e.level===`error`?`error`:`warning`,tool:`astro`}}function qn(e,t){let n=Bn.exec(e);if(n?.groups===void 0)return;let{column:r,file:i,line:a,message:o,rule:s,severity:c}=n.groups;return{column:Number(r),file:E(i??``,t),line:Number(a),message:o??``,rule:s?.trim()??`unknown`,severity:c===`error`?`error`:c===`hint`?`info`:`warning`,tool:`astro`}}function Jn(e){let t=Vn.exec(e);if(t?.groups===void 0)return;let{label:n,message:r,severity:i}=t.groups;return{...n!==void 0&&{rule:n},message:r??``,severity:i===`ERROR`?`error`:`warning`,tool:`astro`}}function Yn(e){let t=e.trimEnd();return Hn.test(t)||Un.test(t)||t.startsWith(`Getting diagnostics for Astro files in `)}function Xn(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=Gn(r);if(i!==void 0){let e=Kn(i);e!==void 0&&t.push(e);continue}let a=qn(r,e.cwd)??Jn(r);if(a!==void 0){t.push(a);continue}if(Yn(r)||Wn.test(r))continue;let o=t.at(-1);if(o!==void 0&&zn(r)){o.message+=`\n${r.trim()}`;continue}n.push(r)}return Y(e,t,`astro`,n)}const Zn=/^(?:Loading svelte-check in workspace: |Getting Svelte diagnostics\.\.\.|svelte-check found 0 errors and 0 warnings$)/v,Qn=/^\d+ (?:START "|COMPLETED \d+ FILES 0 ERRORS 0 WARNINGS 0 FILES_WITH_PROBLEMS$)/v,$n=/^\d+ (?:START "|COMPLETED \d+ FILES \d+ ERRORS \d+ WARNINGS \d+ FILES_WITH_PROBLEMS$)/v,er=/^\d+ (?<severity>ERROR|WARNING) (?<file>"(?:\\.|[^"\\])*") (?<line>\d+):(?<column>\d+) (?<message>"(?:\\.|[^"\\])*")$/v,tr=/^\d+ FAILURE (?<message>.+)$/v,nr=/^\d+\s/v;function rr(e,t){let n=typeof e==`string`&&e.length>0?e:void 0,r=typeof t==`string`||typeof t==`number`?String(t):void 0;return n!==void 0&&r!==void 0?`${n}(${r})`:n??r}function ir(e,t){let n=e.indexOf(`{`);if(!(n<=0||!nr.test(e)))try{let r=JSON.parse(e.slice(n));if(!X(r)||r.type!==`ERROR`&&r.type!==`WARNING`||typeof r.filename!=`string`||typeof r.message!=`string`||!X(r.start)||typeof r.start.line!=`number`||typeof r.start.character!=`number`)return;let i=X(r.end)?r.end:void 0,a=rr(r.source,r.code);return{column:r.start.character+1,...i!==void 0&&typeof i.character==`number`&&{endColumn:i.character+1},...i!==void 0&&typeof i.line==`number`&&{endLine:i.line+1},file:E(r.filename,t),line:r.start.line+1,message:r.message,...a!==void 0&&{rule:a},severity:r.type===`ERROR`?`error`:`warning`,tool:`svelte-check`}}catch{return}}function ar(e,t){let n=er.exec(e);if(n?.groups===void 0)return;let{column:r,file:i,line:a,message:o,severity:s}=n.groups,c=Z(i??``),l=Z(o??``);return c===void 0||l===void 0?void 0:{column:Number(r),file:E(c,t),line:Number(a),message:l,severity:s===`ERROR`?`error`:`warning`,tool:`svelte-check`}}function or(e){let t=tr.exec(e);if(t?.groups===void 0)return;let n=t.groups.message??``;return{message:Z(n)??n,severity:`error`,tool:`svelte-check`}}function sr(e){return Zn.test(e)||Qn.test(e)}function cr(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=ir(r,e.cwd)??ar(r,e.cwd)??or(r);if(i!==void 0){t.push(i);continue}!$n.test(r)&&!sr(r)&&n.push(r)}return Y(e,t,`svelte-check`,n)}const lr=/^(?<file>.+?)\((?<line>\d+),(?<column>\d+)\): (?<severity>error|warning) (?<code>TS\d+): (?<message>.*)$/v,ur=/^(?<severity>error|warning) (?<code>TS\d+): (?<message>.*)$/v;function dr(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=lr.exec(r);if(i?.groups!==void 0){let{code:n,column:r,file:a,line:o,message:s,severity:c}=i.groups;t.push({column:Number(r),file:E(a??``,e.cwd),line:Number(o),message:s??``,rule:n,severity:c===`warning`?`warning`:`error`,tool:`tsc`});continue}let a=ur.exec(r);if(a?.groups!==void 0){let{code:e,message:n,severity:r}=a.groups;t.push({message:n??``,rule:e,severity:r===`warning`?`warning`:`error`,tool:`tsc`});continue}let o=t.at(-1);if(o!==void 0&&zn(r)){o.message+=`\n${r.trim()}`;continue}n.push(r)}return Y(e,t,`tsc`,n)}async function fr(e){let t=await r.readJson(s.join(e,`package.json`));return/* @__PURE__ */ new Set([...Object.keys(t.dependencies??{}),...Object.keys(t.devDependencies??{})])}function pr(e,t=`package-dir`){let n=e.has(`@astrojs/check`),r=e.has(`svelte-check`);if(n||r){let e=n?[{collect:{optionFlags:[`--json`],parse:Xn},cwdOverride:t,name:`astro`,outputFilter:Yn,subcommands:[`check`]}]:[];if(r){let r=n?[]:[`--tsconfig`,`./tsconfig.json`];e.push({collect:{optionFlags:[...r,`--output`,`machine-verbose`],parse:cr},cwdOverride:t,name:`svelte-check`,optionFlags:r,outputFilter:sr})}return e}return[{collect:{parse:dr},cwdOverride:t,name:`tsc`,optionFlags:[`--noEmit`]}]}function mr(e){let t=e.some(({hasTypeScriptConfig:e})=>e);return e.flatMap(({dependencies:e,directory:n,hasTypeScriptConfig:r},i)=>{let a=e.has(`@astrojs/check`)||e.has(`svelte-check`);return r||a||!t&&i===0?pr(e,n):[]})}async function hr(){let e=A();return mr(await Promise.all(e.map(async e=>{let[t,n]=await Promise.all([fr(e),r.pathExists(s.join(e,`tsconfig.json`))]);return{dependencies:t,directory:e,hasTypeScriptConfig:n}})))}const Q=[Vt,Rt,Jt,Qt,rn,an,jn,In,{commands:{init:{locationOptionFlag:!1},lint:{commands:hr,description:`Run type checking on your project. ${G.packageRun} ${G.monorepoRun}`,positionalArgumentMode:`none`,showResolvedCommands:!0},printConfig:{commands:[{name:`tsc`,optionFlags:[`--showConfig`],prettyJsonOutput:!0}],description:`Print the TypeScript configuration for the project. ${G.packageSearch} ${G.monorepoSearch}`,positionalArgumentMode:`none`}},description:`Kitschpatrol's TypeScript shared configuration tools.`,logColor:`blueBright`,logPrefix:`[TypeScript Config]`,name:`ksc-typescript`,order:3}],gr={"ksc-cspell":4,"ksc-eslint":2,"ksc-knip":6,"ksc-mdat":1,"ksc-prettier":5,"ksc-repo":0,"ksc-stylelint":3,"ksc-typescript":6};function $(e,t){t.sort((e,t)=>e.order-t.order);let n=[];for(let r of t)r.commands[e]!==void 0&&n.push({definition:r,effectiveKey:e});if(e===`fix`)for(let e of t)e.commands.fix===void 0&&e.commands.lint!==void 0&&n.push({definition:e,effectiveKey:`lint`});let r=[];for(let{definition:t,effectiveKey:i}of n){let n=i===`lint`?t.commands.lint:i===`fix`?t.commands.fix:void 0;if(n!==void 0&&(e===`lint`||e===`fix`)){let a={commands:n.commands,kind:`group`,logColor:t.logColor,logPrefix:t.logPrefix,name:t.name,parallel:n.parallel,positionalArgumentDefault:n.positionalArgumentDefault,positionalArgumentExtensions:n.positionalArgumentExtensions,positionalArgumentMode:n.positionalArgumentMode,showResolvedCommands:n.showResolvedCommands,stage:e===`fix`?gr[t.name]??7:0,subcommand:Ue(i),verbose:t.verbose};r.push(a);continue}let a={name:t.name,...i===`init`?{receiveOptionFlags:t.commands.init?.locationOptionFlag??!1}:{receivePositionalArguments:t.commands[i]?.positionalArgumentMode!==`none`},subcommands:[Ue(i)]};r.push(a)}return r}await gt({commands:{fix:{commands:$(`fix`,Q),description:`Fix your project with multiple tools in one go. Tools without auto-fixes run their checks afterward, so remaining issues match a subsequent lint. ${G.multiArgumentCaveat}`,parallel:!0,positionalArgumentMode:`optional`},init:{commands:$(`init`,Q),description:`Initialize configuration files for the entire suite of @kitschpatrol/shared-config tools. ${G.multiOptionCaveat}`,locationOptionFlag:!0},lint:{commands:$(`lint`,Q),description:`Lint your project with multiple tools in one go. ${G.multiArgumentCaveat}`,parallel:!0,positionalArgumentMode:`optional`},printConfig:{commands:$(`printConfig`,Q),description:`Print aggregated tool configuration data. ${G.multiArgumentCaveat}`,positionalArgumentMode:`optional`}},description:`Run aggregated @kitschpatrol/shared-config commands.`,logColor:`yellow`,logPrefix:`🔬`,name:`ksc`,order:0,showSummary:!0,verbose:!0});export{};
|
|
14
|
+
`);for(let t of l)e.write(`${t}\n`);return 0}const Fn={commands:{fix:{commands:[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`stylelint`},collect:{optionFlags:[...Y,`--fix`,`--formatter`,`json`],parse:Nn},name:`stylelint`,optionFlags:[...Y,`--fix`],receivePositionalArguments:!0}],description:`Fix your project with Stylelint. ${K.fileRun}`,positionalArgumentDefault:Mn,positionalArgumentExtensions:jn,positionalArgumentMode:`optional`},init:{configFile:`stylelint.config.js`,configPackageJson:{stylelint:{extends:`@kitschpatrol/stylelint-config`}},locationOptionFlag:!0},lint:{commands:[{cache:{flags:[`--cache`,`--cache-strategy`,`content`],name:`stylelint`},collect:{optionFlags:[...Y,`--formatter`,`json`],parse:Nn},name:`stylelint`,optionFlags:Y,receivePositionalArguments:!0}],description:`Lint your project with Stylelint. ${K.fileRun}`,positionalArgumentDefault:Mn,positionalArgumentExtensions:jn,positionalArgumentMode:`optional`},printConfig:{commands:[{execute:Pn,name:`stylelint-config`}],description:`Print the effective Stylelint configuration. ${K.optionalFileRun}.`,positionalArgumentMode:`optional`}},description:`Kitschpatrol's Stylelint shared configuration tools.`,logColor:`greenBright`,logPrefix:`[Stylelint]`,name:`ksc-stylelint`,order:5},In=/^\s/v,Ln=/\berror\b|\bfailed\b|\bfailure\b/iv;function X(e,t,n,r){return e.exitCode!==0&&t.every(({severity:e})=>e!==`error`)&&t.push({message:r.find(e=>Ln.test(e))??`${n} exited with code ${e.exitCode} without a parseable error.`,severity:`error`,tool:n}),{diagnostics:t,unparsed:r}}function Rn(e){return In.test(e)}function Z(e){return typeof e==`object`&&!!e}function Q(e){try{let t=JSON.parse(e);return typeof t==`string`?t:void 0}catch{return}}const zn=/^(?<file>.+?):(?<line>\d+):(?<column>\d+) - (?<severity>error|warning|hint) (?<rule>[^:]+): (?<message>.*)$/v,Bn=/^(?:\d{2}:\d{2}:\d{2} )?(?:✘ )?\[(?<severity>ERROR|WARN)\](?: \[(?<label>[^\]]+)\])? (?<message>.*)$/v,Vn=/^\d{2}:\d{2}:\d{2}\s+\[(?!ERROR\]|WARN\])[^\]]+\]\s+/v,Hn=/^(?:Result \(\d+ files?\):|- \d+ (?:errors?|warnings?|hints?))$/v,Un=/^(?:\d+\s.*|\s*[~^]+)$/v;function Wn(e){try{let t=JSON.parse(e);return!Z(t)||typeof t.message!=`string`||t.level!==`debug`&&t.level!==`error`&&t.level!==`info`&&t.level!==`warn`?void 0:{...typeof t.label==`string`&&t.label.length>0&&{label:t.label},level:t.level,message:t.message}}catch{return}}function Gn(e){return e.level!==`error`&&e.level!==`warn`?void 0:{...e.label!==void 0&&{rule:e.label},message:e.message,severity:e.level===`error`?`error`:`warning`,tool:`astro`}}function Kn(e,t){let n=zn.exec(e);if(n?.groups===void 0)return;let{column:r,file:i=``,line:a,message:o=``,rule:s,severity:c}=n.groups;return{column:Number(r),file:E(i,t),line:Number(a),message:o,rule:s?.trim()??`unknown`,severity:c===`error`?`error`:c===`hint`?`info`:`warning`,tool:`astro`}}function qn(e){let t=Bn.exec(e);if(t?.groups===void 0)return;let{label:n,message:r=``,severity:i}=t.groups;return{...n!==void 0&&{rule:n},message:r,severity:i===`ERROR`?`error`:`warning`,tool:`astro`}}function Jn(e){let t=e.trimEnd();return Vn.test(t)||Hn.test(t)||t.startsWith(`Getting diagnostics for Astro files in `)}function Yn(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=Wn(r);if(i!==void 0){let e=Gn(i);e!==void 0&&t.push(e);continue}let a=Kn(r,e.cwd)??qn(r);if(a!==void 0){t.push(a);continue}if(Jn(r)||Un.test(r))continue;let o=t.at(-1);if(o!==void 0&&Rn(r)){o.message+=`\n${r.trim()}`;continue}n.push(r)}return X(e,t,`astro`,n)}const Xn=/^(?:Loading svelte-check in workspace: |Getting Svelte diagnostics\.\.\.|svelte-check found 0 errors and 0 warnings$)/v,Zn=/^\d+ (?:START "|COMPLETED \d+ FILES 0 ERRORS 0 WARNINGS 0 FILES_WITH_PROBLEMS$)/v,Qn=/^\d+ (?:START "|COMPLETED \d+ FILES \d+ ERRORS \d+ WARNINGS \d+ FILES_WITH_PROBLEMS$)/v,$n=/^\d+ (?<severity>ERROR|WARNING) (?<file>"(?:\\.|[^"\\])*") (?<line>\d+):(?<column>\d+) (?<message>"(?:\\.|[^"\\])*")$/v,er=/^\d+ FAILURE (?<message>.+)$/v,tr=/^\d+\s/v;function nr(e,t){let n=typeof e==`string`&&e.length>0?e:void 0,r=typeof t==`string`||typeof t==`number`?String(t):void 0;return n!==void 0&&r!==void 0?`${n}(${r})`:n??r}function rr(e,t){let n=e.indexOf(`{`);if(!(n<=0||!tr.test(e)))try{let r=JSON.parse(e.slice(n));if(!Z(r)||r.type!==`ERROR`&&r.type!==`WARNING`||typeof r.filename!=`string`||typeof r.message!=`string`||!Z(r.start)||typeof r.start.line!=`number`||typeof r.start.character!=`number`)return;let i=Z(r.end)?r.end:void 0,a=nr(r.source,r.code);return{column:r.start.character+1,...i!==void 0&&typeof i.character==`number`&&{endColumn:i.character+1},...i!==void 0&&typeof i.line==`number`&&{endLine:i.line+1},file:E(r.filename,t),line:r.start.line+1,message:r.message,...a!==void 0&&{rule:a},severity:r.type===`ERROR`?`error`:`warning`,tool:`svelte-check`}}catch{return}}function ir(e,t){let n=$n.exec(e);if(n?.groups===void 0)return;let{column:r,file:i=``,line:a,message:o=``,severity:s}=n.groups,c=Q(i),l=Q(o);return c===void 0||l===void 0?void 0:{column:Number(r),file:E(c,t),line:Number(a),message:l,severity:s===`ERROR`?`error`:`warning`,tool:`svelte-check`}}function ar(e){let t=er.exec(e);if(t?.groups===void 0)return;let n=t.groups.message??``;return{message:Q(n)??n,severity:`error`,tool:`svelte-check`}}function or(e){return Xn.test(e)||Zn.test(e)}function sr(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=rr(r,e.cwd)??ir(r,e.cwd)??ar(r);if(i!==void 0){t.push(i);continue}!Qn.test(r)&&!or(r)&&n.push(r)}return X(e,t,`svelte-check`,n)}const cr=/^(?<file>.+?)\((?<line>\d+),(?<column>\d+)\): (?<severity>error|warning) (?<code>TS\d+): (?<message>.*)$/v,lr=/^(?<severity>error|warning) (?<code>TS\d+): (?<message>.*)$/v;function ur(e){let t=[],n=[];for(let r of D(`${e.stdout}\n${e.stderr}`)){let i=cr.exec(r);if(i?.groups!==void 0){let{code:n,column:r,file:a=``,line:o,message:s=``,severity:c}=i.groups;t.push({column:Number(r),file:E(a,e.cwd),line:Number(o),message:s,rule:n,severity:c===`warning`?`warning`:`error`,tool:`tsc`});continue}let a=lr.exec(r);if(a?.groups!==void 0){let{code:e,message:n=``,severity:r}=a.groups;t.push({message:n,rule:e,severity:r===`warning`?`warning`:`error`,tool:`tsc`});continue}let o=t.at(-1);if(o!==void 0&&Rn(r)){o.message+=`\n${r.trim()}`;continue}n.push(r)}return X(e,t,`tsc`,n)}async function dr(e){let t=await r.readJson(s.join(e,`package.json`));return/* @__PURE__ */ new Set([...Object.keys(t.dependencies??{}),...Object.keys(t.devDependencies??{})])}function fr(e,t=`package-dir`){let n=e.has(`@astrojs/check`),r=e.has(`svelte-check`);if(n||r){let e=n?[{collect:{optionFlags:[`--json`],parse:Yn},cwdOverride:t,name:`astro`,outputFilter:Jn,subcommands:[`check`]}]:[];if(r){let r=n?[]:[`--tsconfig`,`./tsconfig.json`];e.push({collect:{optionFlags:[...r,`--output`,`machine-verbose`],parse:sr},cwdOverride:t,name:`svelte-check`,optionFlags:r,outputFilter:or})}return e}return[{collect:{parse:ur},cwdOverride:t,name:`tsc`,optionFlags:[`--noEmit`]}]}function pr(e){let t=e.some(({hasTypeScriptConfig:e})=>e);return e.flatMap(({dependencies:e,directory:n,hasTypeScriptConfig:r},i)=>{let a=e.has(`@astrojs/check`)||e.has(`svelte-check`);return r||a||!t&&i===0?fr(e,n):[]})}async function mr(){let e=A();return pr(await Promise.all(e.map(async e=>{let[t,n]=await Promise.all([dr(e),r.pathExists(s.join(e,`tsconfig.json`))]);return{dependencies:t,directory:e,hasTypeScriptConfig:n}})))}const hr=[Bt,Lt,qt,Zt,nn,rn,An,Fn,{commands:{init:{locationOptionFlag:!1},lint:{commands:mr,description:`Run type checking on your project. ${K.packageRun} ${K.monorepoRun}`,positionalArgumentMode:`none`,showResolvedCommands:!0},printConfig:{commands:[{name:`tsc`,optionFlags:[`--showConfig`],prettyJsonOutput:!0}],description:`Print the TypeScript configuration for the project. ${K.packageSearch} ${K.monorepoSearch}`,positionalArgumentMode:`none`}},description:`Kitschpatrol's TypeScript shared configuration tools.`,logColor:`blueBright`,logPrefix:`[TypeScript Config]`,name:`ksc-typescript`,order:3}],gr={"ksc-cspell":4,"ksc-eslint":2,"ksc-knip":6,"ksc-mdat":1,"ksc-prettier":5,"ksc-repo":0,"ksc-stylelint":3,"ksc-typescript":6};function $(e){let t=hr.toSorted((e,t)=>e.order-t.order),n=[];for(let r of t)r.commands[e]!==void 0&&n.push({definition:r,effectiveKey:e});if(e===`fix`)for(let e of t)e.commands.fix===void 0&&e.commands.lint!==void 0&&n.push({definition:e,effectiveKey:`lint`});let r=[];for(let{definition:t,effectiveKey:i}of n){let n=i===`lint`?t.commands.lint:i===`fix`?t.commands.fix:void 0;if(n!==void 0&&(e===`lint`||e===`fix`)){let a={commands:n.commands,kind:`group`,logColor:t.logColor,logPrefix:t.logPrefix,name:t.name,parallel:n.parallel,positionalArgumentDefault:n.positionalArgumentDefault,positionalArgumentExtensions:n.positionalArgumentExtensions,positionalArgumentMode:n.positionalArgumentMode,showResolvedCommands:n.showResolvedCommands,stage:e===`fix`?gr[t.name]??7:0,subcommand:Ue(i),verbose:t.verbose};r.push(a);continue}let a={name:t.name,...i===`init`?{receiveOptionFlags:t.commands.init?.locationOptionFlag??!1}:{receivePositionalArguments:t.commands[i]?.positionalArgumentMode!==`none`},subcommands:[Ue(i)]};r.push(a)}return r}await ht({commands:{fix:{commands:$(`fix`),description:`Fix your project with multiple tools in one go. Tools without auto-fixes run their checks afterward, so remaining issues match a subsequent lint. ${K.multiArgumentCaveat}`,parallel:!0,positionalArgumentMode:`optional`},init:{commands:$(`init`),description:`Initialize configuration files for the entire suite of @kitschpatrol/shared-config tools. ${K.multiOptionCaveat}`,locationOptionFlag:!0},lint:{commands:$(`lint`),description:`Lint your project with multiple tools in one go. ${K.multiArgumentCaveat}`,parallel:!0,positionalArgumentMode:`optional`},printConfig:{commands:$(`printConfig`),description:`Print aggregated tool configuration data. ${K.multiArgumentCaveat}`,positionalArgumentMode:`optional`}},description:`Run aggregated @kitschpatrol/shared-config commands.`,logColor:`yellow`,logPrefix:`🔬`,name:`ksc`,order:0,showSummary:!0,verbose:!0});export{};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitschpatrol/shared-config",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.11.0",
|
|
4
4
|
"description": "A collection of shared configurations, linters, and formatting tools for TypeScript projects. All managed as a single dependency. All invoked via a single CLI command.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shared-config",
|
|
@@ -50,25 +50,26 @@
|
|
|
50
50
|
"files": [
|
|
51
51
|
"bin/*",
|
|
52
52
|
"dist/*",
|
|
53
|
-
"init/*"
|
|
53
|
+
"init/*",
|
|
54
|
+
"skills/*"
|
|
54
55
|
],
|
|
55
56
|
"dependencies": {
|
|
56
|
-
"@kitschpatrol/cspell-config": "8.
|
|
57
|
-
"@kitschpatrol/eslint-config": "8.
|
|
58
|
-
"@kitschpatrol/knip-config": "8.
|
|
59
|
-
"@kitschpatrol/mdat-config": "8.
|
|
60
|
-
"@kitschpatrol/prettier-config": "8.
|
|
61
|
-
"@kitschpatrol/remark-config": "8.
|
|
62
|
-
"@kitschpatrol/repo-config": "8.
|
|
63
|
-
"@kitschpatrol/stylelint-config": "8.
|
|
64
|
-
"@kitschpatrol/typescript-config": "8.
|
|
57
|
+
"@kitschpatrol/cspell-config": "8.11.0",
|
|
58
|
+
"@kitschpatrol/eslint-config": "8.11.0",
|
|
59
|
+
"@kitschpatrol/knip-config": "8.11.0",
|
|
60
|
+
"@kitschpatrol/mdat-config": "8.11.0",
|
|
61
|
+
"@kitschpatrol/prettier-config": "8.11.0",
|
|
62
|
+
"@kitschpatrol/remark-config": "8.11.0",
|
|
63
|
+
"@kitschpatrol/repo-config": "8.11.0",
|
|
64
|
+
"@kitschpatrol/stylelint-config": "8.11.0",
|
|
65
|
+
"@kitschpatrol/typescript-config": "8.11.0",
|
|
65
66
|
"@pinojs/json-colorizer": "^4.0.0",
|
|
66
|
-
"@pnpm/lockfile.fs": "^1100.2.
|
|
67
|
+
"@pnpm/lockfile.fs": "^1100.2.12",
|
|
67
68
|
"cosmiconfig": "^10.0.1",
|
|
68
69
|
"cosmiconfig-typescript-loader": "^6.3.0",
|
|
69
|
-
"cspell": "^10.3.
|
|
70
|
-
"cspell-config-lib": "^10.3.
|
|
71
|
-
"cspell-lib": "^10.3.
|
|
70
|
+
"cspell": "^10.3.6",
|
|
71
|
+
"cspell-config-lib": "^10.3.6",
|
|
72
|
+
"cspell-lib": "^10.3.6",
|
|
72
73
|
"decircular": "^1.0.0",
|
|
73
74
|
"deepmerge": "^4.3.1",
|
|
74
75
|
"deepmerge-ts": "^8.0.2",
|
|
@@ -78,12 +79,12 @@
|
|
|
78
79
|
"globby": "^16.2.4",
|
|
79
80
|
"json-stringify-pretty-compact": "^4.0.0",
|
|
80
81
|
"magicast": "^0.5.5",
|
|
81
|
-
"mdat": "^3.
|
|
82
|
+
"mdat": "^3.5.0",
|
|
82
83
|
"package-up": "^5.0.0",
|
|
83
84
|
"picocolors": "^1.1.1",
|
|
84
85
|
"prettier": "^3.9.9",
|
|
85
86
|
"semver": "^7.8.5",
|
|
86
|
-
"stylelint": "^17.
|
|
87
|
+
"stylelint": "^17.16.0",
|
|
87
88
|
"yargs": "^18.2.0"
|
|
88
89
|
},
|
|
89
90
|
"engines": {
|
package/readme.md
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
- [Overview](#overview)
|
|
22
22
|
- [Getting started](#getting-started)
|
|
23
23
|
- [Usage](#usage)
|
|
24
|
+
- [Agent skills](#agent-skills)
|
|
24
25
|
- [Implementation notes](#implementation-notes)
|
|
25
26
|
- [Development notes](#development-notes)
|
|
26
27
|
- [Background](#background)
|
|
@@ -369,6 +370,38 @@ Each task's problem matcher parses the machine-format output and populates VS Co
|
|
|
369
370
|
|
|
370
371
|
The tasks share a problem matcher owner, so the panel reflects the most recent run instead of stacking duplicates across tasks. Existing `tasks.json` files are merged by task label: your own tasks are left alone, and same-label `ksc` tasks are updated in place.
|
|
371
372
|
|
|
373
|
+
<!-- skills -->
|
|
374
|
+
|
|
375
|
+
## Agent skills
|
|
376
|
+
|
|
377
|
+
This project includes an [Agent Skill](https://agentskills.io) that teaches coding agents like Claude Code and Codex how to work with @kitschpatrol/shared-config:
|
|
378
|
+
|
|
379
|
+
- **[`ksc`](skills/ksc/SKILL.md)**: Code conventions and lint workflow for projects that use @kitschpatrol/shared-config and its ksc CLI, which wraps ESLint, Prettier, TypeScript, Stylelint, CSpell, Knip, remark, and mdat. Use when writing or editing TypeScript, JavaScript, CSS, Markdown, JSON, or YAML in a project that depends on @kitschpatrol/shared-config, when running or fixing `ksc lint` / `ksc fix` failures, when writing eslint-disable comments, or when editing the tool config files it manages.
|
|
380
|
+
|
|
381
|
+
The skill is published in the `skills` directory of the `@kitschpatrol/shared-config` package. Nothing is added to your project until you install it with one of the tools below.
|
|
382
|
+
|
|
383
|
+
### Sync from the installed package (recommended)
|
|
384
|
+
|
|
385
|
+
With `@kitschpatrol/shared-config` installed as a project dependency, the [`skills`](https://github.com/vercel-labs/skills) CLI finds skills bundled in your dependencies and copies them into your project's agent skill directories, so they match the version of `@kitschpatrol/shared-config` you have installed:
|
|
386
|
+
|
|
387
|
+
```sh
|
|
388
|
+
npx skills experimental_sync
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Run the command again after upgrading `@kitschpatrol/shared-config` to refresh the copies. The `experimental_sync` command is experimental and its behavior may change.
|
|
392
|
+
|
|
393
|
+
### Install from the repository
|
|
394
|
+
|
|
395
|
+
If `@kitschpatrol/shared-config` is not a dependency of your project, for example because you use a global installation, install the skill from the repository instead:
|
|
396
|
+
|
|
397
|
+
```sh
|
|
398
|
+
npx skills add kitschpatrol/shared-config
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
A skill installed this way follows the repository's default branch rather than your installed version of `@kitschpatrol/shared-config`.
|
|
402
|
+
|
|
403
|
+
<!-- /skills -->
|
|
404
|
+
|
|
372
405
|
## Implementation notes
|
|
373
406
|
|
|
374
407
|
### Line endings
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ksc
|
|
3
|
+
description: Code conventions and lint workflow for projects that use @kitschpatrol/shared-config and its ksc CLI, which wraps ESLint, Prettier, TypeScript, Stylelint, CSpell, Knip, remark, and mdat. Use when writing or editing TypeScript, JavaScript, CSS, Markdown, JSON, or YAML in a project that depends on @kitschpatrol/shared-config, when running or fixing `ksc lint` / `ksc fix` failures, when writing eslint-disable comments, or when editing the tool config files it manages.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Working with @kitschpatrol/shared-config
|
|
8
|
+
|
|
9
|
+
The project lints, formats, and type checks through the `ksc` CLI. The rules are strict and warnings fail the run, so write code that matches the conventions below, then let the tools fix what they can.
|
|
10
|
+
|
|
11
|
+
## Workflow
|
|
12
|
+
|
|
13
|
+
1. Write the code.
|
|
14
|
+
2. Run `pnpm ksc fix`. It applies every auto-fix (formatting, sorting, import style), then reports what remains.
|
|
15
|
+
3. Fix the remaining issues by hand and repeat until `pnpm ksc lint` is clean.
|
|
16
|
+
|
|
17
|
+
Use pnpm, not npm, npx, or yarn. Projects usually map `pnpm lint` and `pnpm fix` to the commands above.
|
|
18
|
+
|
|
19
|
+
Both commands accept file arguments (`pnpm ksc fix src/thing.ts`) and `--skip <tool>`. Tools that only work on the whole package, such as TypeScript and Knip, ignore file arguments. To work on one tool's errors, run it alone:
|
|
20
|
+
|
|
21
|
+
| Command | Tool | `lint` | `fix` |
|
|
22
|
+
| ---------------- | ----------------------------------- | ------ | ----- |
|
|
23
|
+
| `ksc-eslint` | ESLint, including Markdown linting | yes | yes |
|
|
24
|
+
| `ksc-prettier` | Prettier | yes | yes |
|
|
25
|
+
| `ksc-typescript` | Type checking | yes | |
|
|
26
|
+
| `ksc-stylelint` | Stylelint | yes | yes |
|
|
27
|
+
| `ksc-cspell` | Spelling and letter case | yes | yes |
|
|
28
|
+
| `ksc-knip` | Unused files, exports, dependencies | yes | |
|
|
29
|
+
| `ksc-mdat` | Readme placeholder comments | yes | yes |
|
|
30
|
+
|
|
31
|
+
`pnpm ksc print-config [file]` shows the resolved configuration when a rule's settings are unclear.
|
|
32
|
+
|
|
33
|
+
## Gotchas
|
|
34
|
+
|
|
35
|
+
- **Do not sort or format by hand.** Prettier owns formatting, and the Perfectionist ESLint plugin sorts imports, object keys, type members, and unions. `fix` handles both. Some keys intentionally sort semantically instead of alphabetically (`x, y, z`, `width, height`, `min, max`, `start, end`, `r, g, b, a`), so leave whatever order `fix` produces.
|
|
36
|
+
- **ESLint plugins are renamed.** Disable comments must use the short prefix, e.g. `// eslint-disable-next-line ts/no-explicit-any`:
|
|
37
|
+
|
|
38
|
+
| Upstream name | Prefix here |
|
|
39
|
+
| ----------------------------------- | ----------------- |
|
|
40
|
+
| `@typescript-eslint` | `ts` |
|
|
41
|
+
| `import-x` | `import` |
|
|
42
|
+
| `n` | `node` |
|
|
43
|
+
| `vitest` | `test` |
|
|
44
|
+
| `@eslint-community/eslint-comments` | `eslint-comments` |
|
|
45
|
+
| `@eslint-react` | `react` |
|
|
46
|
+
| `@stylistic` | `stylistic` |
|
|
47
|
+
| `jsonc` | `json` |
|
|
48
|
+
| `yml` | `yaml` |
|
|
49
|
+
| `@html-eslint` | `html` |
|
|
50
|
+
| `package-json` | `json-package` |
|
|
51
|
+
|
|
52
|
+
- **Unknown words fail CSpell.** Add legitimate project terms to the `words` array in `cspell.config.ts`. An unscoped `ksc fix` removes words that are no longer used anywhere.
|
|
53
|
+
- **Knip flags anything unused**, including exports, files, and dependencies. Remove dead code instead of leaving it exported.
|
|
54
|
+
- **Generated readme sections are owned by mdat.** Content between `<!-- keyword -->` and `<!-- /keyword -->` comments is regenerated by `ksc fix`. Do not edit it by hand.
|
|
55
|
+
- **ESLint is type-aware and never cached**, so it is the slow step. `--no-cache` disables the other tools' caches if results look stale.
|
|
56
|
+
|
|
57
|
+
## TypeScript rules that fail most often
|
|
58
|
+
|
|
59
|
+
- **No `null`.** Use `undefined` (`unicorn/no-null`, `ts/no-restricted-types`). Convert at API boundaries: `apiResult() ?? undefined`. Comparing against `null` with `===` is allowed.
|
|
60
|
+
- **No `any`.** Use `unknown` and narrow (`ts/no-explicit-any`, plus `ts/no-unsafe-assignment`, `-call`, `-member-access`, `-return`).
|
|
61
|
+
- **No `Buffer` or `object` types.** Use `Uint8Array` and `Record<string, unknown>`.
|
|
62
|
+
- **Handle every promise** (`ts/no-floating-promises`). Use `await`, or `void someAsyncFunction()` for deliberate fire-and-forget. Functions that return a promise must be declared `async` (`ts/promise-function-async`).
|
|
63
|
+
- **Template literals accept only strings and numbers** (`ts/restrict-template-expressions`). Convert the rest: `` `ready: ${String(isReady)}` ``. `+` cannot mix strings and numbers (`ts/restrict-plus-operands`).
|
|
64
|
+
- **Conditions must be boolean** (`ts/strict-boolean-expressions`). Strings and numbers are not allowed as conditions, so write `text !== ''` and `array.length > 0` (`unicorn/explicit-length-check`). Nullable objects and nullable booleans are allowed.
|
|
65
|
+
- **Use `??` and `?.`** instead of `||` and `&&` chains for nullish values (`ts/prefer-nullish-coalescing`, `ts/prefer-optional-chain`).
|
|
66
|
+
- **Indexed access is `T | undefined`** (`noUncheckedIndexedAccess`). Narrow `array[i]` and `record[key]` before use.
|
|
67
|
+
- **Only erasable syntax** (`erasableSyntaxOnly`). No `enum`, runtime `namespace`, or constructor parameter properties.
|
|
68
|
+
- **Type-only imports and exports use separate top-level statements** (`verbatimModuleSyntax`, `import/consistent-type-specifier-style`): `import type { Foo } from './bar'` and `export type { Foo }`, never the inline `import { type Foo }`.
|
|
69
|
+
- **`type`, not `interface`** (`ts/consistent-type-definitions`).
|
|
70
|
+
- **Array types:** `string[]` for simple element types, `Array<string | number>` for anything else (`ts/array-type`).
|
|
71
|
+
- **Unused locals and parameters are errors.** Prefix intentionally unused ones with `_`.
|
|
72
|
+
- **Every code path returns** (`noImplicitReturns`), and overriding class members need `override`.
|
|
73
|
+
|
|
74
|
+
## Naming
|
|
75
|
+
|
|
76
|
+
Enforced by `ts/naming-convention` and unicorn:
|
|
77
|
+
|
|
78
|
+
- `camelCase` for variables, functions, parameters, and properties. `const` variables may also be `UPPER_CASE`.
|
|
79
|
+
- `StrictPascalCase` for types, classes, and type parameters. Strict means `HttpClient`, not `HTTPClient`.
|
|
80
|
+
- Imports and destructured variables may be `camelCase` or `StrictPascalCase`.
|
|
81
|
+
- Properties that need quotes (e.g. `'Content-Type'`) are exempt.
|
|
82
|
+
- File names are `kebab-case` (`unicorn/filename-case`).
|
|
83
|
+
- No abbreviations (`unicorn/name-replacements`): `error` not `err`, `button` not `btn`, `index` not `idx`. The exceptions are `i`, `j`, `acc`, `arg`, `args`, `db`, `dev`, `doc`, `docs`, `env`, `fn`, `lib`, `param`, `params`, `pkg`, `prop`, `props`, `ref`, `refs`, `sep`, `src`, `temp`, `util`, and `utils`.
|
|
84
|
+
- Catch clause variables are named `error` (`unicorn/catch-error-name`).
|
|
85
|
+
|
|
86
|
+
## Style
|
|
87
|
+
|
|
88
|
+
Prettier settings: no semicolons, single quotes, tabs (spaces in Markdown and YAML), trailing commas, 100 column width, LF line endings.
|
|
89
|
+
|
|
90
|
+
ESLint rules that are not auto-fixed or that change how code is written:
|
|
91
|
+
|
|
92
|
+
- Braces on every `if`, `else`, and loop body (`curly`).
|
|
93
|
+
- `for...of` instead of `.forEach()` (`unicorn/no-for-each`). `.reduce()` is allowed only for simple operations like sums (`unicorn/no-array-reduce`).
|
|
94
|
+
- `node:` protocol for Node.js built-ins: `import fs from 'node:fs'`.
|
|
95
|
+
- Comments start with a capital letter (`capitalized-comments`).
|
|
96
|
+
- Exported function declarations need a JSDoc comment with a description (`jsdoc/require-jsdoc`, `jsdoc/require-description`). Do not write types in JSDoc, so `@param name` not `@param {string} name`. `@param` and `@returns` tags are optional in TypeScript files.
|
|
97
|
+
|
|
98
|
+
## Configuration files
|
|
99
|
+
|
|
100
|
+
Each tool is configured through a typed factory function. Pass overrides to the factory instead of replacing the shared config:
|
|
101
|
+
|
|
102
|
+
| File | Contents |
|
|
103
|
+
| --------------------- | ------------------------------------------------------------- |
|
|
104
|
+
| `eslint.config.ts` | `eslintConfig()` from `@kitschpatrol/eslint-config` |
|
|
105
|
+
| `prettier.config.ts` | `prettierConfig()` from `@kitschpatrol/prettier-config` |
|
|
106
|
+
| `cspell.config.ts` | `cspellConfig()` from `@kitschpatrol/cspell-config` |
|
|
107
|
+
| `knip.config.ts` | `knipConfig()` from `@kitschpatrol/knip-config` |
|
|
108
|
+
| `stylelint.config.js` | `stylelintConfig()` from `@kitschpatrol/stylelint-config` |
|
|
109
|
+
| `.remarkrc.js` | `remarkConfig()` from `@kitschpatrol/remark-config` |
|
|
110
|
+
| `mdat.config.ts` | `mdatConfig()` from `@kitschpatrol/mdat-config` |
|
|
111
|
+
| `tsconfig.json` | `"extends": "@kitschpatrol/typescript-config"` (TypeScript 6) |
|
|
112
|
+
|
|
113
|
+
Configs may instead live under the matching keys in `package.json`. `eslintConfig()` detects Astro, React, and Svelte from installed packages. Pass `{ astro: true }`, `{ react: true }`, or `{ svelte: true }` to force one on. Per-file rule overrides go in the factory's options, e.g. `eslintConfig({ ts: { overrides: { 'ts/no-explicit-any': 'off' } } })`.
|