write-npmstat
Version:
write-npmstat makes it easy to collect, filter and save npm statistics to csv files.
2 lines (1 loc) • 5.36 kB
JavaScript
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("fs"),e=require("npm-stat-api"),r=require("enum"),s=require("csv-parser"),a=require("csv-writer"),n=require("node-fetch");function i(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=i(t),h=i(e),c=i(r),u=i(s),m=i(a),d=i(n);class f{#t;#e;constructor(t,e){if(this.#t=f.formatStart(t),this.#e=f.formatEnd(e),this.#t>this.#e)throw new Error("start must be before end")}get start(){return this.#t}set start(t){if(t=f.formatStart(t),this.end&&t&&t>this.end)throw new Error("start must be before end");this.#t=t}get end(){return this.#e}set end(t){if(t=f.formatEnd(t),this.start&&t&&this.start>t)throw new Error("start must be before end");this.#e=t}static formatDate(t){const e=new Date(t),r=e.getFullYear(),s=("0"+e.getDate()).slice(-2);return r+"-"+("0"+(e.getMonth()+1)).slice(-2)+"-"+s}static formatStart(t){t||(t=new Date).setDate(t.getDate()-181),t instanceof Date&&(t=f.formatDate(t));const e=t.split("-");if(1===e.length)t+="-01-01";else if(2===e.length)t+="-01";else if(3!==e.length)throw new Error("start format is incorrect");return t}static formatEnd(t){t||(t=new Date),t instanceof Date&&(t=f.formatDate(t));const e=t.split("-");if(1===e.length)t+="-12-31";else if(2===e.length){t+="-"+("0"+new Date(parseInt(e[0]),parseInt(e[1])+1,0).getDate()).slice(-2)}else if(3!==e.length)throw new Error("end format is incorrect");return t}}var g=f;const p=o.default,w=h.default,l=c.default,D=u.default,S=m.default.createArrayCsvWriter,k=d.default,P=g,N=new l(["year","month","day",null],{ignoreCase:!0},{freeze:!0});class b{#r;outDir;#s;#a;#n;constructor(t,e){if(!t)throw new Error("packageName is a required argument");this.#r=t,this.outDir=e,this.#s=N.year,this.#a=!1,this.#n=!0}get packageName(){return this.#r}get datePeriod(){return this.#s}set datePeriod(t){this.#s=N.get(t)}get writePackageName(){return this.#a}set writePackageName(t){this.#a=Boolean(t)}get mergeStoredData(){return this.#n}set mergeStoredData(t){this.#n=Boolean(t)}getNpmStat(t,e){const r=new P(t,e),s=b.getDays(r.start,r.end);return new Promise((t=>{const e=[];s.forEach((t=>{e.push(this.#i(t,100))})),Promise.all(e).then((e=>{t(Object.fromEntries(e))}))}))}getLastWeekNpmStat(){return new Promise((t=>t(this.#o(100))))}static getDays(t,e){const r=[],s=new Date(t);for(;s<=new Date(e);s.setDate(s.getDate()+1))r.push(P.formatDate(new Date(s)));return r}#i(t,e,r){return e=e||Number.MAX_VALUE,r=Math.max(r||0,0),new Promise((s=>{w.stat(this.packageName,t,t,((a,n)=>{if(a){if(r<e)return this.#i(t,e,r+1);throw new Error("retryLimit reached")}const i=n.start,o=[];return o.push(n.start),this.writePackageName&&o.push(this.#r),o.push(n.downloads),s([i,o])}))}))}#o(t,e){return t=t||Number.MAX_VALUE,e=Math.max(e||0,0),k("https://api.npmjs.org/versions/"+this.#r+"/last-week").then((t=>{if(200!==t.status)throw new Error("response.status: "+t.status);return new Promise((e=>{t.json().then((t=>{const r={},s=P.formatStart(new Date);for(const[e,a]of Object.entries(t.downloads)){const t=s+"_"+e,n=[];n.push(s),this.writePackageName&&n.push(this.#r),n.push(e),n.push(a),r[t]=n}return e(r)}))}))})).catch((r=>{if(e<t)return this.#o(t,e+1);throw r}))}writeNpmStat(t,e,r="npmstat"){return new Promise((s=>{const a=!1;this.getNpmStat(t,e).then((n=>{const i=this.#h(a,n,t,e,r);this.#c(a,i).then((t=>(this.#u(a,t),s(t))))}))}))}writeLastWeekNpmStat(t="lastweek_npmstat"){return new Promise((e=>{const r=!0;this.getLastWeekNpmStat().then((s=>{const a=P.formatStart(new Date);if(0===Object.keys(s).length){const t=a.concat("_","-"),e=[];e.push(a),this.#a&&e.push(this.#r),e.push("-"),e.push(0),s[t]=e}const n=this.#h(r,s,a,a,t);this.#c(r,n).then((t=>(this.#u(r,t),e(t))))}))}))}#h(t,e,r,s,a){const n=new P(r,s),i=b.getDays(n.start,n.end),o={};if(this.datePeriod){let r;this.datePeriod===N.year?r=4:this.datePeriod===N.month?r=7:this.datePeriod===N.month&&(r=10);const s={};i.forEach((n=>{const i=n.substring(0,r);if(s[i]||(s[i]=!0,o[i+"_"+a+".csv"]=[]),t)for(const[t,r]of Object.entries(e))t.startsWith(n)&&o[i+"_"+a+".csv"].push([t,r]);else o[i+"_"+a+".csv"].push([n,e[n]])}))}else o[a+".csv"]=[],i.forEach((r=>{if(t)for(const[t,s]of Object.entries(e))t.startsWith(r)&&o[a+".csv"].push([t,s]);else o[a+".csv"].push([r,e[r]])}));return o}#c(t,e){return new Promise((r=>{if(!this.mergeStoredData)return r(e);const s={},a=[];for(const[r,n]of Object.entries(e)){const e=this.#m(t,r,n[0]);a.push(e),e.then((t=>{Object.assign(s,t)}))}Promise.all(a).then((()=>{for(const[t]of Object.entries(e))s[t]&&(e[t]=s[t].concat(e[t]));return r(e)}))}))}#m(t,e,r){return new Promise((s=>{const a={};if(a[e]=[],!this.outDir)return s(a);const n=this.outDir+"/"+e,i=this.writePackageName;p.stat(n,(function(o){if(null!=o)return s(a);p.createReadStream(n).pipe(D()).on("data",(s=>{if(r&&s.date<r[0].substring(0,10)){const r=s.date,n=[];n.push(s.date),i&&n.push(s.package),t&&n.push(s.version),n.push(s.downloads),a[e].push([r,n])}})).on("end",(()=>s(a)))}))}))}#u(t,e){this.outDir&&p.mkdir(this.outDir,{recursive:!0},(r=>{if(r)throw r;for(const[r,s]of Object.entries(e)){const e=this.outDir+"/"+r,a=["date"];this.writePackageName&&a.push("package"),t&&a.push("version"),a.push("downloads");const n=S({path:e,header:a}),i=[];s.forEach((t=>{i.push(t[1])})),n.writeRecords(i).catch((t=>{throw t}))}}))}}var v=b;exports.default=v;