This has been asked a lot and I still can't wrap my head around it.
My old, working code:
database-setup.mjs file in /
import sqlite3 from 'sqlite3';
import { open } from 'sqlite'
(async () => {
// open the database
const db = await open({
filename: './mydb.sqlite',
driver: sqlite3.Database,
});
await db.migrate({ force: true });
const people = await db.all('SELECT * FROM person');
console.log("All People:", JSON.stringify(people, null, 2));
const vehicles = await db.all('SELECT * FROM vehicle');
console.log("All Vehicles:", JSON.stringify(vehicles, null, 2));
})();
I have a lot of db calls, so I thought I refactor the open method into a separate file.
resulting in this file under /src/lib/db.ts
import sqlite3 from 'sqlite3'
import { open } from 'sqlite'
export async function openDB () {
return open({
filename: 'mydb.sqlite',
driver: sqlite3.Database
})
}
and the previous file from the top now looks like this:
import { openDB } from './src/lib/db'
(async () => {
// open the database
const db= await openDB();
await db.migrate({ force: true });
const people = await db.all('SELECT * FROM person');
console.log("All People:", JSON.stringify(people, null, 2));
const vehicles = await db.all('SELECT * FROM vehicle');
console.log("All Vehicles:", JSON.stringify(vehicles, null, 2));
})();
running this now results in
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'D:\Programming\nextjs\nextjs-basics\src\lib\db' imported from D:\Programming\nextjs\nextjs-basics\database-setup.mjs
My Node version is >14.0.
The path is correct, I see the file ts file there. I do not see any compile file, but I think that's normal? So I don't understand why it is not finding the module?
The tsconfig:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"exclude": [
"node_modules"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
]
}
One way to solve it:
So I had to rename the db.ts file into db.mjs - problem solved.
But now I am running .js files, even though I wanted a 100% ts coverage.
The - in my eyes - proper way to actually tackle the problem instead of avoiding it:
Install ts-node
Create an additional tsconfig (to avoid interference with frameworks, IE11 Polymorph stuff etc) and add this to it:
{
"compilerOptions": {
"target": "ES2017",
"module": "CommonJS"
}
}
Change your package.json dev command accordingly, e.g. for me this was changing
"dev": "node ./database-setup.mjs && next dev"
into
"dev": "ts-node --project ./tsconfig-node.json ./database-setup.ts && next dev"
Both db.ts and database-setup.ts are now in typescript and everything works.
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 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 have been looking through all of the other posts about the same issues in react/typescript projects but none of these have worked for me...not even changing noImplicitAny to false and strict to false is ts.config or setting the "excludes" and "typeRoots".
I've tried declaring a module, I've tried putting it in a .d.ts file, I've tried using #ts-ignore, I can't get anything to work. It's driving me crazy...can somebody tell me how to resolve this once and for all so I can get this to compile properly?
There are a whole lot more issues of the same type in the index.js file but once with a ton of requires throwing the same issue but once I can resolve this, I should be able to fix the others as well...
(function(factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['rest/index'], factory);
} else if (typeof module === 'object' && module.exports) {
// CommonJS-like environments that support module.exports, like Node.
module.exports = factory(require('./rest/index')); **<---- ERROR HERE**
}
}(function(restIndex) {
return restIndex;
}));
EDIT:
Client.js:
var apiKey = process.env.ROCKSET_APIKEY;
var apiServer = process.env.ROCKSET_APISERVER;
var rockset = require('rockset')(apiKey, apiServer);
var getResponseLogger = function(callback) {
return function(error, response, body) {
if(error) {
console.log(error.response.error.text);
callback();
} else {
console.log(response);
callback();
}
}
}
export function getMaxSkill() {
rockset.queries.query({
'sql': {
'query': 'select * from "testCollection"'
}
}, null, getResponseLogger(done))
}
function done() {
console.log('\n\n===done===');
}
App.tsx:
import {getMaxSkill} from './client';
async componentDidMount() {
getMaxSkill();
}
tsconfig
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"typeRoots": [
"../../#types",
"../../node_modules/#types"
]
},
"include": [
"src", "tests/App.test.js"
],
"paths": {
"#material-ui/core": ["./material-ui/src"],
"#material-ui/core/*": ["./material-ui/src/*"],
"#material-ui/lab": ["./material-ui-lab/src"],
"#material-ui/lab/*": ["./material-ui-lab/src/*"],
"#material-ui/styles": ["./material-ui-styles/src"],
"#material-ui/styles/*": ["./material-ui-styles/src/*"],
"#material-ui/system": ["./material-ui-system/src"],
"#material-ui/types": ["./material-ui-types"]
}
}
I'm aggregating files in an index.ts. When I try to import from the index.ts the object returns as undefined. When I try to import directly from the file, it works fine. I'm not sure what I'm doing wrong -- it's my impression that export { ... } from '...' should work fine in Node with TypeScript (which is the case for this app).
fileThatUsesTheExportedVariables.ts
import { dates } from '../consts' // Undefined
import { dates } from '../consts/index' // Undefined
import { dates } from '../consts/dates' // Works
consts/index.ts
export { dates } from './dates'
// ...
export { someNamedExport } from './someFile'
consts/dates.ts
const months = {
// some months stuff
}
export const dates = {
months,
// ...
someOtherChildObject
}
I presume I'm doing something silly. VS Code can connect the dots which makes it all the more frustrating.
Thanks in advance for any and all help
UPDATE: #casieber pointed out it might be helpful to know more about the TS compilation process (uses tsc):
Versions:
tsc 2.9.1
typescript 6.1.0
tsconfig.json
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"lib": ["es2018", "dom"],
"declaration": true,
"sourceMap": true,
"outDir": "dist",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true
},
"include": [
"app/**/*"
]
}
I am trying to run an example built in using typescript(using version 2.6) of async iterator through browser.
`
function* countAppleSales () {
var saleList = [3, 7, 5];
for (var i = 0; i < saleList.length; i++) {
yield saleList[i];
}
}
for(let val of countAppleSales())
console.log(val);
async function* asyncRandomNumbers() {
// This is a web service that returns a random number
const url = 'https://www.random.org/decimal-fractions/?num=1&dec=10&col=1&format=plain&rnd=new';
while (true) {
const response = await fetch(url);
const text = await response.text();
yield Number(text);
}
}
async function example() {
for await (const number of asyncRandomNumbers()) {
console.log(number);
if (number > 0.95) break;
}
}
example();
console.log('we are after await')
;`
above code is running fine in browser but am getting error cannot find name __values logged in console.log.
below is the type script configuration file am using:
{
"compilerOptions": {
"module": "es2015",
"types": [
"node"
],
// typeRoots option has been previously configured
"typeRoots": [
// add path to #types
"node_modules/#types"
],
"target": "es6",
"noImplicitAny": false,
"downlevelIteration": false,
"sourceMap": true,
"moduleResolution": "node",
"watch": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
//"noEmitHelpers": true,
"skipDefaultLibCheck": true,
"strictNullChecks": false,
"outDir": "tmp",
//"lib":["es2017","es2015","es2016","es2015.generator","esnext","dom","esnext.asynciterable"]
"lib": [ "es2017","dom","es2015.generator","es2015","es2015.iterable","esnext.asynciterable","esnext"]
},
"allowSyntheticDefaultImports":true,
"baseUrl": ".",
"paths": {
"lodash/*": [
"node_modules/#types/lodash-es/*"
]},
"awesomeTypescriptLoaderOptions": {
"useBabel": true,
"useCache": true
},
"include": [
"src",
"test"
],
"exclude": [
"node_modules",
"typings"
]
}
please can anybody help with this issue
this issue is resolved now, Issue is due to copy pasting typescript loader rules configuration twice in webpack configuration file. webpack error needs to be more specific though.