mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-25 14:02:58 +00:00
150 lines
4.6 KiB
TypeScript
150 lines
4.6 KiB
TypeScript
import type {
|
|
SettingsMigrationReviewReason,
|
|
SettingsMigrationState,
|
|
} from "@vrtmrz/livesync-commonlib/compat/common/types";
|
|
|
|
export const DATABASE_COMPATIBILITY_VERSION_KEY = "database-compatibility-version";
|
|
export const DATABASE_COMPATIBILITY_LEGACY_VERSION_KEY_PREFIX = "obsidian-live-sync-ver";
|
|
export const COMPATIBILITY_PAUSE_SETTING_MESSAGE =
|
|
"Remote synchronisation is paused until this device's compatibility review has been completed.";
|
|
|
|
export type DatabaseCompatibilityVersionState = "missing" | "invalid" | "upgrade" | "downgrade";
|
|
|
|
export interface DatabaseCompatibilityReason {
|
|
source: "database-version";
|
|
state: DatabaseCompatibilityVersionState;
|
|
acknowledgedVersion?: number;
|
|
currentVersion: number;
|
|
resumable: boolean;
|
|
}
|
|
|
|
export interface SettingsCompatibilityReason {
|
|
source: "settings-schema";
|
|
sourceVersion: number;
|
|
currentVersion: number;
|
|
isFromFutureSchema: boolean;
|
|
resumable: boolean;
|
|
reviewReasons: readonly SettingsMigrationReviewReason[];
|
|
}
|
|
|
|
export interface LegacyCompatibilityReason {
|
|
source: "legacy-review";
|
|
message: string;
|
|
resumable: true;
|
|
}
|
|
|
|
export type CompatibilityPauseReason =
|
|
| DatabaseCompatibilityReason
|
|
| SettingsCompatibilityReason
|
|
| LegacyCompatibilityReason;
|
|
|
|
export interface CompatibilityPause {
|
|
reasons: readonly CompatibilityPauseReason[];
|
|
resumable: boolean;
|
|
}
|
|
|
|
export interface CompatibilityEvaluation {
|
|
pause?: CompatibilityPause;
|
|
initialiseAcknowledgedVersion: boolean;
|
|
}
|
|
|
|
export interface CompatibilityEvaluationInput {
|
|
acknowledgedVersion: string | null;
|
|
currentVersion: number;
|
|
migrationState?: SettingsMigrationState;
|
|
legacyReviewMessage: string;
|
|
}
|
|
|
|
function databaseVersionReason(
|
|
acknowledgedVersion: string | null,
|
|
currentVersion: number,
|
|
isNewVault: boolean
|
|
): DatabaseCompatibilityReason | undefined {
|
|
if (acknowledgedVersion === null || acknowledgedVersion === "") {
|
|
if (isNewVault) return undefined;
|
|
return {
|
|
source: "database-version",
|
|
state: "missing",
|
|
currentVersion,
|
|
resumable: true,
|
|
};
|
|
}
|
|
|
|
const parsed = Number(acknowledgedVersion);
|
|
if (!Number.isSafeInteger(parsed)) {
|
|
return {
|
|
source: "database-version",
|
|
state: "invalid",
|
|
currentVersion,
|
|
resumable: true,
|
|
};
|
|
}
|
|
if (parsed === currentVersion) return undefined;
|
|
if (parsed < currentVersion) {
|
|
return {
|
|
source: "database-version",
|
|
state: "upgrade",
|
|
acknowledgedVersion: parsed,
|
|
currentVersion,
|
|
resumable: true,
|
|
};
|
|
}
|
|
return {
|
|
source: "database-version",
|
|
state: "downgrade",
|
|
acknowledgedVersion: parsed,
|
|
currentVersion,
|
|
resumable: false,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Derives a host-neutral compatibility pause from device-local and settings-schema state.
|
|
*
|
|
* The caller owns persistence, user interaction, and the actual replication gate.
|
|
*/
|
|
export function evaluateCompatibilityPause(input: CompatibilityEvaluationInput): CompatibilityEvaluation {
|
|
const isNewVault = input.migrationState?.isNewVault === true;
|
|
const reasons: CompatibilityPauseReason[] = [];
|
|
const databaseReason = databaseVersionReason(input.acknowledgedVersion, input.currentVersion, isNewVault);
|
|
if (databaseReason) reasons.push(databaseReason);
|
|
|
|
if (input.migrationState?.requiresSyncReview === true) {
|
|
reasons.push({
|
|
source: "settings-schema",
|
|
sourceVersion: input.migrationState.sourceVersion,
|
|
currentVersion: input.migrationState.targetVersion,
|
|
isFromFutureSchema: input.migrationState.isFromFutureSchema,
|
|
resumable: !input.migrationState.isFromFutureSchema,
|
|
reviewReasons: input.migrationState.reviewReasons,
|
|
});
|
|
}
|
|
|
|
if (input.legacyReviewMessage !== "" && reasons.length === 0) {
|
|
reasons.push({
|
|
source: "legacy-review",
|
|
message: input.legacyReviewMessage,
|
|
resumable: true,
|
|
});
|
|
}
|
|
|
|
if (reasons.length === 0) {
|
|
return {
|
|
initialiseAcknowledgedVersion:
|
|
isNewVault && (input.acknowledgedVersion === null || input.acknowledgedVersion === ""),
|
|
};
|
|
}
|
|
|
|
return {
|
|
pause: {
|
|
reasons,
|
|
resumable: reasons.every((reason) => reason.resumable),
|
|
},
|
|
initialiseAcknowledgedVersion: false,
|
|
};
|
|
}
|
|
|
|
export function legacyDatabaseCompatibilityVersionKey(vaultName: string): string {
|
|
return `${DATABASE_COMPATIBILITY_LEGACY_VERSION_KEY_PREFIX}${vaultName}`;
|
|
}
|