Something went wrong. Try again.
Syncing your Obsidian notes with lichen.wiki
Something went wrong. Try again.
4.0 kB · 154 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154import { Client, ok } from "@atcute/client";import { now as tidNow } from "@atcute/tid";import type { Did, Nsid } from "@atcute/lexicons";import { COLLECTIONS } from "./lib/collections";import { createDiff } from "./lib/diff";
/** Build an AT-URI from a did, collection, and rkey. */export function atUri(did: string, collection: string, rkey: string): string { return `at://${did}/${collection}/${rkey}`;}
export interface CreateNoteInput { /** Permanent human-readable slug (from the title). */ slug: string; /** Display title (freely updatable). */ title: string; /** AT-URI of the parent wiki record. */ wikiRef: string; /** Initial markdown content (stored as the first revision's diff from ""). */ content: string; /** Optional commit message for the first revision. */ message?: string;}
export interface CreatedNote { noteUri: string; revisionUri: string;}
/** * Create a new note: write the `wiki.lichen.note` record (rkey = TID) then create * its first `wiki.lichen.noteRevision` (diff from the empty string). */export async function createNote( client: Client, did: Did, input: CreateNoteInput,): Promise<CreatedNote> { const noteTid = tidNow(); const revisionTid = tidNow(); const now = new Date().toISOString();
const noteUri = atUri(did, COLLECTIONS.note, noteTid); const revisionUri = atUri(did, COLLECTIONS.noteRevision, revisionTid);
const noteRecord = { $type: COLLECTIONS.note, slug: input.slug, title: input.title, wikiRef: input.wikiRef, createdAt: now, };
await ok( client.post("com.atproto.repo.putRecord", { input: { repo: did, collection: COLLECTIONS.note as Nsid, rkey: noteTid, record: noteRecord, }, }), );
const revisionRecord = { $type: COLLECTIONS.noteRevision, noteRef: noteUri, diff: createDiff("", input.content), diffFormat: "diff-match-patch", createdAt: now, ...(input.message ? { message: input.message } : {}), };
await ok( client.post("com.atproto.repo.putRecord", { input: { repo: did, collection: COLLECTIONS.noteRevision as Nsid, rkey: revisionTid, record: revisionRecord, }, }), );
return { noteUri, revisionUri };}
export interface PushEditInput { /** AT-URI of the note being edited. */ noteRef: string; /** AT-URI of the current head revision (previous revision); omit for the first. */ parentRevision?: string; /** Current known content to diff from. */ oldContent: string; /** New content to store (as the diff). */ newContent: string; /** Optional commit message. */ message?: string;}
/** * Push an edit to a note as a new `wiki.lichen.noteRevision` diff. Returns the new * revision URI (to use as `parentRevision` for the next edit). */export async function pushNoteEdit( client: Client, did: Did, input: PushEditInput,): Promise<string> { const revisionTid = tidNow(); const revisionUri = atUri(did, COLLECTIONS.noteRevision, revisionTid);
const revisionRecord = { $type: COLLECTIONS.noteRevision, noteRef: input.noteRef, diff: createDiff(input.oldContent, input.newContent), diffFormat: "diff-match-patch", createdAt: new Date().toISOString(), ...(input.parentRevision ? { parentRevision: input.parentRevision } : {}), ...(input.message ? { message: input.message } : {}), };
await ok( client.post("com.atproto.repo.putRecord", { input: { repo: did, collection: COLLECTIONS.noteRevision as Nsid, rkey: revisionTid, record: revisionRecord, }, }), );
return revisionUri;}
/** Delete a note record on the PDS (revisions remain as history). */export async function deleteNote( client: Client, did: Did, noteUri: string,): Promise<void> { const rkey = noteUri.split("/").pop() ?? ""; if (!rkey) throw new Error(`Invalid note URI: ${noteUri}`); await ok( client.post("com.atproto.repo.deleteRecord", { input: { repo: did, collection: COLLECTIONS.note as Nsid, rkey, }, }), );}