chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
// Issue threads about a repository, as the page reads them.
//
// An issue is a record in its filer's repo, a reply is a record naming its
// parent, and the owner's disposition record is what a reader shows as the
// issue's state. The statements come from the repository's own server, which
// reads every voice's own repo; the page threads them and reads the state.
import { issueState, issueThreads } from '@pdsjs/git/issues';
export { issueState, issueThreads };
import { learnProfiles } from './authors.js';
import { ownerClient, serverClient } from './git.js';
/**
* The issues a visitor filed this session, by repository then by record uri.
* A freshly filed issue is a record in the filer's own repo. If the filer is
* nobody the repository lists, the server finds it only through discovery,
* which lags, so the filer would not see their own words on the list until it
* caught up. Held here, the words show at once, and drop once the server
* lists the same uri.
* @type {Map<string, Map<string, Record<string, *>>>}
*/
const filed = new Map();
/**
* Keep an issue the visitor just filed, so the list shows it before the
* server's own read finds it.
* @param {string} repo
* @param {Record<string, *>} statement
*/
export function rememberFiledIssue(repo, statement) {
const mine = filed.get(repo) ?? new Map();
mine.set(statement.uri, statement);
filed.set(repo, mine);
}
/**
* Everything said in this repository's issue threads, as the server lists
* it, with the visitor's own just-filed issues folded in and the faces and
* names of every voice learned alongside.
* @param {string} repo - what the repository is called
* @param {string} [space]
* @returns {Promise<Array<Record<string, *>>>}
*/
export async function loadIssueStatements(repo, space) {
const { statements } = await (space
? ownerClient()
: await serverClient()
).listIssues({ repo, space });
const mine = filed.get(repo);
if (mine) {
const listed = new Set(statements.map((one) => one.uri));
for (const uri of [...mine.keys()]) if (listed.has(uri)) mine.delete(uri);
}
const all = [...(mine?.values() ?? []), ...statements];
await learnProfiles([...new Set(all.map((one) => one.by.did))]);
return all;
}