UNPKG

recently-published

Version:

A simple CLI tool to get the most recently published versions of a package on npm or see which install package versions were most recently published.

3 lines (2 loc) 8.27 kB
#!/usr/bin/env node import{Command as fe}from"commander";var V="recently-published";var O="0.16.0";import _ from"semver/functions/parse.js";import U from"validate-npm-package-name";import z from"util";import{exec as G}from"child_process";import K from"p-limit";var g=z.promisify(G);async function $(n,t,o){let e=K(t??10);return await Promise.all(n.map(r=>e(()=>o(r))))}var I=async n=>{try{let{stdout:t}=await g(`npm view ${n} time --json`),o=JSON.parse(t);return delete o.created,delete o.modified,Object.entries(o).map(([e,r])=>({name:n,version:e,..._(e),publishDate:new Date(r)}))}catch(t){console.error(t.message),process.exit(1)}},M=async()=>{try{let{stdout:n}=await g("npm list --json"),t=JSON.parse(n);if(!t.dependencies)throw new Error("No installed packages found in this directory");return Object.entries(t.dependencies).map(([o,e])=>({name:o,...e}))}catch(n){console.error(n.message),process.exit(1)}},N=n=>{if(n===void 0)return!0;let t=U(n);return!(!t.validForNewPackages&&!t.validForOldPackages)};import{render as E,Box as J,Text as pe,useApp as ce,Spacer as de,useStdout as me}from"ink";import{useEffect as ue}from"react";import{Text as j}from"ink";import Y from"ink-spinner";import{Fragment as Q,jsx as P,jsxs as q}from"react/jsx-runtime";var A=({count:n,total:t})=>P(Q,{children:q(j,{children:[`${t===0||n===0?"Fetching metadata for packages":`Fetched metadata for ${n} of ${t} packages`}`,P(j,{color:"green",children:P(Y,{type:"simpleDots"})})]})});import Z from"react";import{Box as b,Text as x}from"ink";import{sha1 as ee}from"object-hash";import{Fragment as L,jsx as d,jsxs as k}from"react/jsx-runtime";var f=class extends Z.Component{getConfig(){return{data:this.props.data,columns:this.props.columns||this.getDataKeys(),padding:this.props.padding||1,header:this.props.header||te,cell:this.props.cell||ne,skeleton:this.props.skeleton||oe}}getDataKeys(){let t=new Set;for(let o of this.props.data)for(let e in o)t.add(e);return Array.from(t)}getColumns(){let{columns:t,padding:o}=this.getConfig();return t.map(e=>{let r=String(e).length,s=this.props.data.map(a=>{let l=a[e];return l==null?0:String(l).length}),i=Math.max(...s,r)+o*2;return{column:e,width:i,key:String(e)}})}getHeadings(){let{columns:t}=this.getConfig();return t.reduce((o,e)=>({...o,[e]:e}),{})}header=h({cell:this.getConfig().skeleton,padding:this.getConfig().padding,skeleton:{component:this.getConfig().skeleton,line:"\u2500",left:"\u250C",right:"\u2510",cross:"\u252C"}});heading=h({cell:this.getConfig().header,padding:this.getConfig().padding,skeleton:{component:this.getConfig().skeleton,line:" ",left:"",right:"",cross:""}});separator=h({cell:this.getConfig().skeleton,padding:this.getConfig().padding,skeleton:{component:this.getConfig().skeleton,line:" ",left:"",right:"",cross:""}});data=h({cell:this.getConfig().cell,padding:this.getConfig().padding,skeleton:{component:this.getConfig().skeleton,line:" ",left:"",right:"",cross:""}});footer=h({cell:this.getConfig().skeleton,padding:this.getConfig().padding,skeleton:{component:this.getConfig().skeleton,line:"",left:"",right:"",cross:""}});render(){let t=this.getColumns(),o=this.getHeadings();return k(b,{flexDirection:"column",children:[this.header({key:"header",columns:t,data:{}}),this.heading({key:"heading",columns:t,data:o}),this.props.data.map((e,r)=>{let s=`row-${ee(e)}-${r}`;return k(b,{flexDirection:"column",children:[this.separator({key:`separator-${s}`,columns:t,data:{}}),this.data({key:`data-${s}`,columns:t,data:e})]},s)}),this.footer({key:"footer",columns:t,data:{}})]})}};function h(n){let t=n.skeleton;return o=>k(b,{flexDirection:"row",children:[...re(()=>d(L,{}),o.columns.map((e,r)=>{let s=o.data[e.column];if(s==null){let i=`${o.key}-empty-${e.key}`;return d(n.cell,{column:r,children:t.line.repeat(e.width)},i)}else{let i=`${o.key}-cell-${e.key}`,a=0,l=e.width-String(s).length-n.padding+2;return d(n.cell,{column:r,children:`${t.line.repeat(a)}${String(s)}${t.line.repeat(l)}`},i)}}))]})}function te(n){return d(x,{bold:!0,color:"blue",children:n.children})}function ne(n){return d(x,{children:n.children})}function oe(n){return d(x,{bold:!0,children:n.children})}var R=()=>d(L,{});function re(n,t){return t.reduce((o,e,r)=>o.length===0?[e]:[...o,n(r),e],[])}import{createStore as ie}from"zustand/vanilla";import{useStore as ae}from"zustand";function T(n){let o=Math.floor((new Date().getTime()-n.getTime())/1e3),e=Math.floor(o/31536e3);return e>1?`${e} years ago`:(e=Math.floor(o/2592e3),e>1?`${e} months ago`:(e=Math.floor(o/86400),e>1?`${e} days ago`:(e=Math.floor(o/3600),e>1?`${e} hours ago`:(e=Math.floor(o/60),e>1?`${e} minutes ago`:`${Math.floor(o)} seconds ago`))))}function w(n){let t=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],e=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][n.getDay()],r=t[n.getMonth()],s=n.getDate(),i=n.getFullYear(),a=n.getHours(),l=n.getMinutes().toString().padStart(2,"0"),p=a>=12?"PM":"AM";return a=a%12||12,`${e} ${r} ${s} ${i} ${a}:${l} ${p}`}import{compare as se}from"semver";var D=(n,t)=>t.display==="all"?n:n.slice(0,parseInt(t.display)),F=(n,t)=>t.includePrerelease?n:n.filter(o=>Array.isArray(o.prerelease)&&o.prerelease.length==0),v=n=>n.sort((t,o)=>{let e=o.publishDate.getTime()-t.publishDate.getTime();return e===0?se(o.version,t.version):e});var le=ie((n,t)=>({packages:[],count:0,isLoading:!0,tableData:[],packageName:null,setPackages:o=>n({packages:o}),setCount:o=>n({count:o}),setIsLoading:o=>n({isLoading:o}),setTableData:o=>n({tableData:o}),setPackageName:o=>n({packageName:o}),fetchVersionsForAllNodeModules:async o=>{let e=await M();t().setPackages(e);let s=(await $(e,100,async({name:p,version:m})=>{let u=await g(`npm view ${p} time'[${m}]'`);return t().setCount(t().count+1),u})).map(({stdout:p})=>p.replace(/[\n\r]/g,"")),i=e==null?void 0:e.map((p,m)=>(p.publishDate=new Date(s[m]),p)),a=v(i),l=D(a,o).map(({name:p,version:m,publishDate:u})=>({name:p,version:m,publishDate:u,relativePublishDate:T(u),formattedPublishDate:w(u)}));t().setIsLoading(!1),t().setTableData(l)},fetchVersionsForSpecificPackage:async(o,e)=>{t().setPackageName(o),t().setIsLoading(!0),t().setCount(0);let r=await I(o),s=F(r,e),i=v(s),a=D(i,e).map(({version:l,publishDate:p})=>({version:l,publishDate:p,relativePublishDate:T(p),formattedPublishDate:w(p)}));t().setIsLoading(!1),t().setTableData(a)}})),S=n=>ae(le,n);import{Fragment as y,jsx as c,jsxs as W}from"react/jsx-runtime";var ge=({options:n,optionalPackageName:t})=>{let{packages:o,count:e,isLoading:r,fetchVersionsForAllNodeModules:s,fetchVersionsForSpecificPackage:i}=S(l=>l),{exit:a}=ce();return ue(()=>{(async()=>{t?await i(t,n):await s(n),setTimeout(()=>{a()},200)})()},[t,n]),c(y,{children:r&&c(A,{total:o.length,count:e})})},he=({options:n,optionalPackageName:t})=>{let{isLoading:o,tableData:e}=S(i=>i),{write:r}=me();if(n.json&&!o)return r(JSON.stringify(e,null,2)),c(y,{});let s=t?e==null?void 0:e.map(({version:i,relativePublishDate:a,formattedPublishDate:l})=>({Version:i,Published:a,Date:l})):e==null?void 0:e.map(({name:i,version:a,relativePublishDate:l,formattedPublishDate:p})=>({Name:i,Version:a,Published:l,Date:p}));return c(y,{children:W(J,{flexDirection:"column",children:[t&&W(y,{children:[c(J,{flexDirection:"column",children:c(pe,{color:"green",children:t})}),c(de,{})]}),c(f,{data:s,skeleton:R})]})})},B=async(n,t)=>{let{waitUntilExit:o}=E(c(ge,{options:n,optionalPackageName:t}),{stdout:process.stderr});await o();let{unmount:e}=E(c(he,{options:n,optionalPackageName:t}),{stdout:process.stdout});e()};var X=new fe;X.name(V).version(O).argument("[optionalPackageName]","Optional package name whose recently published versions you want to see. If not provided, will display recently published packages installed in the current directory.").option("-d, --display <number>",'Number of recently published versions you would like displayed or "all" if you want to display all of them',"10").option("-ip, --includePrerelease","Include prerelease versions from the list of recently published versions").option("--json","Output the result in JSON format").action(async(n,t)=>{N(n)||(console.error("Invalid input. Please provide a valid npm package name (including scope). Versions ranges are not supported."),process.exit(1)),await B(t,n)});X.parse(process.argv);