bennycode / trading-signals

Technical indicators to run technical analysis with JavaScript & TypeScript. 📈
https://bennycode.com/trading-signals
MIT License
621 stars 90 forks source link

Error while using with TypeScript and Node.js #663

Closed ebinxavier closed 6 months ago

ebinxavier commented 7 months ago

This library is very useful for live charting and I liked the update method on the indicators.

But unfortunately when I installed this in a typescript project I got some errors mentioned below.

How to reproduce

  1. I used a typescript boiler plate to start a project from scratch: https://github.com/stemmlerjs/simple-typescript-starter
  2. Installed the library: npm i trading-signals
  3. Start development run: npm run start:dev

I am using the example mentioned in the library home page at npmjs.com

import {Big, SMA} from 'trading-signals';

const sma = new SMA(3);

// You can add numbers individually:
sma.update(40);
sma.update(30);
sma.update(20);

// You can add multiple numbers at once:
sma.updates([20, 40, 80]);

// You can add strings:
sma.update('10');

// You can replace a previous value (useful for live charts):
sma.update('40', true);

// You can add arbitrary-precision decimals:
sma.update(new Big(30));

// You can get the result in various formats:
console.log(sma.getResult().toFixed(2)); // "40.00"
console.log(sma.getResult().toFixed(4)); // "40.0000"

Now I am getting this error

[nodemon] starting `npx ts-node ./src/index.ts`
/home/ebin/programming/js/simple-typescript-starter/node_modules/ts-node/dist/index.js:851
            return old(m, filename);
                   ^
Error [ERR_REQUIRE_ESM]: require() of ES Module /home/ebin/programming/js/simple-typescript-starter/node_modules/trading-signals/dist/index.js from /home/ebin/programming/js/simple-typescript-starter/src/index.ts not supported.
Instead change the require of index.js in /home/ebin/programming/js/simple-typescript-starter/src/index.ts to a dynamic import() which is available in all CommonJS modules.
    at require.extensions.<computed> [as .js] (/home/ebin/programming/js/simple-typescript-starter/node_modules/ts-node/dist/index.js:851:20)
    at Object.<anonymous> (/home/ebin/programming/js/simple-typescript-starter/src/index.ts:3:25)
    at m._compile (/home/ebin/programming/js/simple-typescript-starter/node_modules/ts-node/dist/index.js:857:29) {
  code: 'ERR_REQUIRE_ESM'
}
[nodemon] app crashed - waiting for file changes before starting...

I found one of the closed issues in this repo: https://github.com/bennycode/trading-signals/issues/644, but I am not using require function to import the library. But the version 3.7 is working for me without any issues, but I would like to get latest version working too because I can leverage most recent updates in this library.

@bennycode any reason why I am getting this?

bennycode commented 7 months ago

Hi @ebinxavier and thank you for your report! Can you upload your "simple-typescript-starter" project to GitHub so that I can take a look at it? Best, Benny

ebinxavier commented 7 months ago

@bennycode here is my repo: https://github.com/ebinxavier/simple-typescript-starter/blob/master/src/index.ts I am using node version 20.

bennycode commented 7 months ago

@bennycode here is my repo: https://github.com/ebinxavier/simple-typescript-starter/blob/master/src/index.ts I am using node version 20.

Thank you for providing this repo. Your main problem is that your tsconfig.json specifies a very old target which is set to ES5. It also specifies the commonjs module syntax in it's module setting.

Version 4 and beyond of trading-signals uses the ECMAScript module syntax (ESM).

There are multiple problems now:

  1. ts-node doesn't load ESM code, you would need ts-node-esm but then your complete project must use ESM instead of CommonJS
  2. CommonJS code cannot load ESM code using require, you will need to use a dynamic import

When running npm run build you will see that the compiled index.js file includes the following:

var trading_signals_1 = require("trading-signals");

This require call is being created by the TypeScript compiler because you have the setting "module": "commonjs" in your tsconfig.json. As trading-signals is an ESM project the require call will fail and needs to be replaced with a dynamic import.

Luckily, you can use a dynamic imports to load ESM code in CommonJS projects:

Using require to load an ES module is not supported because ES modules have asynchronous execution. Instead, use import() to load an ES module from a CommonJS module.

Source: https://nodejs.org/docs/latest-v20.x/api/esm.html#require

ebinxavier commented 7 months ago

@bennycode I updated the code like this by adding dynamic import

import('trading-signals').then((tradingSignals) => {
  const { Big, SMA } = tradingSignals;

  const sma = new SMA(3);

  // You can add numbers individually:
  sma.update(40);
  sma.update(30);
  sma.update(20);

  // You can add multiple numbers at once:
  sma.updates([20, 40, 80]);

  // You can add strings:
  sma.update('10');

  // You can replace a previous value (useful for live charts):
  sma.update('40', true);

  // You can add arbitrary-precision decimals:
  sma.update(new Big(30));

  // You can get the result in various formats:
  console.log(sma.getResult().toFixed(2)); // "40.00"
  console.log(sma.getResult().toFixed(4)); // "40.0000"
});

But still I am getting this error

[nodemon] starting `npx ts-node ./src/index.ts`
/home/ebin/programming/js/AlgoTrade/AlgoTradeCore/node_modules/.pnpm/ts-node@10.9.2_@types+node@18.19.30_typescript@4.9.5/node_modules/ts-node/dist/index.js:851
            return old(m, filename);
                   ^
Error [ERR_REQUIRE_ESM]: require() of ES Module /home/ebin/programming/js/AlgoTrade/AlgoTradeCore/node_modules/.pnpm/trading-signals@5.0.0/node_modules/trading-signals/dist/index.js from /home/ebin/programming/js/AlgoTrade/AlgoTradeCore/src/index.ts not supported.
Instead change the require of index.js in /home/ebin/programming/js/AlgoTrade/AlgoTradeCore/src/index.ts to a dynamic import() which is available in all CommonJS modules.
    at require.extensions.<computed> [as .js] (/home/ebin/programming/js/AlgoTrade/AlgoTradeCore/node_modules/.pnpm/ts-node@10.9.2_@types+node@18.19.30_typescript@4.9.5/node_modules/ts-node/dist/index.js:851:20)
    at /home/ebin/programming/js/AlgoTrade/AlgoTradeCore/src/index.ts:25:58 {
  code: 'ERR_REQUIRE_ESM'
}

Can you give me a sample code snippet?

bennycode commented 7 months ago

@ebinxavier your code looks good but I think you have to modify your tsconfig.json. Try setting "module" to "node16". Does it work?

ebinxavier commented 7 months ago

@bennycode, when I changed module to Node16 trading-signals library got compiled successfully, but now to rectify issues in my other modules I have to change imports from

import saveChartData from './database/saveChartData';

to

import saveChartData from './database/saveChartData.js';

but ./database/saveChartData is actually a typescript file. Seems like weird.

bennycode commented 7 months ago

The .js ending can make sense even for TS files: https://typescript.tv/new-features/what-are-ecmascript-modules/#esm-imports--exports

ebinxavier commented 7 months ago

okay, thanks. I can now move forward with this workaround.

bennycode commented 7 months ago

Thank you, I also got new content for my blog! 😊 https://typescript.tv/errors/#ts1323

ebinxavier commented 6 months ago

Note: @bennycode When I installed trading-signals in my Next.js project everything worked smoothly. I am closing this issue.