@nestarc/feature-flag 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,186 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@nestarc/feature-flag` will be documented in this file.
4
+
5
+ ## [0.6.0] — 2026-09-10
6
+
7
+ Version 0.6.0 adds module provider options and corrects evaluation and SDK integration behavior from 0.5.0.
8
+
9
+ ### Added
10
+ - Accept custom `repository` and `tenantContextProvider` instances in synchronous and asynchronous module registration; Prisma is required only when no repository is supplied.
11
+ - Add invocation-level `bucketBy` selection, including the Admin evaluation endpoint.
12
+
13
+ ### Fixed
14
+ - Preserve explicit `targetingKey` during service context resolution.
15
+ - Apply registry `bucketBy` to typed clients and bulk evaluation.
16
+ - Reject null and non-integer percentages before Prisma and align nullable description/context types with runtime behavior.
17
+ - Provide and test an OpenFeature SDK-compatible provider with boolean resolution and explicit unsupported-type errors.
18
+
19
+ ### Documentation and verification
20
+ - Add a complete consumer guide, runnable standalone examples, and checks against a packed package in CI.
21
+ - Correct cache consistency, dependency, evaluation, and performance descriptions; link the existing 0.5 upgrade notes.
22
+ - Isolate benchmark data in a disposable schema and support environment metadata and raw timing output.
23
+ - Include the consumer guide and changelog in package files and connect npm metadata to the official documentation.
24
+
25
+ ### Migration
26
+ - No Prisma schema migration is required from 0.5.0.
27
+ - Use the new module options for custom repositories and tenant providers; tokens declared only in an importing module do not replace this module's providers.
28
+ - Install `@openfeature/server-sdk@^1.23.0` when consuming the `/openfeature` entry point's public TypeScript types.
29
+ - Review partial-rollout cohorts if you previously supplied `targetingKey` or registry `bucketBy`: these values are now applied consistently, so existing evaluation results can change.
30
+
31
+ ## [0.5.0] — 2026-08-02
32
+
33
+ ### Changed
34
+ - Prisma 7 is now the supported Prisma major (`prisma` and `@prisma/client` 7.9.1 in development)
35
+ - Prisma Client generation now uses the `prisma-client` generator with an explicit output path
36
+ - PostgreSQL tests, benchmarks, and examples now create Prisma Client with `@prisma/adapter-pg`
37
+ - Prisma CLI connection configuration moved from `schema.prisma` to `prisma.config.ts`
38
+ - Node.js 20.19+, 22.12+, or 24+ is now required to match Prisma 7
39
+
40
+ ### Migration
41
+ - Install `@prisma/adapter-pg` and `pg`, then pass a `PrismaPg` adapter to `PrismaClient`
42
+ - Import `PrismaClient` from the generated output path instead of `@prisma/client`
43
+ - Move `DATABASE_URL` into `prisma.config.ts`; no database migration is required
44
+
45
+ ## [0.4.0] — 2026-06-20
46
+
47
+ ### Added
48
+ - `FeatureFlagService.evaluateBoolean()` for detailed boolean evaluation results with `source`, `reason`, `defaultUsed`, `bucket`, `targetingKey`, and timing metadata
49
+ - Invocation-level fallback via `EvaluateBooleanOptions.defaultValue`
50
+ - `FeatureFlagGuardOptions.defaultValue` for route-level missing/error fallback
51
+ - `EvaluationContext.targetingKey` and registry/metadata `bucketBy` support for explicit rollout bucketing
52
+ - Type-safe registry helpers: `defineFlags()`, `createFeatureFlagClient()`, `createFeatureFlagDecorators()`, and lifecycle status helpers
53
+ - `FeatureFlagModuleOptions.flags` for registry defaults, bucket keys, and exposure settings
54
+ - `FeatureFlagEvents.EXPOSED` opt-in exposure events
55
+ - Mutation event metadata fields: `actorId`, `actorType`, `reason`, `requestId`, and `correlationId`
56
+ - `TestFeatureFlagModule.registerRegistry()` and injectable `TestFeatureFlagController`
57
+ - Boolean-only OpenFeature provider adapter at `@nestarc/feature-flag/openfeature`
58
+ - Admin API `POST /feature-flags/:key/evaluate` endpoint
59
+
60
+ ### Changed
61
+ - `isEnabled()` now delegates to `evaluateBoolean()` and returns its `value`
62
+ - Missing flags now emit a structured `feature-flag.evaluated` event with reason `FLAG_NOT_FOUND`
63
+ - Percentage rollout keeps the legacy `userId ?? tenantId` fallback unless `targetingKey` or `bucketBy` is provided
64
+ - `FlagEvaluatedEvent` now includes detailed evaluation fields
65
+ - Package version is now `0.4.0`
66
+
67
+ ### Migration
68
+ - No Prisma migration is required for v0.4.0 core features.
69
+ - OpenFeature support is optional and does not require the SDK unless you wire the adapter into an OpenFeature setup.
70
+ - Variant flags, reusable rule segments, persisted audit logs, and persisted exposure analytics remain out of scope for this release.
71
+
72
+ ## [0.3.0] — 2026-05-12
73
+
74
+ ### Added
75
+ - Attribute-based override targeting with non-empty `attributes` JSON objects
76
+ - Override `priority` for tie-breaking between matching overrides with the same specificity
77
+ - Admin API DTO validation with `class-validator` and `class-transformer`
78
+ - Automatic Prisma migration from fixed override columns to `attributes`
79
+ - Top-level `userId`, `tenantId`, and `environment` merge into targeting attributes during evaluation
80
+ - Example apps for basic route guards, multi-tenant attribute targeting, and Redis events
81
+
82
+ ### Changed
83
+ - `SetOverrideInput` and `RemoveOverrideInput` now use `attributes`
84
+ - `FlagOverride` now exposes `attributes` and `priority`
85
+ - Override evaluation now matches exact attribute key/value pairs instead of a fixed tenant/user/environment hierarchy
86
+ - Matching override tie-break order is more attributes, higher `priority`, earlier `createdAt`, then lower `id`
87
+ - Evaluation event source now uses `override` for matched attribute overrides
88
+ - `FeatureFlagOverride` storage now uses `attributes` `jsonb` plus `priority`
89
+
90
+ ### Breaking
91
+ - Removed direct override fields `tenantId`, `userId`, and `environment`
92
+ - Removed `FeatureFlagRepository.updateOverrideEnabled()`
93
+ - `setOverride()` and Admin API override requests now require a non-empty `attributes` object
94
+ - Legacy override bodies such as `{ "tenantId": "tenant-1", "enabled": true }` are rejected
95
+ - Prisma schema migration is required
96
+ - Legacy global override rows with `tenant_id`, `user_id`, and `environment` all `NULL` are removed during migration
97
+ - Duplicate legacy override rows that backfill to the same `(flag_id, attributes)` are deduplicated during migration
98
+ - `feature_flag_overrides` no longer stores `tenant_id`, `user_id`, or `environment` columns
99
+
100
+ ### Migration
101
+ - Run `npx prisma migrate deploy`
102
+ - Legacy `tenant_id`, `user_id`, and `environment` values are backfilled to `attributes.tenantId`, `attributes.userId`, and `attributes.environment`
103
+ - Duplicate backfilled overrides keep the latest `updated_at`, then latest `created_at`, then highest `id`
104
+ - Replace `{ "tenantId": "t-1", "enabled": true }` with `{ "attributes": { "tenantId": "t-1" }, "enabled": true }`
105
+ - Use `{ "attributes": { "tenantId": "tenant-1" }, "enabled": true }` for Admin API override requests
106
+ - Install `class-validator` and `class-transformer` with the required peer dependencies
107
+
108
+ ## [0.2.0] — 2026-04-10
109
+
110
+ ### Added
111
+ - `CacheAdapter` interface for pluggable cache backends
112
+ - `MemoryCacheAdapter` (refactored from internal FlagCacheService)
113
+ - `RedisCacheAdapter` with Redis Pub/Sub for cross-instance cache invalidation (SCAN-based flush)
114
+ - `FeatureFlagAdminModule` — opt-in REST Admin API with guard injection
115
+ - `POST /feature-flags` — create flag (409 on duplicate key)
116
+ - `GET /feature-flags` — list all flags
117
+ - `GET /feature-flags/:key` — get single flag (404 on missing)
118
+ - `PATCH /feature-flags/:key` — update flag (404 on missing)
119
+ - `DELETE /feature-flags/:key` — archive flag (404 on missing)
120
+ - `POST /feature-flags/:key/overrides` — set override (404 on missing flag)
121
+ - `DELETE /feature-flags/:key/overrides` — remove override (404 on missing flag)
122
+ - `FeatureFlagRepository` interface — pluggable persistence port for custom backends
123
+ - `PrismaFeatureFlagRepository` — default Prisma implementation with error mapping
124
+ - `TenantContextProvider` interface — pluggable tenant resolution port
125
+ - `DefaultTenantContextProvider` — automatic `@nestarc/tenancy` integration
126
+ - `FlagEventPublisher` — extracted conditional event emission service
127
+ - `FlagContextResolver` — extracted ambient/explicit context merge service
128
+ - `findByKey()` method on FeatureFlagService (throws NotFoundException)
129
+ - `removeOverride()` method on FeatureFlagService
130
+ - `RemoveOverrideInput` type
131
+ - `CACHE_ADAPTER`, `FEATURE_FLAG_REPOSITORY`, `TENANT_CONTEXT_PROVIDER` injection tokens
132
+ - `ioredis` as optional peer dependency
133
+ - Cache adapter contract test suite (`cache-adapter.contract.spec.ts`)
134
+ - Admin REST e2e test suite (`admin.e2e-spec.ts`)
135
+ - Redis cross-instance invalidation e2e test suite (`redis-cache.e2e-spec.ts`)
136
+ - Percentage (0-100) range validation in repository layer
137
+
138
+ ### Changed
139
+ - All cache operations are now async (`CacheAdapter` interface)
140
+ - `cacheAdapter` option added to `FeatureFlagModuleOptions` (optional, defaults to `MemoryCacheAdapter`)
141
+ - `FeatureFlagService` now depends on `FeatureFlagRepository` instead of direct Prisma access
142
+ - Cache invalidation on mutation paths is now best-effort (non-fatal); stale entries self-heal via TTL
143
+ - `TestFeatureFlagModule` mock methods now return full `FeatureFlagWithOverrides` objects (LSP compliance)
144
+ - `RemoveOverrideInput` moved from `cache-adapter.interface` to `feature-flag.interface` (ISP)
145
+ - `FeatureFlagAdminModule` uses standard NestJS DI instead of `ModuleRef.get()` for service resolution
146
+
147
+ ### Fixed
148
+ - `setOverride()` now throws `NotFoundException` (was generic `Error` causing 500)
149
+ - Admin `create()` returns 409 Conflict on duplicate key (was 500)
150
+ - Admin `update()`/`archive()` return 404 on missing key (was 500)
151
+ - Override race condition: concurrent `setOverride()` calls no longer 500 on unique index violation
152
+ - Override `deleteOverride()` is idempotent (concurrent delete no longer 500)
153
+
154
+ ### Removed
155
+ - `FlagCacheService` (internal, replaced by `CacheAdapter` + `MemoryCacheAdapter`)
156
+ - Direct `prisma: any` dependency in `FeatureFlagService` (replaced by `FeatureFlagRepository`)
157
+ - `ModuleRef` dependency in `FeatureFlagService` (tenancy resolved via `TenantContextProvider`)
158
+
159
+ ## [0.1.0] - 2026-04-05
160
+
161
+ ### Added
162
+
163
+ - `FeatureFlagModule` with `forRoot` and `forRootAsync` (useFactory / useClass / useExisting) registration
164
+ - `FeatureFlagService` with CRUD operations: `create`, `update`, `archive`, `findAll`
165
+ - `isEnabled()` and `evaluateAll()` for flag evaluation with 6-layer cascade priority
166
+ - `setOverride()` for user / tenant / environment context-specific overrides
167
+ - `@FeatureFlag()` decorator with built-in `UseGuards(FeatureFlagGuard)` for automatic route gating
168
+ - `@BypassFeatureFlag()` decorator to exempt specific routes from guard checks
169
+ - `FlagContextMiddleware` with `AsyncLocalStorage` for request-scoped userId extraction
170
+ - `FlagCacheService` with configurable TTL-based in-memory caching
171
+ - `FlagEvaluatorService` with 5-layer override hierarchy and murmurhash3-based percentage rollout
172
+ - Optional `@nestjs/event-emitter` integration (`emitEvents: true`) sharing NestJS-managed `EventEmitter2` singleton
173
+ - `TestFeatureFlagModule` at `@nestarc/feature-flag/testing` for unit/integration test support
174
+ - Prisma schema with partial unique indexes for NULL-safe override uniqueness on PostgreSQL
175
+ - Docker Compose + e2e test environment with real PostgreSQL (service-level + HTTP tests)
176
+ - Explicit `null` context support: `{ userId: null }` suppresses ambient context from ALS
177
+
178
+ ### Fixed
179
+
180
+ - Override uniqueness: replaced broken `@@unique` compound constraint with 8 partial unique indexes to handle PostgreSQL `NULL != NULL` semantics
181
+ - `allFlagsCache` staleness: per-key `invalidate(key)` now also clears the all-flags cache
182
+ - `forRootAsync` double factory invocation: introduced intermediate `FULL_OPTIONS` provider so factory runs exactly once
183
+ - `EVENT_EMITTER` isolation: changed from `new EventEmitter2()` to `useExisting` / `ModuleRef.get()` so `@OnEvent` listeners receive feature-flag events
184
+ - `@FeatureFlag()` fail-open: decorator now includes `UseGuards(FeatureFlagGuard)` automatically
185
+ - `buildContext()` null semantics: explicit `null` in `EvaluationContext` now overrides ambient values instead of falling through
186
+ - Lint errors: resolved unused destructured variable and unsafe `Function` type in guard tests