Skip to content

@anchor-sdk/core

Core package providing types, client factory, adapters, and plugin system.

Types

User

ts
type User = {
  id: string
  name: string
  avatar?: string
}

Reaction

ts
type Reaction = {
  emoji: string
  userId: string
}

Attachment

ts
type Attachment = {
  id: string
  name: string
  url: string
  mimeType: string
  size: number
  width?: number // images only
  height?: number // images only
}

MessageOptions

ts
interface MessageOptions {
  attachments?: Attachment[]
}

Message

ts
type Message = {
  id: string
  content: string
  createdAt: number
  updatedAt?: number
  user: User
  reactions: Reaction[]
  attachments?: Attachment[]
}

Thread

ts
type Thread = {
  id: string
  anchorId: string
  messages: Message[]
  resolved: boolean
  lastActivityAt: number
}

PresenceStatus

ts
type PresenceStatus = 'online' | 'away' | 'offline'

PresenceInfo

ts
type PresenceInfo = {
  user: User
  status: PresenceStatus
  lastSeen: number
}

ConnectionStatus

ts
type ConnectionStatus = 'online' | 'offline'

Adapter

ts
interface Adapter {
  // Threads
  getThreads(anchorId: string): Promise<Thread[]>
  createThread(anchorId: string, content: string, options?: MessageOptions): Promise<Thread>
  resolveThread(threadId: string): Promise<Thread>
  reopenThread(threadId: string): Promise<Thread>
  deleteThread(threadId: string): Promise<void>

  // Messages
  addMessage(threadId: string, content: string, options?: MessageOptions): Promise<Message>
  editMessage(messageId: string, content: string): Promise<Message>
  deleteMessage(threadId: string, messageId: string): Promise<void>

  // Reactions
  addReaction(messageId: string, emoji: string): Promise<Message>
  removeReaction(messageId: string, emoji: string): Promise<Message>

  // Attachments (optional)
  uploadAttachment?(file: File): Promise<Attachment>

  // Real-time (optional)
  subscribe?(anchorId: string, callback: (threads: Thread[]) => void): () => void

  // Presence (optional)
  setPresence?(anchorId: string, user: User, status: PresenceStatus): Promise<void>
  getPresence?(anchorId: string): Promise<PresenceInfo[]>
  subscribePresence?(anchorId: string, callback: (presence: PresenceInfo[]) => void): () => void

  // Typing indicators (optional)
  setTyping?(anchorId: string, user: User, isTyping: boolean): Promise<void>
  subscribeTyping?(anchorId: string, callback: (users: User[]) => void): () => void

  // Connection lifecycle (optional)
  connect?(): void
  disconnect?(): void
}

Functions

createClient(options)

ts
import { createClient, createMemoryAdapter } from '@anchor-sdk/core'

const client = createClient({
  adapter: createMemoryAdapter(),
  user: { id: 'u1', name: 'Alice' }, // optional, defaults to Anonymous
  plugins: [myPlugin], // optional
})
ParamTypeRequiredDescription
options.adapterAdapterYesData adapter
options.userUserNoCurrent user identity
options.pluginsPlugin[]NoPlugins to apply

createMemoryAdapter(user?)

In-memory adapter for demos and testing. Supports all features including real-time subscriptions, presence, and typing indicators.

ts
const adapter = createMemoryAdapter()
// or with a specific user:
const adapter = createMemoryAdapter({ id: 'u1', name: 'Alice' })

createRestAdapter(options)

REST API adapter for connecting to a backend.

ts
import { createRestAdapter } from '@anchor-sdk/core'

const adapter = createRestAdapter({
  baseUrl: 'https://api.example.com',
  headers: { Authorization: 'Bearer token' },
})

See Custom Adapter for the expected endpoint contract.

createWebSocketAdapter(options)

WebSocket adapter with REST fallback for mutations and real-time subscriptions for threads, presence, and typing.

ts
import { createWebSocketAdapter } from '@anchor-sdk/core'

const adapter = createWebSocketAdapter({
  url: 'wss://api.example.com/ws',
  restBaseUrl: 'https://api.example.com',
  headers: { Authorization: 'Bearer token' },
  reconnectDelay: 1000, // optional, default: 1000ms
  maxReconnectDelay: 30000, // optional, default: 30000ms
})
ParamTypeRequiredDescription
options.urlstringYesWebSocket server URL
options.restBaseUrlstringYesREST API base URL
options.headersRecord<string, string>NoHeaders for REST requests
options.reconnectDelaynumberNoInitial reconnect delay (ms)
options.maxReconnectDelaynumberNoMax reconnect delay (ms)

See Real-Time Collaboration for the WebSocket protocol specification.

createOfflineQueue(options)

Wraps any adapter with an offline queue. Mutations are queued while offline and flushed when connectivity is restored.

ts
import { createOfflineQueue, createRestAdapter } from '@anchor-sdk/core'

const { adapter, goOnline, goOffline, flush, status, pending } = createOfflineQueue({
  adapter: createRestAdapter({ baseUrl: '...' }),
  onStatusChange: (status) => console.log(status),
})
ParamTypeRequiredDescription
options.adapterAdapterYesAdapter to wrap
options.onStatusChange(status: ConnectionStatus) => voidNoStatus change callback

Returns:

PropertyTypeDescription
adapterAdapterWrapped adapter with offline support
goOnline() => voidSwitch to online, flush queue
goOffline() => voidSwitch to offline, start queuing
flush() => Promise<void>Manually flush queued operations
statusConnectionStatusCurrent status ('online' or 'offline')
pendingnumberNumber of queued operations

Plugin System

See Plugins Guide for full documentation.

ts
import type { Plugin } from '@anchor-sdk/core'

const myPlugin: Plugin = {
  name: 'my-plugin',
  install(ctx) {
    /* ... */
  },
  beforeCreateThread(anchorId, content) {
    /* ... */
  },
  afterCreateThread(thread) {
    /* ... */
  },
  beforeAddMessage(threadId, content) {
    /* ... */
  },
  afterAddMessage(message) {
    /* ... */
  },
}