This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / api / knotmirror.ts
3.4 kB 103 lines
1import type { BobbinContext, XrpcRequestInit } from "./client"; 2import { createBobbinClient } from "./client"; 3import { jsonGet, rawGet } from "./_request"; 4import type * as LegacyTree from "./lexicons/types/sh/tangled/git/temp/getTree"; 5import type * as Tree from "./lexicons/types/sh/tangled/repo/tree"; 6import { treeEntryKind, type BranchesResponse, type LogResponse, type TagsResponse } from "./repo"; 7 8const TREE_NSID = "sh.tangled.git.temp.getTree"; 9const BLOB_NSID = "sh.tangled.git.temp.getBlob"; 10const LOG_NSID = "sh.tangled.git.temp.listCommits"; 11const BRANCHES_NSID = "sh.tangled.git.temp.listBranches"; 12const TAGS_NSID = "sh.tangled.git.temp.listTags"; 13const LANGUAGES_NSID = "sh.tangled.git.temp.listLanguages"; 14 15export interface KnotMirrorLanguagesResponse { 16 languages?: { name: string; size: number }[]; 17 total?: number; 18 ref?: string; 19} 20 21export const createKnotMirrorClient = (serviceUrl: string, fetch: typeof globalThis.fetch) => 22 createBobbinClient({ serviceUrl, fetch }); 23 24const normalizeSignature = ( 25 signature: LegacyTree.Signature | undefined 26): Tree.Signature | undefined => 27 signature ? { name: signature.name, email: signature.email, when: signature.when } : undefined; 28 29const normalizeCommit = (commit: LegacyTree.LastCommit | undefined): Tree.LastCommit | undefined => 30 commit 31 ? { 32 hash: commit.hash, 33 message: commit.message, 34 when: commit.when, 35 author: normalizeSignature(commit.author) 36 } 37 : undefined; 38 39const normalizeTree = (tree: LegacyTree.$output): Tree.$output => ({ 40 ref: tree.ref, 41 parent: tree.parent, 42 dotdot: tree.dotdot, 43 lastCommit: normalizeCommit(tree.lastCommit), 44 files: tree.files.map((entry) => ({ 45 name: entry.name, 46 mode: entry.mode, 47 size: entry.size, 48 last_commit: normalizeCommit(entry.last_commit) 49 })) 50}); 51 52const isReadmeFile = (name: string, mode: string): boolean => 53 /^readme(?:\.[^.]+)?$/i.test(name) && treeEntryKind(mode) === "file"; 54 55const pathInTree = (path: string | undefined, name: string): string => 56 path ? `${path}/${name}` : name; 57 58export const tree = async ( 59 ctx: BobbinContext, 60 params: { repo: string; ref: string; path?: string }, 61 init?: XrpcRequestInit 62): Promise<Tree.$output> => { 63 const response = await jsonGet<LegacyTree.$output>(ctx, TREE_NSID, params, init); 64 const result = normalizeTree(response); 65 const readme = response.files.find((entry) => isReadmeFile(entry.name, entry.mode)); 66 if (!readme) return result; 67 68 try { 69 const blob = await rawGet( 70 ctx, 71 BLOB_NSID, 72 { repo: params.repo, ref: params.ref, path: pathInTree(params.path, readme.name) }, 73 init 74 ); 75 return { ...result, readme: { filename: readme.name, contents: await blob.text() } }; 76 } catch { 77 return result; 78 } 79}; 80 81export const log = ( 82 ctx: BobbinContext, 83 params: { repo: string; ref: string; limit: number }, 84 init?: XrpcRequestInit 85) => jsonGet<LogResponse>(ctx, LOG_NSID, params, init); 86 87export const branches = ( 88 ctx: BobbinContext, 89 params: { repo: string; limit: number }, 90 init?: XrpcRequestInit 91) => jsonGet<BranchesResponse>(ctx, BRANCHES_NSID, params, init); 92 93export const tags = ( 94 ctx: BobbinContext, 95 params: { repo: string; limit: number }, 96 init?: XrpcRequestInit 97) => jsonGet<TagsResponse>(ctx, TAGS_NSID, params, init); 98 99export const languages = ( 100 ctx: BobbinContext, 101 params: { repo: string; ref: string }, 102 init?: XrpcRequestInit 103) => jsonGet<KnotMirrorLanguagesResponse>(ctx, LANGUAGES_NSID, params, init);