feat: 增加数据库迁移逻辑

This commit is contained in:
qier222 2022-05-13 01:48:13 +08:00
parent 48869266e4
commit c3ae012d06
No known key found for this signature in database
GPG key ID: 9C85007ED905F14D
4 changed files with 52 additions and 10 deletions

View file

@ -4,8 +4,9 @@ import fs from 'fs'
import SQLite3 from 'better-sqlite3' import SQLite3 from 'better-sqlite3'
import log from './log' import log from './log'
import { createFileIfNotExist } from './utils' import { createFileIfNotExist } from './utils'
import pkg from '../../package.json'
const isDev = process.env.NODE_ENV === 'development' import { compare, validate } from 'compare-versions'
import { dirname } from './utils'
export const enum Tables { export const enum Tables {
Track = 'Track', Track = 'Track',
@ -17,6 +18,7 @@ export const enum Tables {
Audio = 'Audio', Audio = 'Audio',
AccountData = 'AccountData', AccountData = 'AccountData',
CoverColor = 'CoverColor', CoverColor = 'CoverColor',
AppData = 'AppData',
} }
interface CommonTableStructure { interface CommonTableStructure {
id: number id: number
@ -55,10 +57,18 @@ export interface TablesStructures {
id: number id: number
color: string color: string
} }
[Tables.AppData]: {
id: 'appVersion' | 'skippedVersion'
value: string
}
} }
type TableNames = keyof TablesStructures type TableNames = keyof TablesStructures
const readSqlFile = (filename: string) => {
return fs.readFileSync(path.join(dirname, `./migrations/${filename}`), 'utf8')
}
class DB { class DB {
sqlite: SQLite3.Database sqlite: SQLite3.Database
dbFilePath: string = path.resolve( dbFilePath: string = path.resolve(
@ -79,24 +89,48 @@ class DB {
}) })
this.sqlite.pragma('auto_vacuum = FULL') this.sqlite.pragma('auto_vacuum = FULL')
this.initTables() this.initTables()
this.migrate()
log.info('[db] Database initialized') log.info('[db] Database initialized')
} }
initTables() { initTables() {
const migration = fs.readFileSync( const init = readSqlFile('init.sql')
isDev this.sqlite.exec(init)
? path.join(process.cwd(), './migrations/init.sql') }
: path.join(__dirname, './migrations/init.sql'),
'utf8' migrate() {
) const key = 'appVersion'
this.sqlite.exec(migration) const appVersion = this.find(Tables.AppData, key)
const updateAppVersionInDB = () => {
this.upsert(Tables.AppData, {
id: key,
value: pkg.version,
})
}
if (!appVersion?.value) {
updateAppVersionInDB()
return
}
const sqlFiles = fs.readdirSync(path.join(dirname, './migrations'))
sqlFiles.forEach((sqlFile: string) => {
const version = sqlFile.split('.').shift() || ''
if (!validate(version)) return
if (compare(version, pkg.version, '>')) {
const file = readSqlFile(sqlFile)
this.sqlite.exec(file)
}
})
updateAppVersionInDB()
} }
find<T extends TableNames>( find<T extends TableNames>(
table: T, table: T,
key: TablesStructures[T]['id'] key: TablesStructures[T]['id']
): TablesStructures[T] { ): TablesStructures[T] | undefined {
return this.sqlite return this.sqlite
.prepare(`SELECT * FROM ${table} WHERE id = ? LIMIT 1`) .prepare(`SELECT * FROM ${table} WHERE id = ? LIMIT 1`)
.get(key) .get(key)

View file

@ -7,3 +7,4 @@ CREATE TABLE IF NOT EXISTS "Lyric" ("id" integer NOT NULL,"json" text NOT NULL,"
CREATE TABLE IF NOT EXISTS "Playlist" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id)); CREATE TABLE IF NOT EXISTS "Playlist" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE IF NOT EXISTS "Track" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id)); CREATE TABLE IF NOT EXISTS "Track" ("id" integer NOT NULL,"json" text NOT NULL,"updatedAt" int NOT NULL, PRIMARY KEY (id));
CREATE TABLE IF NOT EXISTS "CoverColor" ("id" integer NOT NULL,"color" text NOT NULL, PRIMARY KEY (id)); CREATE TABLE IF NOT EXISTS "CoverColor" ("id" integer NOT NULL,"color" text NOT NULL, PRIMARY KEY (id));
CREATE TABLE IF NOT EXISTS "AppData" ("id" text NOT NULL,"value" text, PRIMARY KEY (id));

View file

@ -21,6 +21,7 @@
"NeteaseCloudMusicApi": "^4.5.12", "NeteaseCloudMusicApi": "^4.5.12",
"better-sqlite3": "7.5.1", "better-sqlite3": "7.5.1",
"change-case": "^4.1.2", "change-case": "^4.1.2",
"compare-versions": "^4.1.3",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"electron-log": "^4.4.6", "electron-log": "^4.4.6",
"electron-store": "^8.0.1", "electron-store": "^8.0.1",

6
pnpm-lock.yaml generated
View file

@ -30,6 +30,7 @@ importers:
axios: ^0.27.2 axios: ^0.27.2
better-sqlite3: 7.5.1 better-sqlite3: 7.5.1
change-case: ^4.1.2 change-case: ^4.1.2
compare-versions: ^4.1.3
cookie-parser: ^1.4.6 cookie-parser: ^1.4.6
cross-env: ^7.0.3 cross-env: ^7.0.3
dotenv: ^16.0.0 dotenv: ^16.0.0
@ -61,6 +62,7 @@ importers:
'@unblockneteasemusic/rust-napi': 0.3.0-pre.1 '@unblockneteasemusic/rust-napi': 0.3.0-pre.1
better-sqlite3: 7.5.1 better-sqlite3: 7.5.1
change-case: 4.1.2 change-case: 4.1.2
compare-versions: 4.1.3
cookie-parser: 1.4.6 cookie-parser: 1.4.6
electron-log: 4.4.7 electron-log: 4.4.7
electron-store: 8.0.1 electron-store: 8.0.1
@ -2554,6 +2556,10 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true dev: true
/compare-versions/4.1.3:
resolution: {integrity: sha512-WQfnbDcrYnGr55UwbxKiQKASnTtNnaAWVi8jZyy8NTpVAXWACSne8lMD1iaIo9AiU6mnuLvSVshCzewVuWxHUg==}
dev: false
/component-emitter/1.3.0: /component-emitter/1.3.0:
resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
dev: true dev: true