···2929 return &Client{api: api, did: did}
3030}
31313232-// DID returns the authenticated user's DID.
3332func (c *Client) DID() syntax.DID { return c.did }
34333534// APIClient returns the underlying indigo APIClient for advanced usage
3635// (custom XRPC calls, service proxying, etc.).
3736func (c *Client) APIClient() *atclient.APIClient { return c.api }
38373939-// CreateRecord creates a new record with an auto-generated TID key.
4038func (c *Client) CreateRecord(ctx context.Context, collection string, record any) (uri, cid string, err error) {
4139 body := map[string]any{
4240 "repo": c.did.String(),
···5452 return result.URI, result.CID, nil
5553}
56545757-// CreateRecordWithRKey creates a new record with a specific record key.
5855func (c *Client) CreateRecordWithRKey(ctx context.Context, collection, rkey string, record any) (uri, cid string, err error) {
5956 body := map[string]any{
6057 "repo": c.did.String(),
···9289 return &Record{URI: result.URI, CID: result.CID, Value: result.Value}, nil
9390}
94919595-// ListRecords retrieves a single page of records from a collection.
9696-// Pass limit <= 0 for the server default (usually 50). Pass empty cursor for the first page.
9292+// Pass limit <= 0 for the server default (usually 50).
9393+// Pass empty cursor for the first page.
9794func (c *Client) ListRecords(ctx context.Context, collection string, limit int, cursor string) (*ListResult, error) {
9895 params := map[string]any{
9996 "repo": c.did.String(),
···130127 return out, nil
131128}
132129133133-// ListAllRecords fetches every record in a collection, handling cursor
134134-// pagination automatically. Returns all records at once.
135130func (c *Client) ListAllRecords(ctx context.Context, collection string) ([]Record, error) {
136131 var all []Record
137132 cursor := ""
···157152 return all, nil
158153}
159154160160-// PutRecord creates or updates a record at a specific record key.
161155func (c *Client) PutRecord(ctx context.Context, collection, rkey string, record any) (uri, cid string, err error) {
162156 body := map[string]any{
163157 "repo": c.did.String(),
···176170 return result.URI, result.CID, nil
177171}
178172179179-// DeleteRecord removes a record from the user's repository.
180173func (c *Client) DeleteRecord(ctx context.Context, collection, rkey string) error {
181174 body := map[string]any{
182175 "repo": c.did.String(),
···191184 return nil
192185}
193186194194-// UploadBlob uploads a blob to the user's PDS.
195187// Data must be at most 1 MB (MaxBlobSize). The mimeType should match the blob content.
196188func (c *Client) UploadBlob(ctx context.Context, data []byte, mimeType string) (*BlobRef, error) {
197189 if len(data) > MaxBlobSize {
···235227 }, nil
236228}
237229238238-// GetBlob downloads a blob from the user's PDS by its CID.
239230func (c *Client) GetBlob(ctx context.Context, cid string) ([]byte, error) {
240231 data, err := atproto.SyncGetBlob(ctx, c.api, cid, c.did.String())
241232 if err != nil {
+1
errors.go
···12121313// WrapPDSError inspects an XRPC error for signals that the OAuth grant is no
1414// longer valid and, if so, wraps it with ErrSessionExpired.
1515+// TODO: handle other common error types
1516func WrapPDSError(err error) error {
1617 if err == nil {
1718 return nil
···9898// LoginCLI runs a complete loopback OAuth flow for CLI applications.
9999// It opens the user's browser, starts a temporary HTTP server to receive the
100100// callback, and blocks until authentication completes.
101101+// TODO: should this be part of the library? probably not? (removeds `browser` dep)
101102func (a *OAuthApp) LoginCLI(ctx context.Context, handle string) (*SessionInfo, error) {
102103 authURL, err := a.app.StartAuthFlow(ctx, handle)
103104 if err != nil {
···182183 return meta
183184}
184185185185-// Store returns the underlying session store, useful for implementing
186186-// features like "list all sessions" or session cleanup.
187186func (a *OAuthApp) Store() oauth.ClientAuthStore {
188187 return a.app.Store
189188}
···24242525// Init creates and registers a tracer provider with an OTLP HTTP exporter.
2626// It reads OTEL_EXPORTER_OTLP_ENDPOINT (default: localhost:4318).
2727-// The serviceName appears in your tracing backend (e.g. "arabica", "solanum").
2727+// The serviceName appears in your tracing backend (e.g. "arabica").
2828// Returns the provider so the caller can defer provider.Shutdown(ctx).
2929+// TODO: allow grpc exporting to port 4317
2930func Init(ctx context.Context, serviceName string) (*sdktrace.TracerProvider, error) {
3031 endpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
3132 if endpoint == "" {