feat(FN-3626): migrate plugin storage to project-scoped storage
Migrated the dependency-graph plugin's storage layer to use the project's scoped storage API (`projectStorage`) and added canonical storage-key assertions. The ChatView.tsx utility reference was updated to match the new storage path. Fusion-Task-Id: FN-3626
This commit is contained in:
@@ -96,9 +96,10 @@ describe("projectStorage", () => {
|
|||||||
"kb-usage-provider-order",
|
"kb-usage-provider-order",
|
||||||
"kb-chat-active-session",
|
"kb-chat-active-session",
|
||||||
"kb-files-line-numbers",
|
"kb-files-line-numbers",
|
||||||
|
"fusion-plugin-dependency-graph:positions",
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
expect(PROJECT_STORAGE_KEYS).toHaveLength(20);
|
expect(PROJECT_STORAGE_KEYS).toHaveLength(21);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("has no overlap between global and project-scoped keys", () => {
|
it("has no overlap between global and project-scoped keys", () => {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const PROJECT_STORAGE_KEYS: string[] = [
|
|||||||
"kb-usage-provider-order",
|
"kb-usage-provider-order",
|
||||||
"kb-chat-active-session",
|
"kb-chat-active-session",
|
||||||
"kb-files-line-numbers",
|
"kb-files-line-numbers",
|
||||||
|
"fusion-plugin-dependency-graph:positions",
|
||||||
];
|
];
|
||||||
|
|
||||||
export function scopedKey(baseKey: string, projectId?: string): string {
|
export function scopedKey(baseKey: string, projectId?: string): string {
|
||||||
|
|||||||
@@ -20,12 +20,22 @@ describe("storage", () => {
|
|||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("builds project-scoped key", () => {
|
it("builds project-scoped key with canonical base key", () => {
|
||||||
expect(projectScopedKey("proj_123")).toBe("kb:proj_123:dependency-graph-positions");
|
expect(projectScopedKey("proj_123")).toBe("kb:proj_123:fusion-plugin-dependency-graph:positions");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to unscoped key when projectId is missing or empty", () => {
|
||||||
|
expect(projectScopedKey()).toBe("fusion-plugin-dependency-graph:positions");
|
||||||
|
expect(projectScopedKey("")).toBe("fusion-plugin-dependency-graph:positions");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("persists and restores positions", () => {
|
it("persists and restores positions", () => {
|
||||||
savePositions("proj_123", { "FN-1": { x: 10, y: 20 } });
|
savePositions("proj_123", { "FN-1": { x: 10, y: 20 } });
|
||||||
expect(loadPositions("proj_123")).toEqual({ "FN-1": { x: 10, y: 20 } });
|
expect(loadPositions("proj_123")).toEqual({ "FN-1": { x: 10, y: 20 } });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("returns empty object for invalid JSON", () => {
|
||||||
|
localStorage.setItem("kb:proj_123:fusion-plugin-dependency-graph:positions", "not-json");
|
||||||
|
expect(loadPositions("proj_123")).toEqual({});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
const BASE_KEY = "dependency-graph-positions";
|
import { getScopedItem, scopedKey, setScopedItem } from "../../../packages/dashboard/app/utils/projectStorage";
|
||||||
|
|
||||||
|
const BASE_KEY = "fusion-plugin-dependency-graph:positions";
|
||||||
|
|
||||||
export function projectScopedKey(projectId?: string): string {
|
export function projectScopedKey(projectId?: string): string {
|
||||||
const suffix = projectId ?? "default";
|
return scopedKey(BASE_KEY, projectId);
|
||||||
return `kb:${suffix}:${BASE_KEY}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function loadPositions(projectId?: string): Record<string, { x: number; y: number }> {
|
export function loadPositions(projectId?: string): Record<string, { x: number; y: number }> {
|
||||||
if (typeof window === "undefined") return {};
|
|
||||||
try {
|
try {
|
||||||
const raw = window.localStorage.getItem(projectScopedKey(projectId));
|
const raw = getScopedItem(BASE_KEY, projectId);
|
||||||
if (!raw) return {};
|
if (!raw) return {};
|
||||||
const parsed = JSON.parse(raw) as Record<string, { x: number; y: number }>;
|
const parsed = JSON.parse(raw) as Record<string, { x: number; y: number }>;
|
||||||
return parsed ?? {};
|
return parsed ?? {};
|
||||||
@@ -18,6 +18,5 @@ export function loadPositions(projectId?: string): Record<string, { x: number; y
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function savePositions(projectId: string | undefined, positions: Record<string, { x: number; y: number }>): void {
|
export function savePositions(projectId: string | undefined, positions: Record<string, { x: number; y: number }>): void {
|
||||||
if (typeof window === "undefined") return;
|
setScopedItem(BASE_KEY, JSON.stringify(positions), projectId);
|
||||||
window.localStorage.setItem(projectScopedKey(projectId), JSON.stringify(positions));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"extends": "../tsconfig.base.json",
|
"extends": "../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"rootDir": "src",
|
"rootDir": "../..",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
|
|||||||
Reference in New Issue
Block a user