@beignet/core
Version:
Core framework primitives for Beignet
290 lines • 9.46 kB
TypeScript
/**
* @beignet/core/flags
*
* Provider-neutral feature flag primitives for Beignet applications.
*/
type MaybePromise<T> = T | Promise<T>;
/**
* JSON-compatible value used by object flags and flag metadata.
*/
export type FlagJsonValue = null | boolean | number | string | readonly FlagJsonValue[] | {
readonly [key: string]: FlagJsonValue;
};
/**
* Object-valued flags intentionally exclude scalar JSON values so the flag
* kind remains predictable.
*/
export type FlagObjectValue = readonly FlagJsonValue[] | {
readonly [key: string]: FlagJsonValue;
};
/**
* Value kinds supported by Beignet flags.
*/
export type FlagValue = boolean | string | number | FlagObjectValue;
/**
* Stable feature flag key.
*/
export type FlagKey = string;
/**
* Feature flag value kind.
*/
export type FlagValueKind = "boolean" | "string" | "number" | "object";
/**
* Subject used for provider-neutral flag targeting.
*/
export type FlagSubject = {
type: string;
id: string;
};
/**
* Tenant or account used for provider-neutral flag targeting.
*/
export type FlagTenant = {
id: string;
slug?: string;
};
/**
* Attribute value accepted by the provider-neutral flag context.
*/
export type FlagAttributeValue = null | boolean | number | string | readonly FlagAttributeValue[] | {
readonly [key: string]: FlagAttributeValue;
};
/**
* Context supplied to flag evaluations, exposure recording, and tracking.
*/
export type FlagEvaluationContext = {
/**
* Stable key used by providers for rollout bucketing and targeting.
*/
targetingKey: string;
/**
* Actor, user, service, tenant, or account being targeted.
*/
subject?: FlagSubject;
/**
* Tenant/account scope, when available.
*/
tenant?: FlagTenant;
/**
* Provider-neutral targeting attributes. Keep private data out unless the
* selected provider and retention policy are approved for it.
*/
attributes?: Record<string, FlagAttributeValue>;
/**
* Attribute keys that should be treated as private by providers and
* instrumentation.
*/
privateAttributes?: readonly string[];
requestId?: string;
traceId?: string;
spanId?: string;
parentSpanId?: string;
traceparent?: string;
};
/**
* Flag definition registered through `defineFlags(...)`.
*/
export type FlagDef<TValue extends FlagValue = FlagValue> = {
kind: "flag";
key: FlagKey;
valueKind: FlagValueKindForValue<TValue>;
defaultValue: TValue;
description?: string;
metadata?: Record<string, unknown>;
};
/**
* Infer the flag value type from a flag definition.
*/
export type InferFlagValue<TFlag> = TFlag extends FlagDef<infer TValue> ? TValue : never;
/**
* Map a value type to its runtime flag kind.
*/
export type FlagValueKindForValue<TValue extends FlagValue> = TValue extends boolean ? "boolean" : TValue extends string ? "string" : TValue extends number ? "number" : "object";
/**
* Options accepted when declaring a flag.
*/
export type DefineFlagOptions<TValue extends FlagValue> = {
default: TValue;
description?: string;
metadata?: Record<string, unknown>;
};
/**
* Registry returned by `defineFlags(...)`.
*/
export type FlagRegistry = Record<string, FlagDef>;
/**
* Reason a flag received its value.
*/
export type FlagEvaluationReason = "static" | "targeting_match" | "default" | "error" | "unknown" | (string & {});
/**
* Normalized error summary for failed flag provider evaluations.
*/
export type FlagEvaluationError = {
message: string;
code?: string;
};
/**
* Options accepted by flag evaluations.
*/
export type FlagEvaluationOptions<TValue extends FlagValue = FlagValue> = {
context?: FlagEvaluationContext;
/**
* Override the flag declaration default for this call.
*/
defaultValue?: TValue;
/**
* Explicitly record an exposure after evaluation succeeds. Plain evaluation
* does not record exposure by default.
*/
expose?: boolean;
};
/**
* Normalized flag evaluation details.
*/
export type FlagEvaluationDetails<TValue extends FlagValue = FlagValue> = {
key: string;
value: TValue;
defaultValue: TValue;
valueKind: FlagValueKindForValue<TValue>;
reason: FlagEvaluationReason;
defaulted: boolean;
variant?: string;
metadata?: Record<string, unknown>;
error?: FlagEvaluationError;
};
/**
* Options accepted by explicit exposure recording.
*/
export type FlagExposureOptions = {
context?: FlagEvaluationContext;
value?: FlagValue;
variant?: string;
metadata?: Record<string, unknown>;
};
/**
* Options accepted by tracking calls.
*/
export type FlagTrackOptions = {
context?: FlagEvaluationContext;
value?: number;
metadata?: Record<string, unknown>;
};
/**
* App-facing feature flag port.
*/
export type FlagsPort = {
evaluate<TValue extends FlagValue>(flag: FlagDef<TValue>, options?: FlagEvaluationOptions<TValue>): Promise<TValue>;
details<TValue extends FlagValue>(flag: FlagDef<TValue>, options?: FlagEvaluationOptions<TValue>): Promise<FlagEvaluationDetails<TValue>>;
recordExposure<TValue extends FlagValue>(flag: FlagDef<TValue>, options?: FlagExposureOptions): Promise<void>;
track(event: string, options?: FlagTrackOptions): Promise<void>;
};
/**
* Flag evaluation observation emitted by memory/static adapters.
*/
export type FlagEvaluationObservation<TValue extends FlagValue = FlagValue> = {
source: "evaluate" | "details";
flag: FlagDef<TValue>;
context?: FlagEvaluationContext;
details: FlagEvaluationDetails<TValue>;
durationMs: number;
requestId?: string;
traceId?: string;
spanId?: string;
parentSpanId?: string;
traceparent?: string;
};
/**
* Explicit flag exposure observation.
*/
export type FlagExposureObservation<TValue extends FlagValue = FlagValue> = {
flag: FlagDef<TValue>;
context?: FlagEvaluationContext;
value?: FlagValue;
variant?: string;
metadata?: Record<string, unknown>;
requestId?: string;
traceId?: string;
spanId?: string;
parentSpanId?: string;
traceparent?: string;
};
/**
* Flag tracking observation.
*/
export type FlagTrackObservation = {
event: string;
context?: FlagEvaluationContext;
value?: number;
metadata?: Record<string, unknown>;
requestId?: string;
traceId?: string;
spanId?: string;
parentSpanId?: string;
traceparent?: string;
};
export type FlagEvaluationObserver = (observation: FlagEvaluationObservation) => MaybePromise<void>;
export type FlagExposureObserver = (observation: FlagExposureObservation) => MaybePromise<void>;
export type FlagTrackObserver = (observation: FlagTrackObservation) => MaybePromise<void>;
/**
* Options for memory/static flag adapters.
*/
export type CreateFlagsOptions = {
onEvaluation?: FlagEvaluationObserver;
onExposure?: FlagExposureObserver;
onTrack?: FlagTrackObserver;
};
/**
* Static flag values keyed by flag key.
*/
export type StaticFlagValues = Record<string, FlagValue>;
/**
* Options for `createStaticFlags(...)`.
*/
export type CreateStaticFlagsOptions = CreateFlagsOptions & {
values?: StaticFlagValues;
};
/**
* In-memory flags port with mutation helpers for tests and local development.
*/
export type MemoryFlagsPort = FlagsPort & {
values: Map<string, FlagValue>;
set<TValue extends FlagValue>(flag: FlagDef<TValue>, value: TValue): void;
reset(flag?: FlagDef): void;
};
declare function defineBooleanFlag(key: string, options: DefineFlagOptions<boolean>): FlagDef<boolean>;
declare function defineStringFlag(key: string, options: DefineFlagOptions<string>): FlagDef<string>;
declare function defineStringFlag<const TValue extends string>(key: string, options: DefineFlagOptions<TValue>): FlagDef<TValue>;
declare function defineNumberFlag(key: string, options: DefineFlagOptions<number>): FlagDef<number>;
declare function defineNumberFlag<const TValue extends number>(key: string, options: DefineFlagOptions<TValue>): FlagDef<TValue>;
declare function defineObjectFlag<TValue extends FlagObjectValue>(key: string, options: DefineFlagOptions<TValue>): FlagDef<TValue>;
/**
* Define one feature flag declaration.
*/
export declare const defineFlag: {
boolean: typeof defineBooleanFlag;
string: typeof defineStringFlag;
number: typeof defineNumberFlag;
object: typeof defineObjectFlag;
};
/**
* Define a typed registry of feature flags.
*/
export declare function defineFlags<const TRegistry extends FlagRegistry>(registry: TRegistry): TRegistry;
/**
* Evaluate a flag through any `FlagsPort`.
*/
export declare function evaluateFlag<TValue extends FlagValue>(flags: FlagsPort, flag: FlagDef<TValue>, options?: FlagEvaluationOptions<TValue>): Promise<TValue>;
/**
* Return detailed flag evaluation information through any `FlagsPort`.
*/
export declare function getFlagDetails<TValue extends FlagValue>(flags: FlagsPort, flag: FlagDef<TValue>, options?: FlagEvaluationOptions<TValue>): Promise<FlagEvaluationDetails<TValue>>;
/**
* Create static flags backed by fixed values.
*/
export declare function createStaticFlags(options?: CreateStaticFlagsOptions): FlagsPort;
/**
* Create mutable in-memory flags for tests, examples, and local development.
*/
export declare function createMemoryFlags(options?: CreateStaticFlagsOptions): MemoryFlagsPort;
export {};
//# sourceMappingURL=index.d.ts.map