From 0add3c71a1eb6475ce0729dc721fe4a78dbc0451 Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 20:07:40 +0700 Subject: [PATCH 1/9] Add more resolution --- packages/generator/src/generator.ts | 2 ++ .../generator/src/shared/generatorContext.ts | 33 ++++++++++++++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/generator/src/generator.ts b/packages/generator/src/generator.ts index 28f51fb..3a954a6 100644 --- a/packages/generator/src/generator.ts +++ b/packages/generator/src/generator.ts @@ -27,6 +27,7 @@ import { getEnumModuleName } from './lib/prisma-helpers/enums' import { isRelationField } from './lib/prisma-helpers/field' import { ImportValue, namedImport, NamedImport } from './lib/syntaxes/imports' import { createModule, Module } from './lib/syntaxes/module' +import { setGeneratorContext } from './shared/generatorContext' const { version } = require('../package.json') @@ -39,6 +40,7 @@ generatorHandler({ } }, onGenerate: async (options: GeneratorOptions) => { + setGeneratorContext(options) logger.applyConfig(options) logger.log('Generating drizzle schema...') diff --git a/packages/generator/src/shared/generatorContext.ts b/packages/generator/src/shared/generatorContext.ts index 901c8b8..1440f54 100644 --- a/packages/generator/src/shared/generatorContext.ts +++ b/packages/generator/src/shared/generatorContext.ts @@ -1,5 +1,6 @@ import path from 'path' import fs from 'fs' +import { GeneratorOptions } from '@prisma/generator-helper' type GeneratorContext = { moduleResolution: string @@ -7,17 +8,22 @@ type GeneratorContext = { let generatorContext_: GeneratorContext | undefined +export function setGeneratorContext(options: GeneratorOptions) { + generatorContext_ = { + moduleResolution: resolveModuleResolution(options), + } +} + export function getGeneratorContext() { if (generatorContext_ == null) { - generatorContext_ = { - moduleResolution: resolveModuleResolution(), - } + throw new Error('Generator context not set') } + return generatorContext_ } -function resolveModuleResolution() { - const tsConfig = readTsConfig() +function resolveModuleResolution(options: GeneratorOptions) { + const tsConfig = readTsConfig(options) const moduleResolution = tsConfig?.compilerOptions?.moduleResolution if (moduleResolution == null) { throw new Error('Could not resolve module resolution') @@ -25,9 +31,20 @@ function resolveModuleResolution() { return moduleResolution } -function readTsConfig() { - const tsConfigPath = path.join(process.cwd(), 'tsconfig.json') - if (!fs.existsSync(tsConfigPath)) return +function readTsConfig(options: GeneratorOptions) { + let tsConfigPath = path.join(process.cwd(), 'tsconfig.json') + + if (!fs.existsSync(tsConfigPath)) { + let resolutionPath = options.generator.output?.value + if (!resolutionPath) return + + while (!fs.existsSync(tsConfigPath)) { + if (resolutionPath === '/') return + resolutionPath = path.join(resolutionPath, '..') + } + + tsConfigPath = path.join(resolutionPath, 'tsconfig.json') + } const tsConfig = JSON.parse(fs.readFileSync(tsConfigPath, 'utf-8')) return tsConfig From 2b8fa4d14c6217f1847e5b98263d4aa9639b1f48 Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 20:08:15 +0700 Subject: [PATCH 2/9] Move generator context call --- packages/generator/src/lib/syntaxes/imports.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/generator/src/lib/syntaxes/imports.ts b/packages/generator/src/lib/syntaxes/imports.ts index f68ea2d..c748ba0 100644 --- a/packages/generator/src/lib/syntaxes/imports.ts +++ b/packages/generator/src/lib/syntaxes/imports.ts @@ -38,14 +38,13 @@ export type ImportValue = | ReturnType | ReturnType -const isNodeNext = - getGeneratorContext().moduleResolution.toLowerCase() !== 'nodenext' - /** * Adds the .js extension to relative imports. */ function renderImportPath(path: string) { - if (isNodeNext) return path + if (getGeneratorContext().moduleResolution.toLowerCase() !== 'nodenext') { + return path + } return path.startsWith('.') ? `${path}.js` : path } From c4fa5e69b26a83e23c6acc6c22dd81cffbf9416a Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 20:17:10 +0700 Subject: [PATCH 3/9] Use dynamic import for adapter --- packages/generator/src/generator.ts | 45 ++++++++++++++++------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/packages/generator/src/generator.ts b/packages/generator/src/generator.ts index 3a954a6..de98497 100644 --- a/packages/generator/src/generator.ts +++ b/packages/generator/src/generator.ts @@ -17,9 +17,6 @@ import { createModelModule, ModelModule, } from './lib/adapter/modules/createModelModule' -import { mysqlAdapter } from './lib/adapter/providers/mysql' -import { postgresAdapter } from './lib/adapter/providers/postgres' -import { sqliteAdapter } from './lib/adapter/providers/sqlite' import { isRelationalQueryEnabled } from './lib/config' import { Context } from './lib/context' import { logger } from './lib/logger' @@ -50,7 +47,7 @@ generatorHandler({ if (options.datasources.length > 1) throw new Error('Only one datasource is supported') - const adapter = getAdapter(options) + const adapter = await getAdapter(options) const ctx: Context = { adapter, config: options.generator.config, @@ -191,23 +188,31 @@ function writeModule(basePath: string, module: Module) { fs.writeFileSync(writeLocation, module.code) } -function getAdapter(options: GeneratorOptions) { - return (() => { - switch (options.datasources[0].provider) { - case 'cockroachdb': // CockroahDB should be postgres compatible - case 'postgres': - case 'postgresql': - return postgresAdapter - case 'mysql': - return mysqlAdapter - case 'sqlite': - return sqliteAdapter - default: - throw new Error( - `Connector ${options.datasources[0].provider} is not supported` - ) +/** + * @dev Importing the adapter dynamically so `getGeneratorContext()` won't + * be called before initialization (`onGenerate`) + */ +async function getAdapter(options: GeneratorOptions) { + switch (options.datasources[0].provider) { + case 'cockroachdb': // CockroahDB should be postgres compatible + case 'postgres': + case 'postgresql': { + const mod = await import('./lib/adapter/providers/postgres') + return mod.postgresAdapter } - })() + case 'mysql': { + const mod = await import('./lib/adapter/providers/mysql') + return mod.mysqlAdapter + } + case 'sqlite': { + const mod = await import('./lib/adapter/providers/sqlite') + return mod.sqliteAdapter + } + default: + throw new Error( + `Connector ${options.datasources[0].provider} is not supported` + ) + } } function deduplicateModels(accum: DMMF.Model[], model: DMMF.Model) { From 6e4166752638a8d7a0bb9f7776a87d25a2e0028b Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 20:39:59 +0700 Subject: [PATCH 4/9] Handle no moduleResolution found --- packages/generator/src/lib/syntaxes/imports.ts | 6 +++--- packages/generator/src/shared/generatorContext.ts | 8 ++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/generator/src/lib/syntaxes/imports.ts b/packages/generator/src/lib/syntaxes/imports.ts index c748ba0..5f8e4d8 100644 --- a/packages/generator/src/lib/syntaxes/imports.ts +++ b/packages/generator/src/lib/syntaxes/imports.ts @@ -42,9 +42,9 @@ export type ImportValue = * Adds the .js extension to relative imports. */ function renderImportPath(path: string) { - if (getGeneratorContext().moduleResolution.toLowerCase() !== 'nodenext') { - return path + if (getGeneratorContext().moduleResolution?.toLowerCase() === 'nodenext') { + return path.startsWith('.') ? `${path}.js` : path } - return path.startsWith('.') ? `${path}.js` : path + return path } diff --git a/packages/generator/src/shared/generatorContext.ts b/packages/generator/src/shared/generatorContext.ts index 1440f54..3f283de 100644 --- a/packages/generator/src/shared/generatorContext.ts +++ b/packages/generator/src/shared/generatorContext.ts @@ -3,7 +3,7 @@ import fs from 'fs' import { GeneratorOptions } from '@prisma/generator-helper' type GeneratorContext = { - moduleResolution: string + moduleResolution?: string } let generatorContext_: GeneratorContext | undefined @@ -24,11 +24,7 @@ export function getGeneratorContext() { function resolveModuleResolution(options: GeneratorOptions) { const tsConfig = readTsConfig(options) - const moduleResolution = tsConfig?.compilerOptions?.moduleResolution - if (moduleResolution == null) { - throw new Error('Could not resolve module resolution') - } - return moduleResolution + return tsConfig?.compilerOptions?.moduleResolution } function readTsConfig(options: GeneratorOptions) { From bbf7fedfa2cc7d89bd371dcdef50d750726fda2c Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 20:42:26 +0700 Subject: [PATCH 5/9] Allow overriding through config --- packages/generator/src/lib/config.ts | 6 ++++++ packages/generator/src/shared/generatorContext.ts | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/packages/generator/src/lib/config.ts b/packages/generator/src/lib/config.ts index afe3f34..3fb2e60 100644 --- a/packages/generator/src/lib/config.ts +++ b/packages/generator/src/lib/config.ts @@ -7,3 +7,9 @@ export function isRelationalQueryEnabled(config: Config) { if (value === 'false') return false return true } + +export function getModuleResolution(config: Config) { + if ('moduleResolution' in config) { + return config.moduleResolution + } +} diff --git a/packages/generator/src/shared/generatorContext.ts b/packages/generator/src/shared/generatorContext.ts index 3f283de..f0fd230 100644 --- a/packages/generator/src/shared/generatorContext.ts +++ b/packages/generator/src/shared/generatorContext.ts @@ -1,6 +1,7 @@ import path from 'path' import fs from 'fs' import { GeneratorOptions } from '@prisma/generator-helper' +import { getModuleResolution } from '~/lib/config' type GeneratorContext = { moduleResolution?: string @@ -23,6 +24,9 @@ export function getGeneratorContext() { } function resolveModuleResolution(options: GeneratorOptions) { + const specified = getModuleResolution(options.generator.config) + if (specified) return specified + const tsConfig = readTsConfig(options) return tsConfig?.compilerOptions?.moduleResolution } From 1ca2302df37c90174c4921c6f836fdb49191d503 Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 20:45:13 +0700 Subject: [PATCH 6/9] Rename --- packages/generator/src/generator.ts | 2 +- packages/generator/src/lib/syntaxes/imports.ts | 2 +- .../src/shared/{generatorContext.ts => generator-context.ts} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/generator/src/shared/{generatorContext.ts => generator-context.ts} (100%) diff --git a/packages/generator/src/generator.ts b/packages/generator/src/generator.ts index de98497..9c5a1ce 100644 --- a/packages/generator/src/generator.ts +++ b/packages/generator/src/generator.ts @@ -24,7 +24,7 @@ import { getEnumModuleName } from './lib/prisma-helpers/enums' import { isRelationField } from './lib/prisma-helpers/field' import { ImportValue, namedImport, NamedImport } from './lib/syntaxes/imports' import { createModule, Module } from './lib/syntaxes/module' -import { setGeneratorContext } from './shared/generatorContext' +import { setGeneratorContext } from './shared/generator-context' const { version } = require('../package.json') diff --git a/packages/generator/src/lib/syntaxes/imports.ts b/packages/generator/src/lib/syntaxes/imports.ts index 5f8e4d8..11e4dcd 100644 --- a/packages/generator/src/lib/syntaxes/imports.ts +++ b/packages/generator/src/lib/syntaxes/imports.ts @@ -1,4 +1,4 @@ -import { getGeneratorContext } from '~/shared/generatorContext' +import { getGeneratorContext } from '~/shared/generator-context' export function namedImport(names: string[], path: string) { return { diff --git a/packages/generator/src/shared/generatorContext.ts b/packages/generator/src/shared/generator-context.ts similarity index 100% rename from packages/generator/src/shared/generatorContext.ts rename to packages/generator/src/shared/generator-context.ts From ea82e0dd82b6e00be699c08d5683926c598991ba Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 21:05:58 +0700 Subject: [PATCH 7/9] Simplify to resolve from cwd --- .../generator/src/shared/generator-context.ts | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/generator/src/shared/generator-context.ts b/packages/generator/src/shared/generator-context.ts index f0fd230..7e083f8 100644 --- a/packages/generator/src/shared/generator-context.ts +++ b/packages/generator/src/shared/generator-context.ts @@ -27,25 +27,19 @@ function resolveModuleResolution(options: GeneratorOptions) { const specified = getModuleResolution(options.generator.config) if (specified) return specified - const tsConfig = readTsConfig(options) + const tsConfigPath = findTsConfig() + if (!tsConfigPath) return + + const tsConfig = JSON.parse(fs.readFileSync(tsConfigPath, 'utf-8')) return tsConfig?.compilerOptions?.moduleResolution } -function readTsConfig(options: GeneratorOptions) { - let tsConfigPath = path.join(process.cwd(), 'tsconfig.json') - - if (!fs.existsSync(tsConfigPath)) { - let resolutionPath = options.generator.output?.value - if (!resolutionPath) return +function findTsConfig() { + let projectDir = process.cwd() + while (projectDir !== '/') { + const tsConfigPath = path.join(projectDir, 'tsconfig.json') + if (fs.existsSync(tsConfigPath)) return tsConfigPath - while (!fs.existsSync(tsConfigPath)) { - if (resolutionPath === '/') return - resolutionPath = path.join(resolutionPath, '..') - } - - tsConfigPath = path.join(resolutionPath, 'tsconfig.json') + projectDir = path.join(projectDir, '..') } - - const tsConfig = JSON.parse(fs.readFileSync(tsConfigPath, 'utf-8')) - return tsConfig } From 80b7549a7f41986a348fe6816833ada251b80b3e Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 21:20:13 +0700 Subject: [PATCH 8/9] Add readme --- README.md | 12 ++++++++++++ packages/generator/README.md | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/README.md b/README.md index ec8ccd1..3376987 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,11 @@ In addition to the Prisma features, you can also generate Drizzle-specific featu | output | Change the output | "./drizzle" | "../models" | | formatter | Run prettier after generation | - | "prettier" | | relationalQuery | Flag to generate relational query | true | false | +| moduleResolution | Specify the [module resolution](https://www.typescriptlang.org/tsconfig#moduleResolution) that will affect the import style | _*auto_ | nodenext | | verbose | Flag to enable verbose logging | - | true | +_* It will find the closest tsconfig from the current working directory. Note that [extends](https://www.typescriptlang.org/tsconfig#extends) is not supported_ + ### Setting up [relational query](https://orm.drizzle.team/docs/rqb) ```ts @@ -187,3 +190,12 @@ export const users = pgTable('User', { ... }) ``` +## Gotchas +### Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. + +By default, the generator will try to find the closest tsconfig from the current working directory to determine the import style, whether to add `.js` or not. + +If the generator still emits the wrong import style, you can explicitly set the `moduleResolution` option in the [generator configuration](#configuration). + +Check also [the discussion](https://github.com/farreldarian/prisma-generator-drizzle/issues/18) + diff --git a/packages/generator/README.md b/packages/generator/README.md index ec8ccd1..3376987 100644 --- a/packages/generator/README.md +++ b/packages/generator/README.md @@ -68,8 +68,11 @@ In addition to the Prisma features, you can also generate Drizzle-specific featu | output | Change the output | "./drizzle" | "../models" | | formatter | Run prettier after generation | - | "prettier" | | relationalQuery | Flag to generate relational query | true | false | +| moduleResolution | Specify the [module resolution](https://www.typescriptlang.org/tsconfig#moduleResolution) that will affect the import style | _*auto_ | nodenext | | verbose | Flag to enable verbose logging | - | true | +_* It will find the closest tsconfig from the current working directory. Note that [extends](https://www.typescriptlang.org/tsconfig#extends) is not supported_ + ### Setting up [relational query](https://orm.drizzle.team/docs/rqb) ```ts @@ -187,3 +190,12 @@ export const users = pgTable('User', { ... }) ``` +## Gotchas +### Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. + +By default, the generator will try to find the closest tsconfig from the current working directory to determine the import style, whether to add `.js` or not. + +If the generator still emits the wrong import style, you can explicitly set the `moduleResolution` option in the [generator configuration](#configuration). + +Check also [the discussion](https://github.com/farreldarian/prisma-generator-drizzle/issues/18) + From 68e3f57d8918edf789486a46a99ec97dc7e6bdec Mon Sep 17 00:00:00 2001 From: farreldarian Date: Sat, 27 Jan 2024 21:22:32 +0700 Subject: [PATCH 9/9] Update --- README.md | 4 ++-- packages/generator/README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3376987..9f78ef3 100644 --- a/README.md +++ b/README.md @@ -193,9 +193,9 @@ export const users = pgTable('User', { ## Gotchas ### Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. -By default, the generator will try to find the closest tsconfig from the current working directory to determine the import style, whether to add `.js` or not. +By default, the generator will try to find the closest tsconfig from the current working directory to determine the import style, whether to add `.js` or not. When there's no config found, it will use the common import (e.g. `import { users } from './users'`). -If the generator still emits the wrong import style, you can explicitly set the `moduleResolution` option in the [generator configuration](#configuration). +You can explicitly set the `moduleResolution` option in the [generator configuration](#configuration). Check also [the discussion](https://github.com/farreldarian/prisma-generator-drizzle/issues/18) diff --git a/packages/generator/README.md b/packages/generator/README.md index 3376987..9f78ef3 100644 --- a/packages/generator/README.md +++ b/packages/generator/README.md @@ -193,9 +193,9 @@ export const users = pgTable('User', { ## Gotchas ### Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. -By default, the generator will try to find the closest tsconfig from the current working directory to determine the import style, whether to add `.js` or not. +By default, the generator will try to find the closest tsconfig from the current working directory to determine the import style, whether to add `.js` or not. When there's no config found, it will use the common import (e.g. `import { users } from './users'`). -If the generator still emits the wrong import style, you can explicitly set the `moduleResolution` option in the [generator configuration](#configuration). +You can explicitly set the `moduleResolution` option in the [generator configuration](#configuration). Check also [the discussion](https://github.com/farreldarian/prisma-generator-drizzle/issues/18)