OpenDecree TypeScript SDK - v0.3.0-alpha.1
    Preparing search index...

    OpenDecree TypeScript SDK - v0.3.0-alpha.1

    OpenDecree TypeScript SDK

    CI npm Node Downloads License Project Status: WIP codecov Open in GitHub Codespaces

    TypeScript SDK for OpenDecree -- schema-driven configuration management.

    Alpha -- This SDK is under active development. APIs and behavior may change without notice between versions.

    • Node.js ≥ 22 (ESM-only package — CommonJS is not supported)
    npm install @opendecree/sdk
    

    The SDK implements Symbol.dispose / Symbol.asyncDispose, so you can use TypeScript 5.2's using statement for automatic cleanup — no try/finally needed.

    import { ConfigClient } from '@opendecree/sdk';

    // `using` closes the gRPC channel automatically when the block exits
    await using client = new ConfigClient('localhost:9090', { subject: 'myapp' });

    // Get config values (default: string)
    const fee = await client.get('tenant-id', 'payments.fee');

    // Typed gets via runtime converters
    const retries = await client.get('tenant-id', 'payments.retries', Number);
    const enabled = await client.get('tenant-id', 'payments.enabled', Boolean);

    // Nullable gets
    const optional = await client.get('tenant-id', 'payments.fee', Number, { nullable: true });

    // Set values
    await client.set('tenant-id', 'payments.fee', '0.5%');

    // Set multiple values atomically
    await client.setMany('tenant-id', {
    'payments.fee': '0.5%',
    'payments.retries': '3',
    });
    Prefer try/finally?
    const client = new ConfigClient('localhost:9090', { subject: 'myapp' });
    try {
    const fee = await client.get('tenant-id', 'payments.fee');
    // ...
    } finally {
    client.close();
    }

    ConfigWatcher also supports await using for automatic stop + close:

    import { ConfigClient } from '@opendecree/sdk';

    await using client = new ConfigClient('localhost:9090', { subject: 'myapp' });
    await using watcher = client.watch('tenant-id');

    // Register fields before starting
    const fee = watcher.field('payments.fee', Number, { default: 0.01 });
    const enabled = watcher.field('payments.enabled', Boolean, { default: false });

    // Load snapshot + start streaming
    await watcher.start();

    // Synchronous access to current values
    console.log(fee.value); // number
    console.log(enabled.value); // boolean

    // EventEmitter pattern
    fee.on('change', (oldVal, newVal) => {
    console.log(`Fee changed: ${oldVal} -> ${newVal}`);
    });

    // Or async iteration (yields Change objects)
    for await (const change of fee) {
    console.log(change.fieldPath, change.newValue);
    }
    // watcher.stop() + client.close() called automatically

    Runnable examples in the examples/ directory:

    Example What it shows
    quickstart using / await using, type converters (Number, Boolean)
    live-config ConfigWatcher, .on('change'), for await...of
    nextjs-integration Singleton watcher for server-side config
    error-handling RetryConfig, { nullable: true }, instanceof narrowing
    • 📖 API Reference -- full TypeDoc API reference
    • Quick Start -- install, first get/set, typed gets, error handling
    • Configuration -- all client options, auth, TLS, retry, timeouts
    • Watching -- ConfigWatcher, WatchedField, EventEmitter, async iteration
    • Node.js 22+
    • A running OpenDecree server (v0.8.0 – v0.x, pre-1.0)

    Head to OpenDecree Discussions -- our community hub covers all OpenDecree repos.

    Apache License 2.0 -- see LICENSE.