shared CloudCode task with Node modules

Hi, I store a lot of common logic in my shared task in CloudCode. Recently I had to use node-fetch as part of one function and I realised that CloudCode does not like this. Is there a way around this?

Example of what I am trying to achieve. In shared I have a file called example.js:

const fetch = require('node-fetch');

async function getGoogle () {
    let google = await fetch('https://www.google.com');
    console.log(await google.text());
}

module.exports = {getGoogle}

In another CloudCode task called test2 I would like to excute the getGoogle function:

let getGoogle = require('../shared/example');

export async function run() {
    await getGoogle();
}

When I run test2 I get the following error:

09:05:22.659 [TASK:ERROR] Error: Cannot find module 'node-fetch'
Require stack:
- /var/task/app/cloudcode/shared/example.js
- /var/task/app/cloudcode/test2/index.js
- /var/task/app/cloudcode/test2/node_modules/@journeyapps/cloudcode/lib/entry.js
- /var/task/entry.js
- /var/runtime/UserFunction.js
- /var/runtime/index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:815:15)
    at Function.Module._load (internal/modules/cjs/loader.js:667:27)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.require (/var/task/app/cloudcode/shared/example.js:2:15)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Module._compile (/var/task/app/cloudcode/test2/node_modules/@journeyapps/cloudcode/node_modules/source-map-support/source-map-support.js:521:25)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)

Is there a another way to share some code which uses an npm module?

To work around this you’ll need to do is pass the node-fetch package to the function e.g.

Shared JS

async function getGoogle (fetch) {
    let google = await fetch('https://www.google.com');
    console.log(await google.text());
}

module.exports = {getGoogle}

Task JS

const getGoogle = require('../shared/example');
const fetch = require('node-fetch');

export async function run() {
    await getGoogle(fetch);
}
1 Like

Thanks @mike_barnes this definitely helps. The use case I have requires 4 npm packages, which I will need to add to 6 tasks, but at least I only need to maintain the logic in one place, which does help a lot.

You’re welcome @david, you could wrap them in an object e.g.

Task:

const getGoogle = require('../shared/example');
const fetch = require('node-fetch');
const moment = require('moment');

// Place them all in one object 
// This might make it easier to manage
const packages = {
    fetch: fetch,
    moment: moment
};

export async function run() {
    await getGoogle(packages);
}

Shared JS:

async function getGoogle (packages) {
    let google = await packages.fetch('https://www.google.com');
    console.log(await google.text());
}

module.exports = {getGoogle}