Skip to content

Commit

Permalink
feat: mysql
Browse files Browse the repository at this point in the history
  • Loading branch information
nichenqin committed Jan 23, 2025
1 parent f661ada commit 5bcd2c2
Show file tree
Hide file tree
Showing 27 changed files with 3,062 additions and 62 deletions.
293 changes: 293 additions & 0 deletions apps/backend/drizzle/mysql/0000_numerous_stepford_cuckoos.sql

Large diffs are not rendered by default.

2,102 changes: 2,102 additions & 0 deletions apps/backend/drizzle/mysql/meta/0000_snapshot.json

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions apps/backend/drizzle/mysql/meta/_journal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "mysql",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1737522284940,
"tag": "0000_numerous_stepford_cuckoos",
"breakpoints": true
}
]
}
26 changes: 20 additions & 6 deletions apps/backend/migrations/deployment.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"idx": 6,
"when": 1728358607342,
"tag": "0006_mature_madame_web",
"hash": "51995ae2bf0f8a52b57786978a421040330fb22121753aa6fbb0a51cb013ebde",
"hash": "2d3c434e963ac561d037554aabde467e4a514dc2f015d938cf0001da7f673bcf",
"sql": [
"ALTER TABLE `undb_outbox` ADD `user_id` text;",
"ALTER TABLE `undb_outbox` DROP COLUMN `operator_id`;"
Expand Down Expand Up @@ -148,9 +148,9 @@
"idx": 10,
"when": 1729306799169,
"tag": "0010_nostalgic_nehzno",
"hash": "c0ffe9e7e3b0523d65603d7cd4ee444fbc8bae9b4f1959741b4c01085c345d44",
"hash": "5ae829af899a7374b61092468af12258938a7f1bcc92b55cb481042dcb59837c",
"sql": [
"CREATE TABLE `undb_dashboard_table_id_mapping` (`dashboard_id` text NOT NULL,`table_id` text NOT NULL,PRIMARY KEY(`dashboard_id`, `table_id`),FOREIGN KEY (`dashboard_id`) REFERENCES `undb_dashboard`(`id`) ON UPDATE no action ON DELETE no action,FOREIGN KEY (`table_id`) REFERENCES `undb_table`(`id`) ON UPDATE no action ON DELETE no action);"
"CREATE TABLE `undb_dashboard_table_id_mapping` (\r`dashboard_id` text NOT NULL,\r`table_id` text NOT NULL,\rPRIMARY KEY(`dashboard_id`, `table_id`),\rFOREIGN KEY (`dashboard_id`) REFERENCES `undb_dashboard`(`id`) ON UPDATE no action ON DELETE no action,\rFOREIGN KEY (`table_id`) REFERENCES `undb_table`(`id`) ON UPDATE no action ON DELETE no action\r);"
]
},
{
Expand Down Expand Up @@ -181,16 +181,16 @@
"idx": 13,
"when": 1730979840099,
"tag": "0013_lovely_mordo",
"hash": "59f5936ab2e03fbff473d3d56883ecce0832b71521b02bfa2ad2907d242dc00b",
"hash": "6a36e0da06793be22662a86e1ff42b9414a8723753addae312cf00de52703f79",
"sql": [
"PRAGMA foreign_keys=OFF;",
"CREATE TABLE `__new_undb_reference_id_mapping` (`field_id` text NOT NULL,`table_id` text NOT NULL,`symmetric_field_id` text,`foreign_table_id` text NOT NULL);",
"CREATE TABLE `__new_undb_reference_id_mapping` (\r`field_id` text NOT NULL,\r`table_id` text NOT NULL,\r`symmetric_field_id` text,\r`foreign_table_id` text NOT NULL\r);",
"INSERT INTO `__new_undb_reference_id_mapping`(\"field_id\", \"table_id\", \"symmetric_field_id\", \"foreign_table_id\") SELECT \"field_id\", \"table_id\", \"symmetric_field_id\", \"foreign_table_id\" FROM `undb_reference_id_mapping`;",
"DROP TABLE `undb_reference_id_mapping`;",
"ALTER TABLE `__new_undb_reference_id_mapping` RENAME TO `undb_reference_id_mapping`;",
"PRAGMA foreign_keys=ON;",
"CREATE UNIQUE INDEX `reference_id_mapping_unique_idx` ON `undb_reference_id_mapping` (`field_id`,`table_id`,`symmetric_field_id`,`foreign_table_id`);",
"CREATE TABLE `__new_undb_rollup_id_mapping` (`field_id` text NOT NULL,`table_id` text NOT NULL,`rollup_id` text NOT NULL,`rollup_table_id` text NOT NULL,PRIMARY KEY(`field_id`, `rollup_id`));",
"CREATE TABLE `__new_undb_rollup_id_mapping` (\r`field_id` text NOT NULL,\r`table_id` text NOT NULL,\r`rollup_id` text NOT NULL,\r`rollup_table_id` text NOT NULL,\rPRIMARY KEY(`field_id`, `rollup_id`)\r);",
"INSERT INTO `__new_undb_rollup_id_mapping`(\"field_id\", \"table_id\", \"rollup_id\", \"rollup_table_id\") SELECT \"field_id\", \"table_id\", \"rollup_id\", \"rollup_table_id\" FROM `undb_rollup_id_mapping`;",
"DROP TABLE `undb_rollup_id_mapping`;",
"ALTER TABLE `__new_undb_rollup_id_mapping` RENAME TO `undb_rollup_id_mapping`;"
Expand All @@ -204,5 +204,19 @@
"sql": [
"ALTER TABLE `undb_user` ADD `otp_secret` text;"
]
},
{
"idx": 15,
"when": 1737446284193,
"tag": "0015_greedy_ben_grimm",
"hash": "f6b79d1c1531adfe3201428645ee289f7854c8bda01d19cd6bae95b025280ed6",
"sql": [
"PRAGMA foreign_keys=OFF;",
"CREATE TABLE `__new_undb_session` (\r`id` text PRIMARY KEY NOT NULL,\r`user_id` text NOT NULL,\r`expires_at` integer NOT NULL,\r`spaceId` text NOT NULL,\rFOREIGN KEY (`user_id`) REFERENCES `undb_user`(`id`) ON UPDATE no action ON DELETE no action,\rFOREIGN KEY (`spaceId`) REFERENCES `undb_space`(`id`) ON UPDATE no action ON DELETE no action\r);",
"INSERT INTO `__new_undb_session`(\"id\", \"user_id\", \"expires_at\", \"spaceId\") SELECT \"id\", \"user_id\", \"expires_at\", \"spaceId\" FROM `undb_session`;",
"DROP TABLE `undb_session`;",
"ALTER TABLE `__new_undb_session` RENAME TO `undb_session`;",
"PRAGMA foreign_keys=ON;"
]
}
]
2 changes: 2 additions & 0 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@json2csv/plainjs": "^7.0.6",
"@kitajs/ts-html-plugin": "latest",
"@lucia-auth/adapter-drizzle": "^1.1.0",
"@lucia-auth/adapter-mysql": "^3.0.2",
"@lucia-auth/adapter-postgresql": "^3.1.2",
"@lucia-auth/adapter-sqlite": "^3.0.2",
"@oslojs/otp": "^1.1.0",
Expand Down Expand Up @@ -54,6 +55,7 @@
"lucia": "^3.2.2",
"mailgun-nodemailer-transport": "^3.0.2",
"minio": "^8.0.3",
"mysql2": "^3.12.0",
"nanoid": "^5.0.9",
"nodemailer": "^6.9.16",
"oslo": "^1.2.1",
Expand Down
49 changes: 24 additions & 25 deletions apps/backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,7 @@ export const app = new Elysia()
await dbMigrate()
logger.info("db migrate done")
await auth.onStart()
})
.use(opentelemetry.plugin())
.use(loggerPlugin())
.onError((ctx) => {
if (ctx.code === "NOT_FOUND") {
ctx.set.status = 404
ctx.logger.error(
{
error: ctx.error,
path: ctx.path,
headers: ctx.headers,
},
"Not Found",
)

return "Not Found :("
}

return new Response(ctx.error.toString())
})
.trace(async ({ set, onHandle }) => {
const { begin, end } = await onHandle()

set.headers["Server-Timing"] = `handle;dur=${(await end) - begin}`
})
.onStart(async () => {
const pubsub = container.resolve(PubSubContext)
const webhookEventHandler = container.resolve(WebhookEventsHandler)
// const auditEventHandler = container.resolve(AuditEventHandler)
Expand All @@ -95,6 +70,30 @@ export const app = new Elysia()
}
}
})
.use(opentelemetry.plugin())
.use(loggerPlugin())
.onError((ctx) => {
if (ctx.code === "NOT_FOUND") {
ctx.set.status = 404
ctx.logger.error(
{
error: ctx.error,
path: ctx.path,
headers: ctx.headers,
},
"Not Found",
)

return "Not Found :("
}

return new Response(ctx.error.toString())
})
.trace(async ({ set, onHandle }) => {
const { begin, end } = await onHandle()

set.headers["Server-Timing"] = `handle;dur=${(await end) - begin}`
})
.use(
staticPlugin({
assets: "./.undb/storage",
Expand Down
18 changes: 16 additions & 2 deletions apps/backend/src/modules/auth/auth.provider.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle"
import { Mysql2Adapter } from "@lucia-auth/adapter-mysql"
import { BunSQLiteAdapter, LibSQLAdapter } from "@lucia-auth/adapter-sqlite"
import { container, inject, instanceCachingFactory } from "@undb/di"
import { Client, DATABASE_CLIENT, DB_PROVIDER, pgSessionTable, pgUsers } from "@undb/persistence/server"
import Database from "bun:sqlite"
import { drizzle } from "drizzle-orm/node-postgres"
import { drizzle as drizzlePg } from "drizzle-orm/node-postgres"
import { Adapter, Lucia } from "lucia"
import mysql from "mysql2"
import pg from "pg"

export const LUCIA_PROVIDER = Symbol.for("LUCIA_PROVIDER")
Expand Down Expand Up @@ -56,13 +58,22 @@ const createSqliteLucia = (sqlite: Database) => {
}

const createPostgresLucia = (pool: pg.Pool) => {
const db = drizzle(pool)
const db = drizzlePg(pool)

const adapter = new DrizzlePostgreSQLAdapter(db, pgSessionTable, pgUsers)

return createLuciaWithAdapter(adapter)
}

const createMysqlLucia = (connection: mysql.Pool) => {
const adapter = new Mysql2Adapter(connection, {
user: "undb_user",
session: "undb_session",
})

return createLuciaWithAdapter(adapter)
}

declare module "lucia" {
interface Register {
Lucia: ReturnType<typeof createTursoLucia>
Expand All @@ -89,6 +100,9 @@ container.register(LUCIA_PROVIDER, {
} else if (dbProvider === "postgres") {
const pool = c.resolve<pg.Pool>(DATABASE_CLIENT)
return createPostgresLucia(pool)
} else if (dbProvider === "mysql") {
const connection = c.resolve<mysql.Pool>(DATABASE_CLIENT)
return createMysqlLucia(connection)
}

const sqlite = c.resolve<Client>(DATABASE_CLIENT)
Expand Down
9 changes: 9 additions & 0 deletions apps/backend/src/registry/db.registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
BaseQueryRepository,
BaseRepository,
Client,
createMysqlClient,
createMysqlQueryBuilder,
createPostgresClient,
createPostgresQueryBuilder,
createSqliteClient,
Expand Down Expand Up @@ -73,6 +75,7 @@ import { TEMPLATE_QUERY_REPOSITORY } from "@undb/template"
import { USER_QUERY_REPOSITORY, USER_REPOSITORY, USER_SERVICE, UserService } from "@undb/user"
import { WEBHOOK_QUERY_REPOSITORY, WEBHOOK_REPOSITORY } from "@undb/webhook"
import Database from "bun:sqlite"
import mysql from "mysql2"
import { AsyncLocalStorage } from "node:async_hooks"
import pg from "pg"

Expand All @@ -90,6 +93,9 @@ export const registerDb = () => {
if (dbProvider === "postgres") {
return createPostgresClient(env.UNDB_DB_POSTGRES_URL!)
}
if (dbProvider === "mysql") {
return createMysqlClient(env.UNDB_DB_MYSQL_URL!)
}
return createTursoClient(env.UNDB_DB_TURSO_URL!, env.UNDB_DB_TURSO_AUTH_TOKEN)
}),
})
Expand All @@ -102,6 +108,9 @@ export const registerDb = () => {
} else if (dbProvider === "postgres") {
const pg = c.resolve<pg.Pool>(DATABASE_CLIENT)
return createPostgresQueryBuilder(pg)
} else if (dbProvider === "mysql") {
const mysql = c.resolve<mysql.Pool>(DATABASE_CLIENT)
return createMysqlQueryBuilder(mysql)
}

const sqlite = c.resolve<Client>(DATABASE_CLIENT)
Expand Down
Binary file modified bun.lockb
Binary file not shown.
8 changes: 8 additions & 0 deletions drizzle.mysql.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from "drizzle-kit"

export default defineConfig({
schema: "./packages/persistence/src/schema/mysql.ts",
out: "./apps/backend/drizzle/mysql",
dialect: "mysql",
tablesFilter: ["undb_*"],
})
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"generate": "run-s generate:db migrate:deploy",
"generate:db": "run-p generate:db:*",
"generate:db:postgres": "drizzle-kit generate --config drizzle.postgres.config.ts",
"generate:db:mysql": "drizzle-kit generate --config drizzle.mysql.config.ts",
"generate:db:sqlite": "drizzle-kit generate --config drizzle.sqlite.config.ts",
"migrate:db": "drizzle-kit push --config drizzle.sqlite.config.ts",
"move-assets": "bun run ./scripts/move-assets.ts",
Expand Down
12 changes: 10 additions & 2 deletions packages/env/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ const postgresEnv = createEnv({
emptyStringAsUndefined: true,
})

const mysqlEnv = createEnv({
server: {
UNDB_DB_MYSQL_URL: z.string().optional(),
},
runtimeEnv: import.meta.env,
emptyStringAsUndefined: true,
})

const oauthEnv = createEnv({
server: {
UNDB_OAUTH_GITHUB_ENABLED: z
Expand Down Expand Up @@ -148,7 +156,7 @@ const emailEnv = createEnv({

const dbEnv = createEnv({
server: {
UNDB_DB_PROVIDER: z.enum(["sqlite", "turso", "postgres"]).default("sqlite").optional(),
UNDB_DB_PROVIDER: z.enum(["sqlite", "turso", "postgres", "mysql"]).default("sqlite").optional(),
UNDB_OUTBOX_SCAN_BATCH_SIZE: z
.string()
.optional()
Expand All @@ -171,5 +179,5 @@ export const env = createEnv({
},
runtimeEnv: import.meta.env,
emptyStringAsUndefined: true,
extends: [tursoEnv, postgresEnv, dbEnv, oauthEnv, storageEnv, s3Env, emailEnv, minioEnv, authEnv],
extends: [tursoEnv, postgresEnv, mysqlEnv, dbEnv, oauthEnv, storageEnv, s3Env, emailEnv, minioEnv, authEnv],
})
1 change: 1 addition & 0 deletions packages/persistence/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"kysely": "^0.27.5",
"kysely-bun-sqlite": "^0.3.2",
"kysely-wasm": "^0.7.0",
"mysql2": "^3.12.0",
"pg": "^8.13.1",
"postgres": "^3.4.5",
"radash": "^12.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import type {
WithDashboardWidgets,
} from "@undb/dashboard"
import { AbstractQBMutationVisitor } from "../abstract-qb.visitor"
import type { IDbProvider } from "../db.provider"
import type { IQueryBuilder } from "../qb.type"
import { json } from "../qb.util"

export class DashboardMutateVisitor extends AbstractQBMutationVisitor implements IDashboardSpecVisitor {
constructor(
private readonly dashboard: Dashboard,
private readonly qb: IQueryBuilder,
private readonly dbProvider: IDbProvider,
) {
super()
}
Expand Down Expand Up @@ -57,7 +59,8 @@ export class DashboardMutateVisitor extends AbstractQBMutationVisitor implements
const sql = this.qb
.insertInto("undb_dashboard_table_id_mapping")
.values({ dashboard_id: dashboardId, table_id: tableId })
.onConflict((ob) => ob.doNothing())
.$if(this.dbProvider.isMysql(), (eb) => eb.ignore())
.$if(this.dbProvider.not.isMysql(), (eb) => eb.onConflict((ob) => ob.doNothing()))
.compile()
this.addSql(sql)
}
Expand Down
5 changes: 4 additions & 1 deletion packages/persistence/src/dashboard/dashboard.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { inject, singleton } from "@undb/di"
import { None, Some, type Option } from "@undb/domain"
import type { ITxContext } from "../ctx.interface"
import { injectTxCTX } from "../ctx.provider"
import { DbProviderService, type IDbProvider } from "../db.provider"
import { injectQueryBuilder } from "../qb.provider"
import type { IQueryBuilder } from "../qb.type"
import { DashboardFilterVisitor } from "./dashboard.filter-visitor"
Expand All @@ -32,6 +33,8 @@ export class DashboardRepository implements IDashboardRepository {
private readonly context: IContext,
@injectTxCTX()
private readonly txContext: ITxContext,
@inject(DbProviderService)
private readonly dbProvider: IDbProvider,
) {}

async find(spec: IDashboardSpecification): Promise<Dashboard[]> {
Expand Down Expand Up @@ -107,7 +110,7 @@ export class DashboardRepository implements IDashboardRepository {
const userId = this.context.mustGetCurrentUserId()

const qb = this.txContext.getCurrentTransaction()
const visitor = new DashboardMutateVisitor(dashboard, qb).$mutate(spec)
const visitor = new DashboardMutateVisitor(dashboard, qb, this.dbProvider).$mutate(spec)

await qb
.updateTable("undb_dashboard")
Expand Down
5 changes: 5 additions & 0 deletions packages/persistence/src/db-client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createClient } from "@libsql/client"
import { inject } from "@undb/di"
import Database from "bun:sqlite"
import mysql from "mysql2"
import pg from "pg"

export const DATABASE_CLIENT = Symbol.for("DATABASE_CLIENT")
Expand All @@ -20,3 +21,7 @@ export const createPostgresClient = (connectionString: string) => {
connectionString,
})
}

export const createMysqlClient = (connectionString: string): mysql.Pool => {
return mysql.createPool(connectionString)
}
Loading

0 comments on commit 5bcd2c2

Please sign in to comment.