Something went wrong. Try again.
Monorepo for Tangled forked from tangled.org/core
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110import type { OAuthUserAgent } from "@atcute/oauth-browser-client";import * as v from "@atcute/lexicons/validations";import type { BobbinContext, XrpcRequestInit } from "#lib/api/client.ts";import { createCob, eraseCob, uploadBlobToKnot, type CobRef } from "#lib/api/cob.ts";import { jsonGet } from "#lib/api/_request.ts";import * as RepoArtifact from "#lib/api/lexicons/types/org/tangled/repo/artifact.ts";import type * as ListArtifacts from "#lib/api/lexicons/types/org/tangled/repo/listArtifacts.ts";import { datetimeOf, nsidOf, type Did, type KnotOrigin } from "#lib/api/syntax.ts";
export const ARTIFACT_COLLECTION = nsidOf("org.tangled.repo.artifact");export const MAX_ARTIFACT_BYTES = 52_428_800;export const MAX_ARTIFACT_NAME_LENGTH = 255;
export interface ArtifactSummary { uri: string; recordCid?: string; oid: string; name: string; blobCid: string; size: number; createdAt: string;}
const GIT_OID_TYPE = "org.tangled.git.oid";
// the lexicon makes subject a union, thus the schema needs subject.$type// the old artifact migration did not write $type into subject// without this function, the schema refuses those records and the ui shows no artifacts// remove this function when all records on the knots have subject.$typeconst withSubjectType = (value: unknown): unknown => { if (typeof value !== "object" || value === null || !("subject" in value)) return value; const { subject } = value; if (typeof subject !== "object" || subject === null || "$type" in subject) return value; return { ...value, subject: { $type: GIT_OID_TYPE, ...subject } };};
export const toArtifactSummary = ({ uri, cid, value}: ListArtifacts.ListItem): ArtifactSummary[] => { const parsed = v.safeParse(RepoArtifact.mainSchema, withSubjectType(value)); if (!parsed.ok) return []; const { name, artifact, createdAt, subject } = parsed.value; return [ { uri, recordCid: cid, oid: subject.oid, name, blobCid: artifact.ref.$link, size: artifact.size, createdAt } ];};
export const listArtifacts = async ( ctx: BobbinContext, repoDid: Did, init?: XrpcRequestInit): Promise<ArtifactSummary[]> => { const page = await jsonGet<ListArtifacts.$output>( ctx, "org.tangled.repo.listArtifacts", { subject: repoDid, limit: 1000 }, init ); return page.items.flatMap(toArtifactSummary);};
export const uploadArtifact = async ( agent: OAuthUserAgent, knot: KnotOrigin, repo: Did, { file, oid }: { file: File; oid: string }): Promise<CobRef & { summary: ArtifactSummary }> => { if (file.size > MAX_ARTIFACT_BYTES) throw new Error("Artifacts can be at most 50 MB."); const blob = await uploadBlobToKnot( agent, knot, repo, await file.arrayBuffer(), file.type || "application/octet-stream" ); const record: RepoArtifact.Main = { $type: "org.tangled.repo.artifact", subject: { $type: GIT_OID_TYPE, oid }, name: file.name, artifact: blob, createdAt: datetimeOf(new Date().toISOString()) }; const ref = await createCob(agent, knot, repo, ARTIFACT_COLLECTION, record); return { ...ref, summary: { uri: ref.uri, recordCid: ref.cid, oid, name: record.name, blobCid: blob.ref.$link, size: blob.size, createdAt: record.createdAt } };};
export const deleteArtifact = (agent: OAuthUserAgent, knot: KnotOrigin, artifact: CobRef) => eraseCob(agent, knot, artifact);