mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-17 20:21:13 +00:00
matrix: break migration runtime import cycle
This commit is contained in:
@@ -1 +1 @@
|
||||
export * from "./src/runtime-heavy-api.js";
|
||||
export * from "./src/matrix-migration.runtime.js";
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
export {
|
||||
autoMigrateLegacyMatrixState,
|
||||
autoPrepareLegacyMatrixCrypto,
|
||||
detectLegacyMatrixCrypto,
|
||||
detectLegacyMatrixState,
|
||||
hasActionableMatrixMigration,
|
||||
hasPendingMatrixMigration,
|
||||
maybeCreateMatrixMigrationSnapshot,
|
||||
} from "./runtime-heavy-api.js";
|
||||
export { autoMigrateLegacyMatrixState, detectLegacyMatrixState } from "./legacy-state.js";
|
||||
export { autoPrepareLegacyMatrixCrypto, detectLegacyMatrixCrypto } from "./legacy-crypto.js";
|
||||
export { hasActionableMatrixMigration, hasPendingMatrixMigration } from "./migration-snapshot.js";
|
||||
export { maybeCreateMatrixMigrationSnapshot } from "./migration-snapshot-backup.js";
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { maybeCreateMatrixMigrationSnapshot } from "../../matrix-migration.runtime.js";
|
||||
export { maybeCreateMatrixMigrationSnapshot } from "../../migration-snapshot-backup.js";
|
||||
|
||||
117
extensions/matrix/src/migration-snapshot-backup.ts
Normal file
117
extensions/matrix/src/migration-snapshot-backup.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
||||
import { resolveRequiredHomeDir } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
|
||||
|
||||
const MATRIX_MIGRATION_SNAPSHOT_DIRNAME = "openclaw-migrations";
|
||||
|
||||
type MatrixMigrationSnapshotMarker = {
|
||||
version: 1;
|
||||
createdAt: string;
|
||||
archivePath: string;
|
||||
trigger: string;
|
||||
includeWorkspace: boolean;
|
||||
};
|
||||
|
||||
export type MatrixMigrationSnapshotResult = {
|
||||
created: boolean;
|
||||
archivePath: string;
|
||||
markerPath: string;
|
||||
};
|
||||
|
||||
function loadSnapshotMarker(filePath: string): MatrixMigrationSnapshotMarker | null {
|
||||
try {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return null;
|
||||
}
|
||||
const parsed = JSON.parse(
|
||||
fs.readFileSync(filePath, "utf8"),
|
||||
) as Partial<MatrixMigrationSnapshotMarker>;
|
||||
if (
|
||||
parsed.version !== 1 ||
|
||||
typeof parsed.createdAt !== "string" ||
|
||||
typeof parsed.archivePath !== "string" ||
|
||||
typeof parsed.trigger !== "string"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
version: 1,
|
||||
createdAt: parsed.createdAt,
|
||||
archivePath: parsed.archivePath,
|
||||
trigger: parsed.trigger,
|
||||
includeWorkspace: parsed.includeWorkspace === true,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveMatrixMigrationSnapshotMarkerPath(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): string {
|
||||
const stateDir = resolveStateDir(env, os.homedir);
|
||||
return path.join(stateDir, "matrix", "migration-snapshot.json");
|
||||
}
|
||||
|
||||
export function resolveMatrixMigrationSnapshotOutputDir(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): string {
|
||||
const homeDir = resolveRequiredHomeDir(env, os.homedir);
|
||||
return path.join(homeDir, "Backups", MATRIX_MIGRATION_SNAPSHOT_DIRNAME);
|
||||
}
|
||||
|
||||
export async function maybeCreateMatrixMigrationSnapshot(params: {
|
||||
trigger: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
outputDir?: string;
|
||||
createBackupArchive?: typeof import("openclaw/plugin-sdk/runtime").createBackupArchive;
|
||||
log?: { info?: (message: string) => void; warn?: (message: string) => void };
|
||||
}): Promise<MatrixMigrationSnapshotResult> {
|
||||
const env = params.env ?? process.env;
|
||||
const createBackupArchive =
|
||||
params.createBackupArchive ?? (await import("openclaw/plugin-sdk/runtime")).createBackupArchive;
|
||||
const markerPath = resolveMatrixMigrationSnapshotMarkerPath(env);
|
||||
const existingMarker = loadSnapshotMarker(markerPath);
|
||||
if (existingMarker?.archivePath && fs.existsSync(existingMarker.archivePath)) {
|
||||
params.log?.info?.(
|
||||
`matrix: reusing existing pre-migration backup snapshot: ${existingMarker.archivePath}`,
|
||||
);
|
||||
return {
|
||||
created: false,
|
||||
archivePath: existingMarker.archivePath,
|
||||
markerPath,
|
||||
};
|
||||
}
|
||||
if (existingMarker?.archivePath && !fs.existsSync(existingMarker.archivePath)) {
|
||||
params.log?.warn?.(
|
||||
`matrix: previous migration snapshot is missing (${existingMarker.archivePath}); creating a replacement backup before continuing`,
|
||||
);
|
||||
}
|
||||
|
||||
const snapshot = await createBackupArchive({
|
||||
output: (() => {
|
||||
const outputDir = params.outputDir ?? resolveMatrixMigrationSnapshotOutputDir(env);
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
return outputDir;
|
||||
})(),
|
||||
includeWorkspace: false,
|
||||
});
|
||||
|
||||
const marker: MatrixMigrationSnapshotMarker = {
|
||||
version: 1,
|
||||
createdAt: snapshot.createdAt,
|
||||
archivePath: snapshot.archivePath,
|
||||
trigger: params.trigger,
|
||||
includeWorkspace: snapshot.includeWorkspace,
|
||||
};
|
||||
await writeJsonFileAtomically(markerPath, marker);
|
||||
params.log?.info?.(`matrix: created pre-migration backup snapshot: ${snapshot.archivePath}`);
|
||||
return {
|
||||
created: true,
|
||||
archivePath: snapshot.archivePath,
|
||||
markerPath,
|
||||
};
|
||||
}
|
||||
@@ -1,75 +1,17 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
|
||||
import { resolveRequiredHomeDir } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
|
||||
import { detectLegacyMatrixCrypto } from "./legacy-crypto.js";
|
||||
import { detectLegacyMatrixState } from "./legacy-state.js";
|
||||
|
||||
const MATRIX_MIGRATION_SNAPSHOT_DIRNAME = "openclaw-migrations";
|
||||
import {
|
||||
maybeCreateMatrixMigrationSnapshot,
|
||||
resolveMatrixMigrationSnapshotMarkerPath,
|
||||
resolveMatrixMigrationSnapshotOutputDir,
|
||||
type MatrixMigrationSnapshotResult,
|
||||
} from "./migration-snapshot-backup.js";
|
||||
|
||||
function isMatrixLegacyCryptoInspectorAvailable(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
type MatrixMigrationSnapshotMarker = {
|
||||
version: 1;
|
||||
createdAt: string;
|
||||
archivePath: string;
|
||||
trigger: string;
|
||||
includeWorkspace: boolean;
|
||||
};
|
||||
|
||||
export type MatrixMigrationSnapshotResult = {
|
||||
created: boolean;
|
||||
archivePath: string;
|
||||
markerPath: string;
|
||||
};
|
||||
|
||||
function loadSnapshotMarker(filePath: string): MatrixMigrationSnapshotMarker | null {
|
||||
try {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return null;
|
||||
}
|
||||
const parsed = JSON.parse(
|
||||
fs.readFileSync(filePath, "utf8"),
|
||||
) as Partial<MatrixMigrationSnapshotMarker>;
|
||||
if (
|
||||
parsed.version !== 1 ||
|
||||
typeof parsed.createdAt !== "string" ||
|
||||
typeof parsed.archivePath !== "string" ||
|
||||
typeof parsed.trigger !== "string"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
version: 1,
|
||||
createdAt: parsed.createdAt,
|
||||
archivePath: parsed.archivePath,
|
||||
trigger: parsed.trigger,
|
||||
includeWorkspace: parsed.includeWorkspace === true,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveMatrixMigrationSnapshotMarkerPath(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): string {
|
||||
const stateDir = resolveStateDir(env, os.homedir);
|
||||
return path.join(stateDir, "matrix", "migration-snapshot.json");
|
||||
}
|
||||
|
||||
export function resolveMatrixMigrationSnapshotOutputDir(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): string {
|
||||
const homeDir = resolveRequiredHomeDir(env, os.homedir);
|
||||
return path.join(homeDir, "Backups", MATRIX_MIGRATION_SNAPSHOT_DIRNAME);
|
||||
}
|
||||
|
||||
export function hasPendingMatrixMigration(params: {
|
||||
cfg: OpenClawConfig;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
@@ -96,55 +38,9 @@ export function hasActionableMatrixMigration(params: {
|
||||
return legacyCrypto.plans.length > 0 && isMatrixLegacyCryptoInspectorAvailable();
|
||||
}
|
||||
|
||||
export async function maybeCreateMatrixMigrationSnapshot(params: {
|
||||
trigger: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
outputDir?: string;
|
||||
createBackupArchive?: typeof import("openclaw/plugin-sdk/runtime").createBackupArchive;
|
||||
log?: { info?: (message: string) => void; warn?: (message: string) => void };
|
||||
}): Promise<MatrixMigrationSnapshotResult> {
|
||||
const env = params.env ?? process.env;
|
||||
const createBackupArchive =
|
||||
params.createBackupArchive ?? (await import("openclaw/plugin-sdk/runtime")).createBackupArchive;
|
||||
const markerPath = resolveMatrixMigrationSnapshotMarkerPath(env);
|
||||
const existingMarker = loadSnapshotMarker(markerPath);
|
||||
if (existingMarker?.archivePath && fs.existsSync(existingMarker.archivePath)) {
|
||||
params.log?.info?.(
|
||||
`matrix: reusing existing pre-migration backup snapshot: ${existingMarker.archivePath}`,
|
||||
);
|
||||
return {
|
||||
created: false,
|
||||
archivePath: existingMarker.archivePath,
|
||||
markerPath,
|
||||
};
|
||||
}
|
||||
if (existingMarker?.archivePath && !fs.existsSync(existingMarker.archivePath)) {
|
||||
params.log?.warn?.(
|
||||
`matrix: previous migration snapshot is missing (${existingMarker.archivePath}); creating a replacement backup before continuing`,
|
||||
);
|
||||
}
|
||||
|
||||
const snapshot = await createBackupArchive({
|
||||
output: (() => {
|
||||
const outputDir = params.outputDir ?? resolveMatrixMigrationSnapshotOutputDir(env);
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
return outputDir;
|
||||
})(),
|
||||
includeWorkspace: false,
|
||||
});
|
||||
|
||||
const marker: MatrixMigrationSnapshotMarker = {
|
||||
version: 1,
|
||||
createdAt: snapshot.createdAt,
|
||||
archivePath: snapshot.archivePath,
|
||||
trigger: params.trigger,
|
||||
includeWorkspace: snapshot.includeWorkspace,
|
||||
};
|
||||
await writeJsonFileAtomically(markerPath, marker);
|
||||
params.log?.info?.(`matrix: created pre-migration backup snapshot: ${snapshot.archivePath}`);
|
||||
return {
|
||||
created: true,
|
||||
archivePath: snapshot.archivePath,
|
||||
markerPath,
|
||||
};
|
||||
}
|
||||
export {
|
||||
maybeCreateMatrixMigrationSnapshot,
|
||||
resolveMatrixMigrationSnapshotMarkerPath,
|
||||
resolveMatrixMigrationSnapshotOutputDir,
|
||||
};
|
||||
export type { MatrixMigrationSnapshotResult };
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
export { autoPrepareLegacyMatrixCrypto, detectLegacyMatrixCrypto } from "./legacy-crypto.js";
|
||||
export { autoMigrateLegacyMatrixState, detectLegacyMatrixState } from "./legacy-state.js";
|
||||
export {
|
||||
hasActionableMatrixMigration,
|
||||
hasPendingMatrixMigration,
|
||||
maybeCreateMatrixMigrationSnapshot,
|
||||
} from "./migration-snapshot.js";
|
||||
Reference in New Issue
Block a user