mv dir to data
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { loggerService } from '@logger'
|
||||
import { drizzle } from 'drizzle-orm/libsql'
|
||||
import { migrate } from 'drizzle-orm/libsql/migrator'
|
||||
import { app } from 'electron'
|
||||
import path from 'path'
|
||||
import { pathToFileURL } from 'url'
|
||||
|
||||
import Seeding from './seeding'
|
||||
import type { DbType } from './types'
|
||||
|
||||
const logger = loggerService.withContext('DbService')
|
||||
|
||||
const DB_NAME = 'cherrystudio.sqlite'
|
||||
const MIGRATIONS_BASE_PATH = 'migrations/sqlite-drizzle'
|
||||
|
||||
class DbService {
|
||||
private static instance: DbService
|
||||
private db: DbType
|
||||
|
||||
private constructor() {
|
||||
this.db = drizzle({
|
||||
connection: { url: pathToFileURL(path.join(app.getPath('userData'), DB_NAME)).href },
|
||||
casing: 'snake_case'
|
||||
})
|
||||
}
|
||||
|
||||
public static getInstance(): DbService {
|
||||
if (!DbService.instance) {
|
||||
DbService.instance = new DbService()
|
||||
}
|
||||
return DbService.instance
|
||||
}
|
||||
|
||||
public async migrateDb() {
|
||||
const migrationsFolder = this.getMigrationsFolder()
|
||||
await migrate(this.db, { migrationsFolder })
|
||||
}
|
||||
|
||||
public getDb(): DbType {
|
||||
return this.db
|
||||
}
|
||||
|
||||
public async migrateSeed(seedName: keyof typeof Seeding): Promise<boolean> {
|
||||
try {
|
||||
const Seed = Seeding[seedName]
|
||||
await new Seed().migrate(this.db)
|
||||
return true
|
||||
} catch (error) {
|
||||
logger.error('migration seeding failed', error as Error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migrations folder based on the app's packaging status
|
||||
* @returns The path to the migrations folder
|
||||
*/
|
||||
private getMigrationsFolder() {
|
||||
if (app.isPackaged) {
|
||||
//see electron-builder.yml, extraResources from/to
|
||||
return path.join(process.resourcesPath, MIGRATIONS_BASE_PATH)
|
||||
} else {
|
||||
// in dev/preview, __dirname maybe /out/main
|
||||
return path.join(__dirname, '../../', MIGRATIONS_BASE_PATH)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export a singleton instance
|
||||
const dbService = DbService.getInstance()
|
||||
|
||||
export default dbService
|
||||
@@ -0,0 +1,2 @@
|
||||
- All the database table names use **singular** form, snake_casing
|
||||
- Export table names use `xxxxTable`
|
||||
@@ -0,0 +1,11 @@
|
||||
import { integer } from 'drizzle-orm/sqlite-core'
|
||||
|
||||
const createTimestamp = () => {
|
||||
return Date.now()
|
||||
}
|
||||
|
||||
export const crudTimestamps = {
|
||||
createdAt: integer().$defaultFn(createTimestamp),
|
||||
updatedAt: integer().$defaultFn(createTimestamp).$onUpdateFn(createTimestamp),
|
||||
deletedAt: integer()
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { index, sqliteTable, text } from 'drizzle-orm/sqlite-core'
|
||||
|
||||
import { crudTimestamps } from './columnHelpers'
|
||||
|
||||
export const preferenceTable = sqliteTable(
|
||||
'preference',
|
||||
{
|
||||
scope: text().notNull(), // scope is reserved for future use, now only 'default' is supported
|
||||
key: text().notNull(),
|
||||
value: text({ mode: 'json' }),
|
||||
...crudTimestamps
|
||||
},
|
||||
(t) => [index('scope_name_idx').on(t.scope, t.key)]
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
import PreferenceSeeding from './preferenceSeeding'
|
||||
|
||||
const seedingList = {
|
||||
preference: PreferenceSeeding
|
||||
}
|
||||
|
||||
export default seedingList
|
||||
@@ -0,0 +1,47 @@
|
||||
import { preferenceTable } from '@data/db/schemas/preference'
|
||||
import { defaultPreferences } from '@shared/data/preferences'
|
||||
|
||||
import type { DbType, ISeed } from '../types'
|
||||
|
||||
class PreferenceSeed implements ISeed {
|
||||
async migrate(db: DbType): Promise<void> {
|
||||
const preferences = await db.select().from(preferenceTable)
|
||||
|
||||
// Convert existing preferences to a Map for quick lookup
|
||||
const existingPrefs = new Map(preferences.map((p) => [`${p.scope}.${p.key}`, p]))
|
||||
|
||||
// Collect all new preferences to insert
|
||||
const newPreferences: Array<{
|
||||
scope: string
|
||||
key: string
|
||||
value: unknown
|
||||
}> = []
|
||||
|
||||
// Process each scope in defaultPreferences
|
||||
for (const [scope, scopeData] of Object.entries(defaultPreferences)) {
|
||||
// Process each key-value pair in the scope
|
||||
for (const [key, value] of Object.entries(scopeData)) {
|
||||
const prefKey = `${scope}.${key}`
|
||||
|
||||
// Skip if this preference already exists
|
||||
if (existingPrefs.has(prefKey)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add to new preferences array
|
||||
newPreferences.push({
|
||||
scope,
|
||||
key,
|
||||
value
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// If there are new preferences to insert, do it in a transaction
|
||||
if (newPreferences.length > 0) {
|
||||
await db.insert(preferenceTable).values(newPreferences)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default PreferenceSeed
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import type { LibSQLDatabase } from 'drizzle-orm/libsql'
|
||||
|
||||
export type DbType = LibSQLDatabase
|
||||
|
||||
export interface ISeed {
|
||||
migrate(db: DbType): Promise<void>
|
||||
}
|
||||
Reference in New Issue
Block a user