I am making a websocket webgame. I am trying to standardize data going over the websocket via some shared "Action" objects. I am using docker volumes to share a "shared" directory between two different containers, and tsconfig.json files to create an alias for easier use. This works fine for client, but I keep getting an error from the server.
The command I'm entering npm run dev:
(base) omitted@omitted CS5001-Scribble-Beasts % npm run dev
> [email protected] dev
> docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
The error I'm running into:
server-1 | import { Actions, ActionType, ParseAction, type AnyAction } from "@shared/actions";
server-1 | ^
server-1 |
server-1 | SyntaxError: The requested module '@shared/actions' does not provide an export named 'ActionType'```
Added Context
Code: https://github.com/2025-Senior-Design-Project/Scribble-Beasts/tree/room-system
(if you want to try and run this yourself, check out CONTRIBUTING.md)
Basic file structure:
/client
/server
/shared
docker-compose.yml
Pertinent Snippets:
docker-compose.yml
server:
build:
context: ./server
dockerfile: Dockerfile
volumes:
- ./server:/app
- ./shared:/shared
server/package.json
"type": "module",
"main": "dist/server/src/index.js",
"exports": "./dist/*.js",
"scripts": {
"start": "node dist/server/src/index.js",
"dev": "tsx watch src/index.ts",
server/tsconfig.json
{
"compilerOptions": {
"lib": ["es2024", "ESNext.Array", "ESNext.Collection", "ESNext.Promise"],
"module": "esnext",
"moduleResolution": "bundler",
"target": "es2017",
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"@shared/*": ["../shared/*"]
},
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"resolveJsonModule": true,
"isolatedModules": true
},
"include": ["src/**/*", "../shared/**/*"],
"exclude": ["node_modules", "dist"]
}
What I know:
- The import/export names are correct. If I put the file into the same directory as room-handler.ts and change the from path it works without issue.
- It's not an issue with the alias. If I swap the alias @shared with the relative path (
../../../../shared) it shows the same error - The file exists in the container. If I use fs to print the contents of the file to the console while room-handler is running, it shows the actual content. If I look in docker-desktop I can see the shared mount.
- Client uses the same setup as server and works (@shared and everything) and can import the file without issues.
What I've tried:
- Changing from tsx to ts-node-dev or ts-node (I get the error:
Error: Cannot find module '/app/src/lib/scripts/roomless-handler' imported from /app/src/index.ts) - Changing the moduleResolution from bundler to Node (same error)
- Moving the shared volume into app instead of being in the root of the container (this worked, but the ts mismatched with the actual/local setup)
serverdirectory it can't see the siblingshareddirectory; see for example How to include files outside of Docker's build context? Delete thevolumes:block, which replace code only after the image is built and which mean you're not actually running the reproducible image at all.