···11import { produceRequirements } from "@cistern/shared";
22import { generateKeys } from "@cistern/crypto";
33import { generateRandomName } from "@puregarlic/randimal";
44+import { parse } from "@atcute/lexicons";
45import type { Did } from "@atcute/lexicons/syntax";
56import type { Client, CredentialManager } from "@atcute/client";
66-import type { AppCisternLexiconPubkey } from "@cistern/lexicon";
77+import {
88+ AppCisternLexiconItem,
99+ type AppCisternLexiconPubkey,
1010+} from "@cistern/lexicon";
711import type { ConsumerOptions, ConsumerParams, LocalKeyPair } from "./types.ts";
812913import type {} from "@atcute/atproto";
···8084 }
81858286 /**
8383- * Returns an async iterator that returns pages of the user's items from their PDS.
8484- * @todo List items from repo
8787+ * Asynchronously iterate through items in the user's PDS
8588 */
8686- async listItems() {}
8989+ async *listItems(): AsyncIterator<
9090+ AppCisternLexiconItem.Main,
9191+ void,
9292+ undefined
9393+ > {
9494+ let cursor: string | undefined;
9595+9696+ while (true) {
9797+ const res = await this.rpc.get("com.atproto.repo.listRecords", {
9898+ params: {
9999+ collection: "app.cistern.lexicon.item",
100100+ repo: this.did,
101101+ cursor,
102102+ },
103103+ });
104104+105105+ if (!res.ok) {
106106+ throw new Error(
107107+ `failed to list items: ${res.status} ${res.data.error}`,
108108+ );
109109+ }
110110+111111+ if (res.data.cursor) cursor = res.data.cursor;
112112+113113+ for (const record of res.data.records) {
114114+ yield parse(AppCisternLexiconItem.mainSchema, record.value);
115115+ }
116116+117117+ if (!cursor) return;
118118+ }
119119+ }
8712088121 /**
89122 * Subscribes to the Jetstreams for the user's items.