> ## Documentation Index
> Fetch the complete documentation index at: https://docs.westyx.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js SDK - OpenFeature

> Use Westyx Nexus feature flags and configs via the OpenFeature Server SDK standard.

The `@westyx-nexus/openfeature-provider-nodejs` package wraps a `NexusClient` as an [OpenFeature Server SDK](https://openfeature.dev) provider. It reads boolean flags from the Nexus flags cache and string/number/object values from the Nexus configs cache - no extra network calls per evaluation.

## Requirements

* `@westyx-nexus/sdk-nodejs` >= 0.8.0
* `@openfeature/server-sdk` >= 1.7.0
* Node.js >= 22

## Installation

<Info>
  The `@westyx-nexus/openfeature-provider-nodejs` package is published to the same GitLab Package Registry as the main SDK. Ensure the `@westyx-nexus` scope points to the GitLab registry in your `.npmrc` - see [Installation](installation).
</Info>

```sh theme={null}
npm install @westyx-nexus/openfeature-provider-nodejs @openfeature/server-sdk
```

## Quick start

```ts theme={null}
import { OpenFeature } from '@openfeature/server-sdk';
import { NexusProvider } from '@westyx-nexus/openfeature-provider-nodejs';
import { NexusClient } from '@westyx-nexus/sdk-nodejs';

const client = await NexusClient.create({
  endpoint: 'https://<slug>.westyx.dev',
  apiKey:   'wxs_...',
});

OpenFeature.setProvider(new NexusProvider(client));

const ofClient = OpenFeature.getClient();
const enabled = await ofClient.getBooleanValue('dark-mode', false);
const theme   = await ofClient.getStringValue('UI_THEME', 'light');
const timeout = await ofClient.getNumberValue('REQUEST_TIMEOUT_MS', 5000);
const dbCfg   = await ofClient.getObjectValue('DB_CONFIG', { host: 'localhost' });
```

## Resolution behaviour

All evaluations are served from the in-memory cache - no per-evaluation network call is made. The cache is kept fresh by the SDK's background polling and SSE live-update stream.

| Method            | Source            | `FLAG_NOT_FOUND`   | `TYPE_MISMATCH`                     |
| ----------------- | ----------------- | ------------------ | ----------------------------------- |
| `getBooleanValue` | Nexus flags cache | key not in flags   | -                                   |
| `getStringValue`  | `getConfig()`     | key not in configs | value is not a string               |
| `getNumberValue`  | `getConfig()`     | key not in configs | value is non-numeric after coercion |
| `getObjectValue`  | `getConfig()`     | key not in configs | value is not an object              |

### Boolean flags

Boolean values come from the Nexus flags cache (`getAllFlags()`). A missing key returns the default value with `FLAG_NOT_FOUND`. No `TYPE_MISMATCH` is possible because Nexus flags are always boolean.

### String configs

The stored config value must already be a string. Numbers, booleans, and objects return `TYPE_MISMATCH` - use `getNumberValue` / `getObjectValue` for those.

### Number configs

If the config value is a `number` it is returned as-is. String values are coerced with `Number(raw)`; `NaN` yields `TYPE_MISMATCH`. Other types (boolean, object) also yield `TYPE_MISMATCH`.

### Object configs

The config value must be a non-null object. Primitive values yield `TYPE_MISMATCH`.

## Resolution reasons

| Situation               | `reason`  |
| ----------------------- | --------- |
| Key found, type matches | `STATIC`  |
| Key not found           | `DEFAULT` |
| Type mismatch           | `ERROR`   |

All successful resolutions report `STATIC`. The provider does not perform targeting or segmentation.

## Lifecycle

The `NexusProvider` does not manage the `NexusClient` lifecycle. Create the client before passing it to `NexusProvider`, and call `client.close()` during shutdown as usual.

```ts theme={null}
process.on('SIGTERM', async () => {
  await client.close();
  process.exit(0);
});
```

## Migration note (v0.8.0)

`getConfig()` return type changed from `string | undefined` to `unknown`. If you previously relied on the (incorrect) `string` type, add an explicit `as string` cast or use `typeof value === 'string'` narrowing.
