-1

I'm writing a configuration for the semantic-release tool using the release.config.js file, which allows generating the configuration dynamically.

Now, I need to call several APIs during the loading process. I found that the best practice for calling APIs is to use fetch().then().

My code (simplified) is the following:

const config = {
  plugins: [
    // some plugins configurations here
  ]
}

if (/* some condition */) {
  fetch(
    // API1 URL and its params
  ).then((response) => response.json()).then((data) => {
    return fetch(
      // API2 URL and its params including `data.field`
    )
  }).then((response) => response.json()).then((data) => {
    return data.another_field
  }).then(function(value){
    if (/* condition using the `value` */) {
      // Prints correctly extracted `value` from the API2 call
      console.log("Detected value", value)
      config.plugins.push(/* Additional plugin */)
    }
  })
}

module.exports = config

The problem here is that in the end semantic-release doesn't load that additional plugin. I don't have enough experience with modern NodeJS, so I'm struggling to understand, how to force it to await results from fetch.

I found that in recent Node versions it's possible to use top-level await, but simply adding await before fetch doesn't work for a reason that is unclear to me:

  await fetch(
  ^^^^^
SyntaxError: await is only valid in async functions and the top level bodies of modules

So, what is the best way to just perform a couple of synchronous API calls, or await results of all the fetches and thens before the module.exports?

  • With a CommonJS module, you cannot wait until an asynchronous operation is done to export its value. It just isn't something a CommonJS module can do. You can do so in an ESM module that uses `import` and `export` and supports top level `await`. The usual work-around in the commonJS world is to export either a function that the caller can call to get a promise which they can then get the value from or to directly export a promise that the caller can use to get the value. – jfriend00 Mar 28 '23 at 17:47

1 Answers1

-1

my solution to this would be converting to using modules :

in your package.json file add "type": "module",

and then use async await instead of .then()

it will look something like this :

// export.js
let plugins = []

 plugins.push(await fetch("http://google.com/"))

export default plugins

and in the import file

import plugins from "./export.js";

console.log(plugins);

note: this may not exactly what u wanted but u can get it to work this way

  • I don't actually have a `package.json`, because I'm writing this configuration for using the tool with different projects, not only nodejs-based. So the only thing I can work with is that `release.config.js` which is later consumed by the tool. – user2950818 Mar 28 '23 at 17:44
  • then you can simply change the files extension to `.mjs` instead of `.js` – ṽïηøṧ Mar 28 '23 at 17:48
  • Unfortunately it doesn't work, because the tool is looking for `.js` or `.cjs` only :( – user2950818 Mar 28 '23 at 17:58