···11+export * as AppBlentoCard from "./types/app/blento/card.js";
22+export * as AppBlentoCardGetRecord from "./types/app/blento/card/getRecord.js";
33+export * as AppBlentoCardListRecords from "./types/app/blento/card/listRecords.js";
44+export * as AppBlentoGetCursor from "./types/app/blento/getCursor.js";
55+export * as AppBlentoGetOverview from "./types/app/blento/getOverview.js";
66+export * as AppBlentoGetProfile from "./types/app/blento/getProfile.js";
77+export * as AppBlentoNotifyOfUpdate from "./types/app/blento/notifyOfUpdate.js";
88+export * as AppBlentoPage from "./types/app/blento/page.js";
99+export * as AppBlentoPageGetRecord from "./types/app/blento/page/getRecord.js";
1010+export * as AppBlentoPageListRecords from "./types/app/blento/page/listRecords.js";
···58585959/**
6060 * Gets the PDS (Personal Data Server) URL for a given DID.
6161- * @param did - The DID to look up
6262- * @returns The PDS service endpoint URL
6363- * @throws If no PDS is found in the DID document
6461 */
6562export async function getPDS(did: Did) {
6663 const doc = await didResolver.resolve(did as Did<'plc'> | Did<'web'>);
···74717572/**
7673 * Fetches a detailed Bluesky profile for a user.
7777- * @param data - Optional object with did and client
7878- * @param data.did - The DID to fetch the profile for (defaults to current user)
7979- * @param data.client - The client to use (defaults to public Bluesky API)
8080- * @returns The profile data or undefined if not found
8174 */
8275export async function getDetailedProfile(data?: { did?: Did; client?: Client }) {
8376 data ??= {};
···109102> {
110103 let blentoProfile;
111104 try {
112112- // try getting blento profile first
113105 blentoProfile = await getRecord({
114106 collection: 'site.standard.publication',
115107 did: data?.did,
···117109 client: data?.client
118110 });
119111 } catch {
120120- console.error('error getting blento profile, falling back to bsky profile');
112112+ // User doesn't have a blento publication — expected for most users
121113 }
122114123115 let response;
···143135144136/**
145137 * Creates an AT Protocol client for a user's PDS.
146146- * @param did - The DID of the user
147147- * @returns A client configured for the user's PDS
148148- * @throws If the PDS cannot be found
149138 */
150139export async function getClient({ did }: { did: Did }) {
151140 const pds = await getPDS(did);
···160149161150/**
162151 * Lists records from a repository collection with pagination support.
163163- * @param did - The DID of the repository (defaults to current user)
164164- * @param collection - The collection to list records from
165165- * @param cursor - Pagination cursor for continuing from a previous request
166166- * @param limit - Maximum number of records to return (default 100, set to 0 for all records)
167167- * @param client - The client to use (defaults to user's PDS client)
168168- * @returns An array of records from the collection
169152 */
170153export async function listRecords({
171154 did,
···216199217200/**
218201 * Fetches a single record from a repository.
219219- * @param did - The DID of the repository (defaults to current user)
220220- * @param collection - The collection the record belongs to
221221- * @param rkey - The record key (defaults to "self")
222222- * @param client - The client to use (defaults to user's PDS client)
223223- * @returns The record data
224202 */
225203export async function getRecord({
226204 did,
···259237}
260238261239/**
262262- * Creates or updates a record in the current user's repository.
263263- * Only accepts collections that are configured in permissions.
264264- * @param collection - The collection to write to (must be in permissions.collections)
265265- * @param rkey - The record key (defaults to "self")
266266- * @param record - The record data to write
267267- * @returns The response from the PDS
268268- * @throws If the user is not logged in
240240+ * Creates or updates a record in the current user's repository via server-side proxy.
269241 */
270242export async function putRecord({
271243 collection,
···276248 rkey?: string;
277249 record: Record<string, unknown>;
278250}) {
279279- if (!user.client || !user.did) throw new Error('No rpc or did');
280280-281281- const response = await user.client.post('com.atproto.repo.putRecord', {
282282- input: {
283283- collection,
284284- repo: user.did,
285285- rkey,
286286- record: {
287287- ...record
288288- }
289289- }
290290- });
291291-292292- return response;
251251+ const { putRecord: serverPutRecord } = await import('./server/repo.remote');
252252+ return serverPutRecord({ collection, rkey, record });
293253}
294254295255/**
296296- * Deletes a record from the current user's repository.
297297- * Only accepts collections that are configured in permissions.
298298- * @param collection - The collection the record belongs to (must be in permissions.collections)
299299- * @param rkey - The record key (defaults to "self")
300300- * @returns True if the deletion was successful
301301- * @throws If the user is not logged in
256256+ * Deletes a record from the current user's repository via server-side proxy.
302257 */
303258export async function deleteRecord({
304259 collection,
···307262 collection: AllowedCollection;
308263 rkey: string;
309264}) {
310310- if (!user.client || !user.did) throw new Error('No profile or rpc or did');
311311-312312- const response = await user.client.post('com.atproto.repo.deleteRecord', {
313313- input: {
314314- collection,
315315- repo: user.did,
316316- rkey
317317- }
318318- });
319319-320320- return response.ok;
265265+ const { deleteRecord: serverDeleteRecord } = await import('./server/repo.remote');
266266+ const result = await serverDeleteRecord({ collection, rkey });
267267+ return result.ok;
321268}
322269323270/**
324324- * Uploads a blob to the current user's PDS.
325325- * @param blob - The blob data to upload
326326- * @returns The blob metadata including ref, mimeType, and size, or undefined on failure
327327- * @throws If the user is not logged in
271271+ * Uploads a blob to the current user's PDS via server-side proxy.
328272 */
329273export async function uploadBlob({ blob }: { blob: Blob }) {
330330- if (!user.did || !user.client) throw new Error("Can't upload blob: Not logged in");
331331-332332- const blobResponse = await user.client.post('com.atproto.repo.uploadBlob', {
333333- params: {
334334- repo: user.did
335335- },
336336- input: blob
337337- });
338338-339339- if (!blobResponse?.ok) return;
340340-341341- const blobInfo = blobResponse?.data.blob as {
342342- $type: 'blob';
343343- ref: {
344344- $link: string;
345345- };
346346- mimeType: string;
347347- size: number;
348348- };
349349-350350- return blobInfo;
274274+ const { uploadBlob: serverUploadBlob } = await import('./server/repo.remote');
275275+ const bytes = Array.from(new Uint8Array(await blob.arrayBuffer()));
276276+ return serverUploadBlob({ bytes, mimeType: blob.type });
351277}
352278353279/**
354280 * Gets metadata about a repository.
355355- * @param client - The client to use
356356- * @param did - The DID of the repository (defaults to current user)
357357- * @returns Repository metadata or undefined on failure
358281 */
359282export async function describeRepo({ client, did }: { client?: Client; did?: Did }) {
360283 did ??= user.did;
···375298376299/**
377300 * Constructs a URL to fetch a blob directly from a user's PDS.
378378- * @param did - The DID of the user who owns the blob
379379- * @param blob - The blob reference object
380380- * @returns The URL to fetch the blob
381301 */
382302export async function getBlobURL({
383303 did,
···397317398318/**
399319 * Constructs a Bluesky CDN URL for an image blob.
400400- * @param did - The DID of the user who owns the blob (defaults to current user)
401401- * @param blob - The blob reference object
402402- * @returns The CDN URL for the image in webp format
403320 */
404321export function getCDNImageBlobUrl({
405322 did,
···423340424341/**
425342 * Searches for actors with typeahead/autocomplete functionality.
426426- * @param q - The search query
427427- * @param limit - Maximum number of results (default 10)
428428- * @param host - The API host to use (defaults to public Bluesky API)
429429- * @returns An object containing matching actors and the original query
430343 */
431344export async function searchActorsTypeahead(
432345 q: string,
···453366454367/**
455368 * Return a TID based on current time
456456- *
457457- * @returns TID for current time
458369 */
459370export function createTID() {
460371 return TID.now();
···492403493404/**
494405 * Fetches posts by their AT URIs.
495495- * @param uris - Array of AT URIs (e.g., "at://did:plc:xyz/app.bsky.feed.post/abc123")
496496- * @param client - The client to use (defaults to public Bluesky API)
497497- * @returns Array of posts or undefined on failure
498406 */
499407export async function getPosts(data: { uris: string[]; client?: Client }) {
500408 data.client ??= new Client({
···520428521429/**
522430 * Fetches a post's thread including replies.
523523- * @param uri - The AT URI of the post
524524- * @param depth - How many levels of replies to fetch (default 1)
525525- * @param client - The client to use (defaults to public Bluesky API)
526526- * @returns The thread data or undefined on failure
527431 */
528432export async function getPostThread({
529433 uri,
···548452}
549453550454/**
551551- * Creates a Bluesky post on the authenticated user's account.
552552- * @param text - The post text
553553- * @param facets - Optional rich text facets (links, mentions, etc.)
554554- * @returns The response containing the post's URI and CID
555555- * @throws If the user is not logged in
455455+ * Creates a Bluesky post on the authenticated user's account via server-side proxy.
556456 */
557457export async function createPost({
558458 text,
···564464 features: Array<{ $type: string; uri?: string; did?: string; tag?: string }>;
565465 }>;
566466}) {
567567- if (!user.client || !user.did) throw new Error('No client or did');
568568-569467 const record: Record<string, unknown> = {
570468 $type: 'app.bsky.feed.post',
571469 text,
···576474 record.facets = facets;
577475 }
578476579579- const response = await user.client.post('com.atproto.repo.createRecord', {
580580- input: {
581581- collection: 'app.bsky.feed.post',
582582- repo: user.did,
583583- record
584584- }
585585- });
586586-587587- return response;
477477+ const { createRecord } = await import('./server/repo.remote');
478478+ return createRecord({ collection: 'app.bsky.feed.post', record });
588479}