Last active
August 3, 2023 19:29
-
-
Save marklawlor/b1c26eefba43539c6611a508e67ee02f to your computer and use it in GitHub Desktop.
Prisma/Kysely database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable @typescript-eslint/ban-types */ | |
/* eslint-disable @typescript-eslint/no-explicit-any */ | |
import type { Prisma, PrismaClient, PrismaPromise } from "@prisma/client"; | |
import type { CamelCase, Merge, SnakeCase, PascalCase } from "type-fest"; | |
import { | |
ColumnType, | |
DummyDriver, | |
Generated, | |
Kysely, | |
MysqlAdapter, | |
MysqlIntrospector, | |
MysqlQueryCompiler, | |
} from "kysely"; | |
type KyselyOverrides = { | |
[Model in Prisma.ModelName]?: { | |
[P in keyof Table<Model>]?: ColumnType<any>; | |
}; | |
}; | |
type NamingConvention = "snake_case" | "camelCase" | "PascalCase"; | |
type ChangeCase<Value, T extends NamingConvention> = T extends "PascalCase" | |
? PascalCase<Value> | |
: T extends "camelCase" | |
? CamelCase<Value> | |
: T extends "snake_case" | |
? SnakeCase<Value> | |
: Value; | |
// A deep version of ChangeCaseProperties that respects Prisma scalar types | |
type ChangeCasePropertiesDeep< | |
Value, | |
Convention extends NamingConvention | |
> = Value extends Prisma.Decimal | |
? Value | |
: Value extends Buffer | |
? Value | |
: Value extends Function | Date | RegExp | |
? Value | |
: Value extends Array<infer U> | |
? Array<ChangeCasePropertiesDeep<U, Convention>> | |
: Value extends Set<infer U> | |
? Set<ChangeCasePropertiesDeep<U, Convention>> | |
: { | |
[K in keyof Value as ChangeCase<K, Convention>]: ChangeCasePropertiesDeep< | |
Value[K], | |
Convention | |
>; | |
}; | |
// Hack to get the raw table types. We extract the ReturnType from a "findFirst" query | |
type Table<TableName extends Prisma.ModelName> = ReturnType< | |
PrismaClient[CamelCase<TableName>]["findFirst"] | |
> extends PrismaPromise<infer T> | |
? NonNullable<T> | |
: never; | |
type Database< | |
Overrides extends KyselyOverrides = Record<string, never>, | |
TableConvention extends NamingConvention = "PascalCase", | |
ColumnConvention extends NamingConvention = "camelCase" | |
> = { | |
[P in Prisma.ModelName as ChangeCase< | |
P, | |
TableConvention | |
>]: Overrides extends Record<string, never> | |
? ChangeCasePropertiesDeep<Table<P>, ColumnConvention> | |
: Merge< | |
ChangeCasePropertiesDeep<Table<P>, ColumnConvention>, | |
ChangeCase<Overrides[P], ColumnConvention> | |
>; | |
}; | |
export type MyDatabase = Database< | |
// You can provide object to specify your Generated keys | |
{ | |
User: { id: Generated<number> }; | |
Post: { id: Generated<number> }; | |
}, | |
"snake_case", // Change the case of Table names | |
"snake_case" // Change the case of columns | |
>; | |
/* | |
MyDatabase is typed as: | |
type MyDatabase = { | |
user: { | |
email: string; | |
name: string | null; | |
profile_views: number | null; | |
role: string | null; | |
id: Generated<number>; | |
}; | |
post: { | |
title: string; | |
content: string | null; | |
likes: number | null; | |
published: boolean; | |
author_id: number; | |
id: Generated<...>; | |
}; | |
time_period: { | |
year: number; | |
quarter: number; | |
total: Prisma.Decimal; | |
}; | |
} | |
*/ | |
export const database = new Kysely<MyDatabase>({ | |
dialect: { | |
createAdapter() { | |
return new MysqlAdapter(); | |
}, | |
createDriver() { | |
return new DummyDriver(); | |
}, | |
// eslint-disable-next-line @cspell/spellchecker | |
createIntrospector(database: Kysely<MyDatabase>) { | |
return new MysqlIntrospector(database); | |
}, | |
createQueryCompiler() { | |
return new MysqlQueryCompiler(); | |
}, | |
}, | |
}); | |
// This is correctly typed | |
export const a = await database | |
.selectFrom("user") | |
.innerJoin("post", "post.author_id", "user.id"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is your Prisma schema file, | |
// learn more about it in the docs: https://pris.ly/d/prisma-schema | |
generator client { | |
provider = "prisma-client-js" | |
} | |
datasource db { | |
provider = "mysql" | |
url = env("DATABASE_URL") | |
} | |
model User { | |
id Int @id @default(autoincrement()) | |
email String @unique | |
name String? | |
profileViews Int? | |
role String? | |
posts Post[] | |
@@map("users") | |
} | |
model Post { | |
id Int @id @default(autoincrement()) | |
title String | |
content String? | |
likes Int? | |
published Boolean @default(false) | |
author User @relation(fields: [authorId], references: [id]) | |
authorId Int @map("author_id") | |
@@map("posts") | |
} | |
model TimePeriod { | |
year Int | |
quarter Int | |
total Decimal | |
@@id([year, quarter]) | |
@@unique(fields: [year, quarter], name: "timePeriodId") | |
} |
@essarn I think this approach was always a bit of a hack. I think a better method is used here https://github.com/lawrencecchen/prisma-generator-kysely
@marklawlor Used this instead https://github.com/RobinBlomberg/kysely-codegen but will also check out that one. Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi there 👋
It's not possible to import
PrismaPromise
anymore from@prisma/client
using the latest version.