Skip to content

Latest commit

 

History

History
167 lines (120 loc) · 4.84 KB

File metadata and controls

167 lines (120 loc) · 4.84 KB

🦍 api-ape Client

api-ape mascot

Overview

The client module provides the browser-side WebSocket client for api-ape. It enables seamless communication with api-ape servers through a proxy-based API that converts method calls like api.users.list() into WebSocket messages.

Key capabilities:

  • Proxy-based API — Call server endpoints like local methods (api.path.method(data))
  • Auto-reconnection — Automatically reconnects with exponential backoff on disconnection
  • Call buffering — Queues calls made before connection is established
  • JSS encoding — Supports Date, RegExp, Error, Set, Map, and undefined over the wire
  • HTTP fallback — Falls back to long-polling when WebSocket is blocked
  • Binary transfers — Transparent file upload/download handling
  • Connection state — Track connection status (offline, connecting, connected, disconnected)
  • Pub/sub subscriptions — Subscribe to channels and receive targeted updates

The client works in both browser environments (via <script> tag) and bundled applications (React, Vue, etc.).

Contributing? See files.md for directory structure and file descriptions.

Usage

Browser (via script tag)

<script src="/api/ape.js"></script>
<script>
  // Call server functions (RPC)
  api.hello('World').then(result => console.log(result))

  // Subscribe to channels (pass a callback function)
  const unsub = api.message(data => console.log(data))

  // Unsubscribe when done
  unsub()
</script>

ES Module Import (React, Vue, etc.)

npm i api-ape
import api from 'api-ape'

// Just use it! Calls are buffered until connected.
api.users.list().then(users => console.log(users))

// Subscribe to channels (pass a callback function)
const unsub = api.news.banking(data => {
  console.log('Received:', data)
})

// Unsubscribe when done
unsub()

// Track connection state
api.onConnectionChange((state) => {
  console.log('Connection:', state)
  // 'offline' | 'walled' | 'disconnected' | 'connecting' | 'connected'
})

Connection States:

  • offline — Browser reports no network
  • walled — Captive portal detected (WiFi without real internet)
  • disconnected — Had connection, lost it
  • connecting — Actively connecting
  • connected — Ready to use
  • closing — Connection is closing

No async setup needed! The client auto-initializes and buffers calls until connected.

Features

  • Proxy-based APIape.path.method(data) converts to WebSocket calls
  • Auto-reconnect — Reconnects on disconnect with queued messages
  • Promise-based — All calls return promises with matched responses via queryId
  • JSS encoding — Supports Date, RegExp, Error, Set, Map, undefined over the wire
  • Request timeout — Configurable timeout (default: 10s)

File Transfers

Binary data is automatically handled. The client fetches binary resources and uploads binary data transparently.

Receiving Binary Data

// Server returns Buffer, client receives ArrayBuffer
const result = await api.files.download('image.png')
console.log(result.data)  // ArrayBuffer

// Display as image
const blob = new Blob([result.data])
img.src = URL.createObjectURL(blob)

Uploading Binary Data

const file = input.files[0]
const arrayBuffer = await file.arrayBuffer()

// Binary data is uploaded automatically
await api.files.upload({
  name: file.name,
  data: arrayBuffer  // Sent via HTTP PUT
})

Binary transfers use /api/ape/data/:hash endpoints with session verification.

Pub/Sub Subscriptions

Subscribe to channels using the same chaining syntax as RPC calls. The key difference: pass a callback function to subscribe, pass data to make an RPC call.

// RPC call - passing data
await api.news.banking({ category: 'stocks' })  // Returns Promise<response>

// Subscribe - passing a callback function
const unsub = api.news.banking(data => {
  console.log('Received:', data)
})

// Unsubscribe when done
unsub()

Chained Subscriptions

// Subscribe to nested channels
const unsub1 = api.stock.AAPL(data => {
  console.log('AAPL:', data.price)
})

const unsub2 = api.health(data => {
  console.log('Health update:', data)
})

// Clean up
unsub1()
unsub2()

Behavior:

  • On subscribe, you receive the last published message immediately (if any)
  • Subscriptions are automatically restored on reconnect
  • Subscriptions are automatically cleaned up on disconnect

Security

CSRF Protection

api-ape includes built-in Cross-Site Request Forgery (CSRF) protection:

  • Origin Validation — WebSocket connections validate Origin header against Host
  • Automatic Rejection — Mismatched origins are rejected immediately
  • Session Verification — Binary transfers verify session cookies

No configuration needed — protection is enabled by default.