mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
fix: add DB migration to add workspace (#3115)
(cherry picked from commit dac4e390aa)
This commit is contained in:
11
packages/native/index.d.ts
vendored
11
packages/native/index.d.ts
vendored
@@ -7,7 +7,7 @@ export interface WatchOptions {
|
||||
recursive?: boolean;
|
||||
}
|
||||
/** Watcher kind enumeration */
|
||||
export const enum WatcherKind {
|
||||
export enum WatcherKind {
|
||||
/** inotify backend (linux) */
|
||||
Inotify = 'Inotify',
|
||||
/** FS-Event backend (mac) */
|
||||
@@ -38,6 +38,12 @@ export interface InsertRow {
|
||||
docId?: string;
|
||||
data: Uint8Array;
|
||||
}
|
||||
export enum ValidationResult {
|
||||
MissingTables = 0,
|
||||
MissingDocIdColumn = 1,
|
||||
GeneralError = 2,
|
||||
Valid = 3,
|
||||
}
|
||||
export class Subscription {
|
||||
toString(): string;
|
||||
unsubscribe(): void;
|
||||
@@ -71,5 +77,6 @@ export class SqliteConnection {
|
||||
): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
get isClose(): boolean;
|
||||
static validate(path: string): Promise<boolean>;
|
||||
static validate(path: string): Promise<ValidationResult>;
|
||||
migrateAddDocId(): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -263,11 +263,18 @@ if (!nativeBinding) {
|
||||
throw new Error(`Failed to load native binding`);
|
||||
}
|
||||
|
||||
const { WatcherKind, Subscription, FsWatcher, moveFile, SqliteConnection } =
|
||||
nativeBinding;
|
||||
const {
|
||||
WatcherKind,
|
||||
Subscription,
|
||||
FsWatcher,
|
||||
moveFile,
|
||||
SqliteConnection,
|
||||
ValidationResult,
|
||||
} = nativeBinding;
|
||||
|
||||
module.exports.WatcherKind = WatcherKind;
|
||||
module.exports.Subscription = Subscription;
|
||||
module.exports.FsWatcher = FsWatcher;
|
||||
module.exports.moveFile = moveFile;
|
||||
module.exports.SqliteConnection = SqliteConnection;
|
||||
module.exports.ValidationResult = ValidationResult;
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"aarch64-pc-windows-msvc"
|
||||
]
|
||||
},
|
||||
"ts": {
|
||||
"constEnum": false
|
||||
}
|
||||
},
|
||||
"license": "MPL-2.0",
|
||||
@@ -29,8 +32,8 @@
|
||||
},
|
||||
"scripts": {
|
||||
"artifacts": "napi artifacts",
|
||||
"build": "napi build --platform --release",
|
||||
"build:debug": "napi build --platform",
|
||||
"build": "napi build --platform --release --no-const-enum",
|
||||
"build:debug": "napi build --platform --no-const-enum",
|
||||
"universal": "napi universal",
|
||||
"test": "cross-env TS_NODE_TRANSPILE_ONLY=1 TS_NODE_PROJECT=./tsconfig.json node --test --loader ts-node/esm --experimental-specifier-resolution=node ./__tests__/**/*.mts",
|
||||
"version": "napi version"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use chrono::NaiveDateTime;
|
||||
use napi::bindgen_prelude::{Buffer, Uint8Array};
|
||||
use napi::bindgen_prelude::{Buffer, FromNapiValue, ToNapiValue, Uint8Array};
|
||||
use napi_derive::napi;
|
||||
use sqlx::{
|
||||
migrate::MigrateDatabase,
|
||||
@@ -34,6 +34,14 @@ pub struct SqliteConnection {
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub enum ValidationResult {
|
||||
MissingTables,
|
||||
MissingDocIdColumn,
|
||||
GeneralError,
|
||||
Valid,
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl SqliteConnection {
|
||||
#[napi(constructor)]
|
||||
@@ -231,14 +239,14 @@ impl SqliteConnection {
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub async fn validate(path: String) -> bool {
|
||||
pub async fn validate(path: String) -> ValidationResult {
|
||||
let pool = match SqlitePoolOptions::new()
|
||||
.max_connections(1)
|
||||
.connect(&path)
|
||||
.await
|
||||
{
|
||||
Ok(pool) => pool,
|
||||
Err(_) => return false,
|
||||
Err(_) => return ValidationResult::GeneralError,
|
||||
};
|
||||
|
||||
let tables_res = sqlx::query("SELECT name FROM sqlite_master WHERE type='table'")
|
||||
@@ -250,26 +258,32 @@ impl SqliteConnection {
|
||||
let names: Vec<String> = res.iter().map(|row| row.get(0)).collect();
|
||||
names.contains(&"updates".to_string()) && names.contains(&"blobs".to_string())
|
||||
}
|
||||
Err(_) => return false,
|
||||
Err(_) => return ValidationResult::GeneralError,
|
||||
};
|
||||
|
||||
let columns_res = sqlx::query("PRAGMA table_info(updates)")
|
||||
.fetch_all(&pool)
|
||||
.await;
|
||||
|
||||
let columns_exist = match columns_res {
|
||||
let doc_id_exist = match columns_res {
|
||||
Ok(res) => {
|
||||
let names: Vec<String> = res.iter().map(|row| row.get(1)).collect();
|
||||
names.contains(&"data".to_string()) && names.contains(&"doc_id".to_string())
|
||||
names.contains(&"doc_id".to_string())
|
||||
}
|
||||
Err(_) => return false,
|
||||
Err(_) => return ValidationResult::GeneralError,
|
||||
};
|
||||
|
||||
tables_exist && columns_exist
|
||||
if !tables_exist {
|
||||
ValidationResult::MissingTables
|
||||
} else if !doc_id_exist {
|
||||
ValidationResult::MissingDocIdColumn
|
||||
} else {
|
||||
ValidationResult::Valid
|
||||
}
|
||||
}
|
||||
|
||||
// todo: have a better way to handle migration
|
||||
async fn migrate_add_doc_id(&self) -> Result<(), anyhow::Error> {
|
||||
#[napi]
|
||||
pub async fn migrate_add_doc_id(&self) -> napi::Result<()> {
|
||||
// ignore errors
|
||||
match sqlx::query("ALTER TABLE updates ADD COLUMN doc_id TEXT")
|
||||
.execute(&self.pool)
|
||||
@@ -280,7 +294,7 @@ impl SqliteConnection {
|
||||
if err.to_string().contains("duplicate column name") {
|
||||
Ok(()) // Ignore error if it's due to duplicate column
|
||||
} else {
|
||||
Err(anyhow::Error::from(err)) // Propagate other errors
|
||||
Err(anyhow::Error::from(err).into()) // Propagate other errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user