@kitschpatrol/shared-config 8.12.0 → 8.12.1
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 +1 -1
- package/package.json +10 -10
- package/skills/ksc-update/SKILL.md +125 -49
package/bin/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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.12.
|
|
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.12.1`;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
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
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.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitschpatrol/shared-config",
|
|
3
|
-
"version": "8.12.
|
|
3
|
+
"version": "8.12.1",
|
|
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",
|
|
@@ -54,15 +54,15 @@
|
|
|
54
54
|
"skills/*"
|
|
55
55
|
],
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@kitschpatrol/cspell-config": "8.12.
|
|
58
|
-
"@kitschpatrol/eslint-config": "8.12.
|
|
59
|
-
"@kitschpatrol/knip-config": "8.12.
|
|
60
|
-
"@kitschpatrol/mdat-config": "8.12.
|
|
61
|
-
"@kitschpatrol/prettier-config": "8.12.
|
|
62
|
-
"@kitschpatrol/remark-config": "8.12.
|
|
63
|
-
"@kitschpatrol/repo-config": "8.12.
|
|
64
|
-
"@kitschpatrol/stylelint-config": "8.12.
|
|
65
|
-
"@kitschpatrol/typescript-config": "8.12.
|
|
57
|
+
"@kitschpatrol/cspell-config": "8.12.1",
|
|
58
|
+
"@kitschpatrol/eslint-config": "8.12.1",
|
|
59
|
+
"@kitschpatrol/knip-config": "8.12.1",
|
|
60
|
+
"@kitschpatrol/mdat-config": "8.12.1",
|
|
61
|
+
"@kitschpatrol/prettier-config": "8.12.1",
|
|
62
|
+
"@kitschpatrol/remark-config": "8.12.1",
|
|
63
|
+
"@kitschpatrol/repo-config": "8.12.1",
|
|
64
|
+
"@kitschpatrol/stylelint-config": "8.12.1",
|
|
65
|
+
"@kitschpatrol/typescript-config": "8.12.1",
|
|
66
66
|
"@pinojs/json-colorizer": "^4.0.0",
|
|
67
67
|
"@pnpm/lockfile.fs": "^1100.2.12",
|
|
68
68
|
"cosmiconfig": "^10.0.1",
|
|
@@ -44,11 +44,13 @@ instruction below to ask, confirm, or await a decision:
|
|
|
44
44
|
including explicit approval for runtime-range restrictions and Node-types
|
|
45
45
|
changes, still apply.
|
|
46
46
|
- **Other decisions and missing prerequisites:** without prior authorization,
|
|
47
|
-
leave approval-dependent changes unapplied, including range restrictions
|
|
48
|
-
peer-warning suppressions
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
leave approval-dependent changes unapplied, including range restrictions.
|
|
48
|
+
Scoped peer-warning suppressions with verified compatibility (step 5) are not
|
|
49
|
+
approval-dependent: apply them and report them. Report missing consumer
|
|
50
|
+
information, credentials, permissions, or validation resources instead of
|
|
51
|
+
requesting them. Continue independent work; if a required prerequisite
|
|
52
|
+
prevents progress, report the affected work as blocked or incomplete without
|
|
53
|
+
waiting or bypassing it.
|
|
52
54
|
|
|
53
55
|
Review and validation remain required in both modes. Defer candidates whose
|
|
54
56
|
impact cannot be established or whose migration cannot be validated. If safe
|
|
@@ -83,12 +85,17 @@ nothing can be applied, produce the report without manufacturing a change.
|
|
|
83
85
|
apply.
|
|
84
86
|
- **Release maturity:** third-party releases must be at least 24 hours old
|
|
85
87
|
(`--maturity-period 1` for Taze, `--min-age 1` for Actions Up, pnpm
|
|
86
|
-
`minimumReleaseAge` of 1440 minutes).
|
|
87
|
-
|
|
88
|
+
`minimumReleaseAge` of 1440 minutes). The period governs which releases a run
|
|
89
|
+
may introduce; it never requires downgrading a version that was locked before
|
|
90
|
+
the run. Never disable installation safeguards to make an update succeed.
|
|
88
91
|
- **Authored packages:** packages owned by `kitschpatrol` (discovered at runtime
|
|
89
92
|
in Setup) are exempt from maturity and target their latest stable release,
|
|
90
|
-
including majors.
|
|
91
|
-
|
|
93
|
+
including majors. pnpm enforces `minimumReleaseAge` silently by selecting the
|
|
94
|
+
newest mature version, so the exemption is only real while a
|
|
95
|
+
`minimumReleaseAgeExclude` entry for the young release exists: add it when
|
|
96
|
+
needed (step 5) and keep it through cleanup (step 6). The maturity period
|
|
97
|
+
must never hold an authored package back or downgrade it. The exemption does
|
|
98
|
+
not bypass security or compatibility review.
|
|
92
99
|
- **Consumer ranges:** review the newest published version allowed by each
|
|
93
100
|
runtime dependency's declared range, as well as the lockfile. A fresh consumer
|
|
94
101
|
install can resolve that version even when CI locks an older one. Holding
|
|
@@ -113,8 +120,8 @@ nothing can be applied, produce the report without manufacturing a change.
|
|
|
113
120
|
exception.
|
|
114
121
|
- **No new noise:** every check is compared against the Setup baseline. A new
|
|
115
122
|
warning, deprecation, or peer issue is a finding to trace and report, not
|
|
116
|
-
background noise. Report compatibility-preserving lint disables
|
|
117
|
-
ask before silencing other findings.
|
|
123
|
+
background noise. Report compatibility-preserving lint disables and scoped
|
|
124
|
+
peer-warning entries from step 5; ask before silencing other findings.
|
|
118
125
|
|
|
119
126
|
## Environment
|
|
120
127
|
|
|
@@ -178,24 +185,37 @@ Under Claude Code's sandbox:
|
|
|
178
185
|
separately in any independent package root. Check Taze config for anything
|
|
179
186
|
that overrides mode, adds maturity exemptions, or auto-writes/installs.
|
|
180
187
|
Record current project and published package versions to determine where the
|
|
181
|
-
zero-versioned exception applies.
|
|
188
|
+
zero-versioned exception applies. Record every existing
|
|
189
|
+
`minimumReleaseAgeExclude` entry with the publish time of that exact version
|
|
190
|
+
(`time` in the registry metadata), so step 6 can tell which entries still
|
|
191
|
+
matter.
|
|
182
192
|
Create the baseline folder and preserve the starting manifests and lockfile
|
|
183
193
|
before the package-manager sync or any other edit.
|
|
184
|
-
3. Sync `packageManager` before installs and parsed pnpm output.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
194
|
+
3. Sync `packageManager` before installs and parsed pnpm output. Choose the
|
|
195
|
+
newest of three versions, so the pin only ever moves up:
|
|
196
|
+
|
|
197
|
+
- the current `packageManager` pin;
|
|
198
|
+
- the pnpm installed on this host, read from a new empty directory under
|
|
199
|
+
`${TMPDIR:-/tmp}` so the project's stale pin cannot select or download
|
|
200
|
+
another version:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
pnpm --version
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
- the newest stable pnpm release at least 24 hours old, from `versions` and
|
|
207
|
+
`time` in `https://registry.npmjs.org/pnpm` (`dist-tags.latest` when it
|
|
208
|
+
qualifies).
|
|
209
|
+
|
|
210
|
+
A CI runner usually installs the pinned version itself, so the installed
|
|
211
|
+
pnpm alone never moves the pin; the registry lookup is what keeps it
|
|
212
|
+
current. Then edit only the workspace root's `packageManager` directly to
|
|
213
|
+
`pnpm@<chosen-version>`, preserving all other manifest fields. Use the
|
|
214
|
+
editor or a structured JSON edit, not `pnpm pkg set`; use direct edits for
|
|
215
|
+
later specifiers and engines too. pnpm downloads and runs the pinned
|
|
216
|
+
version on demand after the pin changes. If this crosses a pnpm major,
|
|
217
|
+
report it, review the pnpm release notes for lockfile and settings changes,
|
|
218
|
+
and verify the CI installer supports the selected version.
|
|
199
219
|
|
|
200
220
|
4. Install the starting dependency declarations and record a baseline before
|
|
201
221
|
dependency updates. Keep the original files saved in Setup 2 even if
|
|
@@ -478,8 +498,13 @@ production changes fully and development-only transitives under step 3's
|
|
|
478
498
|
narrower checks. If a deferred version is still allowed by a published runtime
|
|
479
499
|
range, use the explicit range/consumer decision path rather than fighting the
|
|
480
500
|
resolver with an older lockfile or an unapproved override.
|
|
481
|
-
|
|
482
|
-
|
|
501
|
+
After every `pnpm update -r`, confirm each accepted authored package resolved
|
|
502
|
+
to its accepted version. pnpm does not report a maturity holdback, so a lower
|
|
503
|
+
resolved version means the release is blocked by `minimumReleaseAge`: add only
|
|
504
|
+
that package/version to `minimumReleaseAgeExclude`, never its dependencies,
|
|
505
|
+
and update again. If the release still cannot resolve because its own
|
|
506
|
+
third-party dependencies are too young, defer that authored update, keep the
|
|
507
|
+
previously locked version, and report the date it becomes installable.
|
|
483
508
|
|
|
484
509
|
Compare every result with the baseline:
|
|
485
510
|
|
|
@@ -499,12 +524,16 @@ Compare every result with the baseline:
|
|
|
499
524
|
- **Logs:** for each new warning, deprecation, or peer issue, find the package
|
|
500
525
|
that introduced it (`pnpm why`) and search upstream for a known issue. Report
|
|
501
526
|
it with the link. For a peer declaration lagging a verified compatible
|
|
502
|
-
version,
|
|
503
|
-
`"parent@range>peer": "tested-range"`
|
|
504
|
-
that it suppresses a warning rather
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
527
|
+
version, add a scoped `peerDependencyRules.allowedVersions` entry such as
|
|
528
|
+
`"parent@range>peer": "tested-range"` to `pnpm-workspace.yaml` in both modes,
|
|
529
|
+
and report the entry, the evidence, and that it suppresses a warning rather
|
|
530
|
+
than fixing incompatibility. Compatibility is verified when the checks pass
|
|
531
|
+
with the installed combination and no upstream report contradicts it. Apply
|
|
532
|
+
the entry even when the lagging declaration arrives through an authored
|
|
533
|
+
package: the consumer's `pnpm-workspace.yaml` is where the warning is
|
|
534
|
+
silenced, and the report flags the upstream fix separately. Do not use broad
|
|
535
|
+
`allowAny` or disable strict peer checks. Revisit such workarounds during
|
|
536
|
+
step 9.
|
|
508
537
|
- **Build output:** if the baseline includes build output, rebuild with the
|
|
509
538
|
same command and environment and diff the trees with content-hashed filenames
|
|
510
539
|
normalized (`name.[hash].js`). Explain every remaining difference with an
|
|
@@ -541,15 +570,31 @@ rerun from the failing step:
|
|
|
541
570
|
step 3; resetting a specifier or lockfile may not exclude it.
|
|
542
571
|
|
|
543
572
|
Add focused tests only where a compatibility change touches behavior not
|
|
544
|
-
already covered. Review `readme.md` accuracy and automation opportunities in step
|
|
573
|
+
already covered. Review `readme.md` accuracy and automation opportunities in step 8.
|
|
545
574
|
|
|
546
575
|
## 6. Exclusion cleanup
|
|
547
576
|
|
|
548
577
|
Only if `minimumReleaseAgeExclude` is non-empty in any `pnpm-workspace.yaml`
|
|
549
|
-
(at the start, or after step 5).
|
|
550
|
-
|
|
578
|
+
(at the start, or after step 5). Cleanup removes entries that no longer do
|
|
579
|
+
anything; it never changes which version is installed and never downgrades a
|
|
580
|
+
package.
|
|
581
|
+
|
|
582
|
+
Decide each entry from the publish time recorded in Setup, or look it up now:
|
|
583
|
+
|
|
584
|
+
- **Mature** (published at least 24 hours before the run): remove it; the
|
|
585
|
+
version resolves without it.
|
|
586
|
+
- **Young, authored package:** keep it while that version is the release this
|
|
587
|
+
run installs. Removing it would hold the package back to an older release.
|
|
588
|
+
- **Young, third-party package:** keep it while it holds a version that is
|
|
589
|
+
already locked; removing it would downgrade an installed package rather than
|
|
590
|
+
block a new one. Report it as pending with the date it can be removed. Do not
|
|
591
|
+
add new third-party entries.
|
|
592
|
+
- **Unused** (the version is neither locked nor targeted): remove it.
|
|
593
|
+
|
|
594
|
+
Edit the list directly, preserving neighboring keys and comments; use `[]` or
|
|
595
|
+
remove the key when nothing remains. Then repeat step 5's separate bare
|
|
551
596
|
`pnpm update -r` and `pnpm dedupe --check` invocations, followed by a separate
|
|
552
|
-
`pnpm dedupe` only when the check reports available changes
|
|
597
|
+
`pnpm dedupe` only when the check reports available changes, and run each check
|
|
553
598
|
separately:
|
|
554
599
|
|
|
555
600
|
```bash
|
|
@@ -558,19 +603,46 @@ pnpm test
|
|
|
558
603
|
pnpm lint
|
|
559
604
|
```
|
|
560
605
|
|
|
606
|
+
Compare the resolved versions with the lockfile saved before cleanup. pnpm
|
|
607
|
+
does not report a maturity holdback; it silently selects the newest mature
|
|
608
|
+
version. An authored package that resolved below its latest stable release, or
|
|
609
|
+
any package that resolved below its previous locked version, means a removed
|
|
610
|
+
entry was still needed: re-add that narrowest package/version entry and resolve
|
|
611
|
+
again. Never restore the whole previous list.
|
|
612
|
+
|
|
561
613
|
If `pnpm-lock.yaml` comes out byte-identical and no ranges or build settings
|
|
562
614
|
changed, the installed tree did not change; rerun only `pnpm lint`.
|
|
563
615
|
|
|
564
|
-
If resolution is blocked: for an authored release, re-add the narrowest
|
|
565
|
-
package/version entry; for a third-party release, choose a mature version or
|
|
566
|
-
defer that upgrade. Obtain approval if that choice requires narrowing a
|
|
567
|
-
published runtime range. Never restore the whole previous list.
|
|
568
|
-
|
|
569
616
|
If the list was empty throughout, skip this section and continue to step 7.
|
|
570
617
|
If cleanup changes resolution, repeat step 5's consumer compatibility review
|
|
571
618
|
before reviewing documentation.
|
|
572
619
|
|
|
573
|
-
## 7.
|
|
620
|
+
## 7. Side effects declaration
|
|
621
|
+
|
|
622
|
+
For each published package, check that `sideEffects` in `package.json` tells
|
|
623
|
+
the truth about the shipped code. Bundlers drop any import they consider
|
|
624
|
+
side-effect-free when the declaration says `false`, and keep every module
|
|
625
|
+
otherwise, so a wrong `false` silently removes code consumers rely on and a
|
|
626
|
+
missing `false` on a pure package forfeits tree shaking.
|
|
627
|
+
|
|
628
|
+
1. Read the declaration: `false`, an array of file patterns, `true`, or absent,
|
|
629
|
+
which means `true`.
|
|
630
|
+
2. Inspect the published entry points and every module they reach, in the
|
|
631
|
+
build output that actually ships (`dist/` and the `files` list), including
|
|
632
|
+
bundled dependencies. Look for work that runs on import rather than on
|
|
633
|
+
call: assignments to globals or prototypes, polyfills, registrations such
|
|
634
|
+
as `customElements.define`, event listeners, process or environment setup,
|
|
635
|
+
CSS and asset imports, and bare imports kept only for their effects.
|
|
636
|
+
3. Set the declaration to match: `false` when nothing runs on import, an array
|
|
637
|
+
naming the exact shipped files that do when only some do, and `true` when
|
|
638
|
+
most modules have effects. A package with no importable entry point, such
|
|
639
|
+
as a `bin`-only CLI, is unaffected either way; leave its declaration as is.
|
|
640
|
+
4. Report every evaluation: the package, which modules were inspected, what
|
|
641
|
+
runs on import if anything, the declaration before and after, and why it
|
|
642
|
+
changed or stayed. A wrong `false` is a bug; a newly added `false` is a
|
|
643
|
+
performance improvement. Count either under the release recommendation.
|
|
644
|
+
|
|
645
|
+
## 8. Documentation review
|
|
574
646
|
|
|
575
647
|
Review `readme.md` against the updated project. Correct stale installation
|
|
576
648
|
instructions, requirements, commands, examples, configuration guidance, and
|
|
@@ -594,7 +666,7 @@ no further changes. Validate any new dependency under steps 5 and 6 before
|
|
|
594
666
|
continuing. Include documentation corrections and mdat conversions in the
|
|
595
667
|
final report.
|
|
596
668
|
|
|
597
|
-
##
|
|
669
|
+
## 9. @kitschpatrol/shared-config override minimization
|
|
598
670
|
|
|
599
671
|
Run this as the final cleanup after all accepted updates, migrations,
|
|
600
672
|
validation, release-age exclusion cleanup, and documentation review, before
|
|
@@ -637,7 +709,8 @@ from the largest dependency version bump:
|
|
|
637
709
|
|
|
638
710
|
- **Patch:** compatible bug or security fixes, performance improvements, or
|
|
639
711
|
dependency/tooling maintenance with no new consumer-facing capability. A
|
|
640
|
-
development-only Node.js increase with the required notice can remain a
|
|
712
|
+
development-only Node.js increase with the required notice can remain a
|
|
713
|
+
patch, and so does a corrected or newly added `sideEffects` declaration.
|
|
641
714
|
- **Minor:** backward-compatible functionality or capabilities actually exposed
|
|
642
715
|
to consumers by the accepted updates. Explain what consumers gain; an upstream
|
|
643
716
|
minor or major alone is not a reason for a minor release. For zero-versioned
|
|
@@ -674,11 +747,14 @@ accepted under the zero-versioned policy;
|
|
|
674
747
|
output differences and their upstream or migration explanations;
|
|
675
748
|
consumer Node.js requirements before and after, development Node.js changes and
|
|
676
749
|
their `devEngines.runtime` notices; the release recommendation and its rationale;
|
|
677
|
-
baseline lockfile drift;
|
|
750
|
+
baseline lockfile drift; the `packageManager` version chosen and its source;
|
|
751
|
+
`sideEffects` evaluations with their evidence and outcome; runtime ranges,
|
|
752
|
+
fresh-install exposure, and approved
|
|
678
753
|
range restrictions; TypeScript migrations; new warnings and scoped peer
|
|
679
754
|
workarounds; what was validated, at which exact Node.js versions, and in which
|
|
680
755
|
known consumers, including CLI/fixture comparisons and unavailable baselines;
|
|
681
|
-
remaining `minimumReleaseAgeExclude` entries with reasons
|
|
756
|
+
remaining `minimumReleaseAgeExclude` entries with reasons and the dates they can
|
|
757
|
+
be removed; deferred upgrades,
|
|
682
758
|
documentation corrections and mdat conversions;
|
|
683
759
|
shared-config overrides removed or retained with their justifications and any
|
|
684
760
|
unresolved override reviews; unresolved failures, checks that could not run,
|