Fix Unknown File Extension .ts Error in Apollo GraphQL Server with Prisma
Learn how to resolve the 'Unknown file extension .ts' error when running Apollo GraphQL Server with Prisma in a Turborepo monorepo. Complete guide with ts-node solutions.
How to resolve the ‘Unknown file extension .ts’ error when running Apollo GraphQL Server with Prisma in a Turborepo monorepo? I’m getting a TypeError [ERR_UNKNOWN_FILE_EXTENSION] when trying to execute my compiled TypeScript code in the GraphQL server project, while my web project works fine. Both projects use TypeScript and are part of the same Turborepo setup. The error occurs specifically when running ‘node ./dist/index.js’ after compiling with TypeScript. What configuration or setup is needed to properly run TypeScript-based Apollo GraphQL Server in a Turborepo environment with Prisma?
The “Unknown file extension .ts” error in Apollo GraphQL Server with Prisma in Turborepo occurs when Node.js cannot properly handle TypeScript files in your monorepo setup. This typically happens because your GraphQL server package is either not fully compiled to JavaScript or Node.js is unaware of how to process .ts files, requiring proper TypeScript configuration with ts-node or esm loaders to resolve the ERR_UNKNOWN_FILE_EXTENSION issue.
Contents
- Understanding the Error
- Root Causes in Turborepo Environment
- Solution 1: Using ts-node with ESM Flag
- Solution 2: Configuring TypeScript in Turborepo
- Solution 3: Proper Apollo Server Build Setup
- Solution 4: Prisma Integration in Turborepo
- Best Practices for Turborepo Monorepos
- Troubleshooting Common Issues
- Conclusion
Understanding the Error
The TypeError [ERR_UNKNOWN_FILE_EXTENSION] error is a common issue when working with TypeScript in Node.js environments, particularly in complex setups like Turborepo monorepos. When you encounter the message “Unknown file extension .ts” while trying to run your Apollo GraphQL Server, it indicates that Node.js doesn’t recognize how to handle TypeScript files directly.
This error specifically manifests when you execute node ./dist/index.js after compiling your TypeScript Apollo GraphQL Server, which is puzzling since you’d expect the compiled JavaScript to run without issues. The problem often lies in the fact that even after compilation, your code might still contain references to .ts files or your Node.js environment isn’t properly configured to handle TypeScript.
Root Causes in Turborepo Environment
In a Turborepo monorepo setup with Apollo GraphQL Server and Prisma, several factors can contribute to this error:
-
ES Module Configuration: Turborepo projects often use ES modules (with “type”: “module” in package.json), which changes how Node.js resolves and loads files. This can interfere with how TypeScript files are processed.
-
Incomplete Compilation: Your Apollo GraphQL Server package might not be fully compiled to JavaScript, leaving .ts references in the compiled output.
-
Missing TypeScript Loader: When Node.js encounters a .ts file, it needs a loader like ts-node to process it. Without proper configuration, it throws the unknown file extension error.
-
Prisma Integration Issues: Prisma’s database generation and seeding processes may also encounter this error if they’re not properly configured to run TypeScript files in the monorepo environment.
Solution 1: Using ts-node with ESM Flag
The most direct solution to the “Unknown file extension .ts” error is to configure your project to properly handle TypeScript files with ts-node, especially when working with ES modules.
First, install ts-node as a development dependency in your Apollo GraphQL Server package:
npm install --save-dev ts-node
Then, modify your Turborepo task in the root package.json to explicitly use ts-node with the ESM flag:
{
"scripts": {
"dev": "tsx watch src/index.ts"
}
}
Alternatively, if you prefer to continue using the compiled JavaScript approach, you can use one of these commands when running your Apollo GraphQL Server:
npx ts-node --esm src/index.ts
Or:
node --loader ts-node/esm src/index.ts
As noted in the Prisma GitHub discussion, using tsx (which bundles ts-node) is another popular option that simplifies this process:
tsx src/index.ts
The key is to ensure that Node.js knows how to process .ts files, whether through explicit flags, loaders, or alternative execution tools.
Solution 2: Configuring TypeScript in Turborepo
Proper TypeScript configuration is essential for resolving the “Unknown file extension .ts” error in a Turborepo environment. Your Apollo GraphQL Server package needs specific settings to work seamlessly with the monorepo structure.
First, ensure your tsconfig.json in the GraphQL server package has the following configuration:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"resolveJsonModule": true,
"baseUrl": ".",
"outDir": "dist",
"rootDir": "src"
},
"ts-node": {
"esm": true,
"experimentalSpecifierResolution": "node"
}
}
The ts-node section specifically enables ESM support, which is crucial when working with modern JavaScript projects in Turborepo.
Additionally, check your package.json to ensure proper module configuration. If you’re using ES modules, include:
{
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts"
},
"dependencies": {
"tsx": "^3.12.7"
}
}
According to the Bobbyhadz technical guide, removing “type”: “module” from package.json if you don’t need ES modules can also resolve the issue, as it allows Node.js to default to CommonJS, which works better with ts-node in many cases.
Solution 3: Proper Apollo Server Build Setup
When working with Apollo GraphQL Server in a Turborepo monorepo, the build process is crucial for avoiding the “Unknown file extension .ts” error. The key is to ensure your server package is properly compiled and that the compiled output is what actually gets executed.
First, create a proper build script in your Apollo GraphQL Server package:
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts"
}
}
Then, configure your Turborepo pipeline to ensure the build happens before any execution. In your turbo.json:
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"start": {
"dependsOn": ["build"]
}
}
}
The Turborepo documentation recommends using the “Compiled” strategy for GraphQL servers, which means your server should run on plain JavaScript after compilation. Make sure your exports field in package.json points to the compiled outputs:
{
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.js"
}
}
}
If you’re still encountering the ERR_UNKNOWN_FILE_EXTENSION error, double-check that your server is actually using the compiled JavaScript files rather than the TypeScript source files. The Turborepo TypeScript guide emphasizes that this error often occurs when the compiled bundle still contains import statements pointing to .ts files.
Solution 4: Prisma Integration in Turborepo
Integrating Prisma with Apollo GraphQL Server in a Turborepo monorepo adds another layer of complexity to the “Unknown file extension .ts” error. Prisma has specific requirements for how it handles TypeScript files in monorepo environments.
First, set up Prisma as a shared package in your Turborepo. Create a packages/database package and initialize Prisma there:
npx prisma init
Then, in your Apollo GraphQL Server package, reference the Prisma client from the database package:
import { PrismaClient } from '@my-org/database'
const prisma = new PrismaClient()
The crucial step is to configure Prisma to work with TypeScript files. In your prisma/schema.prisma, add the following:
generator client {
provider = "prisma-client-js"
output = "../packages/database/src/generated/client"
}
For seeding and migration scripts, use ts-node to execute TypeScript files. In your database package’s package.json:
{
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
As the official Prisma documentation for Turborepo explains, the database package holds Prisma while apps consume it. Custom client output keeps types in a shared location, and a global client instance avoids multiple connections in development.
When running Prisma commands, make sure to use TypeScript-aware execution:
npx prisma db generate --preview-feature
The Prisma GitHub discussion specifically addresses this issue, noting that Prisma just runs the command you give it, so you must supply a loader like tsx or ts-node --esm when working with TypeScript files in a monorepo.
Best Practices for Turborepo Monorepos
To avoid the “Unknown file extension .ts” error and ensure smooth operation of your Apollo GraphQL Server with Prisma in a Turborepo monorepo, follow these best practices:
-
Consistent TypeScript Configuration: Maintain consistent TypeScript settings across all packages in your monorepo while allowing package-specific overrides where needed.
-
Proper Build Pipeline: Ensure your Turborepo pipeline correctly builds dependencies before dependent packages. Use the
dependsOnproperty in turbo.json to establish build order. -
Use tsx for Development: For development workflows, use tsx instead of manually specifying ts-node flags. tsx simplifies TypeScript execution by handling the loader configuration automatically.
-
Isolate Prisma Database Package: Keep Prisma in its own dedicated package and have other packages reference it. This prevents multiple Prisma clients and simplifies configuration.
-
Global TypeScript Setup: Consider setting up global TypeScript configuration in your Turborepo root to avoid duplication while allowing package-specific customization.
-
Module Resolution: Pay special attention to module resolution in your monorepo. Use Turborepo’s workspace protocol (
@my-org/package) for internal package references. -
Error Handling: Implement proper error handling in your Apollo GraphQL Server to catch and report any TypeScript-related issues that might occur at runtime.
-
Testing Strategy: Develop a comprehensive testing strategy that accounts for your monorepo structure, ensuring that both individual packages and integrated workflows work correctly.
Troubleshooting Common Issues
Even after implementing the solutions above, you might encounter additional issues when running Apollo GraphQL Server with Prisma in Turborepo. Here are some common problems and their fixes:
- Module Not Found Errors: If you’re seeing “Module not found” errors despite having the correct dependencies, check your Turborepo workspace configuration in package.json:
{
"workspaces": [
"packages/*"
]
}
-
Prisma Client Generation Issues: If Prisma client generation fails with TypeScript-related errors, ensure your output path is correct and that your tsconfig.json includes the generated client directory.
-
Build Order Problems: If your build is failing due to dependency issues, verify the
dependsOnconfiguration in your turbo.json and ensure you’re using the correct Turborepo commands. -
ESM/CommonJS Mixing: If you’re mixing ESM and CommonJS modules, you might encounter additional errors. Consider standardizing on one module system across your monorepo or using proper interoperability settings.
-
Node Version Compatibility: Ensure all packages in your monorepo are using compatible Node versions. The Apollo Server documentation recommends Node.js v20.0.0+ for optimal compatibility.
-
Type Resolution Errors: If TypeScript is having trouble resolving types, check your typeRoots and paths in tsconfig.json, and ensure all necessary @types packages are installed.
Remember that the “Unknown file extension .ts” error often has multiple potential causes, so a systematic approach to troubleshooting is essential. Start by verifying your TypeScript configuration, then check your build process, and finally examine your execution environment.
Conclusion
Resolving the “Unknown file extension .ts” error in Apollo GraphQL Server with Prisma in a Turborepo monorepo requires a systematic approach to TypeScript configuration, build processes, and execution environment setup. The key is understanding that this error occurs when Node.js cannot properly handle TypeScript files, either because they’re not fully compiled or because the execution environment lacks the necessary loaders.
By implementing the solutions outlined in this guide—using ts-node with the ESM flag, configuring TypeScript properly for your Turborepo environment, setting up a proper Apollo Server build process, and integrating Prisma correctly—you can eliminate this error and create a robust, maintainable monorepo structure. Remember to follow the best practices for Turborepo monorepos and be prepared to troubleshoot common issues that may arise during setup.
The official Prisma documentation, Turborepo guides, and community resources like the Prisma GitHub discussions provide additional insights and solutions for working with TypeScript in complex monorepo environments. With proper configuration and attention to detail, you can create a seamless development experience for your Apollo GraphQL Server with Prisma in Turborepo.
Sources
- Prisma Documentation - Turborepo
- GitHub Discussion - Prisma db seed throws ERR_UNKNOWN_FILE_EXTENSION
- Bobbyhadz - Unknown file extension “.ts” error in ts-node [Solved]
- Turborepo Documentation - TypeScript
- Apollo Documentation - Get Started with Apollo Server
- Turborepo Documentation - Internal Packages