refactor(db): finish Drizzle migration for remaining actions and services

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-08-01 13:27:59 +02:00
1 parent 22234fe102
commit 65b2fbee6a
19 files changed
+422 -342

No files matched your search

+31 -23
View File
@@ -8,16 +8,16 @@ const {
downloadFile,
appendFurniEntry,
parseNitroBundle,
execRaw,
queryRaw,
executeFn,
selectLimit,
fsUnlink,
fsReadFile,
} = vi.hoisted(() => ({
downloadFile: vi.fn<AnyFn>(async () => ({ ok: true, size: 200 })),
appendFurniEntry: vi.fn<AnyFn>(async () => {}),
parseNitroBundle: vi.fn<AnyFn>(() => ({ json: {}, png: Buffer.alloc(0) })),
execRaw: vi.fn<AnyFn>(async () => 1),
queryRaw: vi.fn<AnyFn>(async () => [] as unknown[]),
executeFn: vi.fn<AnyFn>(async () => [[{ next: 1 }], []]),
selectLimit: vi.fn<AnyFn>(async () => []),
fsUnlink: vi.fn<AnyFn>(async () => {}),
fsReadFile: vi.fn<AnyFn>(async () => Buffer.from("NITRO")),
}));
@@ -55,13 +55,18 @@ vi.mock("node:fs", async (orig) => {
},
};
});
vi.mock("@/lib/prisma", () => ({
prisma: {
$executeRaw: execRaw as AnyFn,
$queryRaw: queryRaw as AnyFn,
$executeRawUnsafe: execRaw as AnyFn,
$queryRawUnsafe: queryRaw as AnyFn,
vi.mock("@/lib/db", () => ({
db: {
execute: executeFn,
select: vi.fn(() => ({
from: vi.fn(() => ({
where: vi.fn(() => ({
limit: selectLimit,
})),
})),
})),
},
ItemsBase: { id: "id", itemName: "itemName" },
}));
import { cloneSingleFurni, parseFurnidata } from "./clone-import";
@@ -100,11 +105,14 @@ describe("clone-import", () => {
// Reset mocks to clear state from other tests.
downloadFile.mockReset();
downloadFile.mockResolvedValue({ ok: true, size: 200 });
execRaw.mockReset();
execRaw.mockResolvedValue(1);
queryRaw.mockReset();
// First call: dedup check (no existing row); second call: allocateItemsBaseId MAX(id)+1.
queryRaw.mockResolvedValueOnce([]).mockResolvedValueOnce([{ next: 42 }]);
executeFn.mockReset();
// allocateItemsBaseId MAX(id)+1, then items_base INSERT, then catalog INSERT.
executeFn
.mockResolvedValueOnce([[{ next: 42 }], []])
.mockResolvedValueOnce([[], []])
.mockResolvedValueOnce([[], []]);
selectLimit.mockReset();
selectLimit.mockResolvedValue([]);
appendFurniEntry.mockReset();
appendFurniEntry.mockResolvedValue(undefined);
@@ -124,12 +132,12 @@ describe("clone-import", () => {
expect.objectContaining({ validate: "png" }),
);
expect(appendFurniEntry).toHaveBeenCalled();
expect(execRaw).toHaveBeenCalled(); // items_base insert + catalog
expect(executeFn).toHaveBeenCalled(); // items_base insert + catalog
});
it("skips when classname already exists (dedup)", async () => {
queryRaw.mockReset();
queryRaw.mockResolvedValueOnce([{ id: 5 }]); // existing items_base row
selectLimit.mockReset();
selectLimit.mockResolvedValueOnce([{ id: 5 }]); // existing items_base row
const r = await cloneSingleFurni({
source: SOURCE,
entry: { ...ENTRY, itemType: "s" },
@@ -145,14 +153,14 @@ describe("clone-import", () => {
fsUnlink.mockReset();
fsUnlink.mockResolvedValue(undefined);
appendFurniEntry.mockReset();
queryRaw.mockReset();
execRaw.mockReset();
selectLimit.mockReset();
executeFn.mockReset();
// Dedup query: no existing row.
queryRaw.mockResolvedValueOnce([]);
selectLimit.mockResolvedValueOnce([]);
// allocateItemsBaseId: MAX(id)+1 query returns next id.
queryRaw.mockResolvedValueOnce([{ next: 7 }]);
executeFn.mockResolvedValueOnce([[{ next: 7 }], []]);
// items_base INSERT rejects.
execRaw.mockRejectedValueOnce(new Error("Duplicate entry"));
executeFn.mockRejectedValueOnce(new Error("Duplicate entry"));
try {
const r = await cloneSingleFurni({