mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
refactor: split plugin index record reader
This commit is contained in:
58
src/plugins/installed-plugin-index-record-reader.ts
Normal file
58
src/plugins/installed-plugin-index-record-reader.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { PluginInstallRecord } from "../config/types.plugins.js";
|
||||
import { readJsonFile, readJsonFileSync } from "../infra/json-files.js";
|
||||
import {
|
||||
resolveInstalledPluginIndexStorePath,
|
||||
type InstalledPluginIndexStoreOptions,
|
||||
} from "./installed-plugin-index-store-path.js";
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function cloneInstallRecords(
|
||||
records: Record<string, PluginInstallRecord> | undefined,
|
||||
): Record<string, PluginInstallRecord> {
|
||||
return structuredClone(records ?? {});
|
||||
}
|
||||
|
||||
export function extractPluginInstallRecordsFromPersistedInstalledPluginIndex(
|
||||
index: unknown,
|
||||
): Record<string, PluginInstallRecord> | null {
|
||||
if (!isRecord(index) || !Array.isArray(index.plugins)) {
|
||||
return null;
|
||||
}
|
||||
const records: Record<string, PluginInstallRecord> = {};
|
||||
for (const entry of index.plugins) {
|
||||
if (!isRecord(entry) || typeof entry.pluginId !== "string" || !isRecord(entry.installRecord)) {
|
||||
continue;
|
||||
}
|
||||
records[entry.pluginId] = structuredClone(entry.installRecord) as PluginInstallRecord;
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
export async function readPersistedInstalledPluginIndexInstallRecords(
|
||||
options: InstalledPluginIndexStoreOptions = {},
|
||||
): Promise<Record<string, PluginInstallRecord> | null> {
|
||||
const parsed = await readJsonFile<unknown>(resolveInstalledPluginIndexStorePath(options));
|
||||
return extractPluginInstallRecordsFromPersistedInstalledPluginIndex(parsed);
|
||||
}
|
||||
|
||||
export function readPersistedInstalledPluginIndexInstallRecordsSync(
|
||||
options: InstalledPluginIndexStoreOptions = {},
|
||||
): Record<string, PluginInstallRecord> | null {
|
||||
const parsed = readJsonFileSync(resolveInstalledPluginIndexStorePath(options));
|
||||
return extractPluginInstallRecordsFromPersistedInstalledPluginIndex(parsed);
|
||||
}
|
||||
|
||||
export async function loadInstalledPluginIndexInstallRecords(
|
||||
params: InstalledPluginIndexStoreOptions = {},
|
||||
): Promise<Record<string, PluginInstallRecord>> {
|
||||
return cloneInstallRecords((await readPersistedInstalledPluginIndexInstallRecords(params)) ?? {});
|
||||
}
|
||||
|
||||
export function loadInstalledPluginIndexInstallRecordsSync(
|
||||
params: InstalledPluginIndexStoreOptions = {},
|
||||
): Record<string, PluginInstallRecord> {
|
||||
return cloneInstallRecords(readPersistedInstalledPluginIndexInstallRecordsSync(params) ?? {});
|
||||
}
|
||||
@@ -1,17 +1,23 @@
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { PluginInstallRecord } from "../config/types.plugins.js";
|
||||
import {
|
||||
readPersistedInstalledPluginIndex,
|
||||
readPersistedInstalledPluginIndexSync,
|
||||
refreshPersistedInstalledPluginIndex,
|
||||
resolveInstalledPluginIndexStorePath,
|
||||
} from "./installed-plugin-index-store.js";
|
||||
import {
|
||||
extractPluginInstallRecordsFromInstalledPluginIndex,
|
||||
type RefreshInstalledPluginIndexParams,
|
||||
} from "./installed-plugin-index.js";
|
||||
loadInstalledPluginIndexInstallRecords,
|
||||
loadInstalledPluginIndexInstallRecordsSync,
|
||||
readPersistedInstalledPluginIndexInstallRecords,
|
||||
readPersistedInstalledPluginIndexInstallRecordsSync,
|
||||
} from "./installed-plugin-index-record-reader.js";
|
||||
import { resolveInstalledPluginIndexStorePath } from "./installed-plugin-index-store-path.js";
|
||||
import { refreshPersistedInstalledPluginIndex } from "./installed-plugin-index-store.js";
|
||||
import { type RefreshInstalledPluginIndexParams } from "./installed-plugin-index.js";
|
||||
import { recordPluginInstall, type PluginInstallUpdate } from "./installs.js";
|
||||
|
||||
export {
|
||||
loadInstalledPluginIndexInstallRecords,
|
||||
loadInstalledPluginIndexInstallRecordsSync,
|
||||
readPersistedInstalledPluginIndexInstallRecords,
|
||||
readPersistedInstalledPluginIndexInstallRecordsSync,
|
||||
};
|
||||
|
||||
export const PLUGIN_INSTALLS_CONFIG_PATH = ["plugins", "installs"] as const;
|
||||
|
||||
export type InstalledPluginIndexRecordStoreOptions = {
|
||||
@@ -25,39 +31,12 @@ type InstalledPluginIndexRecordRefreshOptions = InstalledPluginIndexRecordStoreO
|
||||
now?: () => Date;
|
||||
};
|
||||
|
||||
function toInstallRecords(
|
||||
index: Awaited<ReturnType<typeof readPersistedInstalledPluginIndex>>,
|
||||
): Record<string, PluginInstallRecord> | null {
|
||||
if (!index) {
|
||||
return null;
|
||||
}
|
||||
return extractPluginInstallRecordsFromInstalledPluginIndex(index);
|
||||
}
|
||||
|
||||
function cloneInstallRecords(
|
||||
records: Record<string, PluginInstallRecord> | undefined,
|
||||
): Record<string, PluginInstallRecord> {
|
||||
return structuredClone(records ?? {});
|
||||
}
|
||||
|
||||
export function resolveInstalledPluginIndexRecordsStorePath(
|
||||
options: InstalledPluginIndexRecordStoreOptions = {},
|
||||
): string {
|
||||
return resolveInstalledPluginIndexStorePath(options);
|
||||
}
|
||||
|
||||
export async function readPersistedInstalledPluginIndexInstallRecords(
|
||||
options: InstalledPluginIndexRecordStoreOptions = {},
|
||||
): Promise<Record<string, PluginInstallRecord> | null> {
|
||||
return toInstallRecords(await readPersistedInstalledPluginIndex(options));
|
||||
}
|
||||
|
||||
export function readPersistedInstalledPluginIndexInstallRecordsSync(
|
||||
options: InstalledPluginIndexRecordStoreOptions = {},
|
||||
): Record<string, PluginInstallRecord> | null {
|
||||
return toInstallRecords(readPersistedInstalledPluginIndexSync(options));
|
||||
}
|
||||
|
||||
export async function writePersistedInstalledPluginIndexInstallRecords(
|
||||
records: Record<string, PluginInstallRecord>,
|
||||
options: InstalledPluginIndexRecordRefreshOptions = {},
|
||||
@@ -70,18 +49,6 @@ export async function writePersistedInstalledPluginIndexInstallRecords(
|
||||
return resolveInstalledPluginIndexRecordsStorePath(options);
|
||||
}
|
||||
|
||||
export async function loadInstalledPluginIndexInstallRecords(
|
||||
params: InstalledPluginIndexRecordStoreOptions = {},
|
||||
): Promise<Record<string, PluginInstallRecord>> {
|
||||
return cloneInstallRecords((await readPersistedInstalledPluginIndexInstallRecords(params)) ?? {});
|
||||
}
|
||||
|
||||
export function loadInstalledPluginIndexInstallRecordsSync(
|
||||
params: InstalledPluginIndexRecordStoreOptions = {},
|
||||
): Record<string, PluginInstallRecord> {
|
||||
return cloneInstallRecords(readPersistedInstalledPluginIndexInstallRecordsSync(params) ?? {});
|
||||
}
|
||||
|
||||
export function withPluginInstallRecords(
|
||||
config: OpenClawConfig,
|
||||
records: Record<string, PluginInstallRecord>,
|
||||
|
||||
21
src/plugins/installed-plugin-index-store-path.ts
Normal file
21
src/plugins/installed-plugin-index-store-path.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import path from "node:path";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
|
||||
export const INSTALLED_PLUGIN_INDEX_STORE_PATH = path.join("plugins", "installs.json");
|
||||
|
||||
export type InstalledPluginIndexStoreOptions = {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
stateDir?: string;
|
||||
filePath?: string;
|
||||
};
|
||||
|
||||
export function resolveInstalledPluginIndexStorePath(
|
||||
options: InstalledPluginIndexStoreOptions = {},
|
||||
): string {
|
||||
if (options.filePath) {
|
||||
return options.filePath;
|
||||
}
|
||||
const env = options.env ?? process.env;
|
||||
const stateDir = options.stateDir ?? resolveStateDir(env);
|
||||
return path.join(stateDir, INSTALLED_PLUGIN_INDEX_STORE_PATH);
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
import path from "node:path";
|
||||
import { z } from "zod";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { readJsonFile, readJsonFileSync, writeJsonAtomic } from "../infra/json-files.js";
|
||||
import { safeParseWithSchema } from "../utils/zod-parse.js";
|
||||
import {
|
||||
resolveInstalledPluginIndexStorePath,
|
||||
type InstalledPluginIndexStoreOptions,
|
||||
} from "./installed-plugin-index-store-path.js";
|
||||
import {
|
||||
diffInstalledPluginIndexInvalidationReasons,
|
||||
extractPluginInstallRecordsFromInstalledPluginIndex,
|
||||
@@ -16,14 +18,11 @@ import {
|
||||
type LoadInstalledPluginIndexParams,
|
||||
type RefreshInstalledPluginIndexParams,
|
||||
} from "./installed-plugin-index.js";
|
||||
|
||||
export const INSTALLED_PLUGIN_INDEX_STORE_PATH = path.join("plugins", "installs.json");
|
||||
|
||||
export type InstalledPluginIndexStoreOptions = {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
stateDir?: string;
|
||||
filePath?: string;
|
||||
};
|
||||
export {
|
||||
INSTALLED_PLUGIN_INDEX_STORE_PATH,
|
||||
resolveInstalledPluginIndexStorePath,
|
||||
type InstalledPluginIndexStoreOptions,
|
||||
} from "./installed-plugin-index-store-path.js";
|
||||
|
||||
export type InstalledPluginIndexStoreState = "missing" | "fresh" | "stale";
|
||||
|
||||
@@ -112,17 +111,6 @@ function parseInstalledPluginIndex(value: unknown): InstalledPluginIndex | null
|
||||
return safeParseWithSchema(InstalledPluginIndexSchema, value) as InstalledPluginIndex | null;
|
||||
}
|
||||
|
||||
export function resolveInstalledPluginIndexStorePath(
|
||||
options: InstalledPluginIndexStoreOptions = {},
|
||||
): string {
|
||||
if (options.filePath) {
|
||||
return options.filePath;
|
||||
}
|
||||
const env = options.env ?? process.env;
|
||||
const stateDir = options.stateDir ?? resolveStateDir(env);
|
||||
return path.join(stateDir, INSTALLED_PLUGIN_INDEX_STORE_PATH);
|
||||
}
|
||||
|
||||
export async function readPersistedInstalledPluginIndex(
|
||||
options: InstalledPluginIndexStoreOptions = {},
|
||||
): Promise<InstalledPluginIndex | null> {
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
type NormalizedPluginsConfig,
|
||||
} from "./config-policy.js";
|
||||
import { discoverOpenClawPlugins, type PluginCandidate } from "./discovery.js";
|
||||
import { loadInstalledPluginIndexInstallRecordsSync } from "./installed-plugin-index-records.js";
|
||||
import { loadInstalledPluginIndexInstallRecordsSync } from "./installed-plugin-index-record-reader.js";
|
||||
import type { PluginManifestCommandAlias } from "./manifest-command-aliases.js";
|
||||
import {
|
||||
clearPluginManifestRegistryCache,
|
||||
|
||||
Reference in New Issue
Block a user