> ## 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.

# Vue SDK - API Reference

> Every composable and imperative method exported by the Vue SDK.

Every public symbol exported by `@westyx-nexus/sdk-vue`. Composables are the primary surface; the imperative `NexusClient` is exposed via `useNexus()` for advanced use cases.

## Setup

### `provideNexus(app, config): Promise<NexusClient>`

Creates the `NexusClient` instance, performs the blocking initial sync, registers the client on the Vue application instance, and starts the SSE stream. Use with `await` so children render against a populated cache.

```ts theme={null}
import { createApp } from 'vue';
import { provideNexus } from '@westyx-nexus/sdk-vue';

const app = createApp(App);
await provideNexus(app, { baseUrl: '...', apiKey: 'wxp_...' });
app.mount('#app');
```

| Throws           | When                                                                                       |
| ---------------- | ------------------------------------------------------------------------------------------ |
| `NexusInitError` | The initial sync failed for any reason. The `cause` property carries the underlying error. |

### `createNexusPlugin(config): Plugin`

Vue plugin factory - alternative to `provideNexus()` for setups that prefer the standard `app.use()` pattern. Does **not** await the initial sync; components must handle the loading state.

```ts theme={null}
import { createNexusPlugin } from '@westyx-nexus/sdk-vue';

app.use(createNexusPlugin({ baseUrl: '...', apiKey: 'wxp_...' }));
```

The plugin starts the initial sync as a fire-and-forget Promise and logs failures via `NexusLogger.error(...)`. While the sync is in flight, all composables return their defaults (`undefined` / `false`).

## Composables

### `useNexus(): NexusClient`

Escape hatch - returns the underlying `NexusClient` instance for advanced use. Reads via this client are not reactive (don't subscribe to the cache). Use the typed composables below unless you have a specific reason.

### `useConfig<T>(key): ComputedRef<T | undefined>`

Read a config value. Returns `undefined` when the key is absent.

```ts theme={null}
const port    = useConfig<number>('server.port');
const banner  = useConfig<string>('public.banner');
```

### `useFlag(key, defaultValue?): ComputedRef<boolean>`

Read a flag value. Returns `defaultValue` (default `false`) when the key is absent.

```ts theme={null}
const isOn = useFlag('checkout.v2');           // false if missing
const isOn = useFlag('checkout.v2', true);     // true if missing
```

### `useSecret(key): ComputedRef<string | undefined>`

Read a secret value. **Returns `undefined`** if the client uses a public key, or if the key is missing - it never throws.

```ts theme={null}
const stripeKey = useSecret('stripe.key');
```

In browser apps you'll typically be using a public key, so `useSecret` always returns `undefined`.

## AB Testing

### `useEvaluateAB(): (keys, userId, attributes) => Promise<Record<string, boolean>>`

Returns a stable bound function that performs a batch AB evaluation. The returned function is safe to destructure and pass around.

```vue theme={null}
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useEvaluateAB } from '@westyx-nexus/sdk-vue';

const evaluateAB = useEvaluateAB();
const showNewCheckout = ref(false);

onMounted(async () => {
  const results = await evaluateAB(
    ['checkout-v2', 'banner-v3'],
    'user-abc',
    { plan: 'pro', country: 'HU' },
  );
  showNewCheckout.value = results['checkout-v2'] ?? false;
});
</script>
```

Missing keys come back as `false`. Re-call the function whenever `userId` or `attributes` change - the result is intentionally not cached by the SDK.

| Throws                             | When                                                                            |
| ---------------------------------- | ------------------------------------------------------------------------------- |
| `NexusAbAddonNotAvailableError`    | Server returned HTTP 403 - the AB Testing add-on is not active for this tenant. |
| `NexusUnauthorizedError`           | Server returned HTTP 401                                                        |
| `NexusBillingError`                | Server returned HTTP 402 - tenant has overdue invoices.                         |
| `NexusQuarantinedError` *(v0.4.0)* | Server returned HTTP 429 with `{"error":"quarantined"}` body.                   |
| `NexusNotFoundError`               | Server returned HTTP 404                                                        |

### `useNexusSyncedAt(): ComputedRef<Date>`

Last successful sync timestamp. Useful for "last refreshed N seconds ago" UIs.

```vue theme={null}
<template>
  <small>Last refreshed: {{ syncedAt.toLocaleTimeString() }}</small>
</template>

<script setup lang="ts">
import { useNexusSyncedAt } from '@westyx-nexus/sdk-vue';
const syncedAt = useNexusSyncedAt();
</script>
```

### `useNexusSync(): () => Promise<void>`

Returns a function that triggers a manual sync. Use sparingly - the SDK syncs automatically.

```vue theme={null}
<template>
  <button @click="sync">Refresh config</button>
</template>

<script setup lang="ts">
import { useNexusSync } from '@westyx-nexus/sdk-vue';
const sync = useNexusSync();
</script>
```

### `useNexusStreamStatus(): ComputedRef<{ connected: boolean }>`

Reactive SSE state. Useful for surfacing a "live" / "polling" indicator.

```vue theme={null}
<template>
  <span>{{ status.connected ? 'Live' : 'Polling' }}</span>
</template>

<script setup lang="ts">
import { useNexusStreamStatus } from '@westyx-nexus/sdk-vue';
const status = useNexusStreamStatus();
</script>
```

## Imperative `NexusClient` (rarely needed)

```ts theme={null}
const nexus = useNexus();

// Read API (non-reactive - for one-shot lookups)
nexus.getConfig<T>(key)        // T | undefined
nexus.getFlag(key, default?)   // boolean
nexus.getSecret(key)           // throws NexusPublicKeyError or NexusSecretNotFoundError
nexus.getAllConfigs()          // Map<string, unknown>
nexus.getAllFlags()            // Map<string, boolean>

// AB Testing (live - not cached)
await nexus.evaluateAB(keys, userId, attributes);  // Promise<Record<string, boolean>>

// Lifecycle
await nexus.sync();            // force a sync now, bypassing the TTL
nexus.connectStream();         // start SSE (idempotent)
nexus.disconnectStream();      // stop SSE
nexus.subscribe(listener);     // listener called on every snapshot replacement

// Metadata
nexus.keyType;                 // 'sk' | 'pk' - always 'pk' in browsers
nexus.syncedAt;                // Date
nexus.streamConnected;         // boolean
```

## Error types

```ts theme={null}
import {
  NexusError,                       // base class
  NexusInitError,                   // initial sync failure (cause carries detail)
  NexusUnauthorizedError,           // HTTP 401
  NexusBillingError,                // HTTP 402 (v0.2.0)
  NexusAbAddonNotAvailableError,    // HTTP 403 on evaluateAB (v0.3.0)
  NexusNotFoundError,               // HTTP 404
  NexusQuarantinedError,            // HTTP 429 quarantine (v0.4.0)
  NexusPublicKeyError,              // imperative getSecret with public key
  NexusServiceKindMismatchError,    // imperative getSecret on kind=frontend (v0.2.0)
  NexusSecretNotFoundError,         // imperative getSecret with unknown key
} from '@westyx-nexus/sdk-vue';
```

## Type helpers

```ts theme={null}
import {
  PublicApiKey,        // branded string type - narrows public keys at compile time
  assertPublicKey,     // runtime guard - throws if key is not wxp_
} from '@westyx-nexus/sdk-vue';
```

```ts theme={null}
const raw: string = import.meta.env.VITE_NEXUS_API_KEY;
assertPublicKey(raw);  // raw is now PublicApiKey

await provideNexus(app, { baseUrl: '...', apiKey: raw });
```
