# NestJS SDK

`@cohorly/nest` is a standard NestJS dynamic module (`forRoot` / `forRootAsync`) plus an injectable `CohorlyService` wrapping `@cohorly/node`, with an automatic final flush on application shutdown. Supports `@nestjs/common` ^10 and ^11.

## Install

```bash
pnpm add @cohorly/nest
```

## Register the module

```typescript
// app.module.ts
import { Module } from "@nestjs/common";
import { CohorlyModule } from "@cohorly/nest";

@Module({
  imports: [
    CohorlyModule.forRoot({
      token: process.env.COHORLY_TOKEN!,
      host: "https://cohorly-service.velloalabs.com",
      isGlobal: true, // inject CohorlyService anywhere without re-importing
    }),
  ],
})
export class AppModule {}
```

## Inject the service

```typescript
import { Injectable } from "@nestjs/common";
import { CohorlyService } from "@cohorly/nest";

@Injectable()
export class SignupService {
  constructor(private readonly cohorly: CohorlyService) {}

  async signUp(userId: string, email: string) {
    this.cohorly.track("signed_up", { distinct_id: userId, method: "email" });
    this.cohorly.people.set(userId, { $email: email, plan: "free" });
  }
}
```

`CohorlyService` exposes the full mixpanel-node-style
surface: `track`, `trackBatch`,
`import`, `importBatch`, `people.*`,
`alias`, `flush`, and the raw client at
`service.client`.

## Async configuration

```typescript
import { ConfigModule, ConfigService } from "@nestjs/config";
import { CohorlyModule } from "@cohorly/nest";

CohorlyModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  isGlobal: true,
  useFactory: (config: ConfigService) => ({
    token: config.getOrThrow("COHORLY_TOKEN"),
    host: config.get("COHORLY_HOST") ?? "https://cohorly-service.velloalabs.com",
  }),
});
```

All `@cohorly/node` config options are accepted
(`host`, `flushIntervalMs`,
`batchSize`, `debug`, `maxQueueSize`,
`maxRetryDelayMs`), plus `token` (required) and
`isGlobal`.

## Graceful shutdown

`CohorlyService` implements
`OnApplicationShutdown`: when the Nest application closes
it stops the SDK's flush timer and performs a final flush. To
also cover process signals, enable Nest's shutdown hooks:

```typescript
const app = await NestFactory.create(AppModule);
app.enableShutdownHooks();
```
