Skip to content

Commit a51fd3f

Browse files
AlpAlp
authored andcommitted
perf: replace multiple tsImport() calls with a shared tsx register
tsImport() from tsx/esm/api creates a new module.register() and MessageChannel per invocation. The CLI calls it up to 3 times. By creating a single register({namespace}) instance and reusing its .import() method, we eliminate redundant hook registrations. Micro-benchmark shows ~90ms savings per additional tsImport call (96ms for 2x tsImport vs 3ms for shared register + 2x import). * Add src/cli/ts-import.ts with lazy shared register singleton * Replace tsImport() in config.ts (1 call) and drizzle-kit.ts (2 calls)
1 parent aa835a4 commit a51fd3f

File tree

4 files changed

+34
-11
lines changed

4 files changed

+34
-11
lines changed

src/cli/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import * as fs from 'node:fs/promises';
22
import * as path from 'node:path';
33
import * as url from 'node:url';
44
import type {Project} from 'ts-morph';
5-
import {tsImport} from 'tsx/esm/api';
65
import type {DrizzleToZeroSchema} from '../relations';
6+
import {tsImportShared} from './ts-import';
77

88
export const defaultConfigFilePath = 'drizzle-zero.config.ts';
99

@@ -40,7 +40,7 @@ export const getConfigFromFile = async ({
4040

4141
try {
4242
const zeroConfigFilePathUrl = url.pathToFileURL(fullConfigPath).href;
43-
const zeroConfigImport = await tsImport(
43+
const zeroConfigImport = await tsImportShared(
4444
zeroConfigFilePathUrl,
4545
import.meta.url,
4646
);

src/cli/drizzle-kit.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import * as fs from 'node:fs/promises';
33
import * as path from 'node:path';
44
import * as url from 'node:url';
55
import type {Project} from 'ts-morph';
6-
import {tsImport} from 'tsx/esm/api';
76
import {drizzleZeroConfig, type DrizzleToZeroSchema} from '../relations';
7+
import {tsImportShared} from './ts-import';
88
import {ensureSourceFileInProject} from './ts-project';
99

1010
export const getDefaultConfig = async ({
@@ -30,7 +30,7 @@ export const getDefaultConfig = async ({
3030
resolvedDrizzleSchemaPath,
3131
).href;
3232

33-
const drizzleSchema = await tsImport(
33+
const drizzleSchema = await tsImportShared(
3434
resolvedDrizzleSchemaPathUrl,
3535
import.meta.url,
3636
);
@@ -92,7 +92,7 @@ export const getFullDrizzleSchemaFilePath = async ({
9292
await fs.access(fullPath);
9393

9494
const drizzleKitConfigFilePathUrl = url.pathToFileURL(fullPath).href;
95-
const drizzleKitConfigImport = await tsImport(
95+
const drizzleKitConfigImport = await tsImportShared(
9696
drizzleKitConfigFilePathUrl,
9797
import.meta.url,
9898
);

src/cli/ts-import.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {register} from 'tsx/esm/api';
2+
3+
type TsxRegister = ReturnType<typeof register> & {
4+
import: (specifier: string, parentURL: string) => Promise<any>;
5+
};
6+
7+
let tsxRegister: TsxRegister | undefined;
8+
9+
/**
10+
* Import a TypeScript module using a shared tsx register instance.
11+
* Lazily creates a single tsx register on first call, then reuses it
12+
* for all subsequent imports. This avoids the overhead of creating a
13+
* new module register per call (which is what `tsImport()` does internally).
14+
*/
15+
export const tsImportShared = (
16+
specifier: string,
17+
parentURL: string,
18+
): Promise<any> => {
19+
tsxRegister ??= register({namespace: 'drizzle-zero'}) as TsxRegister;
20+
return tsxRegister.import(specifier, parentURL);
21+
};

tests/cli.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,13 +1610,15 @@ describe('drizzle-kit functions', () => {
16101610

16111611
try {
16121612
// Setup mocks before importing the function
1613+
const mockImport = vi.fn().mockImplementation(path => {
1614+
if (path.includes('temp-drizzle-schema.ts')) {
1615+
return {users: {}};
1616+
}
1617+
return {};
1618+
});
16131619
vi.doMock('tsx/esm/api', () => ({
1614-
tsImport: vi.fn().mockImplementation(path => {
1615-
if (path.includes('temp-drizzle-schema.ts')) {
1616-
return {users: {}};
1617-
}
1618-
return {};
1619-
}),
1620+
tsImport: mockImport,
1621+
register: vi.fn().mockReturnValue({import: mockImport}),
16201622
}));
16211623

16221624
vi.doMock('../src/relations', () => ({

0 commit comments

Comments
 (0)