I use Node.js application and TS 4.8, and I updated package file-type, but now my project compilation fails with error
[1] const _fileType = /#PURE/ _interopRequireWildcard(require("file-type"));
[1] ^
[1]
[1] Error [ERR_REQUIRE_ESM]: require() of ES Module /home/victor/Desktop/alytics/node_modules/file-type/index.js from /home/victor/Desktop/alytics/dist/routes/index.js not supported.
[1] Instead change the require of /home/victor/Desktop/alytics/node_modules/file-type/index.js in /home/victor/Desktop/alytics/dist/routes/index.js to a dynamic import() which is available in all CommonJS modules.
There is my swc config:
`
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true,
"dynamicImport": true
},
"target": "es2020",
"paths": {
"#routes/*": ["./src/routes/*"],
"#middlewares/*": ["./src/middlewares/*"]
},
"baseUrl": "."
},
"module": {
"type": "commonjs"
}
}
`
And there is my tsconfig:
`
{
"compilerOptions": {
"target": "es2020",
"module": "es2020",
"allowJs": true,
"removeComments": true,
"resolveJsonModule": true,
"typeRoots": ["./node_modules/#types"],
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"outDir": "dist",
"strict": true,
"lib": ["es2020"],
"baseUrl": ".",
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"moduleResolution": "Node",
"skipLibCheck": true,
"paths": {
"#routes/*": ["./src/routes/*"],
"#middlewares/*": ["./src/middlewares/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
`
Where I use file-type:
`
import KoaRouter from "#koa/router";
import { Context } from "koa";
import { logger } from "#middlewares/index.js";
import * as FileType from "file-type";
const router = new KoaRouter();
router.get("/", logger, (ctx: Context): void => {
ctx.body = { message: JSON.stringify(FileType) };
});
export default router;
`
As I understand, file-type package using only ESM import, but , after compilation this import convert to require(). I read about this issue in their repository, but this topic was closed as TS now support ESM.
How can I configure my ts.config to exclude this module to covert to require ??
Is there any way to solve this issue only using TS config?
I find the only solution - convert from commonjs - to ESM (change type: module, and add that to my package.json), but I don't want to update all my import adding .js at the end and I dont want to convert all my imports to ESM.
Related
I'm using tsyringe for dependency injection and trying to run unit tests.
The class is in ts and the test file is in js. When I try to run my tests by executing
TS_NODE_PROJECT=\"tsconfig.testing.json\" mocha -r ts-node/register src/**/*.test.js
I get the following compilation error:
repo.ts:27:14 - error TS1219: Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning.
Here is my code.
// repo.ts
#injectable()
export class Repo {
testAdd = (a, b) => {
return a + b;
};
}
// repo.test.js
const { Repo } = require("../repo");
const expect = require("chai").expect;
describe("testing the add function", () => {
it("addition worked correctly", (done) => {
const r = new Repo();
const res = r.testAdd(4, 5);
expect(res).to.equal(9);
done();
});
});
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "commonjs",
"noImplicitReturns": false,
"noUnusedLocals": false,
"outDir": "lib",
"sourceMap": true,
"strict": false,
"target": "es2017"
},
"compileOnSave": true,
"include": ["src"]
}
// tsconfig.testing.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6"
},
"include": ["**/*.spec.ts"]
}
If I get rid of the injectable() decorator then the tests work.
If I change the test ext from js to ts, then it works.
I tried creating a jsconfig.json and adding in
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
but it didn't help.
What am I doing wrong?
Update, I think the issue is that I needed to add the
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
in the tsconfig.testing.json file as well. So far looks to be working with the .js testing files.
I know there is plenty of topic around this question but I read a lot and I didn't found any answer.
I try to use a 3rd party through NPM in my nodeJS project (nest).
But when it compiles, I have the *.default is not a constructor error.
When I go into the source in the node_modules, I see the error.
const web3_1 = require("web3");
[...]
const getClient = async (options) => {
const { url } = options;
return new web3_1.default(url);
};
If I remove the default in here, it's working like a charm, but this is not something I control ...
I put the esModuleInterop to true in my tsconfig.json but that's not working.
Here is my tsconfig file
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": "./",
"incremental": true,
"strictNullChecks": true,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"esModuleInterop": true,
"module": "CommonJS",
"target": "ES2018",
"declaration": true,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"outDir": "./dist",
"rootDir": "./src",
"skipLibCheck": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
What am I missing?
According to their docs and their source code you shouldn't need to use default. Just
const web3_1 = require("web3");
[...]
const getClient = async (options) => {
const { url } = options;
return new web3_1(url);
};
And you should be good. Looks like they may have their types messed up and you'll need to tell Typescript to ignore it
I want to implement some jest tests in my backend and so I was trying to map my paths that I have configured in tsconfig.json via the moduleNameMapper of jest.config.js but when I run the tests I find the file is still not imported and I am shown this error on line 8 ⬇
Please assist me to map my paths correctly, I would highly appreciate any help.
To help you assist me here are the important files.
jest.config.js (where jest is usually configured) ⬇
/** #type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ["**/***.test.ts"],
verbose: true,
forceExit: true,
moduleNameMapper: {
'#util/(.*)': '<rootDir>/src/util/$1'
}
};
tsconfig.json (normal config file for typescript) ⬇
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"baseUrl": "src",
"paths": {
"#util/*": ["util/*"]
},
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
I created a file named .babelrc with this contents ⬇ :
{
"presets": ["#babel/preset-env"]
}
I then configured jest.config.js as shown below ⬇
/** #type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
transform: {
'^.+\\.ts$': 'ts-jest',
'^.+\\.js$': 'babel-jest',
'^.+\\.mjs$': 'babel-jest',
},
moduleDirectories: ['node_modules', '<rootDir>/src'],
moduleNameMapper: {
'#controllers/(.*)': '<rootDir>/src/controllers/$1',
'#middleware/(.*)': '<rootDir>/src/middleware/$1',
'#models/(.*)': '<rootDir>/src/models/$1',
'#routes/(.*)': '<rootDir>/src/routes/$1',
'#types/(.*)': '<rootDir>/src/types/$1',
'#util/(.*)': '<rootDir>/src/util/$1',
}
};
I then configured tsconfig.json as shown below ⬇:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"baseUrl": "src",
"paths": {
"#util/*": ["util/*"]
},
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"types": ["jest"]
}
}
Vote of thanks to Benjamin Drury & #Ashok for the much helpful support.
This issue is occuring due to absolute import. If you look closely, you can observe that your import statement is util/logger. This kind of imports are not properly resolved.
In case you are using VSCode, then this is a common occurence, since VSCode tries to reduce the length of your import statement.
To fix this, use relative import. So your import should look like as follow:
import logger from '../util/logger'
(Note: Above import is relative to the path src/middleware/authenticateUser.ts, please update the import based on in which file you are using the import)
I am creating tests with Jest and React Testing Library and I am having difficulties with imports to the util folder that exists within the src folder. I am using TypeScript for this which seems to create its own interesting challenges.
My jest.config.ts file looks like the following:
module.exports = {
'preset': 'ts-jest',
'testEnvironment': 'node',
'testPathIgnorePatterns': [
'<rootDir>/dist'
],
'moduleNameMapper': { 'src/(.*)': '<rootDir>/src/$1' }
};
The test looks like the following:
import React from 'react';
import { render, screen } from '#testing-library/react';
import { Tag } from '/components';
describe('Tabs Component', () => {
it('should render a tab component correctly', () => {
render(<Tag id="test" />);
expect(screen.getAllByTestId('test')).toHaveBeenCalled();
});
});
When I run this I am getting import issues:
Cannot find module '/components' from 'src/components/Tag/Tag.spec.tsx'
Additionally my tsconfig looks like the following:
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"/*": [
"*"
]
},
"outDir": "./tested/esm",
"module": "esnext",
"target": "es5",
"lib": [
"es6",
"dom",
"es2016",
"es2017"
],
"jsx": "react",
"declaration": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"esModuleInterop": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"allowSyntheticDefaultImports": true
},
"include": [
"src/**/*.spec.{ts,tsx}",
"./jest.config.ts"
],
"exclude": [
"node_modules",
"dist",
"./src/**/*.stories.tsx",
"./*.js"
]
}
I have tried a few of the tricks from Stack Overflow like:
Jest gives `Cannot find module` when importing components with absolute paths
None of these seemed to fix the issue.
I think the problem here is how the import is done. As the jest.config.ts has already specified the moduleNameMapper as { 'src/(.*)': '<rootDir>/src/$1' }, it means if Tag component is imported as below,
import { Tag } from "src/components";
Jest will look into the <rootDir>/src/components/index.ts to import the Tag component.
If you want to import modules in this way,
import { Tag } from "components"; // not "/components"
It's better to replace moduleNameMapper config with moduleDirectories:
module.exports = {
'preset': 'ts-jest',
'testEnvironment': 'node',
'testPathIgnorePatterns': [
'<rootDir>/dist'
],
'moduleDirectories': ['node_modules', 'src']
};
This tells Jest when it sees an import from "components", it will look into both node_modules and src and see if there is the file components/index.ts or components.ts.
PS: tsconfig.json is only used by the editor. Therefore, Jest won't take it into consideration. jest.config.ts is the config file that matters to Jest.
I am trying to implement encryption into my project using vuejs and typescript. I successfully implemented it in the .vue file, but when I try to write the encryption into a typescript class, the mocha test runs it, but when I try to compile and open it in the browser i get a javascript error in the console:
app.js:128620 Uncaught ReferenceError: require is not defined
at Object.crypto (app.js:128620)
at __webpack_require__ (app.js:20)
at Object../resources/ts/Classes/Model/Crypter.ts (app.js:125233)
at __webpack_require__ (app.js:20)
at Object../resources/ts/Controller/AuthController.ts (app.js:125924)
at __webpack_require__ (app.js:20)
at Object../node_modules/babel-loader/lib/index.js?!./node_modules/babel-
loader/lib/index.js!./node_modules/vue-
loader/lib/index.js?!./resources/js/Components/Includes/Login.vue?
vue&type=script&lang=js& (app.js:3308)
at __webpack_require__ (app.js:20)
at Module../resources/js/Components/Includes/Login.vue?
vue&type=script&lang=js& (app.js:124322)
at __webpack_require__ (app.js:20)
The marked line in the app.js is:
module.exports = require("crypto");
I already tried different importing 'strategies' in the typescript file like:
import * as crypto from "crypto";
import crypto from "crypto";
var crypto = require("crypto");
And also adding this in the webpack.mix.js
"node": {
fs: "empty",
crypto: true,
http: true,
https: true,
os: true,
vm: true,
stream: true,
path: true
},
but it didn't work.
The Crypter.ts
import crypto from "crypto";
export default class Crypter {
public constructor() {
}
public static publicEncrypt(data: JSON, publicKey: string): string{
let dataStr = JSON.stringify(data);
let dataB64 = Buffer.from(dataStr).toString("base64");
var buffer = Buffer.from(dataB64);
return crypto.publicEncrypt(publicKey, buffer).toString("base64");
}
}
The tsconfig.json
"compilerOptions": {
"allowUnreachableCode": false,
"allowUnusedLabels": true,
"alwaysStrict": true,
"charset": "utf8",
"declaration": true,
"declarationDir": "resources/ts/lib/types",
"declarationMap": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"importHelpers": true,
"lib": ["ES5", "ES6", "DOM", "DOM.Iterable", "ScriptHost"],
"locale": "en",
"module": "commonjs",
"moduleResolution": "node",
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitUseStrict": false,
"noUnusedParameters": true,
"outDir": "public/js",
"baseUrl": "resources/",
"paths": {
"Base/*": [ "ts/*" ],
"#js/*": [ "js/*" ],
"#ts/*": [ "ts/*" ],
"Component/*": [ "ts/Components/*" ],
"Interface/*": [ "ts/Interfaces/*" ],
"Model/*": [ "ts/Model/*" ],
"Controller/*": [ "ts/Controller/*" ],
"Helper/*": [ "ts/Helper/*" ]
},
"pretty": true,
"sourceMap": true,
"target": "ES5",
"typeRoots": [
"node_modules/#types"
],
"downlevelIteration": true
},
"include": [
"resources/ts/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
],
"files": [
"./node_modules/#types/node/index.d.ts"
]
}
I expect the error to be resulting from wrong compiling or other misconfigurations.
You can't access nodejs crypto module in a web application. Node.js uses the same javascript syntax, but is not running in the browser.
You may need to install another crypto library such as crypto-js, that you can install using npm install crypto-js. There are probably plenty of other libraries that you can choose from (some ideas)