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

# Node.js SDK - NestJS

> NexusModule.forRoot and forRootAsync, injecting NexusClient, initialisation and teardown.

*New in v0.11.0.*

`@westyx-nexus/sdk-nestjs` registers a single `NexusClient` in the Nest container, so services inject it instead of constructing one.

```sh theme={null}
npm install @westyx-nexus/sdk-nestjs
```

It is a separate package so that a plain Node consumer does not pull `@nestjs/common` and `@nestjs/core`; `@nestjs/*` are optional peer dependencies here. Nest 10 and newer are supported - the module uses only stable dependency-injection primitives.

## Static configuration

```ts theme={null}
import { Module } from '@nestjs/common';
import { NexusModule } from '@westyx-nexus/sdk-nestjs';

@Module({
  imports: [
    NexusModule.forRoot({
      endpoint: process.env.NEXUS_ENDPOINT,
      apiKey: process.env.NEXUS_API_KEY,
      isGlobal: true,
    }),
  ],
})
export class AppModule {}
```

`forRoot` accepts everything [`NexusConfig`](/sdks/nodejs/configuration) accepts, plus `isGlobal`.

## Configuration from `ConfigService`

The form real applications use, because the endpoint and key are only known once the container is up:

```ts theme={null}
import { ConfigModule, ConfigService } from '@nestjs/config';

NexusModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    endpoint: config.getOrThrow<string>('NEXUS_ENDPOINT'),
    apiKey: config.getOrThrow<string>('NEXUS_API_KEY'),
  }),
});
```

The factory may be `async`. Anything it injects has to be reachable from inside the module, which is what `imports` is for.

## Injecting the client

```ts theme={null}
import { Injectable } from '@nestjs/common';
import { NexusClient } from '@westyx-nexus/sdk-nodejs';

@Injectable()
export class PricingService {
  constructor(private readonly nexus: NexusClient) {}

  pageSize(): number {
    return Number(this.nexus.getConfig('pagination.page_size') ?? 25);
  }

  newCheckout(): boolean {
    return this.nexus.getFlag('new-checkout', false);
  }
}
```

`NexusClient` itself is the injection token, so no `@Inject(...)` is needed. It is a **singleton**: every injection site receives the same client, and therefore the same cache and the same SSE connection.

`isGlobal: true` makes it injectable from any module without importing `NexusModule` there. It defaults to `false`, matching `ConfigModule`; for a single SDK client per application, `true` is usually what you want.

## Initialisation

There is deliberately no separate `OnModuleInit` step. The provider factory calls `NexusClient.create()`, which performs the initial blocking sync and opens the stream - so a module that has finished initialising is one whose client is already populated, and no service can observe a half-ready client.

A failing initial sync therefore fails application start-up, which is the behaviour a missing configuration source should have: better to refuse to boot than to serve traffic with an empty cache. A malformed option fails even earlier, before any network call.

## Teardown

`onModuleDestroy` closes the client, which disconnects the SSE stream, cancels the refresh timer, releases the connection pools, and deletes the materialised secret files.

This matters more than it looks. An SSE connection that survives module teardown keeps the process alive - Nest appears to shut down and the process does not exit - and holds a stream slot open on the server. There is a test for exactly that: after `app.close()`, `client.streamConnected` is `false` and no further request reaches the backend.

Nothing to call yourself; enable Nest's shutdown hooks as usual if you want signals to trigger it:

```ts theme={null}
const app = await NestFactory.create(AppModule);
app.enableShutdownHooks();
```

## Logging

Nest's `Logger` is bridged into the SDK's [structured logger](/sdks/nodejs/logging) by default, with the context `Nexus`, so the SDK's diagnostics appear in your application log with nothing configured. A structured Nest logger - `nestjs-pino`, for instance - receives the SDK's fields as real fields.

Pass your own `logger` in the options to override it.

## Next

* [Configuration](/sdks/nodejs/configuration)
* [API reference](/sdks/nodejs/api-reference)
* [Logging](/sdks/nodejs/logging)
