@jewel998/config 0.1.5 → 0.1.7

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.
Files changed (115) hide show
  1. package/dist/cache/browserStorage.d.ts +0 -1
  2. package/dist/cache/memoryStorage.d.ts +0 -1
  3. package/dist/cache/storage.d.ts +14 -0
  4. package/dist/cache/storage.js +43 -0
  5. package/dist/cache/types.d.ts +0 -1
  6. package/dist/client/ConfigClient.d.ts +0 -1
  7. package/dist/context/autoContext.d.ts +0 -1
  8. package/dist/createConfig.d.ts +0 -1
  9. package/dist/errors/index.d.ts +16 -0
  10. package/dist/errors/index.js +29 -0
  11. package/dist/events/EventEmitter.d.ts +0 -1
  12. package/dist/fetch/batchFetcher.d.ts +0 -1
  13. package/dist/fetch/projectedFetcher.d.ts +0 -1
  14. package/dist/index.d.ts +13 -0
  15. package/dist/initConfig.d.ts +0 -1
  16. package/dist/loading/deferred.d.ts +2 -0
  17. package/dist/loading/deferred.js +5 -0
  18. package/dist/loading/optimistic.d.ts +2 -0
  19. package/dist/loading/pessimistic.d.ts +2 -0
  20. package/dist/plugins/evaluatePipeline.d.ts +0 -1
  21. package/dist/plugins/index.d.ts +4 -0
  22. package/dist/plugins/lifecycle/archivedPlugin.d.ts +0 -1
  23. package/dist/plugins/lifecycle/index.d.ts +3 -0
  24. package/dist/plugins/lifecycle/stateTransitions.d.ts +0 -1
  25. package/dist/plugins/models.d.ts +50 -0
  26. package/dist/plugins/models.js +5 -0
  27. package/dist/plugins/overrides/index.d.ts +1 -0
  28. package/dist/plugins/overrides/overridesPlugin.d.ts +0 -1
  29. package/dist/plugins/prerequisites/index.d.ts +2 -0
  30. package/dist/plugins/prerequisites/prerequisitePlugin.d.ts +0 -1
  31. package/dist/plugins/rollout/computeBucket.d.ts +0 -1
  32. package/dist/plugins/rollout/index.d.ts +2 -0
  33. package/dist/plugins/rollout/murmurhash3.d.ts +5 -0
  34. package/dist/plugins/rollout/murmurhash3.js +56 -0
  35. package/dist/plugins/rollout/rolloutPlugin.d.ts +0 -1
  36. package/dist/plugins/schedule/index.d.ts +1 -0
  37. package/dist/plugins/schedule/schedulePlugin.d.ts +0 -1
  38. package/dist/plugins/targeting/index.d.ts +3 -0
  39. package/dist/plugins/targeting/predicates.d.ts +22 -0
  40. package/dist/plugins/targeting/predicates.js +110 -0
  41. package/dist/plugins/targeting/segmentResolver.d.ts +0 -1
  42. package/dist/plugins/targeting/targetingPlugin.d.ts +0 -1
  43. package/dist/plugins/types.d.ts +34 -0
  44. package/dist/plugins/types.js +13 -0
  45. package/dist/retry/RetryEngine.d.ts +0 -1
  46. package/dist/transport/HttpTransport.d.ts +0 -1
  47. package/dist/types.d.ts +203 -0
  48. package/dist/types.js +14 -0
  49. package/dist/webhook-formats.d.ts +91 -0
  50. package/dist/webhook-formats.js +141 -0
  51. package/package.json +3 -2
  52. package/dist/cache/browserStorage.d.ts.map +0 -1
  53. package/dist/cache/browserStorage.js.map +0 -1
  54. package/dist/cache/memoryStorage.d.ts.map +0 -1
  55. package/dist/cache/memoryStorage.js.map +0 -1
  56. package/dist/cache/types.d.ts.map +0 -1
  57. package/dist/cache/types.js.map +0 -1
  58. package/dist/client/ConfigClient.d.ts.map +0 -1
  59. package/dist/client/ConfigClient.js.map +0 -1
  60. package/dist/context/autoContext.d.ts.map +0 -1
  61. package/dist/context/autoContext.js.map +0 -1
  62. package/dist/createConfig.d.ts.map +0 -1
  63. package/dist/createConfig.js.map +0 -1
  64. package/dist/events/EventEmitter.d.ts.map +0 -1
  65. package/dist/events/EventEmitter.js.map +0 -1
  66. package/dist/fetch/batchFetcher.d.ts.map +0 -1
  67. package/dist/fetch/batchFetcher.js.map +0 -1
  68. package/dist/fetch/projectedFetcher.d.ts.map +0 -1
  69. package/dist/fetch/projectedFetcher.js.map +0 -1
  70. package/dist/index.d.ts.map +0 -1
  71. package/dist/index.js.map +0 -1
  72. package/dist/initConfig.d.ts.map +0 -1
  73. package/dist/initConfig.js.map +0 -1
  74. package/dist/loading/optimistic.d.ts.map +0 -1
  75. package/dist/loading/optimistic.js.map +0 -1
  76. package/dist/loading/pessimistic.d.ts.map +0 -1
  77. package/dist/loading/pessimistic.js.map +0 -1
  78. package/dist/plugins/evaluatePipeline.d.ts.map +0 -1
  79. package/dist/plugins/evaluatePipeline.js.map +0 -1
  80. package/dist/plugins/index.d.ts.map +0 -1
  81. package/dist/plugins/index.js.map +0 -1
  82. package/dist/plugins/lifecycle/archivedPlugin.d.ts.map +0 -1
  83. package/dist/plugins/lifecycle/archivedPlugin.js.map +0 -1
  84. package/dist/plugins/lifecycle/index.d.ts.map +0 -1
  85. package/dist/plugins/lifecycle/index.js.map +0 -1
  86. package/dist/plugins/lifecycle/stateTransitions.d.ts.map +0 -1
  87. package/dist/plugins/lifecycle/stateTransitions.js.map +0 -1
  88. package/dist/plugins/overrides/index.d.ts.map +0 -1
  89. package/dist/plugins/overrides/index.js.map +0 -1
  90. package/dist/plugins/overrides/overridesPlugin.d.ts.map +0 -1
  91. package/dist/plugins/overrides/overridesPlugin.js.map +0 -1
  92. package/dist/plugins/prerequisites/index.d.ts.map +0 -1
  93. package/dist/plugins/prerequisites/index.js.map +0 -1
  94. package/dist/plugins/prerequisites/prerequisitePlugin.d.ts.map +0 -1
  95. package/dist/plugins/prerequisites/prerequisitePlugin.js.map +0 -1
  96. package/dist/plugins/rollout/computeBucket.d.ts.map +0 -1
  97. package/dist/plugins/rollout/computeBucket.js.map +0 -1
  98. package/dist/plugins/rollout/index.d.ts.map +0 -1
  99. package/dist/plugins/rollout/index.js.map +0 -1
  100. package/dist/plugins/rollout/rolloutPlugin.d.ts.map +0 -1
  101. package/dist/plugins/rollout/rolloutPlugin.js.map +0 -1
  102. package/dist/plugins/schedule/index.d.ts.map +0 -1
  103. package/dist/plugins/schedule/index.js.map +0 -1
  104. package/dist/plugins/schedule/schedulePlugin.d.ts.map +0 -1
  105. package/dist/plugins/schedule/schedulePlugin.js.map +0 -1
  106. package/dist/plugins/targeting/index.d.ts.map +0 -1
  107. package/dist/plugins/targeting/index.js.map +0 -1
  108. package/dist/plugins/targeting/segmentResolver.d.ts.map +0 -1
  109. package/dist/plugins/targeting/segmentResolver.js.map +0 -1
  110. package/dist/plugins/targeting/targetingPlugin.d.ts.map +0 -1
  111. package/dist/plugins/targeting/targetingPlugin.js.map +0 -1
  112. package/dist/retry/RetryEngine.d.ts.map +0 -1
  113. package/dist/retry/RetryEngine.js.map +0 -1
  114. package/dist/transport/HttpTransport.d.ts.map +0 -1
  115. package/dist/transport/HttpTransport.js.map +0 -1
@@ -1,3 +1,2 @@
1
1
  import type { BrowserStorageOptions, CacheStorage } from "../types.js";
2
2
  export declare const browserStorage: (options?: BrowserStorageOptions) => CacheStorage;
3
- //# sourceMappingURL=browserStorage.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import type { CacheStorage } from "../types.js";
2
2
  export declare const memoryStorage: () => CacheStorage;
3
- //# sourceMappingURL=memoryStorage.d.ts.map
@@ -0,0 +1,14 @@
1
+ export interface CacheStorage {
2
+ get<T>(key: string): Promise<T | undefined> | T | undefined;
3
+ set<T>(key: string, value: T): Promise<void> | void;
4
+ delete(key: string): Promise<void> | void;
5
+ }
6
+ export interface CacheDriver {
7
+ name: string;
8
+ getItem<T>(key: string): Promise<T | undefined>;
9
+ setItem<T>(key: string, value: T): Promise<void>;
10
+ removeItem(key: string): Promise<void>;
11
+ }
12
+ export declare const memoryStorage: () => CacheStorage;
13
+ export declare const createDriverStorage: (driver: CacheDriver, storageKey?: string) => CacheStorage;
14
+ export declare const browserStorage: (storageKey?: string) => CacheStorage;
@@ -0,0 +1,43 @@
1
+ /// <reference lib="dom" />
2
+ export const memoryStorage = () => {
3
+ const store = new Map();
4
+ return {
5
+ get: (key) => store.get(key),
6
+ set: (key, value) => {
7
+ store.set(key, value);
8
+ },
9
+ delete: (key) => {
10
+ store.delete(key);
11
+ },
12
+ };
13
+ };
14
+ export const createDriverStorage = (driver, storageKey = "@jewel998/config") => ({
15
+ get: async (key) => driver.getItem(`${storageKey}:${key}`),
16
+ set: async (key, value) => {
17
+ await driver.setItem(`${storageKey}:${key}`, value);
18
+ },
19
+ delete: async (key) => {
20
+ await driver.removeItem(`${storageKey}:${key}`);
21
+ },
22
+ });
23
+ export const browserStorage = (storageKey = "@jewel998/config") => {
24
+ const isBrowser = typeof window !== "undefined" && typeof window.localStorage !== "undefined";
25
+ if (!isBrowser) {
26
+ return memoryStorage();
27
+ }
28
+ const driver = {
29
+ name: "localStorage",
30
+ getItem: async (key) => {
31
+ const serialized = window.localStorage.getItem(key);
32
+ return serialized ? JSON.parse(serialized) : undefined;
33
+ },
34
+ setItem: async (key, value) => {
35
+ window.localStorage.setItem(key, JSON.stringify(value));
36
+ },
37
+ removeItem: async (key) => {
38
+ window.localStorage.removeItem(key);
39
+ },
40
+ };
41
+ return createDriverStorage(driver, storageKey);
42
+ };
43
+ //# sourceMappingURL=storage.js.map
@@ -1,3 +1,2 @@
1
1
  export type { CacheEntry, CacheStorage, BrowserStorageOptions, } from "../types.js";
2
2
  export { DEFAULT_CACHE_TTL } from "../types.js";
3
- //# sourceMappingURL=types.d.ts.map
@@ -15,4 +15,3 @@ export interface ConfigClientInternals {
15
15
  onContextChange?: (ctx: EvaluationContext) => void;
16
16
  }
17
17
  export declare const buildConfigClient: (internals: ConfigClientInternals) => ConfigClient;
18
- //# sourceMappingURL=ConfigClient.d.ts.map
@@ -25,4 +25,3 @@ export declare function autoContext(user?: {
25
25
  * Deep-merge two evaluation contexts. User-provided values take precedence.
26
26
  */
27
27
  export declare function mergeContext(auto: EvaluationContext, user: EvaluationContext): EvaluationContext;
28
- //# sourceMappingURL=autoContext.d.ts.map
@@ -3,4 +3,3 @@ export declare function createConfig(options: CreateConfigOptions & {
3
3
  loadingStrategy: "pessimistic";
4
4
  }): Promise<ConfigClient>;
5
5
  export declare function createConfig(options: CreateConfigOptions): ConfigClient;
6
- //# sourceMappingURL=createConfig.d.ts.map
@@ -0,0 +1,16 @@
1
+ export type ConfigErrorCode = "MISSING_CLIENT_ID" | "AUTHENTICATION_FAILED" | "INITIALIZATION_FAILED" | "TIMEOUT" | "RATE_LIMITED" | "REVOKED" | "NETWORK_ERROR";
2
+ export declare class ConfigError extends Error {
3
+ readonly code: ConfigErrorCode;
4
+ name: string;
5
+ constructor(message: string, code: ConfigErrorCode);
6
+ }
7
+ export declare class InitializationError extends ConfigError {
8
+ readonly cause?: Error | undefined;
9
+ constructor(message: string, cause?: Error | undefined);
10
+ }
11
+ export declare class TimeoutError extends ConfigError {
12
+ constructor(timeoutMs: number);
13
+ }
14
+ export declare class AuthenticationError extends ConfigError {
15
+ constructor(message: string);
16
+ }
@@ -0,0 +1,29 @@
1
+ export class ConfigError extends Error {
2
+ code;
3
+ name = "ConfigError";
4
+ constructor(message, code) {
5
+ super(message);
6
+ this.code = code;
7
+ }
8
+ }
9
+ export class InitializationError extends ConfigError {
10
+ cause;
11
+ constructor(message, cause) {
12
+ super(message, "INITIALIZATION_FAILED");
13
+ this.cause = cause;
14
+ this.name = "InitializationError";
15
+ }
16
+ }
17
+ export class TimeoutError extends ConfigError {
18
+ constructor(timeoutMs) {
19
+ super(`Config initialization timed out after ${timeoutMs}ms`, "TIMEOUT");
20
+ this.name = "TimeoutError";
21
+ }
22
+ }
23
+ export class AuthenticationError extends ConfigError {
24
+ constructor(message) {
25
+ super(message, "AUTHENTICATION_FAILED");
26
+ this.name = "AuthenticationError";
27
+ }
28
+ }
29
+ //# sourceMappingURL=index.js.map
@@ -6,4 +6,3 @@ export declare class TypedEventEmitter implements EventEmitterInterface {
6
6
  emit<E extends ConfigEventType>(event: E, payload: ConfigEventPayloads[E]): void;
7
7
  removeAllListeners(): void;
8
8
  }
9
- //# sourceMappingURL=EventEmitter.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import type { ConfigFetcher, HttpTransport } from "../types.js";
2
2
  export declare const createBatchFetcher: (transport: HttpTransport) => ConfigFetcher;
3
- //# sourceMappingURL=batchFetcher.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import type { ConfigFetcher, HttpTransport } from "../types.js";
2
2
  export declare const createProjectedFetcher: (transport: HttpTransport) => ConfigFetcher;
3
- //# sourceMappingURL=projectedFetcher.d.ts.map
@@ -0,0 +1,13 @@
1
+ export { initConfig } from "./initConfig.js";
2
+ export type { InitConfigOptions, Flags } from "./initConfig.js";
3
+ export { createConfig } from "./createConfig.js";
4
+ export type { CacheStorage, ClientIdRecord, ConfigClient, ConfigEventCallback, ConfigEventPayloads, ConfigEventType, ConfigRecord, CreateConfigOptions, EnvironmentRecord, EvaluationWarning, FetchGranularity, LoadingStrategy, ProjectRecord, RetryConfig, } from "./types.js";
5
+ export type { EvaluationContext, EvaluationPlugin, PipelineStepId, PipelineStepResult, PipelineHelpers, } from "./plugins/types.js";
6
+ export { PIPELINE_ORDER } from "./plugins/types.js";
7
+ export { autoContext, mergeContext } from "./context/autoContext.js";
8
+ export { WEBHOOK_FORMATS, WEBHOOK_FORMAT_INFO, TEMPLATE_VARIABLES, WEBHOOK_EVENT_TYPES, WEBHOOK_RESOURCE_CATEGORIES, SAMPLE_WEBHOOK_EVENT, } from "./webhook-formats.js";
9
+ export type { WebhookFormat, WebhookEventType, WebhookResourceCategory, } from "./webhook-formats.js";
10
+ export { memoryStorage } from "./cache/memoryStorage.js";
11
+ export { browserStorage } from "./cache/browserStorage.js";
12
+ export { AuthenticationError, ConfigError, InitializationError, TimeoutError, } from "./errors/index.js";
13
+ export type { ConfigErrorCode } from "./errors/index.js";
@@ -63,4 +63,3 @@ export interface Flags {
63
63
  * ```
64
64
  */
65
65
  export declare function initConfig(options: InitConfigOptions): Flags;
66
- //# sourceMappingURL=initConfig.d.ts.map
@@ -0,0 +1,2 @@
1
+ import type { LoadingResult } from "../types.js";
2
+ export declare const executeDeferred: () => LoadingResult;
@@ -0,0 +1,5 @@
1
+ export const executeDeferred = () => {
2
+ // No network activity at init time
3
+ return { initialData: {}, status: "ready" };
4
+ };
5
+ //# sourceMappingURL=deferred.js.map
@@ -0,0 +1,2 @@
1
+ import type { LoadingContext, LoadingResult } from "../types.js";
2
+ export declare const executeOptimistic: (ctx: LoadingContext) => LoadingResult;
@@ -0,0 +1,2 @@
1
+ import type { LoadingContext, LoadingResult } from "../types.js";
2
+ export declare const executePessimistic: (ctx: LoadingContext) => Promise<LoadingResult>;
@@ -12,4 +12,3 @@ import type { EvaluationContext, EvaluationPlugin, PipelineHelpers } from "./typ
12
12
  * Steps with no registered plugin are transparently skipped.
13
13
  */
14
14
  export declare function evaluatePipeline(plugins: EvaluationPlugin[], flag: ConfigFlagData, context: EvaluationContext, helpers: PipelineHelpers): unknown;
15
- //# sourceMappingURL=evaluatePipeline.d.ts.map
@@ -0,0 +1,4 @@
1
+ export type { PipelineStepId, EvaluationContext, PipelineStepResult, EvaluationPlugin, PipelineHelpers, } from "./types.js";
2
+ export { PIPELINE_ORDER } from "./types.js";
3
+ export type { ConfigFlagData, TargetingRule, PredicateGroup, Predicate, PredicateOperator, Segment, } from "./models.js";
4
+ export { evaluatePipeline } from "./evaluatePipeline.js";
@@ -11,4 +11,3 @@ import type { EvaluationPlugin } from "../types.js";
11
11
  * short-circuit before any other evaluation logic runs.
12
12
  */
13
13
  export declare function archivedPlugin(): EvaluationPlugin;
14
- //# sourceMappingURL=archivedPlugin.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { archivedPlugin } from "./archivedPlugin.js";
2
+ export { validateStateTransition, VALID_TRANSITIONS, } from "./stateTransitions.js";
3
+ export type { LifecycleState } from "./stateTransitions.js";
@@ -24,4 +24,3 @@ export declare const VALID_TRANSITIONS: Record<LifecycleState, LifecycleState[]>
24
24
  * @returns `true` if the transition is valid, `false` otherwise
25
25
  */
26
26
  export declare function validateStateTransition(current: LifecycleState, target: LifecycleState): boolean;
27
- //# sourceMappingURL=stateTransitions.d.ts.map
@@ -0,0 +1,50 @@
1
+ /** The full config flag document as fetched from Firestore */
2
+ export interface ConfigFlagData {
3
+ key: string;
4
+ value: unknown;
5
+ valueType: "string" | "number" | "boolean" | "json";
6
+ version: string;
7
+ lifecycleState: "draft" | "active" | "stale" | "archived";
8
+ targetingRules?: TargetingRule[];
9
+ rolloutPercentage?: number;
10
+ rolloutValue?: unknown;
11
+ overrides?: Record<string, unknown>;
12
+ schedule?: {
13
+ targetValue: unknown;
14
+ activateAt: string;
15
+ };
16
+ prerequisites?: Array<{
17
+ flagKey: string;
18
+ operator?: "equals" | "not_equals" | "greater_than" | "less_than" | "contains";
19
+ requiredValue: unknown;
20
+ }>;
21
+ }
22
+ /** A single targeting rule */
23
+ export interface TargetingRule {
24
+ id: string;
25
+ priority: number;
26
+ value: unknown;
27
+ conditions: PredicateGroup[];
28
+ }
29
+ /** A group of predicates combined with AND logic */
30
+ export interface PredicateGroup {
31
+ predicates: Predicate[];
32
+ }
33
+ /** A single predicate */
34
+ export interface Predicate {
35
+ attribute: string;
36
+ operator: PredicateOperator;
37
+ value: string | number | boolean | string[];
38
+ }
39
+ /** Supported predicate operators */
40
+ export type PredicateOperator = "equals" | "not_equals" | "contains" | "starts_with" | "ends_with" | "in_list" | "not_in_list" | "greater_than" | "less_than" | "regex_match" | "in_segment" | "not_in_segment";
41
+ /** A reusable audience segment */
42
+ export interface Segment {
43
+ id: string;
44
+ name: string;
45
+ description: string;
46
+ conditions: PredicateGroup[];
47
+ createdAt: string;
48
+ updatedAt: string;
49
+ createdBy: string;
50
+ }
@@ -0,0 +1,5 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Config Flag Data Models (SDK-side)
3
+ // ═══════════════════════════════════════════════════════════════
4
+ export {};
5
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ export { overridesPlugin } from "./overridesPlugin.js";
@@ -9,4 +9,3 @@ import type { EvaluationPlugin } from "../types.js";
9
9
  * - If userId not in overrides or value is null/undefined → skip (Req 4.4, 4.7)
10
10
  */
11
11
  export declare function overridesPlugin(): EvaluationPlugin;
12
- //# sourceMappingURL=overridesPlugin.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { prerequisitePlugin } from "./prerequisitePlugin.js";
2
+ export type { PrerequisitePluginOptions } from "./prerequisitePlugin.js";
@@ -21,4 +21,3 @@ export interface PrerequisitePluginOptions {
21
21
  * that tracks which flags are currently being evaluated for prerequisites.
22
22
  */
23
23
  export declare function prerequisitePlugin(options?: PrerequisitePluginOptions): EvaluationPlugin;
24
- //# sourceMappingURL=prerequisitePlugin.d.ts.map
@@ -9,4 +9,3 @@
9
9
  * Deterministic — same inputs always produce the same bucket.
10
10
  */
11
11
  export declare function computeBucket(configKey: string, userId: string): number;
12
- //# sourceMappingURL=computeBucket.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { computeBucket } from "./computeBucket.js";
2
+ export { rolloutPlugin } from "./rolloutPlugin.js";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * MurmurHash3_x86_32 — deterministic 32-bit hash.
3
+ * Used for percentage rollout bucketing (same algorithm as flagd/OpenFeature).
4
+ */
5
+ export declare function murmurhash3_32(key: string, seed?: number): number;
@@ -0,0 +1,56 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // MurmurHash3_x86_32
3
+ // Public domain — Austin Appleby
4
+ // Adapted for TypeScript (operates on UTF-8 encoded string bytes)
5
+ // ═══════════════════════════════════════════════════════════════
6
+ /**
7
+ * MurmurHash3_x86_32 — deterministic 32-bit hash.
8
+ * Used for percentage rollout bucketing (same algorithm as flagd/OpenFeature).
9
+ */
10
+ export function murmurhash3_32(key, seed = 0) {
11
+ const encoder = new TextEncoder();
12
+ const bytes = encoder.encode(key);
13
+ const len = bytes.length;
14
+ let h1 = seed >>> 0;
15
+ const c1 = 0xcc9e2d51;
16
+ const c2 = 0x1b873593;
17
+ let i = 0;
18
+ while (i + 4 <= len) {
19
+ let k1 = (bytes[i] |
20
+ (bytes[i + 1] << 8) |
21
+ (bytes[i + 2] << 16) |
22
+ (bytes[i + 3] << 24)) >>>
23
+ 0;
24
+ k1 = Math.imul(k1, c1) >>> 0;
25
+ k1 = ((k1 << 15) | (k1 >>> 17)) >>> 0;
26
+ k1 = Math.imul(k1, c2) >>> 0;
27
+ h1 ^= k1;
28
+ h1 = ((h1 << 13) | (h1 >>> 19)) >>> 0;
29
+ h1 = (Math.imul(h1, 5) + 0xe6546b64) >>> 0;
30
+ i += 4;
31
+ }
32
+ let k1 = 0;
33
+ const remainder = len & 3;
34
+ if (remainder >= 3) {
35
+ k1 ^= bytes[i + 2] << 16;
36
+ }
37
+ if (remainder >= 2) {
38
+ k1 ^= bytes[i + 1] << 8;
39
+ }
40
+ if (remainder >= 1) {
41
+ k1 ^= bytes[i];
42
+ k1 = Math.imul(k1, c1) >>> 0;
43
+ k1 = ((k1 << 15) | (k1 >>> 17)) >>> 0;
44
+ k1 = Math.imul(k1, c2) >>> 0;
45
+ h1 ^= k1;
46
+ }
47
+ h1 ^= len;
48
+ // fmix32
49
+ h1 ^= h1 >>> 16;
50
+ h1 = Math.imul(h1, 0x85ebca6b) >>> 0;
51
+ h1 ^= h1 >>> 13;
52
+ h1 = Math.imul(h1, 0xc2b2ae35) >>> 0;
53
+ h1 ^= h1 >>> 16;
54
+ return h1 >>> 0;
55
+ }
56
+ //# sourceMappingURL=murmurhash3.js.map
@@ -10,4 +10,3 @@ import type { EvaluationPlugin } from "../types.js";
10
10
  * - Otherwise: compute bucket, if bucket < rolloutPercentage → return rollout value, else skip
11
11
  */
12
12
  export declare function rolloutPlugin(): EvaluationPlugin;
13
- //# sourceMappingURL=rolloutPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ export { schedulePlugin } from "./schedulePlugin.js";
@@ -11,4 +11,3 @@ import type { EvaluationPlugin } from "../types.js";
11
11
  * - If activateAt is in the future → skip (Requirement 6.5)
12
12
  */
13
13
  export declare function schedulePlugin(): EvaluationPlugin;
14
- //# sourceMappingURL=schedulePlugin.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { targetingPlugin } from "./targetingPlugin.js";
2
+ export { evaluatePredicate, evaluatePredicateGroups } from "./predicates.js";
3
+ export { resolveSegment } from "./segmentResolver.js";
@@ -0,0 +1,22 @@
1
+ import type { Predicate, PredicateGroup } from "../models.js";
2
+ type AttributeValue = string | number | boolean | string[];
3
+ /**
4
+ * Evaluate a single predicate against the provided attributes.
5
+ *
6
+ * Returns false for:
7
+ * - Missing attributes in context
8
+ * - Type mismatches (e.g., greater_than on a non-numeric value)
9
+ * - Invalid regex patterns (also calls emitError)
10
+ * - in_segment / not_in_segment (handled externally by segment resolver)
11
+ */
12
+ export declare function evaluatePredicate(predicate: Predicate, attributes: Record<string, AttributeValue>, emitError?: (message: string) => void): boolean;
13
+ /**
14
+ * Evaluate predicate groups in Disjunctive Normal Form (DNF).
15
+ *
16
+ * Groups are OR'd — any group matching means the whole expression matches.
17
+ * Within each group, predicates are AND'd — all must match.
18
+ *
19
+ * Returns false if groups array is empty.
20
+ */
21
+ export declare function evaluatePredicateGroups(groups: PredicateGroup[], attributes: Record<string, AttributeValue>, emitError?: (message: string) => void): boolean;
22
+ export {};
@@ -0,0 +1,110 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Predicate Evaluator — DNF logic for targeting rules
3
+ // ═══════════════════════════════════════════════════════════════
4
+ /**
5
+ * Evaluate a single predicate against the provided attributes.
6
+ *
7
+ * Returns false for:
8
+ * - Missing attributes in context
9
+ * - Type mismatches (e.g., greater_than on a non-numeric value)
10
+ * - Invalid regex patterns (also calls emitError)
11
+ * - in_segment / not_in_segment (handled externally by segment resolver)
12
+ */
13
+ export function evaluatePredicate(predicate, attributes, emitError) {
14
+ const { attribute, operator, value } = predicate;
15
+ // in_segment / not_in_segment are resolved externally by the segment resolver
16
+ if (operator === "in_segment" || operator === "not_in_segment") {
17
+ return false;
18
+ }
19
+ // Missing attribute → predicate is non-matching (Property 4)
20
+ if (!(attribute in attributes)) {
21
+ return false;
22
+ }
23
+ const attrValue = attributes[attribute];
24
+ // Attribute value is undefined/null → non-matching
25
+ if (attrValue === undefined || attrValue === null) {
26
+ return false;
27
+ }
28
+ switch (operator) {
29
+ case "equals":
30
+ return attrValue === value;
31
+ case "not_equals":
32
+ return attrValue !== value;
33
+ case "contains": {
34
+ if (typeof attrValue !== "string" || typeof value !== "string") {
35
+ return false;
36
+ }
37
+ return attrValue.includes(value);
38
+ }
39
+ case "starts_with": {
40
+ if (typeof attrValue !== "string" || typeof value !== "string") {
41
+ return false;
42
+ }
43
+ return attrValue.startsWith(value);
44
+ }
45
+ case "ends_with": {
46
+ if (typeof attrValue !== "string" || typeof value !== "string") {
47
+ return false;
48
+ }
49
+ return attrValue.endsWith(value);
50
+ }
51
+ case "in_list": {
52
+ if (!Array.isArray(value)) {
53
+ return false;
54
+ }
55
+ return value.includes(attrValue);
56
+ }
57
+ case "not_in_list": {
58
+ if (!Array.isArray(value)) {
59
+ return false;
60
+ }
61
+ return !value.includes(attrValue);
62
+ }
63
+ case "greater_than": {
64
+ if (typeof attrValue !== "number" || typeof value !== "number") {
65
+ return false;
66
+ }
67
+ return attrValue > value;
68
+ }
69
+ case "less_than": {
70
+ if (typeof attrValue !== "number" || typeof value !== "number") {
71
+ return false;
72
+ }
73
+ return attrValue < value;
74
+ }
75
+ case "regex_match": {
76
+ if (typeof attrValue !== "string" || typeof value !== "string") {
77
+ return false;
78
+ }
79
+ try {
80
+ const regex = new RegExp(value);
81
+ return regex.test(attrValue);
82
+ }
83
+ catch {
84
+ emitError?.(`Invalid regex pattern: ${value}`);
85
+ return false;
86
+ }
87
+ }
88
+ default:
89
+ return false;
90
+ }
91
+ }
92
+ /**
93
+ * Evaluate predicate groups in Disjunctive Normal Form (DNF).
94
+ *
95
+ * Groups are OR'd — any group matching means the whole expression matches.
96
+ * Within each group, predicates are AND'd — all must match.
97
+ *
98
+ * Returns false if groups array is empty.
99
+ */
100
+ export function evaluatePredicateGroups(groups, attributes, emitError) {
101
+ if (groups.length === 0) {
102
+ return false;
103
+ }
104
+ // OR across groups: at least one group must fully match
105
+ return groups.some((group) => {
106
+ // AND within each group: all predicates must match
107
+ return group.predicates.every((predicate) => evaluatePredicate(predicate, attributes, emitError));
108
+ });
109
+ }
110
+ //# sourceMappingURL=predicates.js.map
@@ -13,4 +13,3 @@ type AttributeValue = string | number | boolean | string[];
13
13
  */
14
14
  export declare function resolveSegment(segmentId: string, segments: Record<string, Segment>, attributes: Record<string, AttributeValue>, emitError?: (message: string) => void): boolean;
15
15
  export {};
16
- //# sourceMappingURL=segmentResolver.d.ts.map
@@ -16,4 +16,3 @@ import type { EvaluationPlugin } from "../types.js";
16
16
  * 7. No rule matches → return { resolved: false }
17
17
  */
18
18
  export declare function targetingPlugin(segments?: Record<string, Segment>): EvaluationPlugin;
19
- //# sourceMappingURL=targetingPlugin.d.ts.map
@@ -0,0 +1,34 @@
1
+ import type { ConfigFlagData } from "./models.js";
2
+ /** Pipeline step identifier — determines execution order */
3
+ export type PipelineStepId = "archived" | "prerequisites" | "overrides" | "schedule" | "targeting" | "rollout";
4
+ /** The fixed execution order (per Requirement 11) */
5
+ export declare const PIPELINE_ORDER: PipelineStepId[];
6
+ /** Evaluation context provided by the consumer */
7
+ export interface EvaluationContext {
8
+ userId?: string;
9
+ attributes?: Record<string, string | number | boolean | string[]>;
10
+ consentGranted?: boolean;
11
+ }
12
+ /** Result from a pipeline step */
13
+ export type PipelineStepResult = {
14
+ resolved: true;
15
+ value: unknown;
16
+ } | {
17
+ resolved: false;
18
+ };
19
+ /** A registered evaluation plugin */
20
+ export interface EvaluationPlugin {
21
+ /** Which pipeline step this plugin handles */
22
+ stepId: PipelineStepId;
23
+ /** Evaluate a config flag at this pipeline step */
24
+ evaluate(flag: ConfigFlagData, context: EvaluationContext, helpers: PipelineHelpers): PipelineStepResult;
25
+ }
26
+ /** Helpers provided to plugins for cross-cutting concerns */
27
+ export interface PipelineHelpers {
28
+ /** Evaluate another flag (for prerequisites) */
29
+ evaluateFlag(key: string, context: EvaluationContext): unknown;
30
+ /** Emit an error */
31
+ emitError(message: string): void;
32
+ /** Current timestamp (injectable for testing) */
33
+ now(): number;
34
+ }
@@ -0,0 +1,13 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Plugin System Types and Pipeline Interfaces
3
+ // ═══════════════════════════════════════════════════════════════
4
+ /** The fixed execution order (per Requirement 11) */
5
+ export const PIPELINE_ORDER = [
6
+ "archived",
7
+ "prerequisites",
8
+ "overrides",
9
+ "schedule",
10
+ "targeting",
11
+ "rollout",
12
+ ];
13
+ //# sourceMappingURL=types.js.map
@@ -2,4 +2,3 @@ import type { RetryConfig } from "../types.js";
2
2
  export declare const sleep: (ms: number) => Promise<void>;
3
3
  export declare const isNonRetryableError: (error: unknown) => boolean;
4
4
  export declare const withRetry: <T>(fn: () => Promise<T>, options?: RetryConfig, onRetry?: (attempt: number, error: Error, nextDelay: number) => void) => Promise<T>;
5
- //# sourceMappingURL=RetryEngine.d.ts.map
@@ -8,4 +8,3 @@ export interface TransportConfig {
8
8
  getContext?: () => EvaluationContext;
9
9
  }
10
10
  export declare const createHttpTransport: (config: TransportConfig) => HttpTransport;
11
- //# sourceMappingURL=HttpTransport.d.ts.map