NestJS Guide
NestJS projects place evaluation logic inside injectable services. FlagLint scans TypeScript source directly — no Nest runtime metadata is required.
Typical directory structure
Section titled “Typical directory structure”src/ app.module.ts platform/ feature-flags.module.ts # ← OpenFeature setup lives here feature-flags.service.ts # ← shared evaluation wrapper checkout/ checkout.service.ts # direct LD calls to migrate checkout.module.ts pricing/ pricing.service.tsStep 1 — Audit, excluding tests
Section titled “Step 1 — Audit, excluding tests”npx flaglint audit ./src --exclude-tests✓ Audit complete: 11 flags — 1 high risk, 10 medium riskThe --exclude-tests flag prevents test fixtures from inflating counts.
Step 2 — Scan for detailed inventory
Section titled “Step 2 — Scan for detailed inventory”npx flaglint scan ./src --exclude-tests --format json --output flag-inventory.jsonUse the JSON output to cross-reference flags with your NestJS module boundaries before migrating.
Step 3 — Set up a shared OpenFeature service
Section titled “Step 3 — Set up a shared OpenFeature service”Create src/platform/feature-flags.service.ts:
import { Injectable, OnModuleInit } from "@nestjs/common";import { OpenFeature, Client } from "@openfeature/server-sdk";import { LaunchDarklyProvider } from "@launchdarkly/openfeature-node-server";
@Injectable()export class FeatureFlagsService implements OnModuleInit { client!: Client;
async onModuleInit() { await OpenFeature.setProviderAndWait( new LaunchDarklyProvider(process.env.LD_SDK_KEY!) ); this.client = OpenFeature.getClient(); }}Export it from feature-flags.module.ts and import it into any module that needs flag evaluation.
Add the binding to .flaglintrc:
{ "exclude": ["**/*.spec.ts", "**/*.test.ts"], "openFeatureClientBindings": [ { "importName": "openFeatureClient", "modulePatterns": ["**/platform/feature-flags.service"] } ]}Step 4 — Preview migration
Section titled “Step 4 — Preview migration”npx flaglint migrate ./src --dry-run --exclude-testsExample diff inside a NestJS service:
const enabled = await this.ldClient.boolVariation("new-checkout", ctx, false);const enabled = await this.featureFlagsService.client.getBooleanValue("new-checkout", false, ctx);Review each diff. FlagLint will not rewrite calls where the client binding is ambiguous or injected through a dynamic reference.
Step 5 — Apply on a branch
Section titled “Step 5 — Apply on a branch”git checkout -b migrate/openfeaturenpx flaglint migrate ./src --apply --exclude-testsStep 6 — Enforce in CI
Section titled “Step 6 — Enforce in CI”npx flaglint validate ./src --no-direct-launchdarkly --exclude-testsWrapper detection
Section titled “Wrapper detection”If your team uses a shared evaluation wrapper that accepts dynamic flag keys, configure it so FlagLint surfaces those calls for manual review:
{ "wrappers": ["evaluateFlag", "getFeatureFlag"]}Wrappers are reported but never auto-rewritten.
Edit this page · Report an unsupported pattern · Next: Monorepos