diff --git a/apps/server/src/infrastructure/api-clients/sources-api.ts b/apps/server/src/infrastructure/api-clients/sources-api.ts index 09dbaaa8..2cc341b3 100644 --- a/apps/server/src/infrastructure/api-clients/sources-api.ts +++ b/apps/server/src/infrastructure/api-clients/sources-api.ts @@ -119,12 +119,9 @@ export function restoreSource(id: string, data: unknown) { * @returns Import result */ export async function importSourceZip(id: string, file: File) { - return orpc.sources.importZip({ id, file }); + return orpc.sources.enqueueImport({ id, mode: "zip", file }); } export async function importSourceNdjson(id: string, file: File) { - return await orpc.sources.importNdjson({ - id, - file, - }); + return orpc.sources.enqueueImport({ id, mode: "json", file }); } diff --git a/apps/server/src/tests/unit/infrastructure/api-clients/sources-api-ext.test.ts b/apps/server/src/tests/unit/infrastructure/api-clients/sources-api-ext.test.ts index d524c7de..8b05f9ea 100644 --- a/apps/server/src/tests/unit/infrastructure/api-clients/sources-api-ext.test.ts +++ b/apps/server/src/tests/unit/infrastructure/api-clients/sources-api-ext.test.ts @@ -1,6 +1,7 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { fetchSourceDump, + importSourceNdjson, importSourceZip, restoreSource, } from "~/infrastructure/api-clients/sources-api"; @@ -10,7 +11,7 @@ vi.mock("~/infrastructure/api-clients/orpc-client", () => ({ orpc: { sources: { enqueueExport: vi.fn(), - importZip: vi.fn(), + enqueueImport: vi.fn(), restore: vi.fn(), }, jobs: { downloadArtifact: vi.fn(), get: vi.fn() }, @@ -88,18 +89,41 @@ describe("Sources API Client Extensions", () => { expect(await result.text()).toBe("zip content"); }); - it("should upload imports through oRPC", async () => { + it("should enqueue TAR imports through oRPC", async () => { const id = "test-source-id"; const mockFile = new File(["zip content"], "test.zip", { type: "application/zip", }); - const mockResponse = { importedCount: 1 }; - ((orpc.sources as any).importZip as any).mockResolvedValue(mockResponse); + const mockResponse = { id: "restore-job-id" }; + ((orpc.sources as any).enqueueImport as any).mockResolvedValue( + mockResponse, + ); const result = await importSourceZip(id, mockFile); - expect((orpc.sources as any).importZip).toHaveBeenCalledWith({ + expect((orpc.sources as any).enqueueImport).toHaveBeenCalledWith({ + id, + mode: "zip", + file: mockFile, + }); + expect(result).toEqual(mockResponse); + }); + + it("should enqueue NDJSON imports through oRPC", async () => { + const id = "test-source-id"; + const mockFile = new File(["{}\n"], "test.ndjson", { + type: "application/x-ndjson", + }); + const mockResponse = { id: "restore-job-id" }; + ((orpc.sources as any).enqueueImport as any).mockResolvedValue( + mockResponse, + ); + + const result = await importSourceNdjson(id, mockFile); + + expect((orpc.sources as any).enqueueImport).toHaveBeenCalledWith({ id, + mode: "json", file: mockFile, }); expect(result).toEqual(mockResponse); diff --git a/apps/tauri/src/infrastructure/api-clients/sources-api.ts b/apps/tauri/src/infrastructure/api-clients/sources-api.ts index fe9f0e35..ab60200d 100644 --- a/apps/tauri/src/infrastructure/api-clients/sources-api.ts +++ b/apps/tauri/src/infrastructure/api-clients/sources-api.ts @@ -35,14 +35,11 @@ export async function restoreSource( } export async function importSourceZip(id: string, file: File) { - return client.sources.importZip({ id, file }); + return client.sources.enqueueImport({ id, mode: "zip", file }); } export async function importSourceNdjson(id: string, file: File) { - return client.sources.importNdjson({ - id, - file, - }); + return client.sources.enqueueImport({ id, mode: "json", file }); } export function parseRestoreFile(file: File): Promise { return file.text().then((text) => JSON.parse(text)); diff --git a/packages/ui/src/hooks/use-source-media-page.ts b/packages/ui/src/hooks/use-source-media-page.ts index e9093194..a2e39c56 100644 --- a/packages/ui/src/hooks/use-source-media-page.ts +++ b/packages/ui/src/hooks/use-source-media-page.ts @@ -1,5 +1,6 @@ import type { Character } from "@solid-imager/core/domain/characters/schemas"; import type { Ip } from "@solid-imager/core/domain/ips/schemas"; +import type { JobDto } from "@solid-imager/core/domain/jobs/schemas"; import type { Author, DownloadItem, @@ -122,24 +123,8 @@ export type SourceMediaPageActions = { errors: string[]; cancelled?: boolean; }>; - importSourceZip: ( - sourceId: string, - file: File, - ) => Promise<{ - success: boolean; - importedCount: number; - skippedCount: number; - errors: string[]; - message: string; - }>; - importSourceNdjson?: ( - sourceId: string, - file: File, - ) => Promise<{ - importedCount: number; - skippedCount: number; - errors: string[]; - }>; + importSourceZip: (sourceId: string, file: File) => Promise; + importSourceNdjson?: (sourceId: string, file: File) => Promise; parseRestoreFile?: (file: File) => Promise; }; @@ -642,28 +627,26 @@ export function useSourceMediaPage( }); if (strategies.includes("tar")) { - toast.loading("Importing TAR dump...", { id: "restore-toast" }); - const result = await actions.importSourceZip(sourceId, file); + toast.loading("Queueing TAR restore...", { id: "restore-toast" }); + const job = await actions.importSourceZip(sourceId, file); toast.success( - `Import complete: ${result.importedCount} items imported.`, + `TAR restore queued (${job.id.slice(0, 8)}). Track it in Jobs.`, { id: "restore-toast", }, ); - refreshMediaQuery(); return; } if (strategies[0] === "ndjson" && actions.importSourceNdjson) { - toast.loading("Importing NDJSON dump...", { id: "restore-toast" }); - const result = await actions.importSourceNdjson(sourceId, file); + toast.loading("Queueing NDJSON restore...", { id: "restore-toast" }); + const job = await actions.importSourceNdjson(sourceId, file); toast.success( - `Import complete: ${result.importedCount} items imported.`, + `NDJSON restore queued (${job.id.slice(0, 8)}). Track it in Jobs.`, { id: "restore-toast", }, ); - refreshMediaQuery(); return; }