docker container build failing - node.js

I'm trying to move my service into a Docker container. Building the project works fine locally, but when I try building it as part of docker build, I get the following error:
node_modules/jest-extended/types/index.d.ts(135,39): error TS2694: Namespace 'jest' has no exported member 'Mock'.
Please find my dockerfile:
FROM node:12
COPY package.json /opt/service/
WORKDIR /opt/service/
RUN npm install
COPY . .
RUN npm run build
...
package.json parts that are relevant
"scripts": {
"build": "rm -rf lib && graphql-codegen && tsc -p tsconfig.json && copyfiles -u 1 ./src/**/*.graphql lib && copyfiles -u 1 ./src/**/*.proto lib"
},
"devDependencies": {
"#graphql-codegen/cli": "1.17.8",
"#graphql-codegen/typescript": "1.17.8",
"#graphql-codegen/typescript-resolvers": "^1.18.1",
"#types/jest": "^27.0.2",
"#types/node": "^16.10.2",
"copyfiles": "^2.3.0",
"graphql": "14.7.0",
"jest": "27.2.4",
"jest-cli": "27.2.4",
"jest-extended": "^0.11.5",
"nodemon": "^2.0.4",
"ts-jest": "^27.0.5",
"ts-node": "^10.2.1",
"typescript": "^3.9.7"
},
tsconfig.json
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"lib": ["es2019", "dom"],
"strict": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"typeRoots": ["node_modules/#types"],
"esModuleInterop": true,
"resolveJsonModule": true,
"outDir": "lib",
"rootDir": "src",
"resolveJsonModule": true,
"allowJs": true
},
"ts-node": {
"transpileOnly": true,
"files": true
},
"include": ["**/*"],
"exclude": ["node_modules", "lib", "jest.*.ts", "jest.*.js", "**/generated/*"]
Edit:
Adding "skipLibCheck": true in my compilerOptions fixed the Namespace 'jest' has no exported member 'Mock' error.
I'm still getting errors though that I didn't mention before that I hoped would get resolved by fixing the first error.
The Errors I'm still getting from *.test.ts files are:
error TS2708: Cannot use namespace 'jest' as a value.
error TS2304: Cannot find name 'expect'.
error TS2304: Cannot find name 'beforeAll'.
error TS2582: Cannot find name 'test'.

I have an idea that maybe could resolve your issue, as I had a similar problem that was caused because of version conflicts. Could you try to also copy your package-lock.json file to your docker image?
...
COPY package.json /opt/service/
COPY package-lock.json /opt/service/
...

This turned out to be a problem with tsconfig.json and my folder structure. I have multiple services and packages in this project. In the root folder (two folders up from each service) I have a tsconfig.json file that other services and packages are extending. Because I'm only copying the tsconfig.json file from the root and not node_modules, and the root tsconfig.json file is declaring "typeRoots": ["node_modules/#types"], services expect #types to be found in ../../node_modules.

Related

Error when attempting to launch and debug project after moving project to a new folder

I've moved my project to another folder and now I'm now getting an error:
Uncaught SyntaxError /Users/user/Documents/project/project.ts:1
import express from "express";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at compileFunction (vm:360:18)
at wrapSafe (internal/modules/cjs/loader:1088:15)
at Module._compile (internal/modules/cjs/loader:1123:27)
at Module._extensions..js (internal/modules/cjs/loader:1213:10)
at Module.load (internal/modules/cjs/loader:1037:32)
at Module._load (internal/modules/cjs/loader:878:12)
at executeUserEntryPoint (internal/modules/run_main:81:12)
at <anonymous> (internal/main/run_main_module:23:47)
No debugger available, can not send 'variables'
Although, I didn't move the project, I cloned a version from the repository into another folder.
The debug view shows the difference:
In original working project:
In the new non-working project:
New project jtsconfig.json
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "node",
"target": "ES6",
"allowSyntheticDefaultImports": true,
"resolveJsonModule": false,
"pretty": true,
"sourceMap": true,
"outDir": "./dist",
"stripInternal": true,
"noUncheckedIndexedAccess": true,
"noPropertyAccessFromIndexSignature": false,
"noEmitOnError": true,
"useDefineForClassFields": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"esModuleInterop": true
}
}
New project package.json:
{
"name": "web",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "npx tsc",
"start": "node dist/server.js",
"dev": "nodemon server.ts"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
},
"devDependencies": {
"#types/node": "^18.11.9",
"nodemon": "^2.0.20",
"ts-node": "^10.9.1",
"tslib": "^2.4.1",
"typescript": "^4.9.3"
},
"compilerOptions": {
"noImplicitAny": false
}
}
Clicking on the small debug "button" shows this:
Update:
I closed vscode and restarted. And a few things changed. The debug panel was blank but now it shows this:
I click on the create a launch.json and it shows this
I thought I already have a launch json in the vscode folder???
Welp, I got it to work. I had to restart vscode. I had a few error messages about extension and corrupt installation.
At some point a small debug button appeared in package.json. It might have appeared before or after restart.
The debug panel that was blank but now it shows a few new buttons and messages.
Blank:
Not blank:
It was blank before (meaning it showed the panels panes but there was no content in them.
I then clicked the, Create a launch.json and choose node.js as the type of launch.
This created a new launch.json with default values for that launch type:
I now have a new option in the Run and Debug panel:
Selecting this option and clicking on the launch button successfully launches the app.
Conclusion,
My guess is that vscode didn't like the existing launch.json config. I would delete the existing launch config and let vscode create it, then add in any new values later. I would also restart after the initial opening of the workspace.

error TS2307: Cannot find module or its corresponding type declarations. on Github Actions

I can't find a way to fix this. It is working locally as usual. I have tried using path aliases, relative paths, updating the yaml file many times, but can't find it to work.
The gihub actions spits this
Run yarn build yarn run v1.22.19 warning package.json: No license field $ tsc Error: src/application/Feed/Activity/AddActivity.handler.ts(7,37): error TS2307: Cannot find module '#domain/Feed/Activity/Dto/Activity.response.dto' or its corresponding type declarations. Error: src/domain/Feed/Activity/Activity.mapper.ts(2,37): error TS2307: Cannot find module './Dto/Activity.response.dto' or its corresponding type declarations. Error: src/infrastructure/Serverless/Controller/Feed/Activity/AddActivity.controller.ts(4,37): error TS2307: Cannot find module '#domain/Feed/Activity/Dto/Activity.response.dto' or its corresponding type declarations. Error: src/infrastructure/Serverless/GetStream/Feed/Activity/Mapper/Activity.mapper.ts(6,37): error TS2307: Cannot find module '#domain/Feed/Activity/Dto/Activity.response.dto' or its corresponding type declarations. error Command failed with exit code 2. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. Error: Process completed with exit code 2.
this is my config
name: APP_NAME
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v3
with:
persist-credentials: false
- uses: actions/setup-node#v3
with:
node-version: lts/*
cache: yarn
- name: install
run: yarn --immutable
- name: build
run: yarn build
- name: Install B4A Cli
run: curl https://raw.githubusercontent.com/back4app/parse-cli/back4app/installer.sh | /bin/bash
- name: Configure B4A Cli and set it default
run: echo $ACCOUNT_KEY | b4a configure accountkey && b4a default $APP_NAME
- name: Deploy
run: b4a deploy
Package.json
{
"description": "",
"main": "src/main.js",
"scripts": {
"lint": "eslint src/",
"test": "jest",
"build": "tsc",
"dev:parse": "mongodb-runner start && parse-server --appId 'APP' --masterKey 'MASTER' --clientKey 'CLIENT' --databaseURI mongodb://localhost/test --cloud ./cloud/main.js",
"debug:parse": "mongodb-runner start && parse-server --appId 'APP' --masterKey 'MASTER' --clientKey 'CLIENT' --databaseURI mongodb://localhost/test --cloud ./cloud/main.js --verbose",
"dev:dash": "parse-dashboard --dev --appId APPLICATION_ID --masterKey MASTER_KEY --serverURL http://localhost:1337/parse --appName MY_APP"
},
"devDependencies": {
"#types/jest": "^29.2.3",
"#types/node": "^18.11.9",
"#types/node-fetch": "^2.6.2",
"#types/parse": "^3.0.1",
"#types/uuid": "^8.3.4",
"#typescript-eslint/eslint-plugin": "^5.42.1",
"#typescript-eslint/parser": "^5.42.1",
"eslint": "^8.27.0",
"jest": "^29.3.1",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"typescript": "^4.8.4"
},
"dependencies": {
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"getstream": "^8.1.0",
"module-alias": "^2.2.2",
"parse-server": "^5.3.3",
"reflect-metadata": "^0.1.13",
"tsyringe": "^4.7.0",
"uuid": "^9.0.0"
},
"_moduleAliases": {
"#root": "cloud/",
"#domain": "cloud/domain",
"#application": "cloud/application",
"#infrastructure": "cloud/infrastructure"
}
}
tsconfig.json
{
"compilerOptions": {
"lib": ["es6"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2022",
"module": "commonjs",
"moduleResolution": "node",
"rootDir": "src/",
"baseUrl": ".",
"paths": {
"#root/*": ["./src/*"],
"#domain/*": ["./src/domain/*"],
"#application/*": ["./src/application/*"],
"#infrastructure/*": ["./src/infrastructure/*"],
},
"outDir": "cloud",
"removeComments": true,
"isolatedModules": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": false,
"forceConsistentCasingInFileNames": true,
"strict": true,
"strictPropertyInitialization": false,
"alwaysStrict": true,
"skipLibCheck": true
},
"include": ["src/"],
"exclude": ["src/**/*.spec.ts", "cloud", "node_modules"]
}
I have tried changing the github actions yaml config, switching from relative paths to path aliases, but can't make it work.
Delete node_modules folder and run npm install. Hope this will work

Must use import to load ES module: ...\node_modules\got\dist\source\index.js

There's dozens of other questions with basically the same title, but none of the answers seem to be relevant and just add to the confusion.
This is my tsconfig.json:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"lib": ["es2017", "es7", "es6", "dom"],
"declaration": true,
"outDir": "dist",
"strict": true,
"esModuleInterop": true
},
"exclude": [
"node_modules",
"dist"
]
}
This is what I typed:
import md5 from 'js-md5';
import got from 'got';
import { Design } from './Design';
...
This is my error:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\Users\...\node_modules\got\dist\source\index.js
require() of ES modules is not supported.
What. I'm not using require, I'm using import. I haven't had this error on any other modules, so why is Got different (and why is nothing ever simple)?
Why is this happening and how do I fix it?
As per #jsejcksn's answer, I tried changing my tsconfig.json to the following:
{
"compilerOptions": {
"target": "es6",
"module": "esnext",
"lib": ["es2017", "es7", "es6", "dom"],
"declaration": true,
"outDir": "dist",
"strict": true,
"esModuleInterop": true
},
"exclude": [
"node_modules",
"dist"
]
}
... and added "type": "module" to my package.json:
{
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1",
"fs-extra": "^10.0.0",
"got": "^12.0.1",
"js-md5": "^0.7.3",
"moment": "^2.29.1",
"semver": "^7.3.5",
"typescript": "^4.4.3",
"uuid": "^8.3.2",
"#types/node": "^16.9.2",
"#types/express": "^4.17.13",
"#types/fs-extra": "^9.0.13",
"#types/semver": "^7.3.9",
"#types/uuid": "^8.3.1",
"#types/js-md5": "^0.4.3"
},
"type": "module"
}
But now I just get different errors :|
src/Logging.ts:1:20 - error TS2792: Cannot find module 'moment'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?
1 import moment from 'moment';
src/SyncAPI.ts:2:17 - error TS2792: Cannot find module 'got'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?
2 import got from 'got';
You have configured TypeScript to compile your modules to CommonJS format (your TSConfig option compilerOptions.module is set to "commonjs"). You'll need to set that option to an ESM-compatible setting (such as "esnext") so that the compiled JavaScript emitted by the TS compiler is in ESM format.
In your package.json, you'll probably also need to set the "type" field to "module".
Edit: To use npm packages by name as bare specifiers in your import statements, you'll also need to update your TSConfig compilerOptions.moduleResolution to "node". In your current config, you have included "dom" in the compilerOptions.lib array. "dom" is for environments with a DOM (which Node does not natively have), so that shouldn't be there. Instead, setting that array to ["es2017"] will include the others you have specified.
Edit: In attempt to provide more direct guidance:
Make sure you're not using an outdated version of Node (the current LTS is ^16.x.x)
Make sure you're not using an outdated version of TypeScript (currently at ^4.5.x)
Move all your source files to ./src (if they're not already in that directory), and
Use this as your ./tsconfig.json:
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": true,
"esModuleInterop": true,
"lib": [
"es2021"
],
"module": "esnext",
"moduleResolution": "node",
"outDir": "dist",
"strict": true,
"target": "es2021"
},
"include": [
"src/**/*"
]
}
and make sure that the "type" field in your ./package.json is set to "module":
{
// ...
"type": "module"
// ...
}
You shouldn't have any trouble with import statement module system compatibility after that.
In my case this very error was caused by ts-node-dev package.
If you use the same package (it usually sits in dev dependencies in package.json) you may check the resolution steps I posted in a parallel thread. Hope this helps.
You can also use tsc-node-esm instead of tsc-node to run your script after adding "type": "module" to your package.json

Can't import node-fetch into Typescript

I'm trying to import node-fetch into my Typescript project but I fall into this error:
[ERR_REQUIRE_ESM]: Must use import to load ES Module : /Users/xxx/xxx/xxx/xxx/xxx/xxx/xxx/node_modules/node-fetch/src/index.js require() of ES module is not supportes.
This is my setup:
node: v16.1.0
typescript: 4.5.2
The node-fetch package is imported in my project as followed: import fetch from 'node-fetch';'
This is my tscongif.json:
{
"compilerOptions": {
"module": "CommonJS",
"sModuleInterop": true,
"target": "ES2020",
"allowJs": true,
"noImplicitAny": true,
"moduleResolution": "node",
"outDir": "dist",
"baseUrl": ".",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"resolveJsonModule": true,
"typeRoots": [
"src/#types/",
"node_modules/#types",
],
"strict": true,
"strictNullChecks": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"noEmit": true,
"skipLibCheck": true,
},
"include": [
"src/**/*",
"config/**/*"
]
}
I tried alse to add "type": "module" into the package.json and set "module": "ES2020" into the tsconfig.json but I got a new error:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"
To run my code I use nodemon configured as follow:
{
"watch": ["src"],
"ext": "ts, js, json",
"execMap": {
"ts": "NODE_ENV=development ts-node -T"
}
}
The issue you are experiencing is not a problem in your application code, but is caused by project misconfiguration. ESM support in ts-node is currently experimental. See this GitHub issue to understand the current situation:
https://github.com/TypeStrong/ts-node/issues/1007
According to the data in the repo link you shared in your comment, along with the information in the above issue and the documentation notes here, the following changes will allow you to run your app using the npm start:dev script in the reproduction repo.
./package.json:
Add the following entry to the top-level of the object (this will tell Node that your transpiled *.js files are ES modules and to run them in that mode):
{
"type": "module"
}
./tsconfig.json:
Modify the value of compilerOptions.module to "esnext" (this will tell TypeScript to emit modules in ESM format instead of CJS):
{
"compilerOptions": {
"module": "esnext"
}
}
./nodemon.json:
Modify the value of execMap.ts to the following (configuring the NODE_OPTIONS environment variable this way enables native ESM support in ts-node):
{
"execMap": {
"ts": "NODE_ENV=development NODE_OPTIONS='--loader ts-node/esm' ts-node -T"
}
}
Console output:
$ npm run start:dev
> fetch-problem#1.0.0 start:dev
> NODE_ENV=development nodemon ./src/index.ts
[nodemon] 2.0.15
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**/*
[nodemon] watching extensions: ts,js,json
[nodemon] starting `NODE_ENV=development NODE_OPTIONS='--loader ts-node/esm' ts-node -T ./src/index.ts`
(node:3273) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
START
[nodemon] clean exit - waiting for changes before restart
node-fetch from v3 is an ESM-only module - you are not able to import it with require(),
according to doc.
did u tried using this:
import * as fetch from 'node-fetch';

TSC won't compile on different systems

I created a node app in typescript. When I run tsc locally everything works and I can run the app. But when I deploy on heroku, it is giving me compilation errors :
app/api/controllers/ingredient.controller.ts(3,24): error TS2307: Cannot find module '../schemas/ingredient.schema'.
app/api/controllers/ingredient.controller.ts(23,13): error TS7006: Parameter 'units' implicitly has an 'any' type.
app/api/controllers/ingredient.controller.ts(30,42): error TS7006: Parameter 'result' implicitly has an 'any' type.
app/api/controllers/ingredient.controller.ts(37,70): error TS7006: Parameter 'result' implicitly has an 'any' type.
app/api/controllers/ingredient.controller.ts(44,70): error TS7006: Parameter 'result' implicitly has an 'any' type.
The strange thing is that I made sure all versions are the same: NPM, Node, TSC ...
I have a TSConfig that is picked up and used. Where else am I supposed to look ?
Versions:
> node -v && npm -v && tsc -v && tsc
v13.3.0
6.13.1
Version 3.7.3
Package.json:
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "build/app.js",
"scripts": {
"tsc": "node -v && npm -v && tsc -v && tsc",
"watch-ts": "tsc -w",
"watch-node": "nodemon build/app.js",
"watch": "docker-compose up -d && concurrently -k -p \"[{name}]\" -n \"TypeScript, Node\" -c \"yello.bold, cyan.bold\" \"yarn run watch-ts\" \"yarn run watch-node\"",
"start": "node build/app.js",
"build": "npm run tsc"
},
"author": "",
"license": "ISC",
"dependencies": {
"#overnightjs/core": "^1.6.9",
"#overnightjs/logger": "^1.1.9",
"#types/body-parser": "^1.17.1",
"#types/cors": "^2.8.6",
"#types/dotenv": "^8.2.0",
"#types/express": "^4.17.2",
"#types/mongodb": "^3.3.11",
"#types/mongoose": "^5.5.32",
"#types/multer": "^1.3.10",
"concurrently": "^5.0.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"mongoose": "^5.7.13",
"multer": "^1.4.2",
"nodemon": "^2.0.1",
"typescript": "^3.7.3"
},
"engines": {
"node": "13.3.0",
"npm": "6.13.1"
}
}
TSCONFIG:
{
"compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"outDir": "build", /* Redirect output structure to the directory. */
"rootDir": "./app", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"importHelpers": true, /* Import emit helpers from 'tslib'. */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
/* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": "./", /* Base directory to resolve non-absolute module names. */
"typeRoots": [ /* List of folders to include type definitions from. */
"node_modules/#types"
],
"types": ["node"], /* Type declaration files to be included in compilation. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
/* Experimental Options */
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": [
"app/*"
]
}
Advice
Run tsc locally and deploy the built .js files.
Don't deploy typescript files, that's going to add a lot of code to your remote code base.
The Error
this errors means some ts rules are not getting applied to your local ts.
I noticed rootDir is ./app and you have include as /app. Maybe it's looking for an /app folder under /app. Try ./ as root and see if that fixes it. Btw, I'm the creator of OvernightJS and I highly recommend you transpile all code before deploying.

Resources