Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596import { ok } from "@atcute/client";import type { Did } from "@atcute/lexicons/syntax";import type { BobbinContext } from "$lib/api/client";import { mainSchema as listKnotsSchema } from "$lib/api/lexicons/types/sh/tangled/knot/listKnots";import { mainSchema as listSpindleMembersSchema } from "$lib/api/lexicons/types/sh/tangled/spindle/listMembers";import { mainSchema as listSpindlesSchema } from "$lib/api/lexicons/types/sh/tangled/spindle/listSpindles";import { parseResourceUri } from "@atcute/lexicons/syntax";
interface Page<T> { items: T[]; cursor?: string;}
interface RecordItem { uri: string; value: unknown;}
const allPages = async <T>(load: (cursor?: string) => Promise<Page<T>>): Promise<T[]> => { const items: T[] = []; let cursor: string | undefined; do { const page = await load(cursor); items.push(...page.items); cursor = page.cursor || undefined; } while (cursor); return items;};
const recordName = (uri: unknown): string | null => { if (typeof uri !== "string") return null; try { return parseResourceUri(uri).rkey ?? null; } catch { return null; }};
const spindleInstance = (value: unknown): string | null => { if (typeof value !== "object" || value === null || !("instance" in value)) return null; return typeof value.instance === "string" && value.instance ? value.instance : null;};
const targetNames = ( seed: string[], owned: RecordItem[], memberships: RecordItem[] = [], memberName: (item: RecordItem) => string | null = () => null): string[] => { const names = new Set(seed); for (const item of owned) { const name = recordName(item.uri); if (name) names.add(name); } for (const item of memberships) { const name = memberName(item); if (name) names.add(name); } return [...names].sort((a, b) => a.localeCompare(b));};
// TODO(boltless): list bookmarked repos instead.const SHARED_KNOTS = ["knot2.tngl.boltless.dev"];
export const availableKnots = async (ctx: BobbinContext, did: string): Promise<string[]> => targetNames( SHARED_KNOTS, await allPages((cursor) => ok( ctx.xrpc.call(listKnotsSchema, { params: { subject: did as Did, limit: 1_000, cursor } }) ) ) );
export const availableSpindles = async (ctx: BobbinContext, did: string): Promise<string[]> => { const [owned, memberships] = await Promise.all([ allPages((cursor) => ok( ctx.xrpc.call(listSpindlesSchema, { params: { subject: did as Did, limit: 1_000, cursor } }) ) ), allPages((cursor) => ok( ctx.xrpc.call(listSpindleMembersSchema, { params: { subject: did as Did, limit: 1_000, cursor } }) ) ) ]); return targetNames([], owned, memberships, (item) => spindleInstance(item.value));};