import { expect, test } from "../support/browser/strict-browser-test.ts"; test("runs put, open, remove and reconcile through a native DedicatedWorker, OPFS and IndexedDB", async ({ page, }) => { await page.goto("/"); const result = await page.evaluate(async () => { const runtimeModulePath = "/src/adapters/storage/opfs/browser-opfs-runtime.ts"; const policyModulePath = "/src/adapters/storage/opfs/opfs-policy.ts"; const journalModulePath = "/src/adapters/storage/opfs/indexeddb-opfs-journal.ts"; const { createBrowserOpfsRuntime, inspectBrowserOpfsSupport, } = (await import( /* @vite-ignore */ runtimeModulePath )) as typeof import("../../src/adapters/storage/opfs/browser-opfs-runtime.ts"); const { DEFAULT_OPFS_RUNTIME_POLICY, resolveOpfsRuntimePolicy, } = (await import( /* @vite-ignore */ policyModulePath )) as typeof import("../../src/adapters/storage/opfs/opfs-policy.ts"); const { opfsJournalDatabaseName } = (await import( /* @vite-ignore */ journalModulePath )) as typeof import("../../src/adapters/storage/opfs/indexeddb-opfs-journal.ts"); const policy = resolveOpfsRuntimePolicy(); const support = inspectBrowserOpfsSupport(policy); if (!support.ok) { return { nativeSupport: false as const, capabilities: support, }; } const suffix = crypto.randomUUID().replaceAll("-", ""); const scope = { namespace: "durable-objects", authorityToken: `authority_${suffix}`, namespaceToken: `namespace_${suffix}`, partitionToken: `partition_${suffix}`, } as const; const storagePolicy = { owner: "browser-capability", namespace: scope.namespace, classification: "PERSONAL", authority: "LOCAL_FIRST", accountScope: "OPAQUE_PARTITION", retention: { kind: "EXPLICIT_DELETE" }, softBudgetBytes: 1024 * 1024, hardBudgetBytes: 2 * 1024 * 1024, evictionPriority: "USER_AUTHORED", logoutAction: "EXPORT_THEN_PURGE", accountDeletionAction: "PURGE_PARTITION", pressureAction: "RETAIN", unavailableFallback: "EXPORT_REQUIRED", } as const; const runtime = createBrowserOpfsRuntime({ workerUrl: new URL( "/tests/browser-capabilities/opfs-test.worker.ts", location.href, ), workerName: `opfs-capability-${suffix}`, scope, storagePolicy, policy, }); const bytes = new Uint8Array([3, 1, 4, 1, 5, 9]); let capabilities: unknown; let put: unknown; let opened: | Awaited> | undefined; let readBytes: number[] = []; let removed: unknown; let afterRemove: unknown; let reconciled: unknown; try { capabilities = await runtime.objects.capabilities(); put = await runtime.objects.put({ objectId: "object_browser_12345678", expectedGeneration: null, mediaType: "application/octet-stream", source: { byteLength: bytes.byteLength, async *stream(signal: AbortSignal) { if (signal.aborted) { yield { ok: false as const, error: { code: "ABORTED" as const, operation: "OBJECT_WRITE" as const, retryable: false, recovery: "NONE" as const, }, }; return; } yield { ok: true as const, value: Uint8Array.from(bytes) }; }, }, }); opened = await runtime.objects.open({ objectId: "object_browser_12345678", }); if ( opened && typeof opened === "object" && "ok" in opened && opened.ok ) { for await (const chunk of opened.value.source.stream( new AbortController().signal, )) { if (!chunk.ok) throw new Error(chunk.error.code); readBytes.push(...chunk.value); } } removed = await runtime.objects.remove({ objectId: "object_browser_12345678", expectedGeneration: 1, }); afterRemove = await runtime.objects.open({ objectId: "object_browser_12345678", }); reconciled = await runtime.maintenance.reconcile({ budgetMs: 5_000, maxTransactions: 100, }); } finally { runtime.close(); } const deletion = await new Promise((resolve) => { const request = indexedDB.deleteDatabase( opfsJournalDatabaseName(scope.authorityToken), ); request.onsuccess = () => resolve("DELETED"); request.onerror = () => resolve(request.error?.name ?? "UNKNOWN_ERROR"); request.onblocked = () => resolve("BLOCKED"); }); let opfsCleanup = "ABSENT"; try { const originRoot = await navigator.storage.getDirectory(); const runtimeRoot = await originRoot.getDirectoryHandle( DEFAULT_OPFS_RUNTIME_POLICY.rootDirectoryName, ); const authorities = await runtimeRoot.getDirectoryHandle( "authorities", ); await authorities.removeEntry(scope.authorityToken, { recursive: true, }); opfsCleanup = "DELETED"; } catch (error) { if (!(error instanceof DOMException) || error.name !== "NotFoundError") { throw error; } } return { nativeSupport: true as const, capabilities, put, opened: opened && typeof opened === "object" && "ok" in opened && opened.ok ? { ok: true, generation: opened.value.descriptor.generation, } : opened, readBytes, removed, afterRemove, reconciled, deletion, opfsCleanup, }; }); if (!result.nativeSupport) { expect(result.capabilities).toMatchObject({ ok: false, error: { code: "UNSUPPORTED" }, }); return; } expect(result.capabilities).toMatchObject({ ok: true, value: { available: true, dedicatedWorkerRequired: true, crossContextMutationLockAvailable: true, }, }); expect(result.put).toMatchObject({ ok: true, value: { generation: 1, byteLength: 6 }, }); expect(result.opened).toEqual({ ok: true, generation: 1 }); expect(result.readBytes).toEqual([3, 1, 4, 1, 5, 9]); expect(result.removed).toEqual({ ok: true }); expect(result.afterRemove).toMatchObject({ ok: false, error: { code: "NOT_FOUND" }, }); expect(result.reconciled).toMatchObject({ ok: true, value: { inspectedTransactions: 0, orphanGcStatus: "COMPLETED", }, }); expect(result.deletion).toBe("DELETED"); expect(["DELETED", "ABSENT"]).toContain(result.opfsCleanup); });