chore(deadcode): share nostr state account ids

This commit is contained in:
Vincent Koc
2026-06-21 07:35:37 +08:00
parent 2755112353
commit 22bdda2555
5 changed files with 66 additions and 22 deletions

View File

@@ -102,4 +102,33 @@ describe("nostr doctor state migration", () => {
lastPublishResults: { "wss://relay.example": "ok" },
});
});
it("preserves legacy account key bytes when importing state files", async () => {
const nostrDir = path.join(stateDir, "nostr");
const busPath = path.join(nostrDir, "bus-state-Team.A.json");
await fs.mkdir(nostrDir, { recursive: true });
await fs.writeFile(
busPath,
JSON.stringify({
version: 1,
lastProcessedAt: 1700,
gatewayStartedAt: 1600,
}),
);
const context = createDoctorContext(env);
await stateMigrations[0].migrateLegacyState({
config: {},
env,
stateDir,
oauthDir: path.join(stateDir, "oauth"),
context,
});
const store = context.openPluginStateKeyedStore({ namespace: "bus-state", maxEntries: 256 });
await expect(store.lookup("Team.A")).resolves.toMatchObject({
lastProcessedAt: 1700,
});
await expect(store.lookup("team-a")).resolves.toBeUndefined();
});
});

View File

@@ -3,6 +3,7 @@ import type { Dirent } from "node:fs";
import fs from "node:fs/promises";
import path from "node:path";
import type { PluginDoctorStateMigration } from "openclaw/plugin-sdk/runtime-doctor";
import { normalizeNostrStateAccountId } from "./src/state-account-id.js";
type NostrBusState = {
version: 2;
@@ -22,14 +23,6 @@ const BUS_STATE_NAMESPACE = "bus-state";
const PROFILE_STATE_NAMESPACE = "profile-state";
const MAX_NOSTR_STATE_ENTRIES = 256;
function normalizeAccountId(accountId?: string): string {
const trimmed = accountId?.trim();
if (!trimmed) {
return "default";
}
return trimmed.replace(/[^a-z0-9._-]+/gi, "_");
}
function finiteNumberOrNull(value: unknown): number | null {
return typeof value === "number" && Number.isFinite(value) ? value : null;
}
@@ -114,7 +107,7 @@ async function listLegacyFiles(params: {
continue;
}
const rawAccountId = entry.name.slice(params.prefix.length, -suffix.length);
const accountId = normalizeAccountId(rawAccountId);
const accountId = normalizeNostrStateAccountId(rawAccountId);
const filePath = path.join(dir, entry.name);
try {
const value = params.parse(await readJsonFile(filePath));

View File

@@ -97,6 +97,21 @@ describe("nostr bus state store", () => {
expect(stateB?.lastProcessedAt).toBe(2000);
});
});
it("preserves legacy account key bytes for state lookup", async () => {
await withTempStateDir(async () => {
await writeNostrBusState({
accountId: " Team.A ",
lastProcessedAt: 1234,
gatewayStartedAt: 1200,
});
await expect(readNostrBusState({ accountId: "Team.A" })).resolves.toMatchObject({
lastProcessedAt: 1234,
});
await expect(readNostrBusState({ accountId: "team-a" })).resolves.toBeNull();
});
});
});
describe("nostr profile state store", () => {

View File

@@ -1,5 +1,6 @@
// Nostr plugin module implements nostr state store behavior.
import { getNostrRuntime } from "./runtime.js";
import { normalizeNostrStateAccountId } from "./state-account-id.js";
const STORE_VERSION = 2;
const PROFILE_STATE_VERSION = 1;
@@ -25,14 +26,6 @@ type NostrProfileState = {
lastPublishResults: Record<string, "ok" | "failed" | "timeout"> | null;
};
function normalizeAccountId(accountId?: string): string {
const trimmed = accountId?.trim();
if (!trimmed) {
return "default";
}
return trimmed.replace(/[^a-z0-9._-]+/gi, "_");
}
function openNostrBusStateStore(env?: NodeJS.ProcessEnv) {
return getNostrRuntime().state.openKeyedStore<NostrBusState>({
namespace: "bus-state",
@@ -54,7 +47,9 @@ export async function readNostrBusState(params: {
env?: NodeJS.ProcessEnv;
}): Promise<NostrBusState | null> {
return (
(await openNostrBusStateStore(params.env).lookup(normalizeAccountId(params.accountId))) ?? null
(await openNostrBusStateStore(params.env).lookup(
normalizeNostrStateAccountId(params.accountId),
)) ?? null
);
}
@@ -71,7 +66,10 @@ export async function writeNostrBusState(params: {
gatewayStartedAt: params.gatewayStartedAt,
recentEventIds: (params.recentEventIds ?? []).filter((x): x is string => typeof x === "string"),
};
await openNostrBusStateStore(params.env).register(normalizeAccountId(params.accountId), payload);
await openNostrBusStateStore(params.env).register(
normalizeNostrStateAccountId(params.accountId),
payload,
);
}
/**
@@ -107,8 +105,9 @@ export async function readNostrProfileState(params: {
env?: NodeJS.ProcessEnv;
}): Promise<NostrProfileState | null> {
return (
(await openNostrProfileStateStore(params.env).lookup(normalizeAccountId(params.accountId))) ??
null
(await openNostrProfileStateStore(params.env).lookup(
normalizeNostrStateAccountId(params.accountId),
)) ?? null
);
}
@@ -126,7 +125,7 @@ export async function writeNostrProfileState(params: {
lastPublishResults: params.lastPublishResults,
};
await openNostrProfileStateStore(params.env).register(
normalizeAccountId(params.accountId),
normalizeNostrStateAccountId(params.accountId),
payload,
);
}

View File

@@ -0,0 +1,8 @@
// Nostr state stores keep legacy account key bytes; do not use the newer SDK normalizer here.
export function normalizeNostrStateAccountId(accountId?: string): string {
const trimmed = accountId?.trim();
if (!trimmed) {
return "default";
}
return trimmed.replace(/[^a-z0-9._-]+/gi, "_");
}