import { mock } from "bun:test";
import { memoryScopes } from "../scoped-db/testing";
import type { ScopedValue } from "../scoped-db/types";
/**
* In-memory RepoState/AccountState stores and scope locators for tests: call `install()` before importing the
* module under test, `reset()` in beforeEach, and seed rows with `repo(scope)` / `account(id)` (bun:sqlite).
*/
export function scopedTestState() {
let scopes = memoryScopes();
const locators = new Map<string, string>();
const key = (kind: string, value: string) => `${kind}\u0000${value}`;
const state = {
install(): void {
mock.module("../scoped-db", () => ({
repoDb: (id: string) => scopes.repoDb(id),
accountDb: (id: string) => scopes.accountDb(id),
stmt: (sql: string, ...params: ScopedValue[]) => ({ sql, params }),
}));
mock.module("../scoped-db/locators", () => ({
locate: async (kind: string, value: string) => locators.get(key(kind, value)) ?? null,
registerLocator: async (kind: string, value: string, scopeId: string) => {
locators.set(key(kind, value), scopeId);
},
registerLocators: async (entries: Array<[string, string, string]>) => {
for (const [kind, value, scopeId] of entries) locators.set(key(kind, value), scopeId);
},
forgetLocator: async (kind: string, value: string) => {
locators.delete(key(kind, value));
},
forgetScope: async (scopeId: string) => {
for (const [entry, scope] of locators) if (scope === scopeId) locators.delete(entry);
},
locatedScopes: async (kind: string) => [
...new Set([...locators].filter(([entry]) => entry.startsWith(`${kind}\u0000`)).map(([, scope]) => scope)),
],
locatedScopesFrom: async (kind: string, from: string, limit: number) =>
[
...new Set(
[...locators]