pastoralist
Version:
A tool to watch over node module resolutions and overrides 🐑 👩🏽🌾
5 lines (4 loc) • 6.97 kB
JavaScript
;var E=Object.create;var A=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var T=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var U=(e,s,t,r)=>{if(s&&typeof s=="object"||typeof s=="function")for(let d of L(s))!M.call(e,d)&&d!==t&&A(e,d,{get:()=>s[d],enumerable:!(r=G(s,d))||r.enumerable});return e};var y=(e,s,t)=>(t=e!=null?E(T(e)):{},U(s||!e||!e.__esModule?A(t,"default",{value:e,enumerable:!0}):t,e));var P=require("commander"),J=y(require("ora"),1),C=y(require("gradient-string"),1);var h=require("fs"),S=require("path"),w=y(require("fast-glob"),1),N=require("compare-versions");var m=process.env.DEBUG==="true"||!1,R="\u{1F411} \u{1F469}\u{1F3FD}\u200D\u{1F33E} Pastoralist:";var{sync:F}=w.default,I=async e=>{let s=e?.depPaths||["**/package.json"],t=e?.path||"package.json",r=e?.root||"./",d=e?.ignore||["**/node_modules/**/node_modules/**"],i=e?.isTesting||!1,p=await k(t);if(!p){a.debug("no config found","update");return}let u=q({options:e,config:p}),o=F(s,{cwd:r,ignore:d});a.debug(`Found ${o.length} package.json files`,"update"),o.forEach(g=>a.debug(`Package: ${g}`,"update"));let n=await _(o,u),c=n?B(n):[],l=V(u,c);if(i)return n;await X({appendix:n,path:t,config:p,overrides:l})},_=async(e,s)=>{let t=D(s)||{},r=Object.keys(t);if(!(r.length>0))return;let i={};try{let p={};await Promise.all(e.map(async o=>{let n=await k(o);if(!n||!n.name)return;let c={...n.dependencies||{},...n.devDependencies||{}};p[n.name]={dependencies:c,dependents:[],filePath:o}})),Object.keys(p).forEach(o=>{let n=p[o].dependencies||{};Object.entries(n).forEach(([c,l])=>{p[c]&&p[c].dependents.push({name:o,version:l})})}),r.forEach(o=>{let n=t[o];a.debug(`Processing override: ${o}@${n}`,"constructAppendix");let c=p[o]?.dependents||[];if(a.debug(`Found ${c.length} dependents for ${o}`,"constructAppendix"),c.length>0){let l=`${o}@${n}`,g=c.reduce((f,v)=>(a.debug(`Checking dependent: ${v.name} requires ${o}@${v.version}`,"constructAppendix"),a.debug(`Adding ${v.name} as a dependent for ${o}`,"constructAppendix"),{...f,[v.name]:`${o}@${v.version}`}),{}),O=Object.keys(g).length;a.debug(`Found ${O} dependents that need override for ${o}`,"constructAppendix"),O>0&&(i[l]={dependents:g},a.debug(`Added ${l} to appendix with ${O} dependents`,"constructAppendix"))}}),(await Promise.all(e.map(async o=>await z(o,t,r)))).filter(o=>o).forEach(o=>{let n=o?.appendix||{};i={...i,...n}})}catch(p){a.error("Error constructing appendix","constructAppendix",p)}return i},B=e=>{if(!e)return[];let s=Object.keys(e);return s.length===0?[]:s.filter(t=>{let r=e[t]?.dependents;return!r||Object.keys(r).length===0}).map(t=>t.split("@")[0])},V=(e,s=[])=>{if(!e)return;let t=D(e);if(!t||Object.keys(t).length===0){a.debug("No overrides found to update","updateOverrides");return}return Object.entries(t).reduce((r,[d,i])=>(s.includes(d)||(r[d]=i),r),{})};async function X({appendix:e,path:s,config:t,overrides:r,isTesting:d=!1}){if(!(r&&Object.keys(r).length>0)){let n=["pastoralist","resolutions","overrides","pnpm"];for(let c of n)delete t[c]}if(e&&Object.keys(e).length>0&&(t.pastoralist={appendix:e}),t?.resolutions&&(t.resolutions=r),t?.overrides&&(t.overrides=r),t?.pnpm?.overrides&&(t.pnpm.overrides=r),d)return t;let u=(0,S.resolve)(s),o=JSON.stringify(t,null,2);(0,h.writeFileSync)(u,o)}function q({config:e={}}){let s="resolveOverrides",t="Pastorlist didn't find any overrides or resolutions!",r=K(e);if(!r){a.error(t,s);return}let{type:d,overrides:i}=r;if(!(Object.keys(i)?.length>0)||!d){a.error(t,s);return}let u=Object.keys(i)||[];if(u.some(c=>typeof i[c]=="object")){a.error("Pastoralist only supports simple overrides!",s),a.error("Pastoralist is bypassing the specified complex overrides. \u{1F44C}",s);return}let n=u.reduce((c,l)=>Object.assign(c,{[l]:i[l]}),{});return d==="pnpmOverrides"?{type:"pnpm",pnpm:{overrides:n}}:d==="resolutions"?{type:"resolutions",resolutions:n}:{type:"npm",overrides:n}}var K=({overrides:e={},pnpm:s={},resolutions:t={}}={})=>{let r=s?.overrides||{},d=[{type:"overrides",overrides:e},{type:"pnpmOverrides",overrides:r},{type:"resolutions",overrides:t}].filter(({overrides:o})=>Object.keys(o).length>0),i="defineOverride";if(!(d?.length>0)){a.debug("\u{1F411} \u{1F469}\u{1F3FD}\u200D\u{1F33E} Pastoralist didn't find any overrides!",i);return}if(d?.length>1){a.error("Only 1 override object allowed",i);return}return d[0]},D=e=>{let s=e?.type;if(!s){a.error("no type found","resolveOverridesProp");return}return s==="resolutions"?e?.resolutions:s==="pnpm"?e?.pnpm?.overrides:e?.overrides};async function z(e,s,t){let r=await k(e);if(!r)return;let{name:d,dependencies:i={},devDependencies:p={}}=r,u={...i,...p};if(!Object.keys(u).some(g=>t.includes(g)))return;let c=r?.pastoralist?.appendix||{},l=H({appendix:c,overrides:s,dependencies:i,devDependencies:p,packageName:d});return{name:d,dependencies:i,devDependencies:p,appendix:l}}var H=({overrides:e={},appendix:s={},dependencies:t={},devDependencies:r={},packageName:d="",cache:i=new Map})=>{let p=Object.keys(e),u={...t,...r},o=Object.keys(u);for(let n of p){if(!o.includes(n))continue;let l=e[n],g=u[n];if((0,N.satisfies)(l,g))continue;let f=`${n}@${l}`;if(i.has(f)){s[f]=i.get(f);continue}let $={dependents:{...s?.[f]?.dependents||{},[d]:`${n}@${g}`}};s[f]=$,i.set(f,$)}return Object.keys(s).forEach(n=>{(!s[n].dependents||Object.keys(s[n].dependents).length===0)&&delete s[n]}),s};function k(e){if(x.has(e))return x.get(e);try{let s=(0,h.readFileSync)(e,"utf8"),t=JSON.parse(s);return x.set(e,t),t}catch(s){console.log(s),a.error(`\u{1F411} \u{1F469}\u{1F3FD}\u200D\u{1F33E} Pastoralist found invalid JSON at:
${e}`,"resolveJSON",s);return}}var b=(e,s,t)=>(r,d,...i)=>{if(!s)return;let p=d?`[${d}]`:"";console[e](`${R}[${t}]${p} ${r}`,...i)},j=({file:e,isLogging:s=!1})=>({debug:b("debug",s,e),error:b("error",s,e),info:b("info",s,e)}),a=j({file:"scripts.ts",isLogging:m}),x=new Map;async function Q(e={}){let s=m||e.debug,t=j({file:"program.ts",isLogging:s}),{isTestingCLI:r=!1,...d}=e;if(r){t.debug("action:options:","action",{options:e});return}try{let i=(0,C.default)("green","tan"),p=(0,J.default)(`\u{1F469}\u{1F3FD}\u200D\u{1F33E} ${i("pastoralist")} checking herd...
`).start();await I(d),p.succeed(`\u{1F469}\u{1F3FD}\u200D\u{1F33E} ${i("pastoralist")} the herd is safe!`)}catch(i){t.error("action:fn","action",{error:i}),process.exit(1)}}P.program.description("Pastoralist, a utility CLI to manage your dependency overrides").option("--debug","enables debug mode").option("-p, --path <path>","specifies a path to a package.json").option("-d, --depPaths [depPaths...]","specifies a glob path to a package.jsons").option("--ignore [ignore...]","specifies a glob path to ignore").option("-r","--root <root>","specifies a root path").option("-t, --isTestingCLI","enables CLI testing, no scripts are run").option("--isTesting","enables testing, no scripts are run").action(Q).parse(process.argv);