diff --git a/README.md b/README.md index 6fa0400..5e24844 100644 --- a/README.md +++ b/README.md @@ -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 (**can be easily extended to more**) | +| **Database Support** | PostgreSQL, MySQL, SQLite, MSSQL, LibSQL | PostgreSQL, 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. @@ -107,6 +107,28 @@ export const database = new Kysely({ dialect }) export const databaseTypegen = new KyselyTypegenMySQLDialect({ database }) ``` +#### SQLite + +```sh +npm install better-sqlite3 +``` + +```ts +// database.ts +import Database from "better-sqlite3" +import { Kysely, SqliteDialect } from "kysely" +import { KyselyTypegenSQLiteDialect } from "kysely-typegen/sqlite" + +import type { DB } from "./codegen.ts" + +const dialect = new SqliteDialect({ + database: new Database(process.env["DATABASE_PATH"] ?? "database.sqlite"), +}) + +export const database = new Kysely({ dialect }) +export const databaseTypegen = new KyselyTypegenSQLiteDialect({ database }) +``` + ### Generate the type definitions Create a script that uses `databaseTypegen` to introspect your database and write the generated types to a file. This script is the same regardless of the underlying database: @@ -148,7 +170,7 @@ Fully type-safe queries derived from your actual database schema. ## Extending to other database dialects -`kysely-typegen` ships with `KyselyTypegenPostgresDialect` and `KyselyTypegenMySQLDialect`, but you can add support for any database by extending the abstract `KyselyTypegenDialect` class. +`kysely-typegen` ships with `KyselyTypegenPostgresDialect`, `KyselyTypegenMySQLDialect`, and `KyselyTypegenSQLiteDialect`, but you can add support for any database by extending the abstract `KyselyTypegenDialect` class. Only one thing is required: @@ -189,6 +211,8 @@ protected override async introspectEnums(): Promise { } ``` +If your database needs to normalize column type spellings before scalar lookup (e.g. strip `VARCHAR(255)` → `VARCHAR`, or uppercase keys), override the optional `normalizeDataType(dataType: string): string` hook. + The base class handles introspection (via Kysely's `database.introspection.getTables()`), sorting, and the final type generation. Contributions of new dialects are welcome! ## Contributing diff --git a/package-lock.json b/package-lock.json index 697076d..3f07399 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,10 @@ "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", @@ -2288,6 +2290,16 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/better-sqlite3": { + "version": "7.6.13", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", + "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/docker-modem": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz", @@ -2867,6 +2879,31 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/better-sqlite3": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.10.0.tgz", + "integrity": "sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + }, + "engines": { + "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, "node_modules/birpc": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz", @@ -3659,6 +3696,22 @@ } } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -3686,6 +3739,16 @@ "node": ">=0.10" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4147,6 +4210,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-content-type-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", @@ -4187,6 +4260,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "license": "MIT" + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -4385,6 +4465,13 @@ "traverse": "0.6.8" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT" + }, "node_modules/glob": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", @@ -5189,6 +5276,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "9.0.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", @@ -5311,6 +5411,13 @@ "license": "MIT", "optional": true }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT" + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -5325,6 +5432,19 @@ "dev": true, "license": "MIT" }, + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-emoji": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", @@ -7939,6 +8059,79 @@ "node": ">=0.10.0" } }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prebuild-install/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prebuild-install/node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/prebuild-install/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/pretty-ms": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", @@ -8572,6 +8765,53 @@ "node": ">=4" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/skin-tone": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", @@ -9311,6 +9551,19 @@ "node": ">=0.6.11 <=0.7.0 || >=0.7.3" } }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", diff --git a/package.json b/package.json index 371f6ba..3237a76 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ ".": "./dist/index.mjs", "./mysql": "./dist/mysql.mjs", "./postgres": "./dist/postgres.mjs", + "./sqlite": "./dist/sqlite.mjs", "./package.json": "./package.json" }, "publishConfig": { @@ -42,8 +43,10 @@ "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", diff --git a/src/_test/__snapshots__/sqlite.test.ts.snapshot b/src/_test/__snapshots__/sqlite.test.ts.snapshot new file mode 100644 index 0000000..5e3da1b --- /dev/null +++ b/src/_test/__snapshots__/sqlite.test.ts.snapshot @@ -0,0 +1,69 @@ +exports[`typegen SQLite > 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 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 interface AllTypes {", + " colBlob: Buffer", + " colBoolean: Generated", + " colDatetime: string", + " colInteger: number", + " colJson: Json", + " colNumeric: Numeric", + " colReal: number", + " colText: string", + " colTextNullable: string | null", + " colVarchar: string", + " id: Generated", + "}", + "", + "export interface Orders {", + " amountCents: number", + " createdAt: Generated", + " id: Generated", + " note: string | null", + " userId: number", + "}", + "", + "export interface Users {", + " createdAt: Generated", + " email: string | null", + " id: Generated", + " isActive: Generated", + " username: string", + "}", + "", + "export interface DB {", + " AllTypes: AllTypes", + " Orders: Orders", + " Users: Users", + "}" + ], + "tablesCount": 3, + "enumsCount": 0, + "inlineEnumsCount": 0 +} +`; diff --git a/src/_test/sqlite.test.ts b/src/_test/sqlite.test.ts new file mode 100644 index 0000000..cb3bd4d --- /dev/null +++ b/src/_test/sqlite.test.ts @@ -0,0 +1,110 @@ +import Database from "better-sqlite3" +import { Kysely, sql, SqliteDialect } from "kysely" +import { after, before, describe, it } from "node:test" + +import { KyselyTypegenSQLiteDialect } from "../sqlite.ts" +import "./_setup.ts" + +const createSchema = async (database: Kysely): Promise => { + await database.schema + .createTable("AllTypes") + .addColumn("id", "integer", (column) => { + return column.notNull().primaryKey() + }) + .addColumn("colInteger", "integer", (column) => { + return column.notNull() + }) + .addColumn("colReal", "real", (column) => { + return column.notNull() + }) + .addColumn("colText", "text", (column) => { + return column.notNull() + }) + .addColumn("colBlob", "blob", (column) => { + return column.notNull() + }) + .addColumn("colNumeric", sql`NUMERIC`, (column) => { + return column.notNull() + }) + .addColumn("colBoolean", sql`BOOLEAN`, (column) => { + return column.notNull().defaultTo(0) + }) + .addColumn("colDatetime", sql`DATETIME`, (column) => { + return column.notNull() + }) + .addColumn("colVarchar", sql`VARCHAR(255)`, (column) => { + return column.notNull() + }) + .addColumn("colJson", sql`JSON`, (column) => { + return column.notNull() + }) + .addColumn("colTextNullable", "text") + .execute() + + await database.schema + .createTable("Users") + .addColumn("id", "integer", (column) => { + return column.notNull().primaryKey() + }) + .addColumn("username", sql`VARCHAR(50)`, (column) => { + return column.notNull().unique() + }) + .addColumn("email", "text") + .addColumn("isActive", sql`BOOLEAN`, (column) => { + return column.notNull().defaultTo(1) + }) + .addColumn("createdAt", sql`DATETIME`, (column) => { + return column.notNull().defaultTo(sql`CURRENT_TIMESTAMP`) + }) + .execute() + + await database.schema + .createTable("Orders") + .addColumn("id", "integer", (column) => { + return column.notNull().primaryKey() + }) + .addColumn("userId", "integer", (column) => { + return column.notNull().references("Users.id") + }) + .addColumn("amountCents", "integer", (column) => { + return column.notNull() + }) + .addColumn("note", "text") + .addColumn("createdAt", sql`DATETIME`, (column) => { + return column.notNull().defaultTo(sql`CURRENT_TIMESTAMP`) + }) + .execute() +} + +describe("typegen SQLite", () => { + let database: Kysely + + before(async () => { + database = new Kysely({ + dialect: new SqliteDialect({ + database: new Database(":memory:"), + }), + }) + await createSchema(database) + }) + + after(async () => { + await database.destroy() + }) + + it("generate types matching snapshot", async (testContext) => { + // Arrange - Given + const databaseTypegen = new KyselyTypegenSQLiteDialect({ 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, + }) + }) +}) diff --git a/src/index.ts b/src/index.ts index 72e8c0a..9dfe93a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -55,6 +55,10 @@ export abstract class KyselyTypegenDialect { }) } + protected normalizeDataType(dataType: string): string { + return dataType + } + protected resolveColumnType( table: TableMetadata, column: ColumnMetadata, @@ -65,7 +69,8 @@ export abstract class KyselyTypegenDialect { if (inlineUnion != null) { return inlineUnion } - return scalars[column.dataType] ?? "unknown" + const dataType = this.normalizeDataType(column.dataType) + return scalars[dataType] ?? "unknown" } public getTablesTypegen( diff --git a/src/sqlite.ts b/src/sqlite.ts new file mode 100644 index 0000000..788d167 --- /dev/null +++ b/src/sqlite.ts @@ -0,0 +1,31 @@ +import { KyselyTypegenDialect } from "./index.ts" + +export class KyselyTypegenSQLiteDialect extends KyselyTypegenDialect { + // SQLite is dynamically typed and pragma_table_info preserves the declared + // type spelling verbatim. Lookups are normalized to uppercase, so keys here + // must be uppercase. Covers the five storage classes plus popular aliases. + public override readonly scalars: Record = { + BIGINT: "Int8", + BLOB: "Buffer", + BOOLEAN: "number", + CHAR: "string", + DATE: "string", + DATETIME: "string", + DECIMAL: "Numeric", + DOUBLE: "number", + FLOAT: "number", + INTEGER: "number", + JSON: "Json", + NUMERIC: "Numeric", + REAL: "number", + TEXT: "string", + TIMESTAMP: "string", + VARCHAR: "string", + } + + protected override normalizeDataType(dataType: string): string { + const parenIndex = dataType.indexOf("(") + const stripped = parenIndex === -1 ? dataType : dataType.slice(0, parenIndex) + return stripped.toUpperCase() + } +} diff --git a/tsdown.config.ts b/tsdown.config.ts index 874e2a7..5c287a7 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from "tsdown" export default defineConfig({ - entry: ["./src/index.ts", "./src/mysql.ts", "./src/postgres.ts"], + entry: ["./src/index.ts", "./src/mysql.ts", "./src/postgres.ts", "./src/sqlite.ts"], dts: true, exports: true, })