+37
-6
packages/consumer/mod.ts
+37
-6
packages/consumer/mod.ts
···
1
1
import { produceRequirements } from "@cistern/shared";
2
-
import { generateKeys } from "@cistern/crypto";
2
+
import { decryptText, generateKeys } from "@cistern/crypto";
3
3
import { generateRandomName } from "@puregarlic/randimal";
4
4
import { is, parse, type RecordKey } from "@atcute/lexicons";
5
5
import { JetstreamSubscription } from "@atcute/jetstream";
···
9
9
AppCisternLexiconItem,
10
10
type AppCisternLexiconPubkey,
11
11
} from "@cistern/lexicon";
12
-
import type { ConsumerOptions, ConsumerParams, LocalKeyPair } from "./types.ts";
12
+
import type {
13
+
ConsumerOptions,
14
+
ConsumerParams,
15
+
DecryptedItem,
16
+
LocalKeyPair,
17
+
} from "./types.ts";
13
18
14
19
import type {} from "@atcute/atproto";
15
20
···
88
93
* Asynchronously iterate through items in the user's PDS
89
94
*/
90
95
async *listItems(): AsyncIterator<
91
-
AppCisternLexiconItem.Main,
96
+
DecryptedItem,
92
97
void,
93
98
undefined
94
99
> {
100
+
if (!this.keypair) {
101
+
throw new Error("no key pair set; generate a key before listing items");
102
+
}
103
+
95
104
let cursor: string | undefined;
96
105
97
106
while (true) {
···
112
121
if (res.data.cursor) cursor = res.data.cursor;
113
122
114
123
for (const record of res.data.records) {
115
-
yield parse(AppCisternLexiconItem.mainSchema, record.value);
124
+
const item = parse(AppCisternLexiconItem.mainSchema, record.value);
125
+
const decrypted = decryptText(this.keypair.privateKey, {
126
+
nonce: item.nonce,
127
+
cipherText: item.ciphertext,
128
+
content: item.payload,
129
+
hash: item.contentHash,
130
+
length: item.contentLength,
131
+
});
132
+
133
+
yield {
134
+
tid: item.tid,
135
+
text: decrypted,
136
+
};
116
137
}
117
138
118
139
if (!cursor) return;
···
124
145
* @todo Allow specifying Jetstream endpoint
125
146
*/
126
147
async *subscribeToItems(): AsyncIterator<
127
-
AppCisternLexiconItem.Main,
148
+
DecryptedItem,
128
149
void,
129
150
"stop" | undefined
130
151
> {
···
150
171
continue;
151
172
}
152
173
153
-
if ((yield record) === "stop") return;
174
+
const decrypted = decryptText(this.keypair.privateKey, {
175
+
nonce: record.nonce,
176
+
cipherText: record.ciphertext,
177
+
content: record.payload,
178
+
hash: record.contentHash,
179
+
length: record.contentLength,
180
+
});
181
+
182
+
const command = yield { tid: record.tid, text: decrypted };
183
+
184
+
if (command === "stop") return;
154
185
}
155
186
}
156
187
}
+6
-1
packages/consumer/types.ts
+6
-1
packages/consumer/types.ts
···
1
1
import type { BaseClientOptions, ClientRequirements } from "@cistern/shared";
2
-
import type { ResourceUri } from "@atcute/lexicons";
2
+
import type { ResourceUri, Tid } from "@atcute/lexicons";
3
3
4
4
export interface InputLocalKeyPair {
5
5
privateKey: string;
···
16
16
}
17
17
18
18
export type ConsumerParams = ClientRequirements<ConsumerOptions>;
19
+
20
+
export interface DecryptedItem {
21
+
tid: Tid;
22
+
text: string;
23
+
}