fix: use dynamic import() to load Prisma client (fixes #22)#32
fix: use dynamic import() to load Prisma client (fixes #22)#32tywenk wants to merge 2 commits intocodepunkt:mainfrom
Conversation
The previous implementation used createRequire(import.meta.url) to synchronously require() the Prisma client at options.clientPath. This is incompatible with Prisma 7's `prisma-client` generator, which outputs plain TypeScript (ESM) files that cannot be loaded by Node's native CJS require(). Switch to await import(options.clientPath) so that: - Under Vitest, clientPath can point at the generated TS source directly (e.g. a file:// URL to `client.ts`), and Vite's transform pipeline handles the TypeScript/ESM resolution. - Under plain Node, any ESM-compatible specifier continues to work (package names, file:// URLs, .js/.mjs paths). `createContext` becomes async; callers must `await` it. The only caller is `environment.setup`, which is already async. Fixes codepunkt#22
|
Note
|
| Cohort / File(s) | Summary |
|---|---|
Context loading (async ESM import) src/context.ts |
Replaced CommonJS createRequire(...).require(clientPath) with await import(clientImportPath); normalize relative/absolute paths to file:// URLs; createContext is now async. |
Initialization flow src/index.ts |
Now awaits createContext(options) during environment setup so setup/teardown use the asynchronously created context. |
Tests / helpers updated for async context & clientPath forms src/contest.test.ts, src/index.test.ts |
makeContext updated to await createContext(...) and return appropriate Promise typed tuple; tests switched clientPath from ../test/prisma-client-stub.js to ./test/prisma-client-stub.js and added a case using an absolute file:// URL to verify import and full setup/teardown. |
Sequence Diagram(s)
sequenceDiagram
participant Test as Test Runner
participant Env as Environment (index)
participant Context as createContext
participant Client as Prisma Client (module)
participant Mock as PrismaPgMock
Test->>Env: environment.setup(options with clientPath)
Env->>Context: await createContext(options)
Context->>Client: import(clientImportPath)
Client-->>Context: PrismaClient class/module
Context->>Mock: instantiate/initialize with connectionString
Context-->>Env: context (with setup/teardown)
Env-->>Test: setup complete
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
🐰 I hopped from require to import with glee,
No more stuck on.tsfor me,
file:// paths and async cheer,
Context comes ready — setup’s near! 🥕
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Linked Issues check | ✅ Passed | The PR successfully addresses all coding requirements from issue #22: replacing createRequire()/require() with dynamic import(), adding path normalization for file:// URLs, making createContext async, and including a test case for file:// URL paths. |
| Out of Scope Changes check | ✅ Passed | All changes are directly related to issue #22 requirements: converting to dynamic import, normalizing paths, making createContext async, updating callers, and adding test coverage for file:// URLs. |
| Docstring Coverage | ✅ Passed | Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. |
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title directly addresses the primary change: replacing synchronous CommonJS require() with dynamic ESM import() for loading the Prisma client, which is the core fix for issue #22. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/contest.test.ts (1)
23-24: Add a regression test case forfile://client paths to ensure Prisma 7/Vite compatibility.The current test only covers a relative path. Adding a small test using
pathToFileURL(...).hrefwould verify that absolute file URLs work correctly asclientPathvalues.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/contest.test.ts` around lines 23 - 24, Add a regression test that passes an absolute file:// URL as clientPath to createContext to cover Prisma 7/Vite compatibility; specifically, in the test file where createContext is invoked with clientPath '../test/prisma-client-stub.js', add a new test that constructs a file URL via pathToFileURL(somePath).href and supplies that string as clientPath, then assert the same behaviors as the relative-path case so both relative and file:// absolute clientPath values are validated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/context.ts`:
- Line 31: The dynamic import using options.clientPath should first convert
relative ("./" or "../") and absolute filesystem paths to file:// URLs so they
resolve from the consuming project's CWD instead of src/context.ts; leave bare
module specifiers (like "@prisma/client") and existing file:// URLs unchanged.
Update the import site where you do const { PrismaClient } = await
import(options.clientPath); to: detect if options.clientPath starts with
"file://" or is a bare specifier (no path separators), otherwise resolve with
path.resolve(process.cwd(), options.clientPath) and convert to a URL via
url.pathToFileURL(...).href, then call import(resolvedPath). Ensure path and url
utilities are imported/available in the module.
---
Nitpick comments:
In `@src/contest.test.ts`:
- Around line 23-24: Add a regression test that passes an absolute file:// URL
as clientPath to createContext to cover Prisma 7/Vite compatibility;
specifically, in the test file where createContext is invoked with clientPath
'../test/prisma-client-stub.js', add a new test that constructs a file URL via
pathToFileURL(somePath).href and supplies that string as clientPath, then assert
the same behaviors as the relative-path case so both relative and file://
absolute clientPath values are validated.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d70f8669-ff17-41d4-9fdd-5af4c6df5fc7
📒 Files selected for processing (3)
src/contest.test.tssrc/context.tssrc/index.ts
Normalize relative and absolute filesystem clientPath values to file:// URLs before dynamic import so they resolve from the project root instead of this module's install location. Bare specifiers and existing file:// URLs pass through unchanged. Adds a regression test covering the file:// URL path used by the Prisma 7 setup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes #22.
Problem
The current implementation uses
createRequire(import.meta.url)to synchronouslyrequire()the Prisma client atoptions.clientPath:This is incompatible with Prisma 7's
prisma-clientgenerator, which outputs plain TypeScript (ESM) files that Node's native CJSrequire()cannot load. Under Vitest, those TS files are transformed by Vite — but the plugin'screateRequire-basedrequire()bypasses Vite's loader entirely, so resolution fails with eitherCannot find module(when pointed at an extensionless path) orERR_MODULE_NOT_FOUNDon transitive imports (when pointed at the.tsfile).Fix
Switch to
await import(options.clientPath):clientPathpointed at the generatedclient.ts(orclient.js) is handled by Vite's transform pipeline, which resolves TypeScript/ESM transparently.@prisma/client),file://URLs, or.js/.mjspaths.Before dispatching the dynamic import,
clientPathis normalized so that relative (./foo,../foo) and absolute filesystem paths are resolved against the consuming project'sprocess.cwd()and converted tofile://URLs. Bare module specifiers and pre-builtfile://URLs pass through unchanged. This means users can pass a natural project-relative path —clientPath: "./src/generated/prisma/client.ts"— without manually constructing afile://URL, and absolute paths work correctly on Windows (where ESMimport()otherwise rejects bare drive paths).createContextbecomesasync; the only caller (environment.setupinsrc/index.ts) is already async and just needs anawait.Tested
Unit tests (11 tests across
src/contest.test.tsandsrc/index.test.ts) all pass with 100% coverage preserved. Added a regression test that passes an absolutefile://URL asclientPathto cover the Prisma 7 path and the non-path-like branch of the resolver.Verified end-to-end against Prisma 7's
prisma-clientgenerator in a downstream project: 792 integration tests pass. With the new normalization, the config can be as simple as:A manually constructed
file://URL viapathToFileURL(path.resolve(...))still works too.Breaking change?
Technically yes —
createContextnow returns aPromise. No public users ofcreateContextdirectly are documented in the README; consumers interact only through the Vitest environment, which is updated here. Happy to add a note to CHANGELOG if desired.Summary by CodeRabbit