1

I am using ESM in my node project. Added "type": "module" in package.json

// index.js

import config from 'config'
// default.js

export default {
  time: 123,
  ...
  ...
}

But getting error in node-config

Error: Cannot parse config file: '/home/Documents/.../config/default.js': Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/Documents/.../config/default.js
require() of ES modules is not supported.
require() of /home/Documents/.../config/default.js from /home/Documents/.../node_modules/config/parser.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename default.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/Documents/.../package.json.

I can fix this by adding default.cjs instead of default.js but as I am using ESM so I am expecting it to work with .js extension also. am I missing something??. I can add .json also but I have big config variables and dynamic values that is why using .js.

Thank you in advance !!!

dotnetCarpenter
  • 10,019
  • 6
  • 32
  • 54
Kiran Mali
  • 597
  • 4
  • 12

1 Answers1

2

According to https://github.com/node-config/node-config/wiki/Special-features-for-JavaScript-configuration-files you can not use ESM for configuration files but must use one of the other supported formats.

Loading files as ESM is not yet supported. So .mjs or .js when "type":"module" or --experimental-modules will not work.

But there is a work-around. For example you could have the following structure, where dynamic.js is where you have big config variables and dynamic values:

.
├── config
│   ├── dynamic.js
│   └── test.cjs
├── index.js
├── node_modules
│   ├── config
│   ├── json5
│   └── minimist
├── package-lock.json
└── package.json

You must tell nodejs that you use esm. So in your package.json you will want to have:

{
  "scripts": {
    "start": "NODE_ENV=test node index.js"
  },
  "type": "module"
}

In the beginning of your index.js file, you want to import node-config.

import config from 'config';

const {default:configVariable} = await config.get('variable');

console.debug(configVariable.foo);

In the above case you could write "Hello World!" to your terminal if config/test.cjs and config/dynamic.js has the following:

'use strict'

module.exports = {
    variable: import('./dynamic.js')
}

test.cjs

export default {
    v1: 'var1',
    v2: 'var2',
    foo: 'Hello World!'
}

dynamic.js

The result of the above should then be:

$ npm start

> start
> NODE_ENV=test node index.js

Hello World!

Obviously, you can rename variable and configVariable to what-ever you want.

In my test, I had no issue with the above way of exporting esm as a Promise. But if you do get any issue with with that, you might solve it by wrapping import() in require('config/raw').raw. See: https://github.com/node-config/node-config/wiki/Special-features-for-JavaScript-configuration-files#using-promises-processstdout-and-other-objects-in-javascript-config-files.

dotnetCarpenter
  • 10,019
  • 6
  • 32
  • 54
  • it is working after adding `.cjs` but I want to keep `.js` and export module with esm syntax which is currently not working. no sure `config` npm supports ESM or not? – Kiran Mali Feb 01 '22 at 12:54
  • 1
    If you mean [node-config](https://www.npmjs.com/package/config) then yes it does. You need to add `"type": "module"` to your _package.json_ JSON. Then `.js` will be treated as `.mjs`. – dotnetCarpenter Feb 01 '22 at 16:44
  • Thank you dotnetCarpenter :). so it is working with `.mjs` extension but I was expecting it to work with `.js` extension also. – Kiran Mali Mar 02 '22 at 08:14
  • But I am getting a problem in `NODE_ENV=test` case. `NODE_ENV value of 'test' did not match any deployment config file names`. My file name is `test.mjs`. – Kiran Mali Mar 02 '22 at 08:24
  • 1
    @KiranMali I have updated my answer to specifically answer your use-case and made a git repo available as an example. https://github.com/dotnetCarpenter/SO_node-config – dotnetCarpenter Mar 05 '22 at 11:27
  • excellent work and information! thank you again :) – Kiran Mali Mar 07 '22 at 08:45
  • Glad that it works for and interesting problem as I am also using node-config. You might want to choose this as the answer, if it answer your question. – dotnetCarpenter Mar 07 '22 at 10:40
  • @KiranMali note that you can still have a `default.json5` file for default values. Those will be accessible via `config.get('defaultValue')`, where `defaultValue` is a exported variable in `default.json5`. – dotnetCarpenter Mar 07 '22 at 11:41