@jewel998/config 0.1.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.
Files changed (189) hide show
  1. package/dist/cache/browserStorage.d.ts +3 -0
  2. package/dist/cache/browserStorage.d.ts.map +1 -0
  3. package/dist/cache/browserStorage.js +54 -0
  4. package/dist/cache/browserStorage.js.map +1 -0
  5. package/dist/cache/memoryStorage.d.ts +3 -0
  6. package/dist/cache/memoryStorage.d.ts.map +1 -0
  7. package/dist/cache/memoryStorage.js +30 -0
  8. package/dist/cache/memoryStorage.js.map +1 -0
  9. package/dist/cache/storage.d.ts +15 -0
  10. package/dist/cache/storage.d.ts.map +1 -0
  11. package/dist/cache/storage.js +43 -0
  12. package/dist/cache/storage.js.map +1 -0
  13. package/dist/cache/types.d.ts +3 -0
  14. package/dist/cache/types.d.ts.map +1 -0
  15. package/dist/cache/types.js +2 -0
  16. package/dist/cache/types.js.map +1 -0
  17. package/dist/client/ConfigClient.d.ts +16 -0
  18. package/dist/client/ConfigClient.d.ts.map +1 -0
  19. package/dist/client/ConfigClient.js +215 -0
  20. package/dist/client/ConfigClient.js.map +1 -0
  21. package/dist/client.d.ts +15 -0
  22. package/dist/client.d.ts.map +1 -0
  23. package/dist/client.js +80 -0
  24. package/dist/client.js.map +1 -0
  25. package/dist/core/resolver.d.ts +8 -0
  26. package/dist/core/resolver.d.ts.map +1 -0
  27. package/dist/core/resolver.js +22 -0
  28. package/dist/core/resolver.js.map +1 -0
  29. package/dist/createConfig.d.ts +6 -0
  30. package/dist/createConfig.d.ts.map +1 -0
  31. package/dist/createConfig.js +110 -0
  32. package/dist/createConfig.js.map +1 -0
  33. package/dist/errors/index.d.ts +17 -0
  34. package/dist/errors/index.d.ts.map +1 -0
  35. package/dist/errors/index.js +29 -0
  36. package/dist/errors/index.js.map +1 -0
  37. package/dist/events/EventEmitter.d.ts +9 -0
  38. package/dist/events/EventEmitter.d.ts.map +1 -0
  39. package/dist/events/EventEmitter.js +30 -0
  40. package/dist/events/EventEmitter.js.map +1 -0
  41. package/dist/example.d.ts +2 -0
  42. package/dist/example.d.ts.map +1 -0
  43. package/dist/example.js +23 -0
  44. package/dist/example.js.map +1 -0
  45. package/dist/fetch/batchFetcher.d.ts +3 -0
  46. package/dist/fetch/batchFetcher.d.ts.map +1 -0
  47. package/dist/fetch/batchFetcher.js +12 -0
  48. package/dist/fetch/batchFetcher.js.map +1 -0
  49. package/dist/fetch/projectedFetcher.d.ts +3 -0
  50. package/dist/fetch/projectedFetcher.d.ts.map +1 -0
  51. package/dist/fetch/projectedFetcher.js +43 -0
  52. package/dist/fetch/projectedFetcher.js.map +1 -0
  53. package/dist/index.d.ts +23 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +19 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/loading/deferred.d.ts +3 -0
  58. package/dist/loading/deferred.d.ts.map +1 -0
  59. package/dist/loading/deferred.js +5 -0
  60. package/dist/loading/deferred.js.map +1 -0
  61. package/dist/loading/optimistic.d.ts +3 -0
  62. package/dist/loading/optimistic.d.ts.map +1 -0
  63. package/dist/loading/optimistic.js +35 -0
  64. package/dist/loading/optimistic.js.map +1 -0
  65. package/dist/loading/pessimistic.d.ts +3 -0
  66. package/dist/loading/pessimistic.d.ts.map +1 -0
  67. package/dist/loading/pessimistic.js +24 -0
  68. package/dist/loading/pessimistic.js.map +1 -0
  69. package/dist/management/index.d.ts +3 -0
  70. package/dist/management/index.d.ts.map +1 -0
  71. package/dist/management/index.js +2 -0
  72. package/dist/management/index.js.map +1 -0
  73. package/dist/management/manager.d.ts +34 -0
  74. package/dist/management/manager.d.ts.map +1 -0
  75. package/dist/management/manager.js +21 -0
  76. package/dist/management/manager.js.map +1 -0
  77. package/dist/management/memory-backend.d.ts +6 -0
  78. package/dist/management/memory-backend.d.ts.map +1 -0
  79. package/dist/management/memory-backend.js +78 -0
  80. package/dist/management/memory-backend.js.map +1 -0
  81. package/dist/plugins/evaluatePipeline.d.ts +15 -0
  82. package/dist/plugins/evaluatePipeline.d.ts.map +1 -0
  83. package/dist/plugins/evaluatePipeline.js +39 -0
  84. package/dist/plugins/evaluatePipeline.js.map +1 -0
  85. package/dist/plugins/index.d.ts +5 -0
  86. package/dist/plugins/index.d.ts.map +1 -0
  87. package/dist/plugins/index.js +6 -0
  88. package/dist/plugins/index.js.map +1 -0
  89. package/dist/plugins/lifecycle/archivedPlugin.d.ts +14 -0
  90. package/dist/plugins/lifecycle/archivedPlugin.d.ts.map +1 -0
  91. package/dist/plugins/lifecycle/archivedPlugin.js +26 -0
  92. package/dist/plugins/lifecycle/archivedPlugin.js.map +1 -0
  93. package/dist/plugins/lifecycle/index.d.ts +4 -0
  94. package/dist/plugins/lifecycle/index.d.ts.map +1 -0
  95. package/dist/plugins/lifecycle/index.js +6 -0
  96. package/dist/plugins/lifecycle/index.js.map +1 -0
  97. package/dist/plugins/lifecycle/stateTransitions.d.ts +27 -0
  98. package/dist/plugins/lifecycle/stateTransitions.d.ts.map +1 -0
  99. package/dist/plugins/lifecycle/stateTransitions.js +33 -0
  100. package/dist/plugins/lifecycle/stateTransitions.js.map +1 -0
  101. package/dist/plugins/models.d.ts +50 -0
  102. package/dist/plugins/models.d.ts.map +1 -0
  103. package/dist/plugins/models.js +5 -0
  104. package/dist/plugins/models.js.map +1 -0
  105. package/dist/plugins/overrides/index.d.ts +2 -0
  106. package/dist/plugins/overrides/index.d.ts.map +1 -0
  107. package/dist/plugins/overrides/index.js +5 -0
  108. package/dist/plugins/overrides/index.js.map +1 -0
  109. package/dist/plugins/overrides/overridesPlugin.d.ts +12 -0
  110. package/dist/plugins/overrides/overridesPlugin.d.ts.map +1 -0
  111. package/dist/plugins/overrides/overridesPlugin.js +40 -0
  112. package/dist/plugins/overrides/overridesPlugin.js.map +1 -0
  113. package/dist/plugins/prerequisites/index.d.ts +3 -0
  114. package/dist/plugins/prerequisites/index.d.ts.map +1 -0
  115. package/dist/plugins/prerequisites/index.js +5 -0
  116. package/dist/plugins/prerequisites/index.js.map +1 -0
  117. package/dist/plugins/prerequisites/prerequisitePlugin.d.ts +24 -0
  118. package/dist/plugins/prerequisites/prerequisitePlugin.d.ts.map +1 -0
  119. package/dist/plugins/prerequisites/prerequisitePlugin.js +62 -0
  120. package/dist/plugins/prerequisites/prerequisitePlugin.js.map +1 -0
  121. package/dist/plugins/rollout/computeBucket.d.ts +12 -0
  122. package/dist/plugins/rollout/computeBucket.d.ts.map +1 -0
  123. package/dist/plugins/rollout/computeBucket.js +20 -0
  124. package/dist/plugins/rollout/computeBucket.js.map +1 -0
  125. package/dist/plugins/rollout/index.d.ts +3 -0
  126. package/dist/plugins/rollout/index.d.ts.map +1 -0
  127. package/dist/plugins/rollout/index.js +6 -0
  128. package/dist/plugins/rollout/index.js.map +1 -0
  129. package/dist/plugins/rollout/murmurhash3.d.ts +6 -0
  130. package/dist/plugins/rollout/murmurhash3.d.ts.map +1 -0
  131. package/dist/plugins/rollout/murmurhash3.js +56 -0
  132. package/dist/plugins/rollout/murmurhash3.js.map +1 -0
  133. package/dist/plugins/rollout/rolloutPlugin.d.ts +13 -0
  134. package/dist/plugins/rollout/rolloutPlugin.d.ts.map +1 -0
  135. package/dist/plugins/rollout/rolloutPlugin.js +44 -0
  136. package/dist/plugins/rollout/rolloutPlugin.js.map +1 -0
  137. package/dist/plugins/schedule/index.d.ts +2 -0
  138. package/dist/plugins/schedule/index.d.ts.map +1 -0
  139. package/dist/plugins/schedule/index.js +5 -0
  140. package/dist/plugins/schedule/index.js.map +1 -0
  141. package/dist/plugins/schedule/schedulePlugin.d.ts +14 -0
  142. package/dist/plugins/schedule/schedulePlugin.d.ts.map +1 -0
  143. package/dist/plugins/schedule/schedulePlugin.js +38 -0
  144. package/dist/plugins/schedule/schedulePlugin.js.map +1 -0
  145. package/dist/plugins/targeting/index.d.ts +4 -0
  146. package/dist/plugins/targeting/index.d.ts.map +1 -0
  147. package/dist/plugins/targeting/index.js +4 -0
  148. package/dist/plugins/targeting/index.js.map +1 -0
  149. package/dist/plugins/targeting/predicates.d.ts +23 -0
  150. package/dist/plugins/targeting/predicates.d.ts.map +1 -0
  151. package/dist/plugins/targeting/predicates.js +110 -0
  152. package/dist/plugins/targeting/predicates.js.map +1 -0
  153. package/dist/plugins/targeting/segmentResolver.d.ts +16 -0
  154. package/dist/plugins/targeting/segmentResolver.d.ts.map +1 -0
  155. package/dist/plugins/targeting/segmentResolver.js +27 -0
  156. package/dist/plugins/targeting/segmentResolver.js.map +1 -0
  157. package/dist/plugins/targeting/targetingPlugin.d.ts +19 -0
  158. package/dist/plugins/targeting/targetingPlugin.d.ts.map +1 -0
  159. package/dist/plugins/targeting/targetingPlugin.js +80 -0
  160. package/dist/plugins/targeting/targetingPlugin.js.map +1 -0
  161. package/dist/plugins/types.d.ts +35 -0
  162. package/dist/plugins/types.d.ts.map +1 -0
  163. package/dist/plugins/types.js +13 -0
  164. package/dist/plugins/types.js.map +1 -0
  165. package/dist/registry.d.ts +9 -0
  166. package/dist/registry.d.ts.map +1 -0
  167. package/dist/registry.js +22 -0
  168. package/dist/registry.js.map +1 -0
  169. package/dist/remote/firebase-adapter.d.ts +6 -0
  170. package/dist/remote/firebase-adapter.d.ts.map +1 -0
  171. package/dist/remote/firebase-adapter.js +12 -0
  172. package/dist/remote/firebase-adapter.js.map +1 -0
  173. package/dist/remote/provider.d.ts +6 -0
  174. package/dist/remote/provider.d.ts.map +1 -0
  175. package/dist/remote/provider.js +5 -0
  176. package/dist/remote/provider.js.map +1 -0
  177. package/dist/retry/RetryEngine.d.ts +5 -0
  178. package/dist/retry/RetryEngine.d.ts.map +1 -0
  179. package/dist/retry/RetryEngine.js +36 -0
  180. package/dist/retry/RetryEngine.js.map +1 -0
  181. package/dist/transport/HttpTransport.d.ts +7 -0
  182. package/dist/transport/HttpTransport.d.ts.map +1 -0
  183. package/dist/transport/HttpTransport.js +34 -0
  184. package/dist/transport/HttpTransport.js.map +1 -0
  185. package/dist/types.d.ts +217 -0
  186. package/dist/types.d.ts.map +1 -0
  187. package/dist/types.js +14 -0
  188. package/dist/types.js.map +1 -0
  189. package/package.json +72 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computeBucket.js","sourceRoot":"","sources":["../../../src/plugins/rollout/computeBucket.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,6BAA6B;AAC7B,kEAAkE;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,MAAc;IAC7D,MAAM,KAAK,GAAG,GAAG,SAAS,IAAI,MAAM,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACtC,OAAO,IAAI,GAAG,GAAG,CAAC;AACpB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { computeBucket } from "./computeBucket.js";
2
+ export { rolloutPlugin } from "./rolloutPlugin.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/rollout/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,6 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Rollout Plugin — Public Barrel Export
3
+ // ═══════════════════════════════════════════════════════════════
4
+ export { computeBucket } from "./computeBucket.js";
5
+ export { rolloutPlugin } from "./rolloutPlugin.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/rollout/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,wCAAwC;AACxC,kEAAkE;AAElE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,6 @@
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;
6
+ //# sourceMappingURL=murmurhash3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"murmurhash3.d.ts","sourceRoot":"","sources":["../../../src/plugins/rollout/murmurhash3.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,MAAU,GAAG,MAAM,CAkDpE"}
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"murmurhash3.js","sourceRoot":"","sources":["../../../src/plugins/rollout/murmurhash3.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { EvaluationPlugin } from "../types.js";
2
+ /**
3
+ * Factory function that creates the rollout evaluation plugin.
4
+ *
5
+ * Evaluation logic:
6
+ * - If `rolloutPercentage` is undefined/null → skip (resolved: false)
7
+ * - If rolloutPercentage is 0 → skip (let pipeline continue to default)
8
+ * - If rolloutPercentage is 100 → return rollout value
9
+ * - If no userId in context → skip (can't bucket without userId)
10
+ * - Otherwise: compute bucket, if bucket < rolloutPercentage → return rollout value, else skip
11
+ */
12
+ export declare function rolloutPlugin(): EvaluationPlugin;
13
+ //# sourceMappingURL=rolloutPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolloutPlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/rollout/rolloutPlugin.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,aAAa,CAAC;AAGrB;;;;;;;;;GASG;AACH,wBAAgB,aAAa,IAAI,gBAAgB,CAsChD"}
@@ -0,0 +1,44 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Rollout Evaluation Plugin
3
+ // ═══════════════════════════════════════════════════════════════
4
+ import { computeBucket } from "./computeBucket.js";
5
+ /**
6
+ * Factory function that creates the rollout evaluation plugin.
7
+ *
8
+ * Evaluation logic:
9
+ * - If `rolloutPercentage` is undefined/null → skip (resolved: false)
10
+ * - If rolloutPercentage is 0 → skip (let pipeline continue to default)
11
+ * - If rolloutPercentage is 100 → return rollout value
12
+ * - If no userId in context → skip (can't bucket without userId)
13
+ * - Otherwise: compute bucket, if bucket < rolloutPercentage → return rollout value, else skip
14
+ */
15
+ export function rolloutPlugin() {
16
+ return {
17
+ stepId: "rollout",
18
+ evaluate(flag, context, _helpers) {
19
+ // No rollout configured — skip
20
+ if (flag.rolloutPercentage == null) {
21
+ return { resolved: false };
22
+ }
23
+ // 0% — no one gets the rollout value; let pipeline continue to default
24
+ if (flag.rolloutPercentage === 0) {
25
+ return { resolved: false };
26
+ }
27
+ // 100% — everyone gets the rollout value
28
+ if (flag.rolloutPercentage === 100) {
29
+ return { resolved: true, value: flag.rolloutValue };
30
+ }
31
+ // No userId — can't compute a bucket; skip
32
+ if (!context.userId) {
33
+ return { resolved: false };
34
+ }
35
+ // Compute deterministic bucket and compare against percentage
36
+ const bucket = computeBucket(flag.key, context.userId);
37
+ if (bucket < flag.rolloutPercentage) {
38
+ return { resolved: true, value: flag.rolloutValue };
39
+ }
40
+ return { resolved: false };
41
+ },
42
+ };
43
+ }
44
+ //# sourceMappingURL=rolloutPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolloutPlugin.js","sourceRoot":"","sources":["../../../src/plugins/rollout/rolloutPlugin.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,4BAA4B;AAC5B,kEAAkE;AASlE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,MAAM,EAAE,SAAS;QAEjB,QAAQ,CACN,IAAoB,EACpB,OAA0B,EAC1B,QAAyB;YAEzB,+BAA+B;YAC/B,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,EAAE,CAAC;gBACnC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YAED,uEAAuE;YACvE,IAAI,IAAI,CAAC,iBAAiB,KAAK,CAAC,EAAE,CAAC;gBACjC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YAED,yCAAyC;YACzC,IAAI,IAAI,CAAC,iBAAiB,KAAK,GAAG,EAAE,CAAC;gBACnC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;YACtD,CAAC;YAED,2CAA2C;YAC3C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACpB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YAED,8DAA8D;YAC9D,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACvD,IAAI,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACpC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;YACtD,CAAC;YAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { schedulePlugin } from "./schedulePlugin.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/schedule/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Schedule Plugin — Public Barrel Export
3
+ // ═══════════════════════════════════════════════════════════════
4
+ export { schedulePlugin } from "./schedulePlugin.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/schedule/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,yCAAyC;AACzC,kEAAkE;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { EvaluationPlugin } from "../types.js";
2
+ /**
3
+ * Factory function that creates the schedule evaluation plugin.
4
+ *
5
+ * Evaluation logic:
6
+ * - If `flag.schedule` is undefined/null → skip (resolved: false)
7
+ * - Parse `flag.schedule.activateAt` as a Date
8
+ * - If activateAt is an invalid date string → skip (graceful degradation)
9
+ * - If Date.parse(activateAt) <= helpers.now() (schedule is in the past or exactly now)
10
+ * → return scheduled targetValue (Requirement 6.4)
11
+ * - If activateAt is in the future → skip (Requirement 6.5)
12
+ */
13
+ export declare function schedulePlugin(): EvaluationPlugin;
14
+ //# sourceMappingURL=schedulePlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedulePlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/schedule/schedulePlugin.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,IAAI,gBAAgB,CA+BjD"}
@@ -0,0 +1,38 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Schedule Evaluation Plugin
3
+ // ═══════════════════════════════════════════════════════════════
4
+ /**
5
+ * Factory function that creates the schedule evaluation plugin.
6
+ *
7
+ * Evaluation logic:
8
+ * - If `flag.schedule` is undefined/null → skip (resolved: false)
9
+ * - Parse `flag.schedule.activateAt` as a Date
10
+ * - If activateAt is an invalid date string → skip (graceful degradation)
11
+ * - If Date.parse(activateAt) <= helpers.now() (schedule is in the past or exactly now)
12
+ * → return scheduled targetValue (Requirement 6.4)
13
+ * - If activateAt is in the future → skip (Requirement 6.5)
14
+ */
15
+ export function schedulePlugin() {
16
+ return {
17
+ stepId: "schedule",
18
+ evaluate(flag, _context, helpers) {
19
+ // No schedule configured — skip
20
+ if (flag.schedule == null) {
21
+ return { resolved: false };
22
+ }
23
+ // Parse the activateAt timestamp
24
+ const activateAtMs = Date.parse(flag.schedule.activateAt);
25
+ // Invalid date string — graceful degradation, skip
26
+ if (Number.isNaN(activateAtMs)) {
27
+ return { resolved: false };
28
+ }
29
+ // Schedule is in the past or exactly now — activate
30
+ if (activateAtMs <= helpers.now()) {
31
+ return { resolved: true, value: flag.schedule.targetValue };
32
+ }
33
+ // Schedule is in the future — skip
34
+ return { resolved: false };
35
+ },
36
+ };
37
+ }
38
+ //# sourceMappingURL=schedulePlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedulePlugin.js","sourceRoot":"","sources":["../../../src/plugins/schedule/schedulePlugin.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,6BAA6B;AAC7B,kEAAkE;AAUlE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO;QACL,MAAM,EAAE,UAAU;QAElB,QAAQ,CACN,IAAoB,EACpB,QAA2B,EAC3B,OAAwB;YAExB,gCAAgC;YAChC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;gBAC1B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YAED,iCAAiC;YACjC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAE1D,mDAAmD;YACnD,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC/B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YAED,oDAAoD;YACpD,IAAI,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;gBAClC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YAC9D,CAAC;YAED,mCAAmC;YACnC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { targetingPlugin } from "./targetingPlugin.js";
2
+ export { evaluatePredicate, evaluatePredicateGroups } from "./predicates.js";
3
+ export { resolveSegment } from "./segmentResolver.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/targeting/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { targetingPlugin } from "./targetingPlugin.js";
2
+ export { evaluatePredicate, evaluatePredicateGroups } from "./predicates.js";
3
+ export { resolveSegment } from "./segmentResolver.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/targeting/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,23 @@
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 {};
23
+ //# sourceMappingURL=predicates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicates.d.ts","sourceRoot":"","sources":["../../../src/plugins/targeting/predicates.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9D,KAAK,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC;AAE3D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAC1C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACpC,OAAO,CA4FT;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,cAAc,EAAE,EACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAC1C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACpC,OAAO,CAYT"}
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicates.js","sourceRoot":"","sources":["../../../src/plugins/targeting/predicates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Segment } from "../models.js";
2
+ type AttributeValue = string | number | boolean | string[];
3
+ /**
4
+ * Resolve a segment by ID and evaluate its predicate groups against
5
+ * the provided attributes.
6
+ *
7
+ * - Returns false if the segment does not exist (Requirement 3.6)
8
+ * - Nested segment references (in_segment/not_in_segment within a segment)
9
+ * are disallowed — evaluatePredicateGroups already returns false for those
10
+ * operators (Requirement 3.4)
11
+ * - Evaluates the segment's conditions in DNF (OR of ANDs) using the same
12
+ * predicate operators as targeting rules (Requirement 3.4)
13
+ */
14
+ export declare function resolveSegment(segmentId: string, segments: Record<string, Segment>, attributes: Record<string, AttributeValue>, emitError?: (message: string) => void): boolean;
15
+ export {};
16
+ //# sourceMappingURL=segmentResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmentResolver.d.ts","sourceRoot":"","sources":["../../../src/plugins/targeting/segmentResolver.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,KAAK,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC;AAE3D;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EAC1C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACpC,OAAO,CAYT"}
@@ -0,0 +1,27 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Segment Resolver — resolves segment predicates against context
3
+ // ═══════════════════════════════════════════════════════════════
4
+ import { evaluatePredicateGroups } from "./predicates.js";
5
+ /**
6
+ * Resolve a segment by ID and evaluate its predicate groups against
7
+ * the provided attributes.
8
+ *
9
+ * - Returns false if the segment does not exist (Requirement 3.6)
10
+ * - Nested segment references (in_segment/not_in_segment within a segment)
11
+ * are disallowed — evaluatePredicateGroups already returns false for those
12
+ * operators (Requirement 3.4)
13
+ * - Evaluates the segment's conditions in DNF (OR of ANDs) using the same
14
+ * predicate operators as targeting rules (Requirement 3.4)
15
+ */
16
+ export function resolveSegment(segmentId, segments, attributes, emitError) {
17
+ const segment = segments[segmentId];
18
+ // Segment not found → non-matching (Requirement 3.6)
19
+ if (!segment) {
20
+ return false;
21
+ }
22
+ // Evaluate the segment's predicate groups in DNF against the attributes.
23
+ // in_segment/not_in_segment predicates within a segment will automatically
24
+ // return false (no nesting allowed, Requirement 3.4)
25
+ return evaluatePredicateGroups(segment.conditions, attributes, emitError);
26
+ }
27
+ //# sourceMappingURL=segmentResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmentResolver.js","sourceRoot":"","sources":["../../../src/plugins/targeting/segmentResolver.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,iEAAiE;AACjE,kEAAkE;AAGlE,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAI1D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAiB,EACjB,QAAiC,EACjC,UAA0C,EAC1C,SAAqC;IAErC,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAEpC,qDAAqD;IACrD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yEAAyE;IACzE,2EAA2E;IAC3E,qDAAqD;IACrD,OAAO,uBAAuB,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { Segment } from "../models.js";
2
+ import type { EvaluationPlugin } from "../types.js";
3
+ /**
4
+ * Factory function that creates the targeting rules evaluation plugin.
5
+ *
6
+ * Accepts an optional segments map for resolving `in_segment`/`not_in_segment`
7
+ * predicates within targeting rules.
8
+ *
9
+ * Evaluation logic:
10
+ * 1. stepId: "targeting"
11
+ * 2. If `flag.targetingRules` is undefined or empty → return { resolved: false }
12
+ * 3. Sort rules by priority (lowest number first); same priority → preserve insertion order
13
+ * 4. For each rule: evaluate its conditions (predicate groups in DNF)
14
+ * 5. For predicates with in_segment/not_in_segment: use segment resolver
15
+ * 6. First matching rule → return { resolved: true, value: rule.value }
16
+ * 7. No rule matches → return { resolved: false }
17
+ */
18
+ export declare function targetingPlugin(segments?: Record<string, Segment>): EvaluationPlugin;
19
+ //# sourceMappingURL=targetingPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targetingPlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/targeting/targetingPlugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA6C,OAAO,EAAE,MAAM,cAAc,CAAC;AACvF,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,aAAa,CAAC;AAwDrB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,gBAAgB,CA2ClB"}
@@ -0,0 +1,80 @@
1
+ // ═══════════════════════════════════════════════════════════════
2
+ // Targeting Rules Evaluation Plugin
3
+ // ═══════════════════════════════════════════════════════════════
4
+ import { evaluatePredicate } from "./predicates.js";
5
+ import { resolveSegment } from "./segmentResolver.js";
6
+ /**
7
+ * Evaluate a single predicate, handling segment-based predicates specially.
8
+ *
9
+ * For `in_segment` / `not_in_segment` operators, delegates to the segment
10
+ * resolver rather than the default predicate evaluator.
11
+ */
12
+ function evaluatePredicateWithSegments(predicate, attributes, segments, emitError) {
13
+ if (predicate.operator === "in_segment") {
14
+ const segmentId = String(predicate.value);
15
+ return resolveSegment(segmentId, segments, attributes, emitError);
16
+ }
17
+ if (predicate.operator === "not_in_segment") {
18
+ const segmentId = String(predicate.value);
19
+ return !resolveSegment(segmentId, segments, attributes, emitError);
20
+ }
21
+ return evaluatePredicate(predicate, attributes, emitError);
22
+ }
23
+ /**
24
+ * Evaluate predicate groups in DNF with segment resolution support.
25
+ *
26
+ * Groups are OR'd — any group matching means the whole expression matches.
27
+ * Within each group, predicates are AND'd — all must match.
28
+ */
29
+ function evaluatePredicateGroupsWithSegments(groups, attributes, segments, emitError) {
30
+ if (groups.length === 0) {
31
+ return false;
32
+ }
33
+ // OR across groups: at least one group must fully match
34
+ return groups.some((group) => {
35
+ // AND within each group: all predicates must match
36
+ return group.predicates.every((predicate) => evaluatePredicateWithSegments(predicate, attributes, segments, emitError));
37
+ });
38
+ }
39
+ /**
40
+ * Factory function that creates the targeting rules evaluation plugin.
41
+ *
42
+ * Accepts an optional segments map for resolving `in_segment`/`not_in_segment`
43
+ * predicates within targeting rules.
44
+ *
45
+ * Evaluation logic:
46
+ * 1. stepId: "targeting"
47
+ * 2. If `flag.targetingRules` is undefined or empty → return { resolved: false }
48
+ * 3. Sort rules by priority (lowest number first); same priority → preserve insertion order
49
+ * 4. For each rule: evaluate its conditions (predicate groups in DNF)
50
+ * 5. For predicates with in_segment/not_in_segment: use segment resolver
51
+ * 6. First matching rule → return { resolved: true, value: rule.value }
52
+ * 7. No rule matches → return { resolved: false }
53
+ */
54
+ export function targetingPlugin(segments) {
55
+ const segmentsMap = segments ?? {};
56
+ return {
57
+ stepId: "targeting",
58
+ evaluate(flag, context, helpers) {
59
+ // No targeting rules configured — skip
60
+ if (!flag.targetingRules || flag.targetingRules.length === 0) {
61
+ return { resolved: false };
62
+ }
63
+ // Sort rules by priority (lowest number = highest priority).
64
+ // Array.prototype.sort is stable in modern JS — same priority preserves insertion order.
65
+ const sortedRules = [...flag.targetingRules].sort((a, b) => a.priority - b.priority);
66
+ // Build attributes from context (default to empty object)
67
+ const attributes = context.attributes ?? {};
68
+ // Evaluate each rule in priority order
69
+ for (const rule of sortedRules) {
70
+ const matches = evaluatePredicateGroupsWithSegments(rule.conditions, attributes, segmentsMap, helpers.emitError);
71
+ if (matches) {
72
+ return { resolved: true, value: rule.value };
73
+ }
74
+ }
75
+ // No rule matched
76
+ return { resolved: false };
77
+ },
78
+ };
79
+ }
80
+ //# sourceMappingURL=targetingPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targetingPlugin.js","sourceRoot":"","sources":["../../../src/plugins/targeting/targetingPlugin.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,oCAAoC;AACpC,kEAAkE;AASlE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAItD;;;;;GAKG;AACH,SAAS,6BAA6B,CACpC,SAAoB,EACpB,UAA0C,EAC1C,QAAiC,EACjC,SAAqC;IAErC,IAAI,SAAS,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,SAAS,CAAC,QAAQ,KAAK,gBAAgB,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,iBAAiB,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,SAAS,mCAAmC,CAC1C,MAAwB,EACxB,UAA0C,EAC1C,QAAiC,EACjC,SAAqC;IAErC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,wDAAwD;IACxD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,mDAAmD;QACnD,OAAO,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE,CAC1C,6BAA6B,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAC1E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAkC;IAElC,MAAM,WAAW,GAAG,QAAQ,IAAI,EAAE,CAAC;IAEnC,OAAO;QACL,MAAM,EAAE,WAAW;QAEnB,QAAQ,CACN,IAAoB,EACpB,OAA0B,EAC1B,OAAwB;YAExB,uCAAuC;YACvC,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7D,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7B,CAAC;YAED,6DAA6D;YAC7D,yFAAyF;YACzF,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAC/C,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAClC,CAAC;YAEF,0DAA0D;YAC1D,MAAM,UAAU,GAAmC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;YAE5E,uCAAuC;YACvC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,mCAAmC,CACjD,IAAI,CAAC,UAAU,EACf,UAAU,EACV,WAAW,EACX,OAAO,CAAC,SAAS,CAClB,CAAC;gBAEF,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC/C,CAAC;YACH,CAAC;YAED,kBAAkB;YAClB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
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
+ }
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,4DAA4D;AAC5D,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,eAAe,GACf,WAAW,GACX,UAAU,GACV,WAAW,GACX,SAAS,CAAC;AAEd,qDAAqD;AACrD,eAAO,MAAM,cAAc,EAAE,cAAc,EAO1C,CAAC;AAEF,kDAAkD;AAClD,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;IAClE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,kCAAkC;AAClC,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAClC;IAAE,QAAQ,EAAE,KAAK,CAAA;CAAE,CAAC;AAExB,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,MAAM,EAAE,cAAc,CAAC;IAEvB,mDAAmD;IACnD,QAAQ,CACN,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,eAAe,GACvB,kBAAkB,CAAC;CACvB;AAED,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAC/D,oBAAoB;IACpB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iDAAiD;IACjD,GAAG,IAAI,MAAM,CAAC;CACf"}