fix(saved-sql): preserve folder on metadata save

This commit is contained in:
t8y2 2026-07-02 11:55:26 +08:00
parent f70e04d22a
commit 18710ce2ab
2 changed files with 78 additions and 2 deletions

View File

@ -13,6 +13,16 @@ interface SavedSqlState {
files: SavedSqlFile[];
}
interface SaveFileInput {
id?: string;
connectionId: string;
folderId?: string;
name: string;
database: string;
schema?: string;
sql: string;
}
function nowIso() {
return new Date().toISOString();
}
@ -206,13 +216,16 @@ export const useSavedSqlStore = defineStore("savedSql", () => {
await syncToLocalDirectory();
}
async function saveFile(input: { id?: string; connectionId: string; folderId?: string; name: string; database: string; schema?: string; sql: string }) {
async function saveFile(input: SaveFileInput) {
const timestamp = nowIso();
const existing = input.id ? getFile(input.id) : undefined;
const hasFolderIdInput = Object.prototype.hasOwnProperty.call(input, "folderId");
const file: SavedSqlFile = existing
? {
...existing,
folderId: input.folderId || undefined,
// Partial metadata updates should not move files out of their folder.
// Callers that intentionally move to root pass `folderId: undefined`.
folderId: hasFolderIdInput ? input.folderId || undefined : existing.folderId,
name: input.name,
database: input.database,
schema: input.schema,

View File

@ -8,6 +8,7 @@ const apiMock = vi.hoisted(() => ({
loadSavedSqlLibrary: vi.fn<() => Promise<SavedSqlLibrary>>(),
loadSavedSqlFile: vi.fn<(id: string) => Promise<SavedSqlFile | null>>(),
saveSavedSqlFolder: vi.fn<(folder: SavedSqlFolder) => Promise<SavedSqlFolder>>(),
saveSavedSqlFile: vi.fn<(file: SavedSqlFile) => Promise<SavedSqlFile>>(),
syncSavedSqlDirectory: vi.fn<() => Promise<void>>(),
}));
@ -18,6 +19,7 @@ beforeEach(() => {
apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files: [] });
apiMock.loadSavedSqlFile.mockResolvedValue(null);
apiMock.saveSavedSqlFolder.mockImplementation(async (folder) => folder);
apiMock.saveSavedSqlFile.mockImplementation(async (file) => file);
apiMock.syncSavedSqlDirectory.mockResolvedValue();
vi.clearAllMocks();
});
@ -72,3 +74,64 @@ test("saved SQL summaries load file content on demand", async () => {
assert.equal(store.files[0]?.sql, "SELECT 1;");
assert.equal(apiMock.loadSavedSqlFile.mock.calls.length, 1);
});
test("saving an existing SQL file without folderId keeps its folder", async () => {
const file: SavedSqlFile = {
id: "sql-1",
connectionId: "conn-1",
folderId: "folder-1",
name: "query.sql",
database: "db",
sql: "SELECT 1;",
sqlLoaded: true,
createdAt: "2026-06-27T00:00:00.000Z",
updatedAt: "2026-06-27T00:00:00.000Z",
};
apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files: [file] });
const store = useSavedSqlStore();
await store.initFromStorage();
const saved = await store.saveFile({
id: "sql-1",
connectionId: "conn-2",
name: "query.sql",
database: "other_db",
sql: "SELECT 1;",
});
assert.equal(saved.folderId, "folder-1");
assert.equal(apiMock.saveSavedSqlFile.mock.calls[0]?.[0].folderId, "folder-1");
assert.equal(store.getFile("sql-1")?.folderId, "folder-1");
});
test("saving an existing SQL file with root folder explicitly moves it to root", async () => {
const file: SavedSqlFile = {
id: "sql-1",
connectionId: "conn-1",
folderId: "folder-1",
name: "query.sql",
database: "db",
sql: "SELECT 1;",
sqlLoaded: true,
createdAt: "2026-06-27T00:00:00.000Z",
updatedAt: "2026-06-27T00:00:00.000Z",
};
apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files: [file] });
const store = useSavedSqlStore();
await store.initFromStorage();
const saved = await store.saveFile({
id: "sql-1",
connectionId: "conn-1",
folderId: undefined,
name: "query.sql",
database: "db",
sql: "SELECT 1;",
});
assert.equal(saved.folderId, undefined);
assert.equal(apiMock.saveSavedSqlFile.mock.calls[0]?.[0].folderId, undefined);
assert.equal(store.getFile("sql-1")?.folderId, undefined);
});