/** * @file Diigo dump logic: the bookmark generator over any fluent handle. * Site-flavored configuration (URL, headers, cookie) lives where the webapp * instance is minted (src/index.ts: mint); only the traversal is here. */ export type PagedGet = { pathjoin(ref: string): PagedGet; query(params: Record): PagedGet; get(): Promise; }; export type DumpOptions = { /** fluent handle for the diigo account, cookie attached upstream */ diigoAPI: PagedGet; pages?: number; count?: number; log?: (event: Record) => void; }; /** yield diigo bookmarks, most-recently-updated first, `pages * count` at * most. `diigoAPI` is attenuated authority; over RPC the generator runs in * the caller's address space against a stub. */ export async function* dumpBookmarks({ diigoAPI, pages = 2, count = 24, log = () => {}, }: DumpOptions): AsyncGenerator> { const getUserItems = (page: number) => diigoAPI .pathjoin("load_user_items") .query({ sort: "updated", count, page_num: page }) .get() .then(JSON.parse) as Promise<{ total: number; items: Record[] }>; const first = await getUserItems(1); const totalPages = Math.ceil(first.total / count); log({ event: "start", total: first.total, pages, totalPages }); let got = 0; for (let page = 1; page <= Math.min(pages, totalPages); page += 1) { const data = page === 1 ? first : await getUserItems(page); yield* data.items; got += data.items.length; log({ event: "page", page, of: pages, got }); } }