refactor: isolate plugin index legacy migration

This commit is contained in:
Peter Steinberger
2026-05-09 01:06:05 +01:00
parent 8c15d72319
commit ae475d025f
4 changed files with 77 additions and 56 deletions

View File

@@ -84,7 +84,7 @@ import {
import {
importLegacyInstalledPluginIndexFileToSqlite,
legacyInstalledPluginIndexFileExists,
} from "../plugins/installed-plugin-index-store.js";
} from "../plugins/installed-plugin-index-legacy-migration.js";
import { note } from "../terminal/note.js";
import {
importLegacyTuiLastSessionStoreToSqlite,

View File

@@ -0,0 +1,74 @@
import fs from "node:fs";
import { tryReadJsonSync } from "../infra/json-files.js";
import {
writeOpenClawStateKvJson,
type OpenClawStateJsonValue,
} from "../state/openclaw-state-kv.js";
import { clearCurrentPluginMetadataSnapshotState } from "./current-plugin-metadata-state.js";
import {
INSTALLED_PLUGIN_INDEX_KV_KEY,
INSTALLED_PLUGIN_INDEX_KV_SCOPE,
parseInstalledPluginIndex,
resolveInstalledPluginIndexStateDbOptions,
} from "./installed-plugin-index-persisted-read.js";
import {
resolveInstalledPluginIndexStorePath,
type InstalledPluginIndexStoreOptions,
} from "./installed-plugin-index-store-path.js";
import {
INSTALLED_PLUGIN_INDEX_WARNING,
type InstalledPluginIndex,
} from "./installed-plugin-index-types.js";
function withInstalledPluginIndexWarning(index: InstalledPluginIndex): InstalledPluginIndex & {
warning: string;
} {
return { ...index, warning: INSTALLED_PLUGIN_INDEX_WARNING };
}
export function legacyInstalledPluginIndexFileExists(
options: InstalledPluginIndexStoreOptions = {},
): boolean {
try {
return fs.existsSync(resolveInstalledPluginIndexStorePath(options));
} catch {
return false;
}
}
export type ImportLegacyInstalledPluginIndexResult = {
imported: boolean;
plugins: number;
installRecords: number;
removedSource: boolean;
};
export function importLegacyInstalledPluginIndexFileToSqlite(
options: InstalledPluginIndexStoreOptions = {},
): ImportLegacyInstalledPluginIndexResult {
const filePath = resolveInstalledPluginIndexStorePath(options);
const parsed = parseInstalledPluginIndex(tryReadJsonSync(filePath));
if (!parsed) {
return { imported: false, plugins: 0, installRecords: 0, removedSource: false };
}
writeOpenClawStateKvJson(
INSTALLED_PLUGIN_INDEX_KV_SCOPE,
INSTALLED_PLUGIN_INDEX_KV_KEY,
withInstalledPluginIndexWarning(parsed) as unknown as OpenClawStateJsonValue,
resolveInstalledPluginIndexStateDbOptions({ env: options.env, stateDir: options.stateDir }),
);
let removedSource = false;
try {
fs.unlinkSync(filePath);
removedSource = true;
} catch {
removedSource = false;
}
clearCurrentPluginMetadataSnapshotState();
return {
imported: true,
plugins: parsed.plugins.length,
installRecords: Object.keys(parsed.installRecords ?? {}).length,
removedSource,
};
}

View File

@@ -4,8 +4,8 @@ import { afterEach, describe, expect, it } from "vitest";
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
import { readOpenClawStateKvJson } from "../state/openclaw-state-kv.js";
import type { PluginCandidate } from "./discovery.js";
import { importLegacyInstalledPluginIndexFileToSqlite } from "./installed-plugin-index-legacy-migration.js";
import {
importLegacyInstalledPluginIndexFileToSqlite,
inspectPersistedInstalledPluginIndex,
readPersistedInstalledPluginIndex,
refreshPersistedInstalledPluginIndex,

View File

@@ -1,5 +1,3 @@
import fs from "node:fs";
import { tryReadJsonSync } from "../infra/json-files.js";
import {
deleteOpenClawStateKvJson,
writeOpenClawStateKvJson,
@@ -16,7 +14,6 @@ import { diffInstalledPluginIndexInvalidationReasons } from "./installed-plugin-
import {
INSTALLED_PLUGIN_INDEX_KV_KEY,
INSTALLED_PLUGIN_INDEX_KV_SCOPE,
parseInstalledPluginIndex,
readPersistedInstalledPluginIndex,
readPersistedInstalledPluginIndexSync,
resolveInstalledPluginIndexStateDbOptions,
@@ -25,10 +22,7 @@ import {
resolveCompatRegistryVersion,
resolveInstalledPluginIndexPolicyHash,
} from "./installed-plugin-index-policy.js";
import {
resolveInstalledPluginIndexStorePath,
type InstalledPluginIndexStoreOptions,
} from "./installed-plugin-index-store-path.js";
import type { InstalledPluginIndexStoreOptions } from "./installed-plugin-index-store-path.js";
import {
INSTALLED_PLUGIN_INDEX_MIGRATION_VERSION,
INSTALLED_PLUGIN_INDEX_VERSION,
@@ -102,53 +96,6 @@ export function deletePersistedInstalledPluginIndexSync(
return removed;
}
export function legacyInstalledPluginIndexFileExists(
options: InstalledPluginIndexStoreOptions = {},
): boolean {
try {
return fs.existsSync(resolveInstalledPluginIndexStorePath(options));
} catch {
return false;
}
}
export type ImportLegacyInstalledPluginIndexResult = {
imported: boolean;
plugins: number;
installRecords: number;
removedSource: boolean;
};
export function importLegacyInstalledPluginIndexFileToSqlite(
options: InstalledPluginIndexStoreOptions = {},
): ImportLegacyInstalledPluginIndexResult {
const filePath = resolveInstalledPluginIndexStorePath(options);
const parsed = parseInstalledPluginIndex(tryReadJsonSync(filePath));
if (!parsed) {
return { imported: false, plugins: 0, installRecords: 0, removedSource: false };
}
writeOpenClawStateKvJson(
INSTALLED_PLUGIN_INDEX_KV_SCOPE,
INSTALLED_PLUGIN_INDEX_KV_KEY,
withInstalledPluginIndexWarning(parsed) as unknown as OpenClawStateJsonValue,
resolveInstalledPluginIndexStateDbOptions({ env: options.env, stateDir: options.stateDir }),
);
let removedSource = false;
try {
fs.unlinkSync(filePath);
removedSource = true;
} catch {
removedSource = false;
}
clearCurrentPluginMetadataSnapshotState();
return {
imported: true,
plugins: parsed.plugins.length,
installRecords: Object.keys(parsed.installRecords ?? {}).length,
removedSource,
};
}
function hasPolicyRefreshTargets(
persisted: InstalledPluginIndex,
policyPluginIds: readonly string[] | undefined,