From 8261409d7d2c04fa85fd927015abf53e30b6e0df Mon Sep 17 00:00:00 2001 From: imbytecat Date: Thu, 5 Mar 2026 16:23:30 +0800 Subject: [PATCH] =?UTF-8?q?refactor(server):=20=E5=88=87=E6=8D=A2=20SQLite?= =?UTF-8?q?=20=E5=B9=B6=E9=87=8D=E5=BB=BA=E8=AE=BE=E5=A4=87/=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E8=A1=A8=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +++ apps/server/.env.example | 2 +- apps/server/drizzle.config.ts | 4 +-- apps/server/src/env.ts | 2 +- apps/server/src/server/db/fields.ts | 41 ++++++---------------- apps/server/src/server/db/index.ts | 14 ++++---- apps/server/src/server/db/relations.ts | 12 ++++++- apps/server/src/server/db/schema/device.ts | 11 ++++++ apps/server/src/server/db/schema/index.ts | 3 +- apps/server/src/server/db/schema/task.ts | 16 +++++++++ apps/server/src/server/db/schema/todo.ts | 8 ----- 11 files changed, 68 insertions(+), 50 deletions(-) create mode 100644 apps/server/src/server/db/schema/device.ts create mode 100644 apps/server/src/server/db/schema/task.ts delete mode 100644 apps/server/src/server/db/schema/todo.ts diff --git a/.gitignore b/.gitignore index ce51d38..7776bbd 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,11 @@ # Bun build *.bun-build +# SQLite database files +*.db +*.db-wal +*.db-shm + # Turborepo .turbo/ diff --git a/apps/server/.env.example b/apps/server/.env.example index 5f05b75..9e57bdd 100644 --- a/apps/server/.env.example +++ b/apps/server/.env.example @@ -1 +1 @@ -DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres +DATABASE_PATH=data.db diff --git a/apps/server/drizzle.config.ts b/apps/server/drizzle.config.ts index 292bccb..bbdf584 100644 --- a/apps/server/drizzle.config.ts +++ b/apps/server/drizzle.config.ts @@ -4,8 +4,8 @@ import { env } from '@/env' export default defineConfig({ out: './drizzle', schema: './src/server/db/schema/index.ts', - dialect: 'postgresql', + dialect: 'sqlite', dbCredentials: { - url: env.DATABASE_URL, + url: env.DATABASE_PATH, }, }) diff --git a/apps/server/src/env.ts b/apps/server/src/env.ts index e8825d9..2f77be4 100644 --- a/apps/server/src/env.ts +++ b/apps/server/src/env.ts @@ -3,7 +3,7 @@ import { z } from 'zod' export const env = createEnv({ server: { - DATABASE_URL: z.url(), + DATABASE_PATH: z.string().min(1).default('data.db'), }, clientPrefix: 'VITE_', client: { diff --git a/apps/server/src/server/db/fields.ts b/apps/server/src/server/db/fields.ts index afea8cc..033b961 100644 --- a/apps/server/src/server/db/fields.ts +++ b/apps/server/src/server/db/fields.ts @@ -1,47 +1,28 @@ -import { sql } from 'drizzle-orm' -import { timestamp, uuid } from 'drizzle-orm/pg-core' +import { integer, text } from 'drizzle-orm/sqlite-core' import { v7 as uuidv7 } from 'uuid' -// id +export const pk = (name = 'id') => + text(name) + .primaryKey() + .$defaultFn(() => uuidv7()) -const id = (name: string) => uuid(name) -export const pk = (name: string, strategy?: 'native' | 'extension') => { - switch (strategy) { - // PG 18+ - case 'native': - return id(name).primaryKey().default(sql`uuidv7()`) - - // PG 13+ with extension - case 'extension': - return id(name).primaryKey().default(sql`uuid_generate_v7()`) - - // Any PG version - default: - return id(name) - .primaryKey() - .$defaultFn(() => uuidv7()) - } -} - -// timestamp - -export const createdAt = (name = 'created_at') => timestamp(name, { withTimezone: true }).notNull().defaultNow() +export const createdAt = (name = 'created_at') => + integer(name, { mode: 'timestamp_ms' }) + .notNull() + .$defaultFn(() => new Date()) export const updatedAt = (name = 'updated_at') => - timestamp(name, { withTimezone: true }) + integer(name, { mode: 'timestamp_ms' }) .notNull() - .defaultNow() + .$defaultFn(() => new Date()) .$onUpdateFn(() => new Date()) -// generated fields - export const generatedFields = { id: pk('id'), createdAt: createdAt('created_at'), updatedAt: updatedAt('updated_at'), } -// Helper to create omit keys from generatedFields const createGeneratedFieldKeys = >(fields: T): Record => { return Object.keys(fields).reduce( (acc, key) => { diff --git a/apps/server/src/server/db/index.ts b/apps/server/src/server/db/index.ts index e7fd5f0..d26dac1 100644 --- a/apps/server/src/server/db/index.ts +++ b/apps/server/src/server/db/index.ts @@ -1,12 +1,14 @@ -import { drizzle } from 'drizzle-orm/postgres-js' +import { Database } from 'bun:sqlite' +import { drizzle } from 'drizzle-orm/bun-sqlite' import { env } from '@/env' import { relations } from '@/server/db/relations' -export const createDB = () => - drizzle({ - connection: env.DATABASE_URL, - relations, - }) +export const createDB = () => { + const sqlite = new Database(env.DATABASE_PATH) + sqlite.exec('PRAGMA journal_mode = WAL') + sqlite.exec('PRAGMA foreign_keys = ON') + return drizzle({ client: sqlite, relations }) +} export type DB = ReturnType diff --git a/apps/server/src/server/db/relations.ts b/apps/server/src/server/db/relations.ts index 77b9f38..fbf467e 100644 --- a/apps/server/src/server/db/relations.ts +++ b/apps/server/src/server/db/relations.ts @@ -1,4 +1,14 @@ import { defineRelations } from 'drizzle-orm' import * as schema from './schema' -export const relations = defineRelations(schema, (_r) => ({})) +export const relations = defineRelations(schema, (r) => ({ + deviceTable: { + tasks: r.many.taskTable(), + }, + taskTable: { + device: r.one.deviceTable({ + from: r.taskTable.deviceId, + to: r.deviceTable.id, + }), + }, +})) diff --git a/apps/server/src/server/db/schema/device.ts b/apps/server/src/server/db/schema/device.ts new file mode 100644 index 0000000..3d5d430 --- /dev/null +++ b/apps/server/src/server/db/schema/device.ts @@ -0,0 +1,11 @@ +import { sqliteTable, text } from 'drizzle-orm/sqlite-core' +import { generatedFields } from '../fields' + +export const deviceTable = sqliteTable('device', { + ...generatedFields, + licence: text('licence').notNull().unique(), + fingerprint: text('fingerprint').notNull(), + platformPublicKey: text('platform_public_key').notNull(), + pgpPrivateKey: text('pgp_private_key'), + pgpPublicKey: text('pgp_public_key'), +}) diff --git a/apps/server/src/server/db/schema/index.ts b/apps/server/src/server/db/schema/index.ts index a1cad6c..9808e7c 100644 --- a/apps/server/src/server/db/schema/index.ts +++ b/apps/server/src/server/db/schema/index.ts @@ -1 +1,2 @@ -export * from './todo' +export * from './device' +export * from './task' diff --git a/apps/server/src/server/db/schema/task.ts b/apps/server/src/server/db/schema/task.ts new file mode 100644 index 0000000..96a5190 --- /dev/null +++ b/apps/server/src/server/db/schema/task.ts @@ -0,0 +1,16 @@ +import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core' +import { generatedFields } from '../fields' + +export const taskTable = sqliteTable('task', { + ...generatedFields, + deviceId: text('device_id').notNull(), + taskId: text('task_id').notNull(), + enterpriseId: text('enterprise_id'), + orgName: text('org_name'), + inspectionId: text('inspection_id'), + inspectionPerson: text('inspection_person'), + issuedAt: integer('issued_at', { mode: 'timestamp_ms' }), + status: text('status', { enum: ['pending', 'in_progress', 'done'] }) + .notNull() + .default('pending'), +}) diff --git a/apps/server/src/server/db/schema/todo.ts b/apps/server/src/server/db/schema/todo.ts deleted file mode 100644 index 5ca821c..0000000 --- a/apps/server/src/server/db/schema/todo.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { boolean, pgTable, text } from 'drizzle-orm/pg-core' -import { generatedFields } from '../fields' - -export const todoTable = pgTable('todo', { - ...generatedFields, - title: text('title').notNull(), - completed: boolean('completed').notNull().default(false), -})