/** * @file a stand-in for webapp's `WebAppFactory` entrypoint, for tests: an * auxiliary worker (plain JS — the vitest pool doesn't transform aux * workers) serving diigo-shaped `load_user_items` pages. 30 items, every * third private; one webapp id is known. Counts its diigo calls so tests * can tell a cache hit (no call) from a miss. */ import { RpcTarget, WorkerEntrypoint } from "cloudflare:workers"; const KNOWN_WEBAPP = "fake-webapp-id"; const TOTAL = 30; /** item n (1-based, in diigo's order): diigo's field names, made-up * values. link_id and updated_at are scrambled (distinct; 7 and 11 are * coprime to 31), so neither column sorts back into diigo's order — a * cache that replays by column rather than by fetch order is caught. */ function item(n) { return { link_id: 1000 + ((n * 7) % 31), url: `https://example.com/${n}`, title: `bookmark ${n}`, description: "", private: n % 3 === 0, u_name: "alice_99", first_by: "someone-else", user_id: 4242, tags: "", created_at: 1700000000, updated_at: 1700001000 + ((n * 11) % 31), }; } let calls = 0; class FakeGet extends RpcTarget { #path; #params; constructor(path, params) { super(); this.#path = path; this.#params = params; } pathjoin(ref) { return new FakeGet(ref, this.#params); } query(params) { return new FakeGet(this.#path, { ...this.#params, ...params }); } async get() { calls += 1; if (this.#path !== "load_user_items") throw new Error(`fake webapp: no route ${this.#path}`); const count = Number(this.#params.count); const page = Number(this.#params.page_num); const items = []; for (let n = (page - 1) * count + 1; n <= Math.min(page * count, TOTAL); n += 1) items.push(item(n)); return JSON.stringify({ total: TOTAL, items }); } } export class WebAppFactory extends WorkerEntrypoint { async at(id) { if (id !== KNOWN_WEBAPP) throw new Error("fake webapp: unknown id"); return new FakeGet("", {}); } /** how many diigo calls so far (test hook) */ async calls() { return calls; } } export default { fetch() { return new Response("fake webapp", { status: 404 }); }, };