@mongrov/analytics 0.1.0-alpha.7 → 0.1.0-alpha.9

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 (161) hide show
  1. package/dist/rules/__fakes__/fakeClock.d.ts +7 -0
  2. package/dist/rules/__fakes__/fakeClock.d.ts.map +1 -0
  3. package/dist/rules/__fakes__/fakeClock.js +13 -0
  4. package/dist/rules/__fakes__/fakeClock.js.map +1 -0
  5. package/dist/rules/__fakes__/fakeEngine.d.ts +12 -0
  6. package/dist/rules/__fakes__/fakeEngine.d.ts.map +1 -0
  7. package/dist/rules/__fakes__/fakeEngine.js +33 -0
  8. package/dist/rules/__fakes__/fakeEngine.js.map +1 -0
  9. package/dist/rules/__fakes__/fakeStorage.d.ts +7 -0
  10. package/dist/rules/__fakes__/fakeStorage.d.ts.map +1 -0
  11. package/dist/rules/__fakes__/fakeStorage.js +22 -0
  12. package/dist/rules/__fakes__/fakeStorage.js.map +1 -0
  13. package/dist/rules/compiler-cache.d.ts +16 -0
  14. package/dist/rules/compiler-cache.d.ts.map +1 -0
  15. package/dist/rules/compiler-cache.js +29 -0
  16. package/dist/rules/compiler-cache.js.map +1 -0
  17. package/dist/rules/compiler.d.ts +27 -0
  18. package/dist/rules/compiler.d.ts.map +1 -0
  19. package/dist/rules/compiler.js +210 -0
  20. package/dist/rules/compiler.js.map +1 -0
  21. package/dist/rules/defaults/index.d.ts +13 -0
  22. package/dist/rules/defaults/index.d.ts.map +1 -0
  23. package/dist/rules/defaults/index.js +13 -0
  24. package/dist/rules/defaults/index.js.map +1 -0
  25. package/dist/rules/defaults/loader.d.ts +18 -0
  26. package/dist/rules/defaults/loader.d.ts.map +1 -0
  27. package/dist/rules/defaults/loader.js +37 -0
  28. package/dist/rules/defaults/loader.js.map +1 -0
  29. package/dist/rules/defaults/luminx.d.ts +6 -0
  30. package/dist/rules/defaults/luminx.d.ts.map +1 -0
  31. package/dist/rules/defaults/luminx.js +64 -0
  32. package/dist/rules/defaults/luminx.js.map +1 -0
  33. package/dist/rules/defaults/viva.d.ts +6 -0
  34. package/dist/rules/defaults/viva.d.ts.map +1 -0
  35. package/dist/rules/defaults/viva.js +45 -0
  36. package/dist/rules/defaults/viva.js.map +1 -0
  37. package/dist/rules/defaults/yogaring.d.ts +6 -0
  38. package/dist/rules/defaults/yogaring.d.ts.map +1 -0
  39. package/dist/rules/defaults/yogaring.js +45 -0
  40. package/dist/rules/defaults/yogaring.js.map +1 -0
  41. package/dist/rules/defaults/ziva.d.ts +10 -0
  42. package/dist/rules/defaults/ziva.d.ts.map +1 -0
  43. package/dist/rules/defaults/ziva.js +87 -0
  44. package/dist/rules/defaults/ziva.js.map +1 -0
  45. package/dist/rules/emitter.d.ts +20 -0
  46. package/dist/rules/emitter.d.ts.map +1 -0
  47. package/dist/rules/emitter.js +32 -0
  48. package/dist/rules/emitter.js.map +1 -0
  49. package/dist/rules/evaluator.d.ts +44 -0
  50. package/dist/rules/evaluator.d.ts.map +1 -0
  51. package/dist/rules/evaluator.js +127 -0
  52. package/dist/rules/evaluator.js.map +1 -0
  53. package/dist/rules/factory.d.ts +13 -0
  54. package/dist/rules/factory.d.ts.map +1 -0
  55. package/dist/rules/factory.js +56 -0
  56. package/dist/rules/factory.js.map +1 -0
  57. package/dist/rules/hooks/useRuleRegistry.d.ts +16 -0
  58. package/dist/rules/hooks/useRuleRegistry.d.ts.map +1 -0
  59. package/dist/rules/hooks/useRuleRegistry.js +26 -0
  60. package/dist/rules/hooks/useRuleRegistry.js.map +1 -0
  61. package/dist/rules/hooks/useRuleViolations.d.ts +21 -0
  62. package/dist/rules/hooks/useRuleViolations.d.ts.map +1 -0
  63. package/dist/rules/hooks/useRuleViolations.js +32 -0
  64. package/dist/rules/hooks/useRuleViolations.js.map +1 -0
  65. package/dist/rules/index.d.ts +30 -1
  66. package/dist/rules/index.d.ts.map +1 -1
  67. package/dist/rules/index.js +36 -1
  68. package/dist/rules/index.js.map +1 -1
  69. package/dist/rules/registry.d.ts +32 -0
  70. package/dist/rules/registry.d.ts.map +1 -0
  71. package/dist/rules/registry.js +98 -0
  72. package/dist/rules/registry.js.map +1 -0
  73. package/dist/rules/schema.d.ts +221 -0
  74. package/dist/rules/schema.d.ts.map +1 -0
  75. package/dist/rules/schema.js +80 -0
  76. package/dist/rules/schema.js.map +1 -0
  77. package/dist/rules/throttle.d.ts +27 -0
  78. package/dist/rules/throttle.d.ts.map +1 -0
  79. package/dist/rules/throttle.js +76 -0
  80. package/dist/rules/throttle.js.map +1 -0
  81. package/dist/rules/types.d.ts +88 -0
  82. package/dist/rules/types.d.ts.map +1 -0
  83. package/dist/rules/types.js +9 -0
  84. package/dist/rules/types.js.map +1 -0
  85. package/dist/rules/validator.d.ts +27 -0
  86. package/dist/rules/validator.d.ts.map +1 -0
  87. package/dist/rules/validator.js +97 -0
  88. package/dist/rules/validator.js.map +1 -0
  89. package/dist/sync/factory.d.ts +8 -0
  90. package/dist/sync/factory.d.ts.map +1 -1
  91. package/dist/sync/factory.js +31 -1
  92. package/dist/sync/factory.js.map +1 -1
  93. package/dist/sync/flusher.d.ts +6 -0
  94. package/dist/sync/flusher.d.ts.map +1 -1
  95. package/dist/sync/flusher.js +13 -1
  96. package/dist/sync/flusher.js.map +1 -1
  97. package/dist/tools/__fakes__/engine.d.ts +25 -0
  98. package/dist/tools/__fakes__/engine.d.ts.map +1 -0
  99. package/dist/tools/__fakes__/engine.js +37 -0
  100. package/dist/tools/__fakes__/engine.js.map +1 -0
  101. package/dist/tools/audit.d.ts +31 -0
  102. package/dist/tools/audit.d.ts.map +1 -0
  103. package/dist/tools/audit.js +157 -0
  104. package/dist/tools/audit.js.map +1 -0
  105. package/dist/tools/authorize.d.ts +36 -0
  106. package/dist/tools/authorize.d.ts.map +1 -0
  107. package/dist/tools/authorize.js +87 -0
  108. package/dist/tools/authorize.js.map +1 -0
  109. package/dist/tools/budget.d.ts +15 -0
  110. package/dist/tools/budget.d.ts.map +1 -0
  111. package/dist/tools/budget.js +64 -0
  112. package/dist/tools/budget.js.map +1 -0
  113. package/dist/tools/factory.d.ts +43 -0
  114. package/dist/tools/factory.d.ts.map +1 -0
  115. package/dist/tools/factory.js +137 -0
  116. package/dist/tools/factory.js.map +1 -0
  117. package/dist/tools/formatters.d.ts +17 -0
  118. package/dist/tools/formatters.d.ts.map +1 -0
  119. package/dist/tools/formatters.js +30 -0
  120. package/dist/tools/formatters.js.map +1 -0
  121. package/dist/tools/impls/activity.d.ts +15 -0
  122. package/dist/tools/impls/activity.d.ts.map +1 -0
  123. package/dist/tools/impls/activity.js +61 -0
  124. package/dist/tools/impls/activity.js.map +1 -0
  125. package/dist/tools/impls/anomaly.d.ts +21 -0
  126. package/dist/tools/impls/anomaly.d.ts.map +1 -0
  127. package/dist/tools/impls/anomaly.js +70 -0
  128. package/dist/tools/impls/anomaly.js.map +1 -0
  129. package/dist/tools/impls/compare.d.ts +21 -0
  130. package/dist/tools/impls/compare.d.ts.map +1 -0
  131. package/dist/tools/impls/compare.js +68 -0
  132. package/dist/tools/impls/compare.js.map +1 -0
  133. package/dist/tools/impls/hrv.d.ts +15 -0
  134. package/dist/tools/impls/hrv.d.ts.map +1 -0
  135. package/dist/tools/impls/hrv.js +36 -0
  136. package/dist/tools/impls/hrv.js.map +1 -0
  137. package/dist/tools/impls/insights.d.ts +18 -0
  138. package/dist/tools/impls/insights.d.ts.map +1 -0
  139. package/dist/tools/impls/insights.js +41 -0
  140. package/dist/tools/impls/insights.js.map +1 -0
  141. package/dist/tools/impls/sleep.d.ts +15 -0
  142. package/dist/tools/impls/sleep.d.ts.map +1 -0
  143. package/dist/tools/impls/sleep.js +43 -0
  144. package/dist/tools/impls/sleep.js.map +1 -0
  145. package/dist/tools/index.d.ts +13 -1
  146. package/dist/tools/index.d.ts.map +1 -1
  147. package/dist/tools/index.js +21 -1
  148. package/dist/tools/index.js.map +1 -1
  149. package/dist/tools/rate-limit.d.ts +26 -0
  150. package/dist/tools/rate-limit.d.ts.map +1 -0
  151. package/dist/tools/rate-limit.js +67 -0
  152. package/dist/tools/rate-limit.js.map +1 -0
  153. package/dist/tools/types.d.ts +121 -0
  154. package/dist/tools/types.d.ts.map +1 -0
  155. package/dist/tools/types.js +16 -0
  156. package/dist/tools/types.js.map +1 -0
  157. package/dist/tools/wrap.d.ts +53 -0
  158. package/dist/tools/wrap.d.ts.map +1 -0
  159. package/dist/tools/wrap.js +135 -0
  160. package/dist/tools/wrap.js.map +1 -0
  161. package/package.json +5 -1
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Viva brand default rules. Sidecar: `viva.toml`.
3
+ */
4
+ import { parseCatalog } from './loader';
5
+ const TOML = `
6
+ [[rule]]
7
+ id = "viva.battery-low"
8
+ brand = "viva"
9
+ name = "Viva battery low"
10
+ description = "Device battery below 20% in the past hour."
11
+ metric = "device_battery"
12
+ window = "1h"
13
+ aggregation = "last"
14
+ compare = "less_than"
15
+ severity = "warn"
16
+
17
+ [rule.target]
18
+ type = "absolute"
19
+ value = 20
20
+
21
+ [rule.throttle]
22
+ minGapMinutes = 360
23
+ maxPerDay = 2
24
+
25
+ [[rule]]
26
+ id = "viva.disconnect-24h"
27
+ brand = "viva"
28
+ name = "Viva disconnected"
29
+ description = "No device battery events observed in the past 24h."
30
+ metric = "device_battery"
31
+ window = "24h"
32
+ aggregation = "count"
33
+ compare = "equals"
34
+ severity = "warn"
35
+
36
+ [rule.target]
37
+ type = "absolute"
38
+ value = 0
39
+
40
+ [rule.throttle]
41
+ minGapMinutes = 720
42
+ maxPerDay = 1
43
+ `;
44
+ export const vivaDefaults = parseCatalog(TOML, { name: 'viva' });
45
+ //# sourceMappingURL=viva.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viva.js","sourceRoot":"","sources":["../../../src/rules/defaults/viva.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCZ,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAW,YAAY,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * YogaRing brand default rules. Sidecar: `yogaring.toml`.
3
+ */
4
+ import type { Rule } from '../schema';
5
+ export declare const yogaringDefaults: Rule[];
6
+ //# sourceMappingURL=yogaring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yogaring.d.ts","sourceRoot":"","sources":["../../../src/rules/defaults/yogaring.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AA0CrC,eAAO,MAAM,gBAAgB,EAAE,IAAI,EAA6C,CAAA"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * YogaRing brand default rules. Sidecar: `yogaring.toml`.
3
+ */
4
+ import { parseCatalog } from './loader';
5
+ const TOML = `
6
+ [[rule]]
7
+ id = "yogaring.stress-elevated"
8
+ brand = "yogaring"
9
+ name = "YogaRing stress nudge"
10
+ description = "Average stress score over 6h rose above 65."
11
+ metric = "stress"
12
+ window = "6h"
13
+ aggregation = "avg"
14
+ compare = "greater_than"
15
+ severity = "info"
16
+
17
+ [rule.target]
18
+ type = "absolute"
19
+ value = 65
20
+
21
+ [rule.throttle]
22
+ minGapMinutes = 240
23
+ maxPerDay = 2
24
+
25
+ [[rule]]
26
+ id = "yogaring.activity-low"
27
+ brand = "yogaring"
28
+ name = "YogaRing activity nudge"
29
+ description = "Daily step count is below 2500."
30
+ metric = "activity_steps"
31
+ window = "24h"
32
+ aggregation = "sum"
33
+ compare = "less_than"
34
+ severity = "info"
35
+
36
+ [rule.target]
37
+ type = "absolute"
38
+ value = 2500
39
+
40
+ [rule.throttle]
41
+ minGapMinutes = 720
42
+ maxPerDay = 1
43
+ `;
44
+ export const yogaringDefaults = parseCatalog(TOML, { name: 'yogaring' });
45
+ //# sourceMappingURL=yogaring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yogaring.js","sourceRoot":"","sources":["../../../src/rules/defaults/yogaring.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCZ,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAW,YAAY,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ziva brand default rules.
3
+ *
4
+ * The template string below is a verbatim copy of `ziva.toml`. Edit the
5
+ * TOML sidecar, then either run `scripts/sync-toml.mjs` or copy-paste
6
+ * back into this literal. Metro/tsup do not read `.toml` files directly.
7
+ */
8
+ import type { Rule } from '../schema';
9
+ export declare const zivaDefaults: Rule[];
10
+ //# sourceMappingURL=ziva.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ziva.d.ts","sourceRoot":"","sources":["../../../src/rules/defaults/ziva.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAgFrC,eAAO,MAAM,YAAY,EAAE,IAAI,EAAyC,CAAA"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Ziva brand default rules.
3
+ *
4
+ * The template string below is a verbatim copy of `ziva.toml`. Edit the
5
+ * TOML sidecar, then either run `scripts/sync-toml.mjs` or copy-paste
6
+ * back into this literal. Metro/tsup do not read `.toml` files directly.
7
+ */
8
+ import { parseCatalog } from './loader';
9
+ const TOML = `
10
+ [[rule]]
11
+ id = "ziva.hrv-drop-30"
12
+ brand = "ziva"
13
+ name = "HRV drop below 30 ms"
14
+ description = "Average HRV over the last 24h fell below 30 ms."
15
+ metric = "hrv_ms"
16
+ window = "24h"
17
+ aggregation = "avg"
18
+ compare = "less_than"
19
+ severity = "warn"
20
+
21
+ [rule.target]
22
+ type = "absolute"
23
+ value = 30
24
+
25
+ [rule.throttle]
26
+ minGapMinutes = 360
27
+ maxPerDay = 2
28
+
29
+ [[rule]]
30
+ id = "ziva.sleep-deprivation-3d"
31
+ brand = "ziva"
32
+ name = "Sleep deprivation"
33
+ description = "Average nightly sleep across 3 nights below 360 minutes."
34
+ metric = "sleep_total_minutes"
35
+ window = "3d"
36
+ aggregation = "avg"
37
+ compare = "less_than"
38
+ severity = "warn"
39
+
40
+ [rule.target]
41
+ type = "absolute"
42
+ value = 360
43
+
44
+ [rule.throttle]
45
+ minGapMinutes = 720
46
+ maxPerDay = 1
47
+
48
+ [[rule]]
49
+ id = "ziva.stress-elevated"
50
+ brand = "ziva"
51
+ name = "Elevated stress"
52
+ description = "Average stress score over 6h rose above 70."
53
+ metric = "stress"
54
+ window = "6h"
55
+ aggregation = "avg"
56
+ compare = "greater_than"
57
+ severity = "info"
58
+
59
+ [rule.target]
60
+ type = "absolute"
61
+ value = 70
62
+
63
+ [rule.throttle]
64
+ minGapMinutes = 120
65
+ maxPerDay = 3
66
+
67
+ [[rule]]
68
+ id = "ziva.activity-low-24h"
69
+ brand = "ziva"
70
+ name = "Low activity"
71
+ description = "Daily step count is below 3000."
72
+ metric = "activity_steps"
73
+ window = "24h"
74
+ aggregation = "sum"
75
+ compare = "less_than"
76
+ severity = "info"
77
+
78
+ [rule.target]
79
+ type = "absolute"
80
+ value = 3000
81
+
82
+ [rule.throttle]
83
+ minGapMinutes = 720
84
+ maxPerDay = 1
85
+ `;
86
+ export const zivaDefaults = parseCatalog(TOML, { name: 'ziva' });
87
+ //# sourceMappingURL=ziva.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ziva.js","sourceRoot":"","sources":["../../../src/rules/defaults/ziva.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4EZ,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAW,YAAY,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Minimal typed event emitter for the rules engine.
3
+ *
4
+ * Only the `'violation'` event is supported. Handler exceptions are
5
+ * caught and logged so a single subscriber can't take down evaluation.
6
+ * `on(...)` returns an `Unsubscribe` closure per spec's public surface.
7
+ */
8
+ import type { Unsubscribe } from '../core/types';
9
+ import type { RuleViolation, RulesLogger } from './types';
10
+ type ViolationHandler = (v: RuleViolation) => void;
11
+ export interface RulesEmitter {
12
+ on(event: 'violation', handler: ViolationHandler): Unsubscribe;
13
+ emit(event: 'violation', payload: RuleViolation): void;
14
+ }
15
+ export interface CreateEmitterConfig {
16
+ logger?: RulesLogger;
17
+ }
18
+ export declare function createEmitter({ logger }?: CreateEmitterConfig): RulesEmitter;
19
+ export {};
20
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/rules/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAEzD,KAAK,gBAAgB,GAAG,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;AAElD,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,GAAG,WAAW,CAAA;IAC9D,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAAA;CACvD;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,GAAE,mBAAwB,GAAG,YAAY,CAwBhF"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Minimal typed event emitter for the rules engine.
3
+ *
4
+ * Only the `'violation'` event is supported. Handler exceptions are
5
+ * caught and logged so a single subscriber can't take down evaluation.
6
+ * `on(...)` returns an `Unsubscribe` closure per spec's public surface.
7
+ */
8
+ export function createEmitter({ logger } = {}) {
9
+ const handlers = new Set();
10
+ return {
11
+ on(_event, handler) {
12
+ handlers.add(handler);
13
+ return () => {
14
+ handlers.delete(handler);
15
+ };
16
+ },
17
+ emit(_event, payload) {
18
+ for (const h of handlers) {
19
+ try {
20
+ h(payload);
21
+ }
22
+ catch (err) {
23
+ logger?.error('rules.emitter: violation handler threw', {
24
+ err: err.message,
25
+ ruleId: payload.ruleId,
26
+ });
27
+ }
28
+ }
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../src/rules/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,UAAU,aAAa,CAAC,EAAE,MAAM,KAA0B,EAAE;IAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAA;IAE5C,OAAO;QACL,EAAE,CAAC,MAAM,EAAE,OAAO;YAChB,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACrB,OAAO,GAAG,EAAE;gBACV,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YAC1B,CAAC,CAAA;QACH,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,OAAO;YAClB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,CAAC,CAAC,OAAO,CAAC,CAAA;gBACZ,CAAC;gBACD,OAAO,GAAG,EAAE,CAAC;oBACX,MAAM,EAAE,KAAK,CAAC,wCAAwC,EAAE;wBACtD,GAAG,EAAG,GAAa,CAAC,OAAO;wBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;qBACvB,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Rule evaluator — glues registry + compiler cache + throttle + emitter to
3
+ * `analytics.execute`.
4
+ *
5
+ * Two entry points:
6
+ * - `evaluateOnBatch(batch)` — called by sync after a successful flush.
7
+ * Considers only rules whose metric table intersects `batch.affectedTables`.
8
+ * - `evaluateScheduled()` — called by the sync scheduler cadence. Considers
9
+ * every active brand-matching rule, fanned out over family members.
10
+ *
11
+ * Both funnel through `evaluateRule(rule, ctx)` which is the throttle-gated
12
+ * single-user check. A returned `RuleViolation` is emitted synchronously via
13
+ * the shared emitter and echoed to callers.
14
+ *
15
+ * `analytics.execute` throws are caught + logged; a failing rule never
16
+ * blocks the rest of the pass.
17
+ */
18
+ import type { AnalyticsEngine } from '../core/types';
19
+ import type { CompilerCache } from './compiler-cache';
20
+ import type { createEmitter } from './emitter';
21
+ import type { RulesRegistry } from './registry';
22
+ import type { createThrottleStore } from './throttle';
23
+ import type { Clock, RuleViolation, RulesLogger, FlushSummary } from './types';
24
+ export interface EvaluatorConfig {
25
+ registry: RulesRegistry;
26
+ cache: CompilerCache;
27
+ throttle: ReturnType<typeof createThrottleStore>;
28
+ emitter: ReturnType<typeof createEmitter>;
29
+ analytics: AnalyticsEngine;
30
+ brand: string;
31
+ familyId: string;
32
+ familyMembersProvider: (ctx: {
33
+ brand: string;
34
+ familyId: string;
35
+ }) => Promise<string[]>;
36
+ clock: Clock;
37
+ logger?: RulesLogger;
38
+ }
39
+ export interface Evaluator {
40
+ evaluateOnBatch(batch: FlushSummary): Promise<RuleViolation[]>;
41
+ evaluateScheduled(): Promise<RuleViolation[]>;
42
+ }
43
+ export declare function createEvaluator(config: EvaluatorConfig): Evaluator;
44
+ //# sourceMappingURL=evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/rules/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACb,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,aAAa,CAAA;IACvB,KAAK,EAAE,aAAa,CAAA;IACpB,QAAQ,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;IAChD,OAAO,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA;IACzC,SAAS,EAAE,eAAe,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,qBAAqB,EAAE,CAAC,GAAG,EAAE;QAC3B,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,MAAM,CAAA;KACjB,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACvB,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAOD,MAAM,WAAW,SAAS;IACxB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IAC9D,iBAAiB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;CAC9C;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAkIlE"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Rule evaluator — glues registry + compiler cache + throttle + emitter to
3
+ * `analytics.execute`.
4
+ *
5
+ * Two entry points:
6
+ * - `evaluateOnBatch(batch)` — called by sync after a successful flush.
7
+ * Considers only rules whose metric table intersects `batch.affectedTables`.
8
+ * - `evaluateScheduled()` — called by the sync scheduler cadence. Considers
9
+ * every active brand-matching rule, fanned out over family members.
10
+ *
11
+ * Both funnel through `evaluateRule(rule, ctx)` which is the throttle-gated
12
+ * single-user check. A returned `RuleViolation` is emitted synchronously via
13
+ * the shared emitter and echoed to callers.
14
+ *
15
+ * `analytics.execute` throws are caught + logged; a failing rule never
16
+ * blocks the rest of the pass.
17
+ */
18
+ import { METRIC_METADATA } from '../core/metric_metadata';
19
+ export function createEvaluator(config) {
20
+ const { registry, cache, throttle, emitter, analytics, brand, familyId, familyMembersProvider, clock, logger, } = config;
21
+ async function evaluateRule(rule, ctx) {
22
+ const throttled = await throttle.isThrottled(rule.id, ctx.userId, rule.throttle);
23
+ if (throttled) {
24
+ logger?.debug('rules.evaluator: throttled', {
25
+ ruleId: rule.id,
26
+ userId: ctx.userId,
27
+ });
28
+ return null;
29
+ }
30
+ let rows;
31
+ try {
32
+ const compiled = cache.getCompiled(rule, registry.rev);
33
+ const params = {
34
+ userId: ctx.userId,
35
+ brand,
36
+ familyId: ctx.familyId,
37
+ ...compiled.params,
38
+ };
39
+ rows = await analytics.execute(compiled.sql, params);
40
+ }
41
+ catch (err) {
42
+ logger?.error('rules.evaluator: execute failed', {
43
+ ruleId: rule.id,
44
+ userId: ctx.userId,
45
+ err: err.message,
46
+ });
47
+ return null;
48
+ }
49
+ if (rows.length === 0) {
50
+ return null;
51
+ }
52
+ const row = rows[0];
53
+ const violation = {
54
+ ruleId: rule.id,
55
+ ruleName: rule.name,
56
+ severity: rule.severity,
57
+ userId: ctx.userId,
58
+ familyId: ctx.familyId,
59
+ brand: rule.brand ?? brand,
60
+ observedValue: Number(row.observed_value),
61
+ thresholdValue: Number(row.threshold_value),
62
+ observedAt: clock(),
63
+ evidence: {
64
+ metric: rule.metric,
65
+ window: rule.window,
66
+ aggregation: rule.aggregation,
67
+ compare: rule.compare,
68
+ target: rule.target,
69
+ },
70
+ };
71
+ await throttle.recordFire(rule.id, ctx.userId);
72
+ emitter.emit('violation', violation);
73
+ return violation;
74
+ }
75
+ function rulesForTables(rules, affectedTables) {
76
+ const tableSet = new Set(affectedTables);
77
+ return rules.filter((r) => {
78
+ const meta = METRIC_METADATA[r.metric];
79
+ return tableSet.has(meta.table);
80
+ });
81
+ }
82
+ return {
83
+ async evaluateOnBatch(batch) {
84
+ const active = registry.getByBrand(brand);
85
+ const relevant = rulesForTables(active, batch.affectedTables);
86
+ if (relevant.length === 0 || batch.affectedUserIds.length === 0) {
87
+ return [];
88
+ }
89
+ const violations = [];
90
+ for (const rule of relevant) {
91
+ for (const userId of batch.affectedUserIds) {
92
+ const v = await evaluateRule(rule, { userId, familyId });
93
+ if (v)
94
+ violations.push(v);
95
+ }
96
+ }
97
+ return violations;
98
+ },
99
+ async evaluateScheduled() {
100
+ const active = registry.getByBrand(brand);
101
+ if (active.length === 0) {
102
+ return [];
103
+ }
104
+ let members;
105
+ try {
106
+ members = await familyMembersProvider({ brand, familyId });
107
+ }
108
+ catch (err) {
109
+ logger?.error('rules.evaluator: familyMembersProvider failed', {
110
+ familyId,
111
+ err: err.message,
112
+ });
113
+ return [];
114
+ }
115
+ const violations = [];
116
+ for (const rule of active) {
117
+ for (const userId of members) {
118
+ const v = await evaluateRule(rule, { userId, familyId });
119
+ if (v)
120
+ violations.push(v);
121
+ }
122
+ }
123
+ return violations;
124
+ },
125
+ };
126
+ }
127
+ //# sourceMappingURL=evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../../src/rules/evaluator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `createRulesEngine(config)` — assembles registry, compiler cache,
3
+ * throttle store, emitter, and evaluator into the public `RulesEngine`
4
+ * surface.
5
+ *
6
+ * The factory holds no persistent state of its own; all state lives on
7
+ * the sub-modules. Callers pass a `KVStore` for durable state (rule
8
+ * enable flags, throttle counters) and an `AnalyticsEngine` for SQL
9
+ * execution.
10
+ */
11
+ import type { RulesEngine, RulesEngineConfig } from './types';
12
+ export declare function createRulesEngine(config: RulesEngineConfig): RulesEngine;
13
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/rules/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAE7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAiDxE"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * `createRulesEngine(config)` — assembles registry, compiler cache,
3
+ * throttle store, emitter, and evaluator into the public `RulesEngine`
4
+ * surface.
5
+ *
6
+ * The factory holds no persistent state of its own; all state lives on
7
+ * the sub-modules. Callers pass a `KVStore` for durable state (rule
8
+ * enable flags, throttle counters) and an `AnalyticsEngine` for SQL
9
+ * execution.
10
+ */
11
+ import { createCompilerCache } from './compiler-cache';
12
+ import { createEmitter } from './emitter';
13
+ import { createEvaluator } from './evaluator';
14
+ import { createRulesRegistry } from './registry';
15
+ import { createThrottleStore } from './throttle';
16
+ export function createRulesEngine(config) {
17
+ const { analytics, storage, familyMembersProvider, brand, familyId, logger, clock = () => new Date(), } = config;
18
+ const emitter = createEmitter({ logger });
19
+ const throttle = createThrottleStore({ storage, clock, logger });
20
+ const cache = createCompilerCache();
21
+ const registry = createRulesRegistry({
22
+ storage,
23
+ logger,
24
+ defaultBrand: brand,
25
+ });
26
+ const evaluator = createEvaluator({
27
+ registry,
28
+ cache,
29
+ throttle,
30
+ emitter,
31
+ analytics,
32
+ brand,
33
+ familyId,
34
+ familyMembersProvider,
35
+ clock,
36
+ logger,
37
+ });
38
+ return {
39
+ register: (rules) => registry.register(rules),
40
+ enable: (ruleId) => {
41
+ cache.invalidate(ruleId);
42
+ return registry.enable(ruleId);
43
+ },
44
+ disable: (ruleId) => {
45
+ cache.invalidate(ruleId);
46
+ return registry.disable(ruleId);
47
+ },
48
+ list: () => registry.list(),
49
+ getActive: () => registry.getActive(),
50
+ evaluateOnBatch: (batch) => evaluator.evaluateOnBatch(batch),
51
+ evaluateScheduled: () => evaluator.evaluateScheduled(),
52
+ on: (event, handler) => emitter.on(event, handler),
53
+ subscribeRegistry: (listener) => registry.subscribe(listener),
54
+ };
55
+ }
56
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/rules/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGhD,MAAM,UAAU,iBAAiB,CAAC,MAAyB;IACzD,MAAM,EACJ,SAAS,EACT,OAAO,EACP,qBAAqB,EACrB,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,GACzB,GAAG,MAAM,CAAA;IAEV,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;IACzC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAChE,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAA;IACnC,MAAM,QAAQ,GAAG,mBAAmB,CAAC;QACnC,OAAO;QACP,MAAM;QACN,YAAY,EAAE,KAAK;KACpB,CAAC,CAAA;IACF,MAAM,SAAS,GAAG,eAAe,CAAC;QAChC,QAAQ;QACR,KAAK;QACL,QAAQ;QACR,OAAO;QACP,SAAS;QACT,KAAK;QACL,QAAQ;QACR,qBAAqB;QACrB,KAAK;QACL,MAAM;KACP,CAAC,CAAA;IAEF,OAAO;QACL,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC7C,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;YACjB,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;YACxB,OAAO,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAChC,CAAC;QACD,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE;YAClB,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;YACxB,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACjC,CAAC;QACD,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE;QAC3B,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE;QACrC,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC;QAC5D,iBAAiB,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,iBAAiB,EAAE;QACtD,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC;QAClD,iBAAiB,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC;KAC9D,CAAA;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `useRuleRegistry(engine)` — live registry state.
3
+ *
4
+ * Uses `useSyncExternalStore` bound to `engine.subscribeRegistry` so the
5
+ * component re-renders on register / enable / disable. `enable` + `disable`
6
+ * are stable references passed through from the engine.
7
+ */
8
+ import type { Rule } from '../schema';
9
+ import type { RulesEngine } from '../types';
10
+ export interface UseRuleRegistryResult {
11
+ rules: Rule[];
12
+ enable(ruleId: string): Promise<void>;
13
+ disable(ruleId: string): Promise<void>;
14
+ }
15
+ export declare function useRuleRegistry(engine: RulesEngine): UseRuleRegistryResult;
16
+ //# sourceMappingURL=useRuleRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRuleRegistry.d.ts","sourceRoot":"","sources":["../../../src/rules/hooks/useRuleRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvC;AAkBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,qBAAqB,CAQ1E"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `useRuleRegistry(engine)` — live registry state.
3
+ *
4
+ * Uses `useSyncExternalStore` bound to `engine.subscribeRegistry` so the
5
+ * component re-renders on register / enable / disable. `enable` + `disable`
6
+ * are stable references passed through from the engine.
7
+ */
8
+ import { useMemo, useSyncExternalStore, useCallback } from 'react';
9
+ function makeCache(engine) {
10
+ let snapshot = engine.list();
11
+ return {
12
+ subscribe: (onStoreChange) => engine.subscribeRegistry(() => {
13
+ snapshot = engine.list();
14
+ onStoreChange();
15
+ }),
16
+ get: () => snapshot,
17
+ };
18
+ }
19
+ export function useRuleRegistry(engine) {
20
+ const cache = useMemo(() => makeCache(engine), [engine]);
21
+ const rules = useSyncExternalStore(cache.subscribe, cache.get, cache.get);
22
+ const enable = useCallback((ruleId) => engine.enable(ruleId), [engine]);
23
+ const disable = useCallback((ruleId) => engine.disable(ruleId), [engine]);
24
+ return { rules, enable, disable };
25
+ }
26
+ //# sourceMappingURL=useRuleRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRuleRegistry.js","sourceRoot":"","sources":["../../../src/rules/hooks/useRuleRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAelE,SAAS,SAAS,CAAC,MAAmB;IACpC,IAAI,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IAC5B,OAAO;QACL,SAAS,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,GAAG,EAAE;YAC1D,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;YACxB,aAAa,EAAE,CAAA;QACjB,CAAC,CAAC;QACF,GAAG,EAAE,GAAG,EAAE,CAAC,QAAQ;KACpB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAmB;IACjD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IACxD,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;IAEzE,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAC/E,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEjF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AACnC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `useRuleViolations(engine, options?)` — session-scoped violation feed.
3
+ *
4
+ * Subscribes to `engine.on('violation', ...)` for the lifetime of the
5
+ * component and buffers the most-recent `limit` violations in state. On
6
+ * unmount the subscription tears down.
7
+ *
8
+ * React is an optional peer of `@mongrov/analytics`; this file is only
9
+ * imported when the app pulls the `/rules` subpath.
10
+ */
11
+ import type { RuleViolation, RulesEngine } from '../types';
12
+ export interface UseRuleViolationsOptions {
13
+ /** Maximum number of retained violations. Default `50`. */
14
+ limit?: number;
15
+ }
16
+ export interface UseRuleViolationsResult {
17
+ violations: RuleViolation[];
18
+ clear(): void;
19
+ }
20
+ export declare function useRuleViolations(engine: RulesEngine, options?: UseRuleViolationsOptions): UseRuleViolationsResult;
21
+ //# sourceMappingURL=useRuleViolations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRuleViolations.d.ts","sourceRoot":"","sources":["../../../src/rules/hooks/useRuleViolations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAI1D,MAAM,WAAW,wBAAwB;IACvC,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,aAAa,EAAE,CAAA;IAC3B,KAAK,IAAI,IAAI,CAAA;CACd;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE,wBAAwB,GACjC,uBAAuB,CAoBzB"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `useRuleViolations(engine, options?)` — session-scoped violation feed.
3
+ *
4
+ * Subscribes to `engine.on('violation', ...)` for the lifetime of the
5
+ * component and buffers the most-recent `limit` violations in state. On
6
+ * unmount the subscription tears down.
7
+ *
8
+ * React is an optional peer of `@mongrov/analytics`; this file is only
9
+ * imported when the app pulls the `/rules` subpath.
10
+ */
11
+ import { useEffect, useState, useCallback } from 'react';
12
+ const DEFAULT_LIMIT = 50;
13
+ export function useRuleViolations(engine, options) {
14
+ const limit = options?.limit ?? DEFAULT_LIMIT;
15
+ const [violations, setViolations] = useState([]);
16
+ useEffect(() => {
17
+ const unsub = engine.on('violation', (v) => {
18
+ setViolations((prev) => {
19
+ const next = [v, ...prev];
20
+ if (next.length > limit)
21
+ next.length = limit;
22
+ return next;
23
+ });
24
+ });
25
+ return unsub;
26
+ }, [engine, limit]);
27
+ const clear = useCallback(() => {
28
+ setViolations([]);
29
+ }, []);
30
+ return { violations, clear };
31
+ }
32
+ //# sourceMappingURL=useRuleViolations.js.map