Skip to content

API Reference

Complete API reference for Pura's immutable data structures.

Core Functions

Primary APIs

FunctionPurposeUse Case
produceFast()Optimized helper-based mutationsNew code, maximum performance
produce()Immer-compatible proxy mutationsMigrating from Immer, prefer mutation syntax

Utility Functions

FunctionPurposeUse Case
pura()Wrap value in persistent structureRarely needed - produce/produceFast auto-convert
unpura()Convert to native JavaScriptThird-party libraries, hot loops
isPura()Check if value is Pura proxyType checking, debugging

Quick Start

typescript
import { produceFast } from '@sylphx/pura'

const next = produceFast(state, $ => {
  $.set(['items', 0], 999)    // Helper-based API
  $.push(4)                    // Array methods
  $.set(['user', 'name'], 'Jane')
})

Best for: New code, performance-critical paths

produce() - Immer-Compatible

typescript
import { produce } from '@sylphx/pura'

const next = produce(state, draft => {
  draft.items[0] = 999        // Direct mutation
  draft.items.push(4)          // Array methods
  draft.user.name = 'Jane'     // Deep updates
})

Best for: Migrating from Immer, prefer mutation syntax

Helper APIs (produceFast)

ArrayHelper

typescript
interface ArrayHelper<E> {
  set(index: number, value: E): void
  delete(index: number): void
  push(...items: E[]): void
  pop(): E | undefined
  unshift(...items: E[]): void
  shift(): E | undefined
  splice(start: number, deleteCount?: number, ...items: E[]): void
  reverse(): void
  sort(compareFn?: (a: E, b: E) => number): void
  fill(value: E, start?: number, end?: number): void
  copyWithin(target: number, start: number, end?: number): void
  filter(fn: (item: E, index: number) => boolean): E[]  // Must return!
  map<U>(fn: (item: E, index: number) => U): U[]  // Must return!
}

ObjectHelper

typescript
interface ObjectHelper<T> {
  set<P extends Path>(path: P, value: PathValue<T, P>): void
  update<P extends Path>(path: P, updater: (old: PathValue<T, P>) => PathValue<T, P>): void
  delete<P extends Path>(path: P): void
  merge<P extends Path>(path: P, value: Partial<PathValue<T, P>>): void
}

MapHelper

typescript
interface MapHelper<K, V> {
  set(key: K, value: V): void
  delete(key: K): void
  clear(): void
  has(key: K): boolean
}

SetHelper

typescript
interface SetHelper<V> {
  add(value: V): void
  delete(value: V): void
  clear(): void
  has(value: V): boolean
}

Type Safety

Perfect TypeScript inference across all APIs:

typescript
interface User {
  name: string
  age: number
}

const user: User = { name: 'John', age: 30 }

// produceFast - type-safe paths
const next1 = produceFast(user, $ => {
  $.set(['age'], 31)        // ✅ Valid
  $.set(['invalid'], 'x')   // ❌ Type error
  $.set(['age'], 'x')       // ❌ Type error
})

// produce - type-safe mutations
const next2 = produce(user, draft => {
  draft.age = 31            // ✅ Valid
  draft.invalid = 'x'       // ❌ Type error
  draft.age = 'x'           // ❌ Type error
})

Performance Comparison

APIvs Immervs ManualUse Case
produceFast()1.06-105× fasterFaster for large (512+)Maximum performance
produce()1.06-105× fasterFaster for large (512+)Immer migration
Native-Fastest for small (<512)Shallow updates

See Performance Guide for optimization tips.

Adaptive Strategy

Pura automatically chooses representation based on size:

SizeRepresentationAPI Overhead
<512 elementsNative JavaScriptZero (uses native operations)
>=512 elementsPersistent tree (RRB-Tree/HAMT)O(log n) structural sharing

See Understanding Adaptive Strategy for details.

Common Patterns

Redux Reducer

typescript
import { produceFast } from '@sylphx/pura'

const todosReducer = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return produceFast(state, $ => $.push(action.payload))

    case 'UPDATE_TODO':
      return produceFast(state, $ => {
        for (let i = 0; i < state.length; i++) {
          if (state[i].id === action.id) {
            $.set([i, 'text'], action.text)
            break
          }
        }
      })

    default:
      return state
  }
}

React State

typescript
import { produceFast } from '@sylphx/pura'
import { useState } from 'react'

function TodoApp() {
  const [todos, setTodos] = useState([])

  const addTodo = (text) => {
    setTodos(current =>
      produceFast(current, $ => {
        $.push({ id: Date.now(), text, completed: false })
      })
    )
  }

  return (/* ... */)
}

Zustand Store

typescript
import { create } from 'zustand'
import { produceFast } from '@sylphx/pura'

const useStore = create((set) => ({
  items: [],

  addItem: (item) => set((state) => ({
    items: produceFast(state.items, $ => $.push(item))
  }))
}))

Migration from Immer

Step 1: Change import

typescript
// Before
import { produce } from 'immer'

// After
import { produce } from '@sylphx/pura'

Step 2 (optional): Upgrade to produceFast() for maximum performance

typescript
import { produceFast } from '@sylphx/pura'

// Before (Immer)
const next = produce(state, draft => {
  draft.items[0] = 999
})

// After (Pura produceFast)
const next = produceFast(state, $ => {
  $.set(['items', 0], 999)
})

See Migration Guide for complete migration steps.

API by Use Case

When to Use Each Function

produceFast()

  • New code
  • Performance-critical paths
  • Clear, explicit updates
  • Type-safe path-based access

produce()

  • Migrating from Immer
  • Prefer mutation syntax
  • Complex nested logic
  • Existing Immer codebase

pura()

  • Rarely needed
  • Manual wrapping (produce/produceFast auto-convert)
  • Pre-wrapping for reuse

unpura()

  • Third-party libraries expecting native
  • Performance-critical hot loops
  • Serialization (optional - Pura serializes natively)
  • Explicit type checks

isPura()

  • Type checking
  • Debugging
  • Conditional logic based on representation

Next Steps

Released under the MIT License.