diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30e6ddf..82cc0e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,9 +24,16 @@ jobs: 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" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8239fa9..0f94f38 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,6 +47,7 @@ node --run lint:oxfmt # Tests node --run test +node --run test:bun # Build node --run build diff --git a/README.md b/README.md index f715360..81dde7a 100644 --- a/README.md +++ b/README.md @@ -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,38 @@ export const database = new Kysely({ 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({ 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. @@ -179,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`, and you're done! diff --git a/package-lock.json b/package-lock.json index 44e0c7f..cdd5496 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@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", @@ -2093,6 +2094,16 @@ "@types/node": "*" } }, + "node_modules/@types/bun": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.4.3.tgz", + "integrity": "sha512-N67Pqy8JXbAY/j0tNraS3V5mubGvc6rrrNDmDCtZLlFzccbUJPDb0tvgUBC5q4m8ybkP93Jcn1QB+RYQ6PvBhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bun-types": "1.4.3" + } + }, "node_modules/@types/docker-modem": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz", @@ -3477,6 +3488,17 @@ "node": ">=10.0.0" } }, + "node_modules/bun-types": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.4.3.tgz", + "integrity": "sha512-tinRJNGOmUN+tEAsn2y2e942n9JHRHR42iUYzDH75NmhJqVBokGSQkkfSFdNWwsANIdrK6ACH9t01M452YyTwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "undici-types": "*" + } + }, "node_modules/byline": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", diff --git a/package.json b/package.json index 05c441a..14355d2 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "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" }, @@ -45,6 +46,7 @@ "@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", diff --git a/src/_test/_postgres.ts b/src/_test/_postgres.ts new file mode 100644 index 0000000..6860bba --- /dev/null +++ b/src/_test/_postgres.ts @@ -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): Promise => { + 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, + ) +} diff --git a/src/_test/bun/__snapshots__/postgres.test.ts.snap b/src/_test/bun/__snapshots__/postgres.test.ts.snap new file mode 100644 index 0000000..df411d0 --- /dev/null +++ b/src/_test/bun/__snapshots__/postgres.test.ts.snap @@ -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 extends ColumnType ? ColumnType : ColumnType", + "", + "export type Timestamp = ColumnType", + "", + "export type Numeric = ColumnType", + "", + "export type Int8 = ColumnType", + "", + "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", + " 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", + " 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", + " colTimestamptz: Timestamp", + " colTimetz: string", + " colTsquery: string", + " colTsvector: string", + " colUuid: string", + " colVarbit: string", + " colVarchar: string", + " colXml: string", + " createdAt: Generated", + " id: Generated", + " updatedAt: Timestamp | null", + "}", + "", + "export interface Orders {", + " /**", + " * Total amount in cents.", + " *", + " * Excludes taxes.", + " */", + " amountCents: number", + " createdAt: Generated", + " currency: Generated", + " id: Generated", + " /** Free text, may contain *\\/ characters. */", + " note: string | null", + " status: Generated", + " userId: string", + "}", + "", + "export interface Users {", + " createdAt: Generated", + " /** Contact email address. */", + " email: string | null", + " id: Generated", + " isActive: Generated", + " role: Generated", + " username: string", + "}", + "", + "export interface DB {", + " AllTypes: AllTypes", + " Orders: Orders", + " Users: Users", + "}", + ], + "tablesCount": 3, +} +`; diff --git a/src/_test/bun/postgres.test.ts b/src/_test/bun/postgres.test.ts new file mode 100644 index 0000000..d386e9e --- /dev/null +++ b/src/_test/bun/postgres.test.ts @@ -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 + + beforeAll(async () => { + container = await new PostgreSqlContainer(POSTGRES_IMAGE).start() + database = new Kysely({ + 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() + }) +}) diff --git a/src/_test/postgres.test.ts b/src/_test/postgres.test.ts index b742f32..034100b 100644 --- a/src/_test/postgres.test.ts +++ b/src/_test/postgres.test.ts @@ -1,213 +1,16 @@ import { PGlite } from "@electric-sql/pglite" import type { StartedPostgreSqlContainer } from "@testcontainers/postgresql" import { PostgreSqlContainer } from "@testcontainers/postgresql" -import { Kysely, PGliteDialect, 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): Promise => { - 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, - ) -} - describe("typegen PostgreSQL", () => { let container: StartedPostgreSqlContainer let database: Kysely diff --git a/tsconfig.json b/tsconfig.json index 164146f..227a4a8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,6 +29,6 @@ "resolveJsonModule": true, "lib": ["ESNext"], - "types": ["@types/node"] + "types": ["@types/node", "@types/bun"] } }