mirror of
https://github.com/theoludwig/kysely-typegen.git
synced 2026-10-16 19:16:47 +02:00
Compare commits
5
Commits
b3c01aee90
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d826ffe978
|
||
|
|
6e1dafbfce
|
||
|
|
ff16be6787
|
||
|
|
3849b14615
|
||
|
|
f956a31c92
|
No files matched your search
@@ -15,18 +15,25 @@ jobs:
|
||||
TZ: "Europe/Paris"
|
||||
DO_NOT_TRACK: "1"
|
||||
steps:
|
||||
- uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" # v6.0.2
|
||||
- uses: "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1" # v7.0.1
|
||||
|
||||
- name: "Setup Node.js"
|
||||
uses: "actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e" # v6.4.0
|
||||
uses: "actions/setup-node@820762786026740c76f36085b0efc47a31fe5020" # v7.0.0
|
||||
with:
|
||||
node-version: "24.15.0"
|
||||
node-version: "24.16.0"
|
||||
cache: "npm"
|
||||
- run: "node --version"
|
||||
|
||||
- name: "Setup Bun"
|
||||
uses: "oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6" # v2.2.0
|
||||
with:
|
||||
bun-version: "1.4.3"
|
||||
- run: "bun --revision"
|
||||
|
||||
- run: "npm clean-install"
|
||||
# - run: "node --run lint:typescript" # already covered by oxlint
|
||||
- run: "node --run lint:oxlint"
|
||||
- run: "node --run lint:oxfmt"
|
||||
- run: "node --run test"
|
||||
- run: "node --run test:bun"
|
||||
- run: "node --run build"
|
||||
@@ -17,15 +17,15 @@ jobs:
|
||||
pull-requests: "write"
|
||||
id-token: "write"
|
||||
steps:
|
||||
- uses: "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" # v6.0.2
|
||||
- uses: "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1" # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Setup Node.js"
|
||||
uses: "actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e" # v6.4.0
|
||||
uses: "actions/setup-node@820762786026740c76f36085b0efc47a31fe5020" # v7.0.0
|
||||
with:
|
||||
node-version: "24.15.0"
|
||||
node-version: "24.16.0"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
package-manager-cache: false
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ node --run lint:oxfmt
|
||||
|
||||
# Tests
|
||||
node --run test
|
||||
node --run test:bun
|
||||
|
||||
# Build
|
||||
node --run build
|
||||
|
||||
@@ -16,7 +16,7 @@ Why `kysely-typegen` if there is already `kysely-codegen`? Comparison:
|
||||
| **Dependencies** | 35 total | 0 (no runtime dependencies) |
|
||||
| **Type** | CLI | Library/Programmatic Usage |
|
||||
| **Code Size/Maintainability** | Heavy | Lightweight/Simple and straightforward (string manipulation instead of complex AST) |
|
||||
| **Database Support** | PostgreSQL, MySQL, SQLite, MSSQL, LibSQL | PostgreSQL, MySQL, SQLite (**can be easily extended to more**) |
|
||||
| **Database Support** | PostgreSQL, MySQL, SQLite, MSSQL, LibSQL | PostgreSQL, PGlite, MySQL, SQLite (**can be easily extended to more**) |
|
||||
|
||||
`kysely-typegen` is a **library** (not a CLI), which means you are in control of where and how to run it, and is designed to be **extensible**, easy to add support for more database dialects.
|
||||
|
||||
@@ -50,7 +50,7 @@ Create your Kysely database instance and export a `databaseTypegen` for the scri
|
||||
|
||||
#### PostgreSQL
|
||||
|
||||
`KyselyTypegenPostgresDialect` works with any Kysely PostgreSQL dialect, including the built-in [`PostgresDialect`](https://kysely.dev/docs/dialects/postgres) (using [`pg`](https://npmx.dev/package/pg)) and [`PostgresJSDialect`](https://npmx.dev/package/kysely-postgres-js) (using [`postgres`](https://npmx.dev/package/postgres)). The example below uses `kysely-postgres-js`.
|
||||
`KyselyTypegenPostgresDialect` works with any Kysely PostgreSQL dialect, including the built-in [`PostgresDialect`](https://kysely.dev/docs/dialects/postgres) (using [`pg`](https://npmx.dev/package/pg)) and [`PostgresJSDialect`](https://npmx.dev/package/kysely-postgres-js) (using [`postgres`](https://npmx.dev/package/postgres) or [`Bun.SQL`](#bunsql)). The example below uses `kysely-postgres-js`.
|
||||
|
||||
```sh
|
||||
npm install kysely-postgres-js postgres
|
||||
@@ -79,6 +79,62 @@ export const database = new Kysely<DB>({ dialect })
|
||||
export const databaseTypegen = new KyselyTypegenPostgresDialect({ database })
|
||||
```
|
||||
|
||||
#### Bun.SQL
|
||||
|
||||
With [Bun](https://bun.com/), pass the built-in [`Bun.SQL`](https://bun.com/docs/runtime/sql) client to `PostgresJSDialect` instead of `postgres`, so no extra driver is required.
|
||||
|
||||
```sh
|
||||
bun add kysely-postgres-js
|
||||
```
|
||||
|
||||
```ts
|
||||
// database.ts
|
||||
import Bun from "bun"
|
||||
import { Kysely } from "kysely"
|
||||
import { PostgresJSDialect } from "kysely-postgres-js"
|
||||
import { KyselyTypegenPostgresDialect } from "kysely-typegen/postgres"
|
||||
|
||||
import type { DB } from "./codegen.ts"
|
||||
|
||||
const dialect = new PostgresJSDialect({
|
||||
postgres: new Bun.SQL({
|
||||
adapter: "postgres",
|
||||
database: process.env["DATABASE_NAME"] ?? "database",
|
||||
hostname: process.env["DATABASE_HOST"] ?? "localhost",
|
||||
username: process.env["DATABASE_USER"] ?? "user",
|
||||
password: process.env["DATABASE_PASSWORD"] ?? "password",
|
||||
port: Number.parseInt(process.env["DATABASE_PORT"] ?? "5432", 10),
|
||||
}),
|
||||
})
|
||||
|
||||
export const database = new Kysely<DB>({ dialect })
|
||||
export const databaseTypegen = new KyselyTypegenPostgresDialect({ database })
|
||||
```
|
||||
|
||||
#### PGlite
|
||||
|
||||
[PGlite](https://pglite.dev/) is PostgreSQL compiled to WebAssembly that runs in-process. Use Kysely's built-in [`PGliteDialect`](https://kysely-org.github.io/kysely-apidoc/classes/PGliteDialect.html) with `KyselyTypegenPostgresDialect`: PGlite is introspected exactly like PostgreSQL. Because `kysely-typegen` is a library, you pass it the `Kysely` instance you already have, so it works with in-process databases like PGlite, including in-memory ones, without a connection string or CLI-specific dialect support.
|
||||
|
||||
```sh
|
||||
npm install @electric-sql/pglite
|
||||
```
|
||||
|
||||
```ts
|
||||
// database.ts
|
||||
import { PGlite } from "@electric-sql/pglite"
|
||||
import { Kysely, PGliteDialect } from "kysely"
|
||||
import { KyselyTypegenPostgresDialect } from "kysely-typegen/postgres"
|
||||
|
||||
import type { DB } from "./codegen.ts"
|
||||
|
||||
const dialect = new PGliteDialect({
|
||||
pglite: new PGlite(process.env["DATABASE_PATH"] ?? "./pgdata"),
|
||||
})
|
||||
|
||||
export const database = new Kysely<DB>({ dialect })
|
||||
export const databaseTypegen = new KyselyTypegenPostgresDialect({ database })
|
||||
```
|
||||
|
||||
#### MySQL
|
||||
|
||||
```sh
|
||||
@@ -155,6 +211,12 @@ Run with Node.js (using `--env-file` to load environment variables, no `dotenv`
|
||||
node --env-file=.env scripts/typegen.ts
|
||||
```
|
||||
|
||||
Or run with Bun (loads `.env` automatically):
|
||||
|
||||
```sh
|
||||
bun scripts/typegen.ts
|
||||
```
|
||||
|
||||
### Using the type definitions
|
||||
|
||||
Import `DB` into `new Kysely<DB>`, and you're done!
|
||||
@@ -168,6 +230,19 @@ const rows = await database.selectFrom("User").selectAll().execute()
|
||||
|
||||
Fully type-safe queries derived from your actual database schema.
|
||||
|
||||
### Column comments
|
||||
|
||||
Column comments (`COMMENT ON COLUMN` in PostgreSQL, `COMMENT '...'` in MySQL) are emitted as JSDoc above the column, so they show up in your editor on hover:
|
||||
|
||||
```ts
|
||||
export interface Users {
|
||||
/** Contact email address. */
|
||||
email: string | null
|
||||
}
|
||||
```
|
||||
|
||||
SQLite has no column comments, so none are generated.
|
||||
|
||||
## Extending to other database dialects
|
||||
|
||||
`kysely-typegen` ships with `KyselyTypegenPostgresDialect`, `KyselyTypegenMySQLDialect`, and `KyselyTypegenSQLiteDialect`, but you can add support for any database by extending the abstract `KyselyTypegenDialect` class.
|
||||
|
||||
Generated
+1550
-1195
File diff suppressed because it is too large.
Load diff
+20
-17
@@ -36,28 +36,31 @@
|
||||
"lint:oxlint": "oxlint .",
|
||||
"lint:oxfmt": "oxfmt . --check",
|
||||
"oxfmt": "oxfmt .",
|
||||
"test": "node --test",
|
||||
"test": "node --test \"src/_test/*.test.ts\"",
|
||||
"test:bun": "bun test src/_test/bun",
|
||||
"build": "tsdown",
|
||||
"release": "semantic-release"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testcontainers/mysql": "12.0.0",
|
||||
"@testcontainers/postgresql": "12.0.0",
|
||||
"@types/better-sqlite3": "7.6.13",
|
||||
"@types/node": "25.9.1",
|
||||
"@types/pg": "8.20.0",
|
||||
"better-sqlite3": "12.10.0",
|
||||
"kysely": "0.29.2",
|
||||
"kysely-postgres-js": "3.0.0",
|
||||
"mysql2": "3.22.3",
|
||||
"oxfmt": "0.51.0",
|
||||
"oxlint": "1.66.0",
|
||||
"oxlint-tsgolint": "0.23.0",
|
||||
"pg": "8.21.0",
|
||||
"@electric-sql/pglite": "0.5.8",
|
||||
"@testcontainers/mysql": "12.2.0",
|
||||
"@testcontainers/postgresql": "12.2.0",
|
||||
"@types/better-sqlite3": "9.6.0",
|
||||
"@types/bun": "1.4.3",
|
||||
"@types/node": "26.6.4",
|
||||
"@types/pg": "8.23.1",
|
||||
"better-sqlite3": "13.0.3",
|
||||
"kysely": "0.29.6",
|
||||
"kysely-postgres-js": "5.0.1",
|
||||
"mysql2": "3.24.5",
|
||||
"oxfmt": "0.71.0",
|
||||
"oxlint": "1.86.0",
|
||||
"oxlint-tsgolint": "7.0.2003",
|
||||
"pg": "8.23.1",
|
||||
"postgres": "3.4.9",
|
||||
"semantic-release": "25.0.3",
|
||||
"tsdown": "0.22.0",
|
||||
"typescript": "6.0.3"
|
||||
"semantic-release": "25.0.9",
|
||||
"tsdown": "0.23.0",
|
||||
"typescript": "7.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"kysely": ">=0.29.0"
|
||||
|
||||
@@ -62,10 +62,16 @@ exports[`typegen MySQL > generate types matching snapshot 1`] = `
|
||||
"}",
|
||||
"",
|
||||
"export interface Orders {",
|
||||
" /**",
|
||||
" * Total amount in cents.",
|
||||
" *",
|
||||
" * Excludes taxes.",
|
||||
" */",
|
||||
" amountCents: number",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" currency: Generated<\\"EUR\\" | \\"GBP\\" | \\"USD\\">",
|
||||
" id: Generated<Int8>",
|
||||
" /** Free text, may contain *\\\\/ characters. */",
|
||||
" note: string | null",
|
||||
" status: Generated<\\"cancelled\\" | \\"paid\\" | \\"pending\\" | \\"shipped\\">",
|
||||
" userId: number",
|
||||
@@ -73,6 +79,7 @@ exports[`typegen MySQL > generate types matching snapshot 1`] = `
|
||||
"",
|
||||
"export interface Users {",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" /** Contact email address. */",
|
||||
" email: string | null",
|
||||
" id: Generated<number>",
|
||||
" isActive: Generated<number>",
|
||||
|
||||
@@ -1,3 +1,121 @@
|
||||
exports[`typegen PGlite > generate types matching snapshot 1`] = `
|
||||
{
|
||||
"lines": [
|
||||
"// This file was automatically generated by \`kysely-typegen\`.",
|
||||
"// Do not edit this file manually.",
|
||||
"",
|
||||
"import type { ColumnType } from \\"kysely\\"",
|
||||
"",
|
||||
"export type Generated<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>",
|
||||
"",
|
||||
"export type Timestamp = ColumnType<Date, Date | string, Date | string>",
|
||||
"",
|
||||
"export type Numeric = ColumnType<string, number | string, number | string>",
|
||||
"",
|
||||
"export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>",
|
||||
"",
|
||||
"export type Json = JsonValue",
|
||||
"",
|
||||
"export type JsonArray = JsonValue[]",
|
||||
"",
|
||||
"export interface JsonObject {",
|
||||
" [x: string]: JsonValue | undefined",
|
||||
"}",
|
||||
"",
|
||||
"export type JsonPrimitive = boolean | number | string | null",
|
||||
"",
|
||||
"export type JsonValue = JsonArray | JsonObject | JsonPrimitive",
|
||||
"",
|
||||
"export type Currency = \\"EUR\\" | \\"GBP\\" | \\"USD\\"",
|
||||
"",
|
||||
"export type OrderStatus = \\"cancelled\\" | \\"paid\\" | \\"pending\\" | \\"shipped\\"",
|
||||
"",
|
||||
"export type UserRole = \\"admin\\" | \\"guest\\" | \\"member\\"",
|
||||
"",
|
||||
"export interface AllTypes {",
|
||||
" colBit: string",
|
||||
" colBool: boolean",
|
||||
" colBoolDefault: Generated<boolean>",
|
||||
" colBoolNullable: boolean | null",
|
||||
" colBox: string",
|
||||
" colBpchar: string",
|
||||
" colBytea: Buffer",
|
||||
" colCidr: string",
|
||||
" colDate: Timestamp",
|
||||
" colFloat4: number",
|
||||
" colFloat8: number",
|
||||
" colInet: string",
|
||||
" colInt2: number",
|
||||
" colInt4: number",
|
||||
" colInt8: Int8",
|
||||
" colJson: Json",
|
||||
" colJsonb: Json",
|
||||
" colJsonbDefault: Generated<Json>",
|
||||
" colLine: string",
|
||||
" colLseg: string",
|
||||
" colMacaddr: string",
|
||||
" colMoney: string",
|
||||
" colNumeric: Numeric",
|
||||
" colOid: number",
|
||||
" colPath: string",
|
||||
" colPoint: unknown",
|
||||
" colPolygon: string",
|
||||
" colText: string",
|
||||
" colTextNullable: string | null",
|
||||
" colTime: string",
|
||||
" colTimestamp: Timestamp",
|
||||
" colTimestampDefault: Generated<Timestamp>",
|
||||
" colTimestamptz: Timestamp",
|
||||
" colTimetz: string",
|
||||
" colTsquery: string",
|
||||
" colTsvector: string",
|
||||
" colUuid: string",
|
||||
" colVarbit: string",
|
||||
" colVarchar: string",
|
||||
" colXml: string",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" id: Generated<string>",
|
||||
" updatedAt: Timestamp | null",
|
||||
"}",
|
||||
"",
|
||||
"export interface Orders {",
|
||||
" /**",
|
||||
" * Total amount in cents.",
|
||||
" *",
|
||||
" * Excludes taxes.",
|
||||
" */",
|
||||
" amountCents: number",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" currency: Generated<Currency>",
|
||||
" id: Generated<Int8>",
|
||||
" /** Free text, may contain *\\\\/ characters. */",
|
||||
" note: string | null",
|
||||
" status: Generated<OrderStatus>",
|
||||
" userId: string",
|
||||
"}",
|
||||
"",
|
||||
"export interface Users {",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" /** Contact email address. */",
|
||||
" email: string | null",
|
||||
" id: Generated<string>",
|
||||
" isActive: Generated<boolean>",
|
||||
" role: Generated<UserRole>",
|
||||
" username: string",
|
||||
"}",
|
||||
"",
|
||||
"export interface DB {",
|
||||
" AllTypes: AllTypes",
|
||||
" Orders: Orders",
|
||||
" Users: Users",
|
||||
"}"
|
||||
],
|
||||
"tablesCount": 3,
|
||||
"enumsCount": 3,
|
||||
"inlineEnumsCount": 0
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`typegen PostgreSQL > generate types matching snapshot (kysely-postgres-js) 1`] = `
|
||||
{
|
||||
"lines": [
|
||||
@@ -79,10 +197,16 @@ exports[`typegen PostgreSQL > generate types matching snapshot (kysely-postgres-
|
||||
"}",
|
||||
"",
|
||||
"export interface Orders {",
|
||||
" /**",
|
||||
" * Total amount in cents.",
|
||||
" *",
|
||||
" * Excludes taxes.",
|
||||
" */",
|
||||
" amountCents: number",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" currency: Generated<Currency>",
|
||||
" id: Generated<Int8>",
|
||||
" /** Free text, may contain *\\\\/ characters. */",
|
||||
" note: string | null",
|
||||
" status: Generated<OrderStatus>",
|
||||
" userId: string",
|
||||
@@ -90,6 +214,7 @@ exports[`typegen PostgreSQL > generate types matching snapshot (kysely-postgres-
|
||||
"",
|
||||
"export interface Users {",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" /** Contact email address. */",
|
||||
" email: string | null",
|
||||
" id: Generated<string>",
|
||||
" isActive: Generated<boolean>",
|
||||
@@ -190,10 +315,16 @@ exports[`typegen PostgreSQL > generate types matching snapshot (pg) 1`] = `
|
||||
"}",
|
||||
"",
|
||||
"export interface Orders {",
|
||||
" /**",
|
||||
" * Total amount in cents.",
|
||||
" *",
|
||||
" * Excludes taxes.",
|
||||
" */",
|
||||
" amountCents: number",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" currency: Generated<Currency>",
|
||||
" id: Generated<Int8>",
|
||||
" /** Free text, may contain *\\\\/ characters. */",
|
||||
" note: string | null",
|
||||
" status: Generated<OrderStatus>",
|
||||
" userId: string",
|
||||
@@ -201,6 +332,7 @@ exports[`typegen PostgreSQL > generate types matching snapshot (pg) 1`] = `
|
||||
"",
|
||||
"export interface Users {",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" /** Contact email address. */",
|
||||
" email: string | null",
|
||||
" id: Generated<string>",
|
||||
" isActive: Generated<boolean>",
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
import type { Kysely } from "kysely"
|
||||
import { sql } from "kysely"
|
||||
|
||||
export const POSTGRES_IMAGE =
|
||||
"docker.io/postgres:18.4@sha256:f7ce845ee6873dd84be93c9828fe0d1fab0f9707dc9ac569694657398b290bce"
|
||||
|
||||
export const createSchema = async (database: Kysely<any>): Promise<void> => {
|
||||
await database.schema.createType("Currency").asEnum(["EUR", "USD", "GBP"]).execute()
|
||||
await database.schema.createType("UserRole").asEnum(["admin", "member", "guest"]).execute()
|
||||
await database.schema
|
||||
.createType("OrderStatus")
|
||||
.asEnum(["pending", "paid", "shipped", "cancelled"])
|
||||
.execute()
|
||||
|
||||
await database.schema
|
||||
.createTable("AllTypes")
|
||||
.addColumn("id", "uuid", (column) => {
|
||||
return column
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.defaultTo(sql`uuidv7()`)
|
||||
})
|
||||
.addColumn("colBool", "boolean", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBoolNullable", "boolean")
|
||||
.addColumn("colBoolDefault", "boolean", (column) => {
|
||||
return column.notNull().defaultTo(false)
|
||||
})
|
||||
.addColumn("colInt2", "smallint", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colInt4", "integer", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colInt8", "bigint", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colFloat4", "real", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colFloat8", "double precision", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colNumeric", sql`numeric(12, 2)`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colMoney", sql`money`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colText", "text", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colVarchar", "varchar(255)", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBpchar", sql`char(10)`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBytea", "bytea", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colDate", "date", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTime", "time", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTimetz", sql`timetz`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTimestamp", "timestamp", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTimestamptz", "timestamptz", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colJson", "json", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colJsonb", "jsonb", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colUuid", "uuid", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colInet", sql`inet`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colCidr", sql`cidr`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colMacaddr", sql`macaddr`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBit", sql`bit(8)`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colVarbit", sql`varbit(16)`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colXml", sql`xml`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTsvector", sql`tsvector`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTsquery", sql`tsquery`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colPoint", sql`point`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colLine", sql`line`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colLseg", sql`lseg`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBox", sql`box`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colPath", sql`path`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colPolygon", sql`polygon`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colOid", sql`oid`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTextNullable", "text")
|
||||
.addColumn("colJsonbDefault", "jsonb", (column) => {
|
||||
return column.notNull().defaultTo(sql`'{}'::jsonb`)
|
||||
})
|
||||
.addColumn("colTimestampDefault", "timestamp", (column) => {
|
||||
return column.notNull().defaultTo(sql`now()`)
|
||||
})
|
||||
.addColumn("createdAt", "timestamptz", (column) => {
|
||||
return column.notNull().defaultTo(sql`now()`)
|
||||
})
|
||||
.addColumn("updatedAt", "timestamptz")
|
||||
.execute()
|
||||
|
||||
await database.schema
|
||||
.createTable("Users")
|
||||
.addColumn("id", "uuid", (column) => {
|
||||
return column
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.defaultTo(sql`uuidv7()`)
|
||||
})
|
||||
.addColumn("username", "varchar(50)", (column) => {
|
||||
return column.notNull().unique()
|
||||
})
|
||||
.addColumn("email", "text")
|
||||
.addColumn("role", sql`"UserRole"`, (column) => {
|
||||
return column.notNull().defaultTo("member")
|
||||
})
|
||||
.addColumn("isActive", "boolean", (column) => {
|
||||
return column.notNull().defaultTo(true)
|
||||
})
|
||||
.addColumn("createdAt", "timestamptz", (column) => {
|
||||
return column.notNull().defaultTo(sql`now()`)
|
||||
})
|
||||
.execute()
|
||||
|
||||
await database.schema
|
||||
.createTable("Orders")
|
||||
.addColumn("id", "bigserial", (column) => {
|
||||
return column.notNull().primaryKey()
|
||||
})
|
||||
.addColumn("userId", "uuid", (column) => {
|
||||
return column.notNull().references("Users.id")
|
||||
})
|
||||
.addColumn("status", sql`"OrderStatus"`, (column) => {
|
||||
return column.notNull().defaultTo("pending")
|
||||
})
|
||||
.addColumn("currency", sql`"Currency"`, (column) => {
|
||||
return column.notNull().defaultTo("EUR")
|
||||
})
|
||||
.addColumn("amountCents", "integer", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("note", "text")
|
||||
.addColumn("createdAt", "timestamptz", (column) => {
|
||||
return column.notNull().defaultTo(sql`now()`)
|
||||
})
|
||||
.execute()
|
||||
|
||||
await sql`comment on column ${sql.ref("Users.email")} is ${sql.lit("Contact email address.")}`.execute(
|
||||
database,
|
||||
)
|
||||
await sql`comment on column ${sql.ref("Orders.amountCents")} is ${sql.lit("Total amount in cents.\n\nExcludes taxes.")}`.execute(
|
||||
database,
|
||||
)
|
||||
await sql`comment on column ${sql.ref("Orders.note")} is ${sql.lit("Free text, may contain */ characters.")}`.execute(
|
||||
database,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
|
||||
|
||||
exports[`typegen PostgreSQL (Bun.SQL) generate types matching snapshot 1`] = `
|
||||
{
|
||||
"enumsCount": 3,
|
||||
"inlineEnumsCount": 0,
|
||||
"lines": [
|
||||
"// This file was automatically generated by \`kysely-typegen\`.",
|
||||
"// Do not edit this file manually.",
|
||||
"",
|
||||
"import type { ColumnType } from "kysely"",
|
||||
"",
|
||||
"export type Generated<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>",
|
||||
"",
|
||||
"export type Timestamp = ColumnType<Date, Date | string, Date | string>",
|
||||
"",
|
||||
"export type Numeric = ColumnType<string, number | string, number | string>",
|
||||
"",
|
||||
"export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>",
|
||||
"",
|
||||
"export type Json = JsonValue",
|
||||
"",
|
||||
"export type JsonArray = JsonValue[]",
|
||||
"",
|
||||
"export interface JsonObject {",
|
||||
" [x: string]: JsonValue | undefined",
|
||||
"}",
|
||||
"",
|
||||
"export type JsonPrimitive = boolean | number | string | null",
|
||||
"",
|
||||
"export type JsonValue = JsonArray | JsonObject | JsonPrimitive",
|
||||
"",
|
||||
"export type Currency = "EUR" | "GBP" | "USD"",
|
||||
"",
|
||||
"export type OrderStatus = "cancelled" | "paid" | "pending" | "shipped"",
|
||||
"",
|
||||
"export type UserRole = "admin" | "guest" | "member"",
|
||||
"",
|
||||
"export interface AllTypes {",
|
||||
" colBit: string",
|
||||
" colBool: boolean",
|
||||
" colBoolDefault: Generated<boolean>",
|
||||
" colBoolNullable: boolean | null",
|
||||
" colBox: string",
|
||||
" colBpchar: string",
|
||||
" colBytea: Buffer",
|
||||
" colCidr: string",
|
||||
" colDate: Timestamp",
|
||||
" colFloat4: number",
|
||||
" colFloat8: number",
|
||||
" colInet: string",
|
||||
" colInt2: number",
|
||||
" colInt4: number",
|
||||
" colInt8: Int8",
|
||||
" colJson: Json",
|
||||
" colJsonb: Json",
|
||||
" colJsonbDefault: Generated<Json>",
|
||||
" colLine: string",
|
||||
" colLseg: string",
|
||||
" colMacaddr: string",
|
||||
" colMoney: string",
|
||||
" colNumeric: Numeric",
|
||||
" colOid: number",
|
||||
" colPath: string",
|
||||
" colPoint: unknown",
|
||||
" colPolygon: string",
|
||||
" colText: string",
|
||||
" colTextNullable: string | null",
|
||||
" colTime: string",
|
||||
" colTimestamp: Timestamp",
|
||||
" colTimestampDefault: Generated<Timestamp>",
|
||||
" colTimestamptz: Timestamp",
|
||||
" colTimetz: string",
|
||||
" colTsquery: string",
|
||||
" colTsvector: string",
|
||||
" colUuid: string",
|
||||
" colVarbit: string",
|
||||
" colVarchar: string",
|
||||
" colXml: string",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" id: Generated<string>",
|
||||
" updatedAt: Timestamp | null",
|
||||
"}",
|
||||
"",
|
||||
"export interface Orders {",
|
||||
" /**",
|
||||
" * Total amount in cents.",
|
||||
" *",
|
||||
" * Excludes taxes.",
|
||||
" */",
|
||||
" amountCents: number",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" currency: Generated<Currency>",
|
||||
" id: Generated<Int8>",
|
||||
" /** Free text, may contain *\\/ characters. */",
|
||||
" note: string | null",
|
||||
" status: Generated<OrderStatus>",
|
||||
" userId: string",
|
||||
"}",
|
||||
"",
|
||||
"export interface Users {",
|
||||
" createdAt: Generated<Timestamp>",
|
||||
" /** Contact email address. */",
|
||||
" email: string | null",
|
||||
" id: Generated<string>",
|
||||
" isActive: Generated<boolean>",
|
||||
" role: Generated<UserRole>",
|
||||
" username: string",
|
||||
"}",
|
||||
"",
|
||||
"export interface DB {",
|
||||
" AllTypes: AllTypes",
|
||||
" Orders: Orders",
|
||||
" Users: Users",
|
||||
"}",
|
||||
],
|
||||
"tablesCount": 3,
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,54 @@
|
||||
import type { StartedPostgreSqlContainer } from "@testcontainers/postgresql"
|
||||
import { PostgreSqlContainer } from "@testcontainers/postgresql"
|
||||
import Bun from "bun"
|
||||
import { afterAll, beforeAll, describe, expect, it } from "bun:test"
|
||||
import { Kysely } from "kysely"
|
||||
import { PostgresJSDialect } from "kysely-postgres-js"
|
||||
|
||||
import { KyselyTypegenPostgresDialect } from "../../postgres.ts"
|
||||
import { createSchema, POSTGRES_IMAGE } from "../_postgres.ts"
|
||||
|
||||
const CONTAINER_START_TIMEOUT_MILLISECONDS = 120_000
|
||||
|
||||
describe("typegen PostgreSQL (Bun.SQL)", () => {
|
||||
let container: StartedPostgreSqlContainer
|
||||
let database: Kysely<any>
|
||||
|
||||
beforeAll(async () => {
|
||||
container = await new PostgreSqlContainer(POSTGRES_IMAGE).start()
|
||||
database = new Kysely<any>({
|
||||
dialect: new PostgresJSDialect({
|
||||
postgres: new Bun.SQL({
|
||||
adapter: "postgres",
|
||||
database: container.getDatabase(),
|
||||
hostname: container.getHost(),
|
||||
port: container.getPort(),
|
||||
username: container.getUsername(),
|
||||
password: container.getPassword(),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
await createSchema(database)
|
||||
}, CONTAINER_START_TIMEOUT_MILLISECONDS)
|
||||
|
||||
afterAll(async () => {
|
||||
await database.destroy()
|
||||
await container.stop()
|
||||
})
|
||||
|
||||
it("generate types matching snapshot", async () => {
|
||||
// Arrange - Given
|
||||
const databaseTypegen = new KyselyTypegenPostgresDialect({ database })
|
||||
|
||||
// Act - When
|
||||
const result = await databaseTypegen.typegen()
|
||||
|
||||
// Assert - Then
|
||||
expect({
|
||||
lines: result.lines,
|
||||
tablesCount: result.tables.length,
|
||||
enumsCount: result.enums.length,
|
||||
inlineEnumsCount: result.inlineEnums.size,
|
||||
}).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
@@ -117,7 +117,9 @@ const createSchema = async (database: Kysely<any>): Promise<void> => {
|
||||
.addColumn("username", "varchar(50)", (column) => {
|
||||
return column.notNull().unique()
|
||||
})
|
||||
.addColumn("email", "text")
|
||||
.addColumn("email", "text", (column) => {
|
||||
return column.modifyEnd(sql`comment ${sql.lit("Contact email address.")}`)
|
||||
})
|
||||
.addColumn("role", sql`enum('admin','member','guest')`, (column) => {
|
||||
return column.notNull().defaultTo("member")
|
||||
})
|
||||
@@ -144,9 +146,13 @@ const createSchema = async (database: Kysely<any>): Promise<void> => {
|
||||
return column.notNull().defaultTo("EUR")
|
||||
})
|
||||
.addColumn("amountCents", "integer", (column) => {
|
||||
return column.notNull()
|
||||
return column
|
||||
.notNull()
|
||||
.modifyEnd(sql`comment ${sql.lit("Total amount in cents.\n\nExcludes taxes.")}`)
|
||||
})
|
||||
.addColumn("note", "text", (column) => {
|
||||
return column.modifyEnd(sql`comment ${sql.lit("Free text, may contain */ characters.")}`)
|
||||
})
|
||||
.addColumn("note", "text")
|
||||
.addColumn("createdAt", "timestamp", (column) => {
|
||||
return column.notNull().defaultTo(sql`current_timestamp`)
|
||||
})
|
||||
|
||||
+36
-189
@@ -1,202 +1,16 @@
|
||||
import { PGlite } from "@electric-sql/pglite"
|
||||
import type { StartedPostgreSqlContainer } from "@testcontainers/postgresql"
|
||||
import { PostgreSqlContainer } from "@testcontainers/postgresql"
|
||||
import { Kysely, PostgresDialect, sql } from "kysely"
|
||||
import { Kysely, PGliteDialect, PostgresDialect } from "kysely"
|
||||
import { PostgresJSDialect } from "kysely-postgres-js"
|
||||
import { after, before, describe, it } from "node:test"
|
||||
import pg from "pg"
|
||||
import postgres from "postgres"
|
||||
|
||||
import { KyselyTypegenPostgresDialect } from "../postgres.ts"
|
||||
import { createSchema, POSTGRES_IMAGE } from "./_postgres.ts"
|
||||
import "./_setup.ts"
|
||||
|
||||
const POSTGRES_IMAGE =
|
||||
"docker.io/postgres:18.4@sha256:f7ce845ee6873dd84be93c9828fe0d1fab0f9707dc9ac569694657398b290bce"
|
||||
|
||||
const createSchema = async (database: Kysely<any>): Promise<void> => {
|
||||
await database.schema.createType("Currency").asEnum(["EUR", "USD", "GBP"]).execute()
|
||||
await database.schema.createType("UserRole").asEnum(["admin", "member", "guest"]).execute()
|
||||
await database.schema
|
||||
.createType("OrderStatus")
|
||||
.asEnum(["pending", "paid", "shipped", "cancelled"])
|
||||
.execute()
|
||||
|
||||
await database.schema
|
||||
.createTable("AllTypes")
|
||||
.addColumn("id", "uuid", (column) => {
|
||||
return column
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.defaultTo(sql`uuidv7()`)
|
||||
})
|
||||
.addColumn("colBool", "boolean", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBoolNullable", "boolean")
|
||||
.addColumn("colBoolDefault", "boolean", (column) => {
|
||||
return column.notNull().defaultTo(false)
|
||||
})
|
||||
.addColumn("colInt2", "smallint", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colInt4", "integer", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colInt8", "bigint", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colFloat4", "real", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colFloat8", "double precision", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colNumeric", sql`numeric(12, 2)`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colMoney", sql`money`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colText", "text", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colVarchar", "varchar(255)", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBpchar", sql`char(10)`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBytea", "bytea", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colDate", "date", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTime", "time", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTimetz", sql`timetz`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTimestamp", "timestamp", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTimestamptz", "timestamptz", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colJson", "json", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colJsonb", "jsonb", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colUuid", "uuid", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colInet", sql`inet`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colCidr", sql`cidr`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colMacaddr", sql`macaddr`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBit", sql`bit(8)`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colVarbit", sql`varbit(16)`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colXml", sql`xml`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTsvector", sql`tsvector`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTsquery", sql`tsquery`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colPoint", sql`point`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colLine", sql`line`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colLseg", sql`lseg`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colBox", sql`box`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colPath", sql`path`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colPolygon", sql`polygon`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colOid", sql`oid`, (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("colTextNullable", "text")
|
||||
.addColumn("colJsonbDefault", "jsonb", (column) => {
|
||||
return column.notNull().defaultTo(sql`'{}'::jsonb`)
|
||||
})
|
||||
.addColumn("colTimestampDefault", "timestamp", (column) => {
|
||||
return column.notNull().defaultTo(sql`now()`)
|
||||
})
|
||||
.addColumn("createdAt", "timestamptz", (column) => {
|
||||
return column.notNull().defaultTo(sql`now()`)
|
||||
})
|
||||
.addColumn("updatedAt", "timestamptz")
|
||||
.execute()
|
||||
|
||||
await database.schema
|
||||
.createTable("Users")
|
||||
.addColumn("id", "uuid", (column) => {
|
||||
return column
|
||||
.notNull()
|
||||
.primaryKey()
|
||||
.defaultTo(sql`uuidv7()`)
|
||||
})
|
||||
.addColumn("username", "varchar(50)", (column) => {
|
||||
return column.notNull().unique()
|
||||
})
|
||||
.addColumn("email", "text")
|
||||
.addColumn("role", sql`"UserRole"`, (column) => {
|
||||
return column.notNull().defaultTo("member")
|
||||
})
|
||||
.addColumn("isActive", "boolean", (column) => {
|
||||
return column.notNull().defaultTo(true)
|
||||
})
|
||||
.addColumn("createdAt", "timestamptz", (column) => {
|
||||
return column.notNull().defaultTo(sql`now()`)
|
||||
})
|
||||
.execute()
|
||||
|
||||
await database.schema
|
||||
.createTable("Orders")
|
||||
.addColumn("id", "bigserial", (column) => {
|
||||
return column.notNull().primaryKey()
|
||||
})
|
||||
.addColumn("userId", "uuid", (column) => {
|
||||
return column.notNull().references("Users.id")
|
||||
})
|
||||
.addColumn("status", sql`"OrderStatus"`, (column) => {
|
||||
return column.notNull().defaultTo("pending")
|
||||
})
|
||||
.addColumn("currency", sql`"Currency"`, (column) => {
|
||||
return column.notNull().defaultTo("EUR")
|
||||
})
|
||||
.addColumn("amountCents", "integer", (column) => {
|
||||
return column.notNull()
|
||||
})
|
||||
.addColumn("note", "text")
|
||||
.addColumn("createdAt", "timestamptz", (column) => {
|
||||
return column.notNull().defaultTo(sql`now()`)
|
||||
})
|
||||
.execute()
|
||||
}
|
||||
|
||||
describe("typegen PostgreSQL", () => {
|
||||
let container: StartedPostgreSqlContainer
|
||||
let database: Kysely<any>
|
||||
@@ -266,3 +80,36 @@ describe("typegen PostgreSQL", () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("typegen PGlite", () => {
|
||||
let database: Kysely<any>
|
||||
|
||||
before(async () => {
|
||||
database = new Kysely<any>({
|
||||
dialect: new PGliteDialect({
|
||||
pglite: new PGlite(),
|
||||
}),
|
||||
})
|
||||
await createSchema(database)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await database.destroy()
|
||||
})
|
||||
|
||||
it("generate types matching snapshot", async (testContext) => {
|
||||
// Arrange - Given
|
||||
const databaseTypegen = new KyselyTypegenPostgresDialect({ database })
|
||||
|
||||
// Act - When
|
||||
const result = await databaseTypegen.typegen()
|
||||
|
||||
// Assert - Then
|
||||
testContext.assert.snapshot({
|
||||
lines: result.lines,
|
||||
tablesCount: result.tables.length,
|
||||
enumsCount: result.enums.length,
|
||||
inlineEnumsCount: result.inlineEnums.size,
|
||||
})
|
||||
})
|
||||
})
|
||||
+31
-8
@@ -73,6 +73,24 @@ export abstract class KyselyTypegenDialect {
|
||||
return scalars[dataType] ?? "unknown"
|
||||
}
|
||||
|
||||
protected formatColumnComment(comment: string): string[] {
|
||||
const trimmedComment = comment.trim()
|
||||
if (trimmedComment.length === 0) {
|
||||
return []
|
||||
}
|
||||
const lines = trimmedComment.replaceAll("*/", "*\\/").split(/\r?\n/u)
|
||||
if (lines.length === 1) {
|
||||
return [` /** ${lines[0]} */`]
|
||||
}
|
||||
return [
|
||||
" /**",
|
||||
...lines.map((line) => {
|
||||
return line.length === 0 ? " *" : ` * ${line}`
|
||||
}),
|
||||
" */",
|
||||
]
|
||||
}
|
||||
|
||||
public getTablesTypegen(
|
||||
tables: TableMetadata[],
|
||||
enums: EnumMetadata[],
|
||||
@@ -94,6 +112,9 @@ export abstract class KyselyTypegenDialect {
|
||||
if (column.hasDefaultValue || column.isAutoIncrementing) {
|
||||
columnType = `Generated<${columnType}>`
|
||||
}
|
||||
if (column.comment != null) {
|
||||
result.push(...this.formatColumnComment(column.comment))
|
||||
}
|
||||
result.push(` ${column.name}: ${columnType}`)
|
||||
}
|
||||
result.push("}", "")
|
||||
@@ -146,14 +167,16 @@ export abstract class KyselyTypegenDialect {
|
||||
tables: TableMetadata[]
|
||||
}> {
|
||||
const [tables, { enums, inlineEnums }] = await Promise.all([this.getTables(), this.getEnums()])
|
||||
const lines: string[] = [...PREAMBLE_LINES]
|
||||
lines.push(...this.getEnumsTypegen(enums))
|
||||
lines.push(...this.getTablesTypegen(tables, enums, inlineEnums))
|
||||
lines.push("export interface DB {")
|
||||
for (const table of tables) {
|
||||
lines.push(` ${table.name}: ${table.name}`)
|
||||
}
|
||||
lines.push("}")
|
||||
const lines: string[] = [
|
||||
...PREAMBLE_LINES,
|
||||
...this.getEnumsTypegen(enums),
|
||||
...this.getTablesTypegen(tables, enums, inlineEnums),
|
||||
"export interface DB {",
|
||||
...tables.map((table) => {
|
||||
return ` ${table.name}: ${table.name}`
|
||||
}),
|
||||
"}",
|
||||
]
|
||||
return { lines, enums, inlineEnums, tables }
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -52,12 +52,12 @@ export class KyselyTypegenMySQLDialect extends KyselyTypegenDialect {
|
||||
])
|
||||
.where("columns.TABLE_SCHEMA", "=", sql`database()`)
|
||||
.where("columns.DATA_TYPE", "in", ["enum", "set"])
|
||||
.$castTo<{ tableName: string; columnName: string; columnType: string }>()
|
||||
.execute()
|
||||
|
||||
const inline = new Map<string, string[]>()
|
||||
for (const row of rows) {
|
||||
const data = row as { tableName: string; columnName: string; columnType: string }
|
||||
inline.set(`${data.tableName}.${data.columnName}`, parseMysqlEnumColumnType(data.columnType))
|
||||
inline.set(`${row.tableName}.${row.columnName}`, parseMysqlEnumColumnType(row.columnType))
|
||||
}
|
||||
return { named: [], inline }
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,6 +29,6 @@
|
||||
"resolveJsonModule": true,
|
||||
|
||||
"lib": ["ESNext"],
|
||||
"types": ["@types/node"]
|
||||
"types": ["@types/node", "@types/bun"]
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user