Skip to content

Commit b2db036

Browse files
tywenkclaude
andcommitted
refactor: load Prisma client via dynamic import() with path normalization
Ports upstream PR codepunkt#32 (codepunkt#32). createContext becomes async and loads clientPath via await import() with paths normalized so relative and absolute filesystem specifiers resolve against process.cwd() and convert to file:// URLs, while bare specifiers and existing file:// URLs pass through. Fixes Prisma 7 prisma-client generator compatibility. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7c25595 commit b2db036

4 files changed

Lines changed: 35 additions & 9 deletions

File tree

src/context.test.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { resolve } from 'node:path';
2+
import { pathToFileURL } from 'node:url';
13
import { beforeEach, describe, expect, it, vi } from 'vitest';
24
import {
35
type PrismaClient as PrismaClientStub,
@@ -19,9 +21,9 @@ const makeContext = async (
1921
| 'transactionPending'
2022
| 'transactionStarted'
2123
| 'transactionEnded' = 'transactionPending',
22-
): Promise<[ReturnType<typeof createContext>, PrismaClientStub]> => {
23-
const context = createContext({
24-
clientPath: '../test/prisma-client-stub.js',
24+
): Promise<[Awaited<ReturnType<typeof createContext>>, PrismaClientStub]> => {
25+
const context = await createContext({
26+
clientPath: './test/prisma-client-stub.js',
2527
databaseUrl: 'postgres://fake',
2628
log: ['query'],
2729
transactionOptions: { timeout: 123 },
@@ -53,6 +55,24 @@ describe('createContext', () => {
5355
await ctx.teardown();
5456
});
5557

58+
it('accepts an absolute file:// URL as clientPath', async () => {
59+
vi.stubEnv('DATABASE_URL', 'postgres://fake');
60+
const fileUrl = pathToFileURL(resolve('./test/prisma-client-stub.js')).href;
61+
const ctx = await createContext({
62+
clientPath: fileUrl,
63+
databaseUrl: 'postgres://fake',
64+
log: ['query'],
65+
transactionOptions: { timeout: 123 },
66+
});
67+
await ctx.setup();
68+
69+
expect(PrismaPgMock).toHaveBeenCalledWith({
70+
connectionString: 'postgres://fake',
71+
});
72+
73+
await ctx.teardown();
74+
});
75+
5676
it('throws when client is accessed outside of a test transaction', async () => {
5777
const [transactionPendingContext] = await makeContext('transactionPending');
5878
const [transactionEndedContext] = await makeContext('transactionEnded');

src/context.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
import { createRequire } from 'node:module';
1+
import { isAbsolute, resolve } from 'node:path';
2+
import { pathToFileURL } from 'node:url';
23
import { PrismaPg } from '@prisma/adapter-pg';
34
import type {
45
PrismaClientLike,
56
PrismaEnvironmentOptions,
67
} from './dts/index.js';
78

8-
const require = createRequire(import.meta.url);
9+
const resolveModuleSpecifier = (specifier: string): string => {
10+
const isPathLike = specifier.startsWith('.') || isAbsolute(specifier);
11+
return isPathLike ? pathToFileURL(resolve(specifier)).href : specifier;
12+
};
913

1014
/**
1115
* Creates the test context used by the `prisma` Vitest environment.
@@ -14,7 +18,7 @@ const require = createRequire(import.meta.url);
1418
* @returns The test context object used by both the Vitest environment and the
1519
* user's Prisma client mock.
1620
*/
17-
export function createContext(options: PrismaEnvironmentOptions) {
21+
export async function createContext(options: PrismaEnvironmentOptions) {
1822
let savePointCounter = 0;
1923

2024
/**
@@ -31,7 +35,9 @@ export function createContext(options: PrismaEnvironmentOptions) {
3135
*/
3236
let internalEndTestTransaction: (() => void) | null = null;
3337

34-
const { PrismaClient } = require(options.clientPath);
38+
const { PrismaClient } = await import(
39+
resolveModuleSpecifier(options.clientPath)
40+
);
3541
const originalClient: PrismaClientLike = new PrismaClient({
3642
adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL }),
3743
log: options.log,

src/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import environment from '../src/index.js';
2424
describe('prisma environment', () => {
2525
const global: any = {};
2626
const options = {
27-
clientPath: '../test/prisma-client-stub.js',
27+
clientPath: './test/prisma-client-stub.js',
2828
};
2929

3030
beforeEach(() => {

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const environment: Environment = {
1616
throw new Error('no DATABASE_URL defined!');
1717
}
1818

19-
const ctx = createContext(options);
19+
const ctx = await createContext(options);
2020
await ctx.setup();
2121

2222
// make context available globally for setupFiles.

0 commit comments

Comments
 (0)