TransWikia.com

get-release npm module

Code Review Asked by Khushraj Rathod on October 27, 2021

Solved, question with improved code

I’ve created a simple npm module and CLI program to get the latest GitHub and Bitbucket release from their APIs using Node.js. Please tell me if there’s anything to improve!

Module code:

#!/usr/bin/env node
const fetch = require("node-fetch");

/**
 * @param {string} string
 * @return {string}
 */
const normalize = (string) => {
    try {
        return string.toUpperCase().trim()
    } catch (e) {
        return string
    }
}

/**
 * @param {string} provider
 * @param {string} user
 * @param {string} repo
 * @param {string} part
 */
module.exports.getRelease = async ({provider, user, repo, part = ""}) => {
    if (normalize(provider) === normalize("github")) {
        let json = (await (await fetch(`https://api.github.com/repos/${user}/${repo}/releases/latest`)).json())
        if (json.message === "Not Found") throw "Invalid repository"
        if (!("assets" in json)) throw "Rate limit exceeded"
        let browser_download_urls = json.assets.map(asset => asset.browser_download_url)
        return browser_download_urls.filter(url => url.includes(part))
    } else if (normalize(provider) === normalize("bitbucket")) {
        let json = (await (await fetch(`https://api.bitbucket.org/2.0/repositories/${user}/${repo}/downloads/`)).json())
        if (json.type === "error") throw "Invalid repository"
        let links = json.values.map(value => value.links.self.href)
        return links.filter(url => url.includes(part))
    } else {
        throw "Invalid provider"
    }
}

const usage = _ => {
    console.log(
        `Usage: get-release (github|bitbucket) user repo [partofreleasefile]
   Ex: get-release github phhusson treble_experimentations
       get-release github phhusson treble_experimentations arm64-ab-gapps
       get-release bitbucket JesusFreke smali
       get-release bitbucket JesusFreke smali baksmali`
    )
    process.exit(1)
}

// If via CLI
if (require.main === module) {
    let args = process.argv.slice(2)
    if (args.length !== 3 && args.length !== 4) {
        usage()
    }
    module.exports.getRelease({
        provider: args[0],
        user: args[1],
        repo: args[2],
        part: args[3]
    }).then(result => {
        if (result.length !== 1) {
            console.log(result)
        } else {
            console.log(result[0])
        }
    }).catch(error => {
        console.log(error)
        usage()
        process.exit(1)
    })
}

Called using:

const { getRelease } = require("get-release")
;(async _ => {
  let url = await getRelease(
      {
          provider: "github",
          user: "phhusson",
          repo: "treble_experimentations",
          part: "arm64-ab-gapps"
      }
  )
  console.log(url[0])
})()

One Answer

Consider using a hashmap of provider -> process. This will enable you to register new providers with relative ease.

async function githubRelease({user, repo, part = ""}) {
  let json = (await (await fetch(`https://api.github.com/repos/${user}/${repo}/releases/latest`)).json())
  if (json.message === "Not Found") throw "Invalid repository"
  if (!("assets" in json)) throw "Rate limit exceeded"
  let browser_download_urls = json.assets.map(asset => asset.browser_download_url)
  return browser_download_urls.filter(url => url.includes(part))
}

It will then be mapped inside the getRelease function as follows:

module.exports.getRelease = async ({provider, user, repo, part = ""}) => {
    if !(providerMethods[normalise(provider)]) {
        throw "Invalid provider"
    }
    return providerMethods[normalise(provider)](user, repo, part)
}

where providerMethods would be:

let providerMethods = {
    normalise("github"): githubReleases
}

This will enable users of your module to register new (or private) registry providers. They can add a new provider to the providerMethods object (gitlab etc) and don't have to wait for you to update the library first for supporting any extra providers (you can add providers if popular).

The await (await fetch()).json() can be extracted to another function. Although, I'd prefer using the promise.then(r => r.json()).catch() chain over multiple awaits, it is entirely dependent on your comfort with the language.

Answered by hjpotter92 on October 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP