@hoist/sdk (0.1.0)

Published 2026-01-27 15:53:00 +00:00 by insidiousfiddler in macco/hoist

Installation

@hoist:registry=
npm install @hoist/sdk@0.1.0
"@hoist/sdk": "0.1.0"

About this package

Hoist TypeScript SDK

TypeScript SDK for Hoist feature flags with real-time updates.

Features

  • TypeScript-first with full type safety
  • Real-time streaming updates via WebSocket
  • Local evaluation for server-side SDKs
  • Remote evaluation for client-side SDKs
  • Comprehensive targeting rules and segments
  • Percentage rollouts and A/B testing
  • Hooks for lifecycle events
  • Zero dependencies (streaming requires WebSocket)
  • Works in Node.js and modern browsers

Installation

npm config set @hoist:registry https://git.macco.dev/api/packages/macco/npm/
npm install @hoist/sdk

Quick Start

Server-Side Usage (Node.js)

import { HoistClient } from '@hoist/sdk'

const client = new HoistClient({
  apiKey: 'hoist_live_...', // Server API key
  streaming: true,         // Enable real-time updates
})

// Wait for initial config load
await client.waitForInitialization()

// Evaluate flags
const enabled = await client.booleanValue('new-feature', false, {
  targetingKey: 'user-123',
  attributes: {
    plan: 'pro',
    region: 'us-east',
  },
})

if (enabled) {
  // Feature is enabled
}

// Cleanup when done
client.close()

Client-Side Usage (Browser)

import { HoistClient } from '@hoist/sdk'

const client = new HoistClient({
  apiKey: 'client-key', // Client API key (no prefix)
  streaming: false,      // Client keys use remote evaluation
})

const variant = await client.stringValue('banner-text', 'default', {
  targetingKey: 'session-abc',
  attributes: {
    language: 'en',
  },
})

API Reference

HoistClient

Constructor

new HoistClient(config: HoistConfig)

Config Options:

  • apiKey (required): Your Hoist API key
  • baseURL (optional): API base URL (default: https://hoist.macco.dev/api)
  • streaming (optional): Enable WebSocket streaming (default: true for server keys, false for client keys)
  • timeout (optional): HTTP request timeout in milliseconds (default: 5000)
  • hooks (optional): Array of lifecycle hooks
  • logger (optional): Custom logger implementation

Methods

waitForInitialization(): Promise<void>

Wait for the client to finish initializing (loading config or connecting to stream).

await client.waitForInitialization()
booleanValue(key, defaultValue, context?): Promise<boolean>

Evaluate a boolean flag.

const enabled = await client.booleanValue('feature-enabled', false, {
  targetingKey: 'user-123',
})
stringValue(key, defaultValue, context?): Promise<string>

Evaluate a string flag.

const variant = await client.stringValue('button-color', 'blue', {
  targetingKey: 'user-123',
})
numberValue(key, defaultValue, context?): Promise<number>

Evaluate a number flag.

const limit = await client.numberValue('rate-limit', 100, {
  targetingKey: 'user-123',
})
jsonValue<T>(key, defaultValue, context?): Promise<T>

Evaluate a JSON flag.

interface Config {
  theme: string
  features: string[]
}

const config = await client.jsonValue<Config>('ui-config', {
  theme: 'light',
  features: [],
})
evaluate<T>(key, defaultValue, context?): Promise<EvaluationResult<T>>

Evaluate a flag with full details.

const result = await client.evaluate('feature', false, {
  targetingKey: 'user-123',
})

console.log({
  value: result.value,
  reason: result.reason,        // Why this value was returned
  variantKey: result.variantKey, // Matched variant
  ruleID: result.ruleID,        // Matched rule
  version: result.version,      // Flag version
})
close(): void

Close the client and cleanup resources (disconnect WebSocket, etc.).

client.close()

Evaluation Context

The evaluation context provides information for targeting rules:

interface EvaluationContext {
  targetingKey?: string              // Unique identifier (user ID, session ID, etc.)
  attributes?: Record<string, unknown> // Additional attributes for targeting
}

Example:

const context = {
  targetingKey: 'user-123',
  attributes: {
    email: 'user@example.com',
    plan: 'pro',
    region: 'us-east',
    age: 25,
    beta: true,
  },
}

Hooks

Hooks allow you to observe flag evaluation lifecycle:

const logger = {
  before: (key, context) => {
    console.log(`Evaluating ${key}`, context)
  },
  after: (key, result) => {
    console.log(`Result for ${key}:`, result.value, result.reason)
  },
  error: (key, error) => {
    console.error(`Error evaluating ${key}:`, error)
  },
}

const client = new HoistClient({
  apiKey: 'hoist_live_...',
  hooks: [logger],
})

Evaluation Reasons

The reason field in EvaluationResult explains why a value was returned:

  • DEFAULT - No rules matched, using default value
  • TARGETING_MATCH - A targeting rule matched
  • SEGMENT_MATCH - A segment rule matched
  • DISABLED - Flag is disabled
  • ROLLOUT - User not in rollout percentage
  • NOT_FOUND - Flag doesn't exist
  • ERROR - Evaluation error occurred
  • IDENTITY_OVERRIDE - Identity-specific override matched

Advanced Usage

Custom Logger

import type { Logger } from '@hoist/sdk'

const customLogger: Logger = {
  debug: (msg, ...args) => console.debug(msg, ...args),
  info: (msg, ...args) => console.info(msg, ...args),
  warn: (msg, ...args) => console.warn(msg, ...args),
  error: (msg, ...args) => console.error(msg, ...args),
}

const client = new HoistClient({
  apiKey: 'hoist_live_...',
  logger: customLogger,
})

Error Handling

The SDK is designed to fail gracefully. If evaluation fails, it returns the default value:

const result = await client.evaluate('my-flag', false)

if (result.error) {
  console.error('Evaluation failed:', result.error)
  console.log('Using default value:', result.value)
}

Real-time Updates

Server keys with streaming enabled receive real-time updates when flags change:

const client = new HoistClient({
  apiKey: 'hoist_live_...',
  streaming: true, // Default for server keys
})

await client.waitForInitialization()

// Flags are automatically updated when changes occur
// No action needed - subsequent evaluations use latest config

TypeScript Support

This SDK is written in TypeScript and provides full type definitions:

import { HoistClient, EvaluationContext, EvaluationResult, Reason } from '@hoist/sdk'

// Type-safe flag evaluation
interface FeatureConfig {
  enabled: boolean
  options: string[]
}

const config = await client.jsonValue<FeatureConfig>('feature-config', {
  enabled: false,
  options: [],
})

// config is typed as FeatureConfig

Package Exports

This package supports both CommonJS and ES Modules:

// CommonJS
const { HoistClient } = require('@hoist/sdk')

// ES Modules
import { HoistClient } from '@hoist/sdk'

Development

# Install dependencies
pnpm install

# Run type checking
pnpm typecheck

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Build the package
pnpm build

# Build in watch mode
pnpm dev

License

MIT

Dependencies

Development dependencies

ID Version
@types/node ^22.10.5
@typescript-eslint/eslint-plugin ^8.20.0
@typescript-eslint/parser ^8.20.0
eslint ^9.18.0
tsup ^8.3.5
typescript ^5.7.2
vitest ^2.1.8

Keywords

feature-flags feature-toggles hoist real-time streaming typescript
Details
npm
2026-01-27 15:53:00 +00:00
4
MIT
latest
9.7 KiB
Assets (1)
sdk-0.1.0.tgz 9.7 KiB
Versions (1) View all
0.1.0 2026-01-27