Prisma + Deno Compatibility: Fixing .js Import Specifiers
Prisma + Deno Compatibility: Fixing .js Import Specifiers
Problem
Prisma’s code generator emits Node-style .js extension imports in every file it
writes to prisma/generated/ and prisma/generated-d1/. For example:
import * as $Class from "./internal/class.js"import * as $Enums from "./enums.js"export * from "./enums.js"In a Node.js / bundler environment these resolve correctly, because the bundler (or
ts-node) transparently maps .js → .ts at the module resolution step. Deno’s
resolver, however, is strict: a specifier must match the actual file on disk. Since
the generated files are .ts files, not .js files, Deno cannot resolve the import
without assistance.
Why --sloppy-imports is not a solution
--sloppy-imports is a Deno escape hatch that relaxes module resolution. It is
intentionally not a stable, production-grade feature. Using it project-wide:
- Masks genuine typos in import paths (a missing file silently resolves to the wrong extension instead of failing at compile time).
- Signals to consumers of the package that strict Deno conventions are not followed.
- Is flagged in
deno checkoutput as a warning.
The correct fix is to make the import specifiers exactly match the files on disk.
Solution: post-process generated files after prisma generate
After prisma generate writes the files, a lightweight post-processing script rewrites
every relative .js specifier to .ts:
from "./foo.js"→from "./foo.ts"export * from "../bar.js"→export * from "../bar.ts"import("./baz.js")→import("./baz.ts")
Only relative specifiers (those starting with ./ or ../) are rewritten. Bare
npm/jsr specifiers such as "@prisma/client/runtime/client" are left untouched.
How scripts/prisma-fix-imports.ts works
The script is located at scripts/prisma-fix-imports.ts and can be run directly or via
deno task:
deno run --allow-read --allow-write scripts/prisma-fix-imports.tsAlgorithm
flowchart TD
A[Start] --> B{prisma/generated exists?}
B -- No --> C[⚠️ Skip with warning]
B -- Yes --> D[Walk .ts files recursively]
D --> E[Read file content]
E --> F{Contains .js relative specifiers?}
F -- No --> G[Skip — no-op]
F -- Yes --> H[Replace .js → .ts via regex]
H --> I[Write file back to disk]
I --> J[Log filename + replacement count]
J --> K{More files?}
G --> K
K -- Yes --> E
K -- No --> L{prisma/generated-d1 exists?}
L -- No --> M[⚠️ Skip with warning]
L -- Yes --> D
M --> N[Print aggregate summary]
N --> O[Exit 0]
Key implementation details
| Detail | Value |
|---|---|
| Target dirs | ./prisma/generated, ./prisma/generated-d1 |
| File filter | .ts files only |
from regex | /(\bfrom\s+['"](?:\.\.?\/[^'"]*))\.js(['"])/g |
| Dynamic import regex | /(\bimport\s*\(\s*['"](?:\.\.?\/[^'"]*))\.js(['"])/g |
| Write-back | Only when at least one replacement was made (avoids mtime churn) |
| Missing dir | Graceful skip with ⚠️ warning — safe to call before prisma generate has ever run |
| Non-zero exit | On any unhandled I/O error, so CI fails loudly |
Idempotency
Running the script a second time with already-fixed files still scans the .ts files but
produces zero replacements and performs no writes. It is safe to run on every db:generate invocation.
Wire-up in deno.json
The script is automatically invoked at the end of both generate tasks:
"db:generate": "deno run -A --env=.envrc npm:prisma generate && deno run --allow-read --allow-write scripts/prisma-fix-imports.ts","db:generate:d1": "deno run -A npm:prisma generate --schema=prisma/schema.d1.prisma && deno run --allow-read --allow-write scripts/prisma-fix-imports.ts",The golden rule
Always use
deno task db:generateordeno task db:generate:d1— never runnpx prisma generateorprisma generatedirectly.
Running Prisma directly without the fixup step will restore the .js specifiers in the
generated files. This will break deno task check:worker and deno task test:worker
with resolution errors like:
error: Module not found "file:///…/prisma/generated/enums.js"Verifying the fix is in effect
After running deno task db:generate (or after the initial commit that applied the fix),
verify with:
# Must pass with zero errors — no --sloppy-imports flagdeno task check:worker
# Also confirm no .js relative specifiers remain in generated filesgrep -r "from.*\.\./.*\.js['\"]" prisma/ --include="*.ts"grep -r "from.*\./.*\.js['\"]" prisma/ --include="*.ts"# Both commands should produce no outputTroubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Module not found "…enums.js" | prisma generate was run without the fix script | Run deno run --allow-read --allow-write scripts/prisma-fix-imports.ts |
check:worker fails after regeneration | Same as above | Always use deno task db:generate |
Script exits non-zero with ❌ Fatal error | Disk permission issue or corrupted generated file | Check file permissions in prisma/generated/ |
Bloqr AI™ — The privacy you didn't know you needed.
© 2026 Bloqr AI™, a trademark of Bloqr Systems™. Created by Bloqr Systems™, founded by Jayson Knight.
Internet Hygiene (n.) — the ongoing practices that keep your digital life clean, private, and safe.
Our product repos live in the BloqrAI org, part of the Bloqr Systems GitHub Enterprise. Product repos are internal-visibility — enterprise membership is required to view them.