@avsbhq/node 0.3.0 → 1.0.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/dist/index.d.cts CHANGED
@@ -1,7 +1,9 @@
1
- import { FlagDatafile } from '@avsbhq/js';
2
- export { ExposureEvent, FlagDatafile, FlagEvaluationDetails, MetricEvent } from '@avsbhq/js';
1
+ import { FlagDatafile, StickyBucketService, Logger, EvaluationSource, StickyAssignment, DecideOption, Flag, TrackPayload, DecisionLog, InitResult, EvalContext } from '@avsbhq/core';
2
+ export { DecideOption, DecisionLog, DecisionLogEntry, EvalContext, EvaluationSource, ExposureEvent, Flag, FlagDatafile, FlagEvaluationDetails, InitResult, Logger, MetricEvent, MultiContext, RuleType, SingleContext, StickyAssignment, StickyBucketService, TrackPayload, consoleLogger, consoleTransport, createLogger, noopLogger } from '@avsbhq/core';
3
+ import { AvsbUtils } from '@avsbhq/utils';
4
+ export { AvsbUtils } from '@avsbhq/utils';
3
5
 
4
- interface AvsBServerOptions {
6
+ interface AvsbServerOptions {
5
7
  /** SDK key for the flag environment (e.g., "env_abc123") */
6
8
  sdkKey: string;
7
9
  /** Datafile polling interval in ms. Default: 60_000 (60s). Min: 5_000. */
@@ -33,67 +35,6 @@ interface EventOptions {
33
35
  /** Retry attempts on flush failure. Default: 3. */
34
36
  retryAttempts?: number;
35
37
  }
36
- interface UserContext {
37
- /** User identifier for bucketing. Required. */
38
- userId: string;
39
- /** Targeting attributes (plan, country, device, etc.). */
40
- attributes?: Record<string, unknown>;
41
- /** When true, evaluate without firing an exposure event. Default: false. */
42
- suppressExposure?: boolean;
43
- /** Collect evaluation details into this log. */
44
- decisionLog?: DecisionLog;
45
- /** Attribute keys to strip from event payloads (used for targeting, not sent to analytics). */
46
- privateAttributes?: string[];
47
- }
48
- interface TrackContext {
49
- /** User identifier. Required. */
50
- userId: string;
51
- /** Revenue value for conversion tracking. */
52
- revenue?: number;
53
- /** Custom event properties. */
54
- properties?: Record<string, unknown>;
55
- }
56
- interface DecisionLog {
57
- readonly entries: DecisionLogEntry[];
58
- }
59
- interface DecisionLogEntry {
60
- flagKey: string;
61
- value: unknown;
62
- variationKey: string | null;
63
- source: EvaluationSource;
64
- ruleId: string | null;
65
- ruleType: 'targeted_delivery' | 'ab_test' | null;
66
- reasons: string[];
67
- evaluatedAt: number;
68
- durationMs: number;
69
- }
70
- type EvaluationSource = 'override' | 'sticky' | 'rule' | 'default' | 'not_found' | 'disabled' | 'runtime_override';
71
- interface ServerFlagEvaluationDetails {
72
- value: unknown;
73
- variationKey: string | null;
74
- source: EvaluationSource;
75
- ruleId: string | null;
76
- ruleType: 'targeted_delivery' | 'ab_test' | null;
77
- flagKey: string;
78
- reasons: string[];
79
- }
80
- interface InitResult {
81
- success: boolean;
82
- source: 'network' | 'bootstrap' | 'cache' | 'timeout' | 'error';
83
- error?: Error;
84
- }
85
- interface StickyBucketService {
86
- /** Look up stored variation for a user+flag. Return variationId or null. Synchronous. */
87
- lookup(userId: string, flagKey: string): string | null;
88
- /** Persist a variation assignment. Fire-and-forget (may be async internally). */
89
- save(userId: string, flagKey: string, variationId: string): void;
90
- }
91
- interface Logger {
92
- debug(message: string, data?: Record<string, unknown>): void;
93
- info(message: string, data?: Record<string, unknown>): void;
94
- warn(message: string, data?: Record<string, unknown>): void;
95
- error(message: string, data?: Record<string, unknown>): void;
96
- }
97
38
  type ServerEventMap = {
98
39
  ready: () => void;
99
40
  configUpdate: (data: {
@@ -106,6 +47,12 @@ type ServerEventMap = {
106
47
  source: EvaluationSource;
107
48
  }) => void;
108
49
  error: (error: Error) => void;
50
+ /** Fired when a sticky assignment references a rule that no longer matches the datafile. */
51
+ stickyOrphan: (data: {
52
+ flagKey: string;
53
+ userId: string;
54
+ assignment: StickyAssignment;
55
+ }) => void;
109
56
  };
110
57
  type ServerEventName = keyof ServerEventMap;
111
58
  interface MiddlewareConfig {
@@ -114,26 +61,57 @@ interface MiddlewareConfig {
114
61
  /** Extract targeting attributes from the request. */
115
62
  attributesFrom?: (req: unknown) => Record<string, unknown>;
116
63
  }
117
- interface RequestAvsB {
118
- /** Evaluate a flag for the request's user. */
119
- getFlag<T = unknown>(flagKey: string, defaultValue?: T): T;
120
- /** Get full evaluation details for the request's user. */
121
- getFlagDetails(flagKey: string): ServerFlagEvaluationDetails;
122
- /** Get all flag values for the request's user. */
123
- getAllFlags(): Record<string, unknown>;
124
- /** Track a conversion event for the request's user. */
125
- track(eventKey: string, properties?: {
126
- revenue?: number;
127
- [key: string]: unknown;
64
+
65
+ /**
66
+ * A per-request scoped client with a bound EvalContext.
67
+ *
68
+ * Created via `server.forUser(ctx)` or the `server.createUserContext(ctx)`
69
+ * alias. All flag evaluations and track calls use the bound context.
70
+ *
71
+ * Forced decisions set on a UserBoundClient survive only for the lifetime
72
+ * of the instance — they do not affect the shared AvsbServer override state.
73
+ * This makes them safe for test middleware and per-request debugging.
74
+ *
75
+ * Spec §5.8.
76
+ */
77
+ interface UserBoundClient {
78
+ getFlag<T>(flagKey: string, defaultValue: T, options?: {
79
+ decideOptions?: DecideOption[];
80
+ }): Flag<T>;
81
+ getBoolFlag(flagKey: string, defaultValue: boolean, options?: {
82
+ decideOptions?: DecideOption[];
83
+ }): Flag<boolean>;
84
+ getStringFlag(flagKey: string, defaultValue: string, options?: {
85
+ decideOptions?: DecideOption[];
86
+ }): Flag<string>;
87
+ getNumberFlag(flagKey: string, defaultValue: number, options?: {
88
+ decideOptions?: DecideOption[];
89
+ }): Flag<number>;
90
+ getJsonFlag<T>(flagKey: string, defaultValue: T, options?: {
91
+ decideOptions?: DecideOption[];
92
+ }): Flag<T>;
93
+ getAllFlags(options?: GetAllFlagsOptions): Record<string, Flag>;
94
+ track(eventKey: string, payload?: Omit<TrackPayload, 'context'>): void;
95
+ setForcedDecision(flagKey: string, opts: {
96
+ ruleId?: string;
97
+ variationKey: string;
128
98
  }): void;
129
- }
130
- interface OverrideEntry {
131
- flagKey: string;
132
- variationKey: string;
133
- userId?: string;
99
+ clearForcedDecision(flagKey: string): void;
100
+ getDecisionLog(): DecisionLog;
134
101
  }
135
102
 
136
- declare class AvsBServer {
103
+ interface GetFlagOptions {
104
+ context?: EvalContext;
105
+ decideOptions?: DecideOption[];
106
+ decisionLog?: DecisionLog;
107
+ /** Internal: UserBoundClient forced decision override. */
108
+ forcedVariationKey?: string;
109
+ }
110
+ interface GetAllFlagsOptions {
111
+ fireExposures?: boolean;
112
+ decideOptions?: DecideOption[];
113
+ }
114
+ declare class AvsbServer {
137
115
  private sdkKey;
138
116
  private pollingInterval;
139
117
  private cdnHost;
@@ -141,57 +119,87 @@ declare class AvsBServer {
141
119
  private logger;
142
120
  private stickyBucketService;
143
121
  private eventOptions;
122
+ private streamingEnabled;
123
+ private streamingEndpoint;
144
124
  private datafile;
145
125
  private ready;
146
126
  private destroyed;
147
127
  private tracker;
128
+ private streamingClient;
148
129
  private pollingId;
130
+ private abortController;
149
131
  private overrides;
150
132
  private listeners;
151
133
  private readyPromise;
152
- constructor(options: AvsBServerOptions);
134
+ private pendingEvents;
135
+ /**
136
+ * §6 — `client.utils.*` surface. Constructed lazily on first access so
137
+ * the utils package is only imported when actually consumed.
138
+ *
139
+ * The server's event surface (`ServerEventMap`) is a subset of the
140
+ * shared `ClientEventMap`; the utils-adapter `on` here ignores events
141
+ * the server doesn't emit (e.g. `flagChange`). Workstream 5 (CoW 6)
142
+ * harmonises the two maps when the streaming evaluator lands.
143
+ */
144
+ private _utils;
145
+ get utils(): AvsbUtils;
146
+ constructor(options: AvsbServerOptions);
153
147
  onReady(): Promise<InitResult>;
154
148
  private initializeAndReady;
155
149
  close(): Promise<void>;
156
150
  flush(): Promise<void>;
157
151
  refreshDatafile(): Promise<void>;
158
- getFlag<T = unknown>(flagKey: string, userContext: UserContext, defaultValue?: T): T;
159
- getFlagDetails(flagKey: string, userContext: UserContext): ServerFlagEvaluationDetails;
160
- getAllFlags(userContext: UserContext): Record<string, unknown>;
161
- track(eventKey: string, context: TrackContext): void;
162
- logExposure(flagKey: string, userContext: {
163
- userId: string;
152
+ getFlag<T>(flagKey: string, defaultValue: NoInfer<T> | T, options?: GetFlagOptions): Flag<T>;
153
+ getBoolFlag(flagKey: string, defaultValue: NoInfer<boolean> | boolean, options?: GetFlagOptions): Flag<boolean>;
154
+ getStringFlag(flagKey: string, defaultValue: NoInfer<string> | string, options?: GetFlagOptions): Flag<string>;
155
+ getNumberFlag(flagKey: string, defaultValue: NoInfer<number> | number, options?: GetFlagOptions): Flag<number>;
156
+ getJsonFlag<T>(flagKey: string, defaultValue: NoInfer<T> | T, options?: GetFlagOptions): Flag<T>;
157
+ getAllFlags(context: EvalContext, options?: GetAllFlagsOptions): Record<string, Flag>;
158
+ track(eventKey: string, payload: TrackPayload & {
159
+ context: EvalContext;
164
160
  }): void;
165
- setOverride(flagKey: string, variationKey: string, userId?: string): void;
166
- clearOverride(flagKey: string, userId?: string): void;
161
+ manualExposure(flagKey: string, context: EvalContext): void;
162
+ forUser(context: EvalContext): UserBoundClient;
163
+ createUserContext(context: EvalContext): UserBoundClient;
164
+ setOverrideForUser(flagKey: string, contextKey: string, variationKey: string, contextKind?: string): void;
165
+ setGlobalOverride(flagKey: string, variationKey: string): void;
166
+ clearOverrideForUser(flagKey: string, contextKey: string, contextKind?: string): void;
167
+ clearGlobalOverride(flagKey: string): void;
167
168
  clearAllOverrides(): void;
168
169
  createDecisionLog(): DecisionLog;
169
- on<E extends ServerEventName>(event: E, cb: ServerEventMap[E]): void;
170
+ on<E extends ServerEventName>(event: E, cb: ServerEventMap[E]): () => void;
170
171
  off<E extends ServerEventName>(event: E, cb: ServerEventMap[E]): void;
171
172
  private evaluate;
173
+ private getTypedFlag;
174
+ private toFlag;
175
+ /** toFlag variant that never writes a decision log (used by getAllFlags suppressed path). */
176
+ private toFlagNoLog;
177
+ /** Build a Flag<T> from a forced variation key (per-request override). */
178
+ private buildFlagFromVariationKey;
179
+ private buildLegacyContext;
180
+ private resolveRuntimeOverride;
181
+ private resolveStickyBucket;
182
+ private findVariation;
183
+ private fireExposureForStickyAssignment;
172
184
  private emit;
185
+ private emitEvaluation;
173
186
  private initTracker;
187
+ private startStreamingIfEnabled;
174
188
  private fetchDatafile;
175
189
  private startPolling;
176
190
  private sendHeartbeat;
177
- private resolveRuntimeOverride;
178
- private resolveStickyBucket;
179
- private findVariation;
180
- private fireExposureForVariation;
181
- private recordDecisionLog;
182
- private emitEvaluation;
183
191
  }
184
192
 
185
- declare function expressMiddleware(client: AvsBServer, config: MiddlewareConfig): (req: unknown, res: unknown, next: () => void) => void;
193
+ declare function expressMiddleware(client: AvsbServer, config: MiddlewareConfig): (req: unknown, res: unknown, next: () => void) => void;
186
194
  declare function fastifyPlugin(instance: unknown, opts: {
187
- client: AvsBServer;
195
+ client: AvsbServer;
188
196
  } & MiddlewareConfig, done: () => void): void;
189
197
 
190
198
  declare class InMemoryStickyBucketService implements StickyBucketService {
191
199
  private cache;
192
200
  private key;
193
- lookup(userId: string, flagKey: string): string | null;
194
- save(userId: string, flagKey: string, variationId: string): void;
201
+ lookup(userId: string, flagKey: string): StickyAssignment | null;
202
+ save(userId: string, flagKey: string, assignment: StickyAssignment): void;
195
203
  }
196
204
  interface RedisLike {
197
205
  get(key: string): Promise<string | null>;
@@ -216,8 +224,8 @@ declare class RedisStickyBucketService implements StickyBucketService {
216
224
  constructor(options: RedisStickyBucketOptions);
217
225
  private redisKey;
218
226
  private cacheKey;
219
- lookup(userId: string, flagKey: string): string | null;
220
- save(userId: string, flagKey: string, variationId: string): void;
227
+ lookup(userId: string, flagKey: string): StickyAssignment | null;
228
+ save(userId: string, flagKey: string, assignment: StickyAssignment): void;
221
229
  private backgroundFetch;
222
230
  private evictIfNeeded;
223
231
  }
@@ -238,9 +246,6 @@ declare function createStreamingClient(options: StreamingOptions): StreamingClie
238
246
 
239
247
  declare function createDecisionLog(): DecisionLog;
240
248
 
241
- /** No-op logger — used when no custom logger is provided. */
242
- declare const noopLogger: Logger;
243
-
244
249
  declare const SDK_VERSION = "0.3.0";
245
250
 
246
- export { AvsBServer, type AvsBServerOptions, type DecisionLog, type DecisionLogEntry, type EvaluationSource, type EventOptions, InMemoryStickyBucketService, type InitResult, type Logger, type MiddlewareConfig, type OverrideEntry, type RedisLike, type RedisStickyBucketOptions, RedisStickyBucketService, type RequestAvsB, SDK_VERSION, type ServerEventMap, type ServerEventName, type ServerFlagEvaluationDetails, type StickyBucketService, type StreamingClient, type StreamingOptions, type TrackContext, type UserContext, createDecisionLog, createStreamingClient, expressMiddleware, fastifyPlugin, noopLogger };
251
+ export { AvsbServer, type AvsbServerOptions, type EventOptions, type GetAllFlagsOptions, type GetFlagOptions, InMemoryStickyBucketService, type MiddlewareConfig, type RedisLike, type RedisStickyBucketOptions, RedisStickyBucketService, SDK_VERSION, type StreamingClient, type StreamingOptions, type UserBoundClient, createDecisionLog, createStreamingClient, expressMiddleware, fastifyPlugin };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
- import { FlagDatafile } from '@avsbhq/js';
2
- export { ExposureEvent, FlagDatafile, FlagEvaluationDetails, MetricEvent } from '@avsbhq/js';
1
+ import { FlagDatafile, StickyBucketService, Logger, EvaluationSource, StickyAssignment, DecideOption, Flag, TrackPayload, DecisionLog, InitResult, EvalContext } from '@avsbhq/core';
2
+ export { DecideOption, DecisionLog, DecisionLogEntry, EvalContext, EvaluationSource, ExposureEvent, Flag, FlagDatafile, FlagEvaluationDetails, InitResult, Logger, MetricEvent, MultiContext, RuleType, SingleContext, StickyAssignment, StickyBucketService, TrackPayload, consoleLogger, consoleTransport, createLogger, noopLogger } from '@avsbhq/core';
3
+ import { AvsbUtils } from '@avsbhq/utils';
4
+ export { AvsbUtils } from '@avsbhq/utils';
3
5
 
4
- interface AvsBServerOptions {
6
+ interface AvsbServerOptions {
5
7
  /** SDK key for the flag environment (e.g., "env_abc123") */
6
8
  sdkKey: string;
7
9
  /** Datafile polling interval in ms. Default: 60_000 (60s). Min: 5_000. */
@@ -33,67 +35,6 @@ interface EventOptions {
33
35
  /** Retry attempts on flush failure. Default: 3. */
34
36
  retryAttempts?: number;
35
37
  }
36
- interface UserContext {
37
- /** User identifier for bucketing. Required. */
38
- userId: string;
39
- /** Targeting attributes (plan, country, device, etc.). */
40
- attributes?: Record<string, unknown>;
41
- /** When true, evaluate without firing an exposure event. Default: false. */
42
- suppressExposure?: boolean;
43
- /** Collect evaluation details into this log. */
44
- decisionLog?: DecisionLog;
45
- /** Attribute keys to strip from event payloads (used for targeting, not sent to analytics). */
46
- privateAttributes?: string[];
47
- }
48
- interface TrackContext {
49
- /** User identifier. Required. */
50
- userId: string;
51
- /** Revenue value for conversion tracking. */
52
- revenue?: number;
53
- /** Custom event properties. */
54
- properties?: Record<string, unknown>;
55
- }
56
- interface DecisionLog {
57
- readonly entries: DecisionLogEntry[];
58
- }
59
- interface DecisionLogEntry {
60
- flagKey: string;
61
- value: unknown;
62
- variationKey: string | null;
63
- source: EvaluationSource;
64
- ruleId: string | null;
65
- ruleType: 'targeted_delivery' | 'ab_test' | null;
66
- reasons: string[];
67
- evaluatedAt: number;
68
- durationMs: number;
69
- }
70
- type EvaluationSource = 'override' | 'sticky' | 'rule' | 'default' | 'not_found' | 'disabled' | 'runtime_override';
71
- interface ServerFlagEvaluationDetails {
72
- value: unknown;
73
- variationKey: string | null;
74
- source: EvaluationSource;
75
- ruleId: string | null;
76
- ruleType: 'targeted_delivery' | 'ab_test' | null;
77
- flagKey: string;
78
- reasons: string[];
79
- }
80
- interface InitResult {
81
- success: boolean;
82
- source: 'network' | 'bootstrap' | 'cache' | 'timeout' | 'error';
83
- error?: Error;
84
- }
85
- interface StickyBucketService {
86
- /** Look up stored variation for a user+flag. Return variationId or null. Synchronous. */
87
- lookup(userId: string, flagKey: string): string | null;
88
- /** Persist a variation assignment. Fire-and-forget (may be async internally). */
89
- save(userId: string, flagKey: string, variationId: string): void;
90
- }
91
- interface Logger {
92
- debug(message: string, data?: Record<string, unknown>): void;
93
- info(message: string, data?: Record<string, unknown>): void;
94
- warn(message: string, data?: Record<string, unknown>): void;
95
- error(message: string, data?: Record<string, unknown>): void;
96
- }
97
38
  type ServerEventMap = {
98
39
  ready: () => void;
99
40
  configUpdate: (data: {
@@ -106,6 +47,12 @@ type ServerEventMap = {
106
47
  source: EvaluationSource;
107
48
  }) => void;
108
49
  error: (error: Error) => void;
50
+ /** Fired when a sticky assignment references a rule that no longer matches the datafile. */
51
+ stickyOrphan: (data: {
52
+ flagKey: string;
53
+ userId: string;
54
+ assignment: StickyAssignment;
55
+ }) => void;
109
56
  };
110
57
  type ServerEventName = keyof ServerEventMap;
111
58
  interface MiddlewareConfig {
@@ -114,26 +61,57 @@ interface MiddlewareConfig {
114
61
  /** Extract targeting attributes from the request. */
115
62
  attributesFrom?: (req: unknown) => Record<string, unknown>;
116
63
  }
117
- interface RequestAvsB {
118
- /** Evaluate a flag for the request's user. */
119
- getFlag<T = unknown>(flagKey: string, defaultValue?: T): T;
120
- /** Get full evaluation details for the request's user. */
121
- getFlagDetails(flagKey: string): ServerFlagEvaluationDetails;
122
- /** Get all flag values for the request's user. */
123
- getAllFlags(): Record<string, unknown>;
124
- /** Track a conversion event for the request's user. */
125
- track(eventKey: string, properties?: {
126
- revenue?: number;
127
- [key: string]: unknown;
64
+
65
+ /**
66
+ * A per-request scoped client with a bound EvalContext.
67
+ *
68
+ * Created via `server.forUser(ctx)` or the `server.createUserContext(ctx)`
69
+ * alias. All flag evaluations and track calls use the bound context.
70
+ *
71
+ * Forced decisions set on a UserBoundClient survive only for the lifetime
72
+ * of the instance — they do not affect the shared AvsbServer override state.
73
+ * This makes them safe for test middleware and per-request debugging.
74
+ *
75
+ * Spec §5.8.
76
+ */
77
+ interface UserBoundClient {
78
+ getFlag<T>(flagKey: string, defaultValue: T, options?: {
79
+ decideOptions?: DecideOption[];
80
+ }): Flag<T>;
81
+ getBoolFlag(flagKey: string, defaultValue: boolean, options?: {
82
+ decideOptions?: DecideOption[];
83
+ }): Flag<boolean>;
84
+ getStringFlag(flagKey: string, defaultValue: string, options?: {
85
+ decideOptions?: DecideOption[];
86
+ }): Flag<string>;
87
+ getNumberFlag(flagKey: string, defaultValue: number, options?: {
88
+ decideOptions?: DecideOption[];
89
+ }): Flag<number>;
90
+ getJsonFlag<T>(flagKey: string, defaultValue: T, options?: {
91
+ decideOptions?: DecideOption[];
92
+ }): Flag<T>;
93
+ getAllFlags(options?: GetAllFlagsOptions): Record<string, Flag>;
94
+ track(eventKey: string, payload?: Omit<TrackPayload, 'context'>): void;
95
+ setForcedDecision(flagKey: string, opts: {
96
+ ruleId?: string;
97
+ variationKey: string;
128
98
  }): void;
129
- }
130
- interface OverrideEntry {
131
- flagKey: string;
132
- variationKey: string;
133
- userId?: string;
99
+ clearForcedDecision(flagKey: string): void;
100
+ getDecisionLog(): DecisionLog;
134
101
  }
135
102
 
136
- declare class AvsBServer {
103
+ interface GetFlagOptions {
104
+ context?: EvalContext;
105
+ decideOptions?: DecideOption[];
106
+ decisionLog?: DecisionLog;
107
+ /** Internal: UserBoundClient forced decision override. */
108
+ forcedVariationKey?: string;
109
+ }
110
+ interface GetAllFlagsOptions {
111
+ fireExposures?: boolean;
112
+ decideOptions?: DecideOption[];
113
+ }
114
+ declare class AvsbServer {
137
115
  private sdkKey;
138
116
  private pollingInterval;
139
117
  private cdnHost;
@@ -141,57 +119,87 @@ declare class AvsBServer {
141
119
  private logger;
142
120
  private stickyBucketService;
143
121
  private eventOptions;
122
+ private streamingEnabled;
123
+ private streamingEndpoint;
144
124
  private datafile;
145
125
  private ready;
146
126
  private destroyed;
147
127
  private tracker;
128
+ private streamingClient;
148
129
  private pollingId;
130
+ private abortController;
149
131
  private overrides;
150
132
  private listeners;
151
133
  private readyPromise;
152
- constructor(options: AvsBServerOptions);
134
+ private pendingEvents;
135
+ /**
136
+ * §6 — `client.utils.*` surface. Constructed lazily on first access so
137
+ * the utils package is only imported when actually consumed.
138
+ *
139
+ * The server's event surface (`ServerEventMap`) is a subset of the
140
+ * shared `ClientEventMap`; the utils-adapter `on` here ignores events
141
+ * the server doesn't emit (e.g. `flagChange`). Workstream 5 (CoW 6)
142
+ * harmonises the two maps when the streaming evaluator lands.
143
+ */
144
+ private _utils;
145
+ get utils(): AvsbUtils;
146
+ constructor(options: AvsbServerOptions);
153
147
  onReady(): Promise<InitResult>;
154
148
  private initializeAndReady;
155
149
  close(): Promise<void>;
156
150
  flush(): Promise<void>;
157
151
  refreshDatafile(): Promise<void>;
158
- getFlag<T = unknown>(flagKey: string, userContext: UserContext, defaultValue?: T): T;
159
- getFlagDetails(flagKey: string, userContext: UserContext): ServerFlagEvaluationDetails;
160
- getAllFlags(userContext: UserContext): Record<string, unknown>;
161
- track(eventKey: string, context: TrackContext): void;
162
- logExposure(flagKey: string, userContext: {
163
- userId: string;
152
+ getFlag<T>(flagKey: string, defaultValue: NoInfer<T> | T, options?: GetFlagOptions): Flag<T>;
153
+ getBoolFlag(flagKey: string, defaultValue: NoInfer<boolean> | boolean, options?: GetFlagOptions): Flag<boolean>;
154
+ getStringFlag(flagKey: string, defaultValue: NoInfer<string> | string, options?: GetFlagOptions): Flag<string>;
155
+ getNumberFlag(flagKey: string, defaultValue: NoInfer<number> | number, options?: GetFlagOptions): Flag<number>;
156
+ getJsonFlag<T>(flagKey: string, defaultValue: NoInfer<T> | T, options?: GetFlagOptions): Flag<T>;
157
+ getAllFlags(context: EvalContext, options?: GetAllFlagsOptions): Record<string, Flag>;
158
+ track(eventKey: string, payload: TrackPayload & {
159
+ context: EvalContext;
164
160
  }): void;
165
- setOverride(flagKey: string, variationKey: string, userId?: string): void;
166
- clearOverride(flagKey: string, userId?: string): void;
161
+ manualExposure(flagKey: string, context: EvalContext): void;
162
+ forUser(context: EvalContext): UserBoundClient;
163
+ createUserContext(context: EvalContext): UserBoundClient;
164
+ setOverrideForUser(flagKey: string, contextKey: string, variationKey: string, contextKind?: string): void;
165
+ setGlobalOverride(flagKey: string, variationKey: string): void;
166
+ clearOverrideForUser(flagKey: string, contextKey: string, contextKind?: string): void;
167
+ clearGlobalOverride(flagKey: string): void;
167
168
  clearAllOverrides(): void;
168
169
  createDecisionLog(): DecisionLog;
169
- on<E extends ServerEventName>(event: E, cb: ServerEventMap[E]): void;
170
+ on<E extends ServerEventName>(event: E, cb: ServerEventMap[E]): () => void;
170
171
  off<E extends ServerEventName>(event: E, cb: ServerEventMap[E]): void;
171
172
  private evaluate;
173
+ private getTypedFlag;
174
+ private toFlag;
175
+ /** toFlag variant that never writes a decision log (used by getAllFlags suppressed path). */
176
+ private toFlagNoLog;
177
+ /** Build a Flag<T> from a forced variation key (per-request override). */
178
+ private buildFlagFromVariationKey;
179
+ private buildLegacyContext;
180
+ private resolveRuntimeOverride;
181
+ private resolveStickyBucket;
182
+ private findVariation;
183
+ private fireExposureForStickyAssignment;
172
184
  private emit;
185
+ private emitEvaluation;
173
186
  private initTracker;
187
+ private startStreamingIfEnabled;
174
188
  private fetchDatafile;
175
189
  private startPolling;
176
190
  private sendHeartbeat;
177
- private resolveRuntimeOverride;
178
- private resolveStickyBucket;
179
- private findVariation;
180
- private fireExposureForVariation;
181
- private recordDecisionLog;
182
- private emitEvaluation;
183
191
  }
184
192
 
185
- declare function expressMiddleware(client: AvsBServer, config: MiddlewareConfig): (req: unknown, res: unknown, next: () => void) => void;
193
+ declare function expressMiddleware(client: AvsbServer, config: MiddlewareConfig): (req: unknown, res: unknown, next: () => void) => void;
186
194
  declare function fastifyPlugin(instance: unknown, opts: {
187
- client: AvsBServer;
195
+ client: AvsbServer;
188
196
  } & MiddlewareConfig, done: () => void): void;
189
197
 
190
198
  declare class InMemoryStickyBucketService implements StickyBucketService {
191
199
  private cache;
192
200
  private key;
193
- lookup(userId: string, flagKey: string): string | null;
194
- save(userId: string, flagKey: string, variationId: string): void;
201
+ lookup(userId: string, flagKey: string): StickyAssignment | null;
202
+ save(userId: string, flagKey: string, assignment: StickyAssignment): void;
195
203
  }
196
204
  interface RedisLike {
197
205
  get(key: string): Promise<string | null>;
@@ -216,8 +224,8 @@ declare class RedisStickyBucketService implements StickyBucketService {
216
224
  constructor(options: RedisStickyBucketOptions);
217
225
  private redisKey;
218
226
  private cacheKey;
219
- lookup(userId: string, flagKey: string): string | null;
220
- save(userId: string, flagKey: string, variationId: string): void;
227
+ lookup(userId: string, flagKey: string): StickyAssignment | null;
228
+ save(userId: string, flagKey: string, assignment: StickyAssignment): void;
221
229
  private backgroundFetch;
222
230
  private evictIfNeeded;
223
231
  }
@@ -238,9 +246,6 @@ declare function createStreamingClient(options: StreamingOptions): StreamingClie
238
246
 
239
247
  declare function createDecisionLog(): DecisionLog;
240
248
 
241
- /** No-op logger — used when no custom logger is provided. */
242
- declare const noopLogger: Logger;
243
-
244
249
  declare const SDK_VERSION = "0.3.0";
245
250
 
246
- export { AvsBServer, type AvsBServerOptions, type DecisionLog, type DecisionLogEntry, type EvaluationSource, type EventOptions, InMemoryStickyBucketService, type InitResult, type Logger, type MiddlewareConfig, type OverrideEntry, type RedisLike, type RedisStickyBucketOptions, RedisStickyBucketService, type RequestAvsB, SDK_VERSION, type ServerEventMap, type ServerEventName, type ServerFlagEvaluationDetails, type StickyBucketService, type StreamingClient, type StreamingOptions, type TrackContext, type UserContext, createDecisionLog, createStreamingClient, expressMiddleware, fastifyPlugin, noopLogger };
251
+ export { AvsbServer, type AvsbServerOptions, type EventOptions, type GetAllFlagsOptions, type GetFlagOptions, InMemoryStickyBucketService, type MiddlewareConfig, type RedisLike, type RedisStickyBucketOptions, RedisStickyBucketService, SDK_VERSION, type StreamingClient, type StreamingOptions, type UserBoundClient, createDecisionLog, createStreamingClient, expressMiddleware, fastifyPlugin };