Track your Node package downloads

Use Node-RED v1.1+ to keep track of how many downloads your NPM packages get per day.

Uses the newer Inject node features to avoid needing an extra Change node. Also uses the $moment feature of JSONata to select and format the appropriate date range.

This is fed into a request node and from there to a function node that accumulates the daily data into an object:

global-var -> by package-name -> downloads-by-day

A summary of the date ranges and total downloads is also kept.

You can only download a maximum of 12 months when selecting multiple packages but the data goes back to 2015-01-10. I manually downloaded all of the previous years but you can just change the date range in the inject node as it uses MomentJS's very easy to follow format, subtracting days from today.

It doesn't hurt to rerun the query over dates you've already included, the duplicates are ignored.

Make sure you change the date range and package names in the inject node before running.

You may also want to change the global variable settings at the top of the function node.

The flow example given here runs once a week on a Sunday at 00:01 and captures the last 8 days.

[{"id":"e514269e.74fb58","type":"debug","z":"a851b997.a01c18","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":715,"y":1220,"wires":[],"l":false},{"id":"893de9f.e508e18","type":"function","z":"a851b997.a01c18","name":"","func":"const myNpmStats = 'myNpmStats'\nconst fileStore = 'file'\n\nconst out = global.get(myNpmStats, fileStore) || {}\n\nObject.keys(msg.payload).forEach( package => {\n\n    if ( !out[package] ) {\n        out[package] = {\n            'downloads': {},\n            'package': package,\n            'start': '',\n            'end': '',\n            'days': 0,\n            'totalDownloads': 0,\n        }\n    }\n\n    msg.payload[package].downloads.forEach( entry => {\n        \n        // Loose any zeros until the first download\n        if ( out[package].totalDownloads === 0 ) {\n            if ( entry.downloads === 0 ) return\n        }\n        \n        // If this day has already been recorded, skip\n        if ( entry.day in out[package].downloads ) return\n        \n        out[package].downloads[entry.day] = {\n            'date': entry.day,\n            'downloads': entry.downloads,\n        }\n        \n        out[package].totalDownloads += entry.downloads\n        \n        if ( entry.day < out[package].start || out[package].start === '' ) out[package].start = entry.day\n        if ( entry.day > out[package].end ) out[package].end = entry.day\n      \n        out[package].days++\n        \n    })\n    \n})\n\nglobal.set(myNpmStats, out, fileStore)\nmsg.payload = out\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":655,"y":1220,"wires":[["e514269e.74fb58"]],"l":false},{"id":"9a41f93d.2035f8","type":"inject","z":"a851b997.a01c18","name":"URL/Date-Range/package-set","props":[{"p":"url","v":"\"https://api.npmjs.org/downloads/range/\" & \t\t$moment().subtract(8, 'days').format(\"YYYY-MM-DD\")\t\t& \":\" &\t\t$moment().subtract(1, 'days').format(\"YYYY-MM-DD\")\t\t& \"/\" &\t\t$join([\t        \"node-red-contrib-uibuilder\",\t        \"node-red-contrib-moment\",\t        \"node-red-contrib-globalgetset\",\t        \"node-red-contrib-fs\",\t        \"node-red-contrib-jktesting\",\t        \"node-red-contrib-static-markdown\",\t        \"alternate-node-red-installer\"\t    ], \",\")\t","vt":"jsonata"}],"repeat":"","crontab":"01 00 * * 0","once":false,"onceDelay":0.1,"topic":"","x":360,"y":1220,"wires":[["d2b0e949.dc6a38"]]},{"id":"d2b0e949.dc6a38","type":"http request","z":"a851b997.a01c18","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":535,"y":1220,"wires":[["893de9f.e508e18"]],"l":false}]

Flow Info

Created 3 years, 10 months ago
Rating: not yet rated

Actions

Rate:

Node Types

Core
  • debug (x1)
  • function (x1)
  • http request (x1)
  • inject (x1)

Tags

  • npm
  • stats
  • packages
  • modules
  • nodes
  • MomentJS
  • Moment
  • $moment
  • JSONata
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option