@miragon/pulse-analytics-connector 0.0.0-bootstrap.0 → 0.21.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 (357) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -3
  3. package/dist/bpmn-name-lookup.d.ts +72 -0
  4. package/dist/bpmn-name-lookup.d.ts.map +1 -0
  5. package/dist/bpmn-name-lookup.js +123 -0
  6. package/dist/bpmn-name-lookup.js.map +1 -0
  7. package/dist/bpmn-name-lookup.test.d.ts +2 -0
  8. package/dist/bpmn-name-lookup.test.d.ts.map +1 -0
  9. package/dist/bpmn-name-lookup.test.js +287 -0
  10. package/dist/bpmn-name-lookup.test.js.map +1 -0
  11. package/dist/bpmn-names.d.ts +38 -0
  12. package/dist/bpmn-names.d.ts.map +1 -0
  13. package/dist/bpmn-names.js +22 -0
  14. package/dist/bpmn-names.js.map +1 -0
  15. package/dist/brand-gates.test.d.ts +2 -0
  16. package/dist/brand-gates.test.d.ts.map +1 -0
  17. package/dist/brand-gates.test.js +58 -0
  18. package/dist/brand-gates.test.js.map +1 -0
  19. package/dist/builder-texts.d.ts +4 -0
  20. package/dist/builder-texts.d.ts.map +1 -0
  21. package/dist/builder-texts.js +14 -0
  22. package/dist/builder-texts.js.map +1 -0
  23. package/dist/builder-texts.test.d.ts +2 -0
  24. package/dist/builder-texts.test.d.ts.map +1 -0
  25. package/dist/builder-texts.test.js +32 -0
  26. package/dist/builder-texts.test.js.map +1 -0
  27. package/dist/definition.d.ts +3 -0
  28. package/dist/definition.d.ts.map +1 -0
  29. package/dist/definition.js +151 -0
  30. package/dist/definition.js.map +1 -0
  31. package/dist/engine-ids.d.ts +42 -0
  32. package/dist/engine-ids.d.ts.map +1 -0
  33. package/dist/engine-ids.js +50 -0
  34. package/dist/engine-ids.js.map +1 -0
  35. package/dist/engine-scope.test.d.ts +2 -0
  36. package/dist/engine-scope.test.d.ts.map +1 -0
  37. package/dist/engine-scope.test.js +260 -0
  38. package/dist/engine-scope.test.js.map +1 -0
  39. package/dist/heatmap-data.d.ts +15 -0
  40. package/dist/heatmap-data.d.ts.map +1 -0
  41. package/dist/heatmap-data.js +2 -0
  42. package/dist/heatmap-data.js.map +1 -0
  43. package/dist/index.d.ts +5 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +3 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/instructions.d.ts +8 -0
  48. package/dist/instructions.d.ts.map +1 -0
  49. package/dist/instructions.js +33 -0
  50. package/dist/instructions.js.map +1 -0
  51. package/dist/messages/de.ask-ai.d.ts +9 -0
  52. package/dist/messages/de.ask-ai.d.ts.map +1 -0
  53. package/dist/messages/de.ask-ai.js +18 -0
  54. package/dist/messages/de.ask-ai.js.map +1 -0
  55. package/dist/messages/de.builder.d.ts +12 -0
  56. package/dist/messages/de.builder.d.ts.map +1 -0
  57. package/dist/messages/de.builder.js +53 -0
  58. package/dist/messages/de.builder.js.map +1 -0
  59. package/dist/messages/de.server.d.ts +8 -0
  60. package/dist/messages/de.server.d.ts.map +1 -0
  61. package/dist/messages/de.server.js +26 -0
  62. package/dist/messages/de.server.js.map +1 -0
  63. package/dist/messages/de.sweep.d.ts +10 -0
  64. package/dist/messages/de.sweep.d.ts.map +1 -0
  65. package/dist/messages/de.sweep.js +203 -0
  66. package/dist/messages/de.sweep.js.map +1 -0
  67. package/dist/messages/en.ask-ai.d.ts +25 -0
  68. package/dist/messages/en.ask-ai.d.ts.map +1 -0
  69. package/dist/messages/en.ask-ai.js +24 -0
  70. package/dist/messages/en.ask-ai.js.map +1 -0
  71. package/dist/messages/en.builder.d.ts +12 -0
  72. package/dist/messages/en.builder.d.ts.map +1 -0
  73. package/dist/messages/en.builder.js +53 -0
  74. package/dist/messages/en.builder.js.map +1 -0
  75. package/dist/messages/en.server.d.ts +8 -0
  76. package/dist/messages/en.server.d.ts.map +1 -0
  77. package/dist/messages/en.server.js +26 -0
  78. package/dist/messages/en.server.js.map +1 -0
  79. package/dist/messages/en.sweep.d.ts +11 -0
  80. package/dist/messages/en.sweep.d.ts.map +1 -0
  81. package/dist/messages/en.sweep.js +204 -0
  82. package/dist/messages/en.sweep.js.map +1 -0
  83. package/dist/messages/glossary.d.ts +26 -0
  84. package/dist/messages/glossary.d.ts.map +1 -0
  85. package/dist/messages/glossary.js +37 -0
  86. package/dist/messages/glossary.js.map +1 -0
  87. package/dist/messages/glossary.test.d.ts +2 -0
  88. package/dist/messages/glossary.test.d.ts.map +1 -0
  89. package/dist/messages/glossary.test.js +109 -0
  90. package/dist/messages/glossary.test.js.map +1 -0
  91. package/dist/messages/index.d.ts +12 -0
  92. package/dist/messages/index.d.ts.map +1 -0
  93. package/dist/messages/index.js +23 -0
  94. package/dist/messages/index.js.map +1 -0
  95. package/dist/messages/plural.d.ts +10 -0
  96. package/dist/messages/plural.d.ts.map +1 -0
  97. package/dist/messages/plural.js +17 -0
  98. package/dist/messages/plural.js.map +1 -0
  99. package/dist/messages/use-t.d.ts +10 -0
  100. package/dist/messages/use-t.d.ts.map +1 -0
  101. package/dist/messages/use-t.js +10 -0
  102. package/dist/messages/use-t.js.map +1 -0
  103. package/dist/module.d.ts +48 -0
  104. package/dist/module.d.ts.map +1 -0
  105. package/dist/module.js +174 -0
  106. package/dist/module.js.map +1 -0
  107. package/dist/module.test.d.ts +2 -0
  108. package/dist/module.test.d.ts.map +1 -0
  109. package/dist/module.test.js +230 -0
  110. package/dist/module.test.js.map +1 -0
  111. package/dist/named-views.d.ts +27 -0
  112. package/dist/named-views.d.ts.map +1 -0
  113. package/dist/named-views.js +73 -0
  114. package/dist/named-views.js.map +1 -0
  115. package/dist/named-views.test.d.ts +2 -0
  116. package/dist/named-views.test.d.ts.map +1 -0
  117. package/dist/named-views.test.js +110 -0
  118. package/dist/named-views.test.js.map +1 -0
  119. package/dist/plugin.d.ts +44 -0
  120. package/dist/plugin.d.ts.map +1 -0
  121. package/dist/plugin.js +52 -0
  122. package/dist/plugin.js.map +1 -0
  123. package/dist/prometheus-wiring.test.d.ts +2 -0
  124. package/dist/prometheus-wiring.test.d.ts.map +1 -0
  125. package/dist/prometheus-wiring.test.js +142 -0
  126. package/dist/prometheus-wiring.test.js.map +1 -0
  127. package/dist/server-locale.d.ts +48 -0
  128. package/dist/server-locale.d.ts.map +1 -0
  129. package/dist/server-locale.js +33 -0
  130. package/dist/server-locale.js.map +1 -0
  131. package/dist/settings-tools.d.ts +23 -0
  132. package/dist/settings-tools.d.ts.map +1 -0
  133. package/dist/settings-tools.js +100 -0
  134. package/dist/settings-tools.js.map +1 -0
  135. package/dist/settings.d.ts +77 -0
  136. package/dist/settings.d.ts.map +1 -0
  137. package/dist/settings.js +99 -0
  138. package/dist/settings.js.map +1 -0
  139. package/dist/settings.test.d.ts +2 -0
  140. package/dist/settings.test.d.ts.map +1 -0
  141. package/dist/settings.test.js +299 -0
  142. package/dist/settings.test.js.map +1 -0
  143. package/dist/steps/app-config.d.ts +30 -0
  144. package/dist/steps/app-config.d.ts.map +1 -0
  145. package/dist/steps/app-config.js +46 -0
  146. package/dist/steps/app-config.js.map +1 -0
  147. package/dist/steps/dashboard.d.ts +12 -0
  148. package/dist/steps/dashboard.d.ts.map +1 -0
  149. package/dist/steps/dashboard.js +58 -0
  150. package/dist/steps/dashboard.js.map +1 -0
  151. package/dist/steps/failure-dashboard.d.ts +10 -0
  152. package/dist/steps/failure-dashboard.d.ts.map +1 -0
  153. package/dist/steps/failure-dashboard.js +32 -0
  154. package/dist/steps/failure-dashboard.js.map +1 -0
  155. package/dist/steps/index.d.ts +3 -0
  156. package/dist/steps/index.d.ts.map +1 -0
  157. package/dist/steps/index.js +3 -0
  158. package/dist/steps/index.js.map +1 -0
  159. package/dist/steps/steps.test.d.ts +2 -0
  160. package/dist/steps/steps.test.d.ts.map +1 -0
  161. package/dist/steps/steps.test.js +153 -0
  162. package/dist/steps/steps.test.js.map +1 -0
  163. package/dist/tool-names.d.ts +13 -0
  164. package/dist/tool-names.d.ts.map +1 -0
  165. package/dist/tool-names.js +27 -0
  166. package/dist/tool-names.js.map +1 -0
  167. package/dist/tools/cluster-compare.d.ts +8 -0
  168. package/dist/tools/cluster-compare.d.ts.map +1 -0
  169. package/dist/tools/cluster-compare.js +17 -0
  170. package/dist/tools/cluster-compare.js.map +1 -0
  171. package/dist/tools/element.d.ts +8 -0
  172. package/dist/tools/element.d.ts.map +1 -0
  173. package/dist/tools/element.js +25 -0
  174. package/dist/tools/element.js.map +1 -0
  175. package/dist/tools/engine-compare.d.ts +8 -0
  176. package/dist/tools/engine-compare.d.ts.map +1 -0
  177. package/dist/tools/engine-compare.js +18 -0
  178. package/dist/tools/engine-compare.js.map +1 -0
  179. package/dist/tools/engine-compare.test.d.ts +2 -0
  180. package/dist/tools/engine-compare.test.d.ts.map +1 -0
  181. package/dist/tools/engine-compare.test.js +166 -0
  182. package/dist/tools/engine-compare.test.js.map +1 -0
  183. package/dist/tools/engine-landscape.d.ts +7 -0
  184. package/dist/tools/engine-landscape.d.ts.map +1 -0
  185. package/dist/tools/engine-landscape.js +13 -0
  186. package/dist/tools/engine-landscape.js.map +1 -0
  187. package/dist/tools/engine-landscape.test.d.ts +2 -0
  188. package/dist/tools/engine-landscape.test.d.ts.map +1 -0
  189. package/dist/tools/engine-landscape.test.js +110 -0
  190. package/dist/tools/engine-landscape.test.js.map +1 -0
  191. package/dist/tools/failures.d.ts +7 -0
  192. package/dist/tools/failures.d.ts.map +1 -0
  193. package/dist/tools/failures.js +13 -0
  194. package/dist/tools/failures.js.map +1 -0
  195. package/dist/tools/health.d.ts +7 -0
  196. package/dist/tools/health.d.ts.map +1 -0
  197. package/dist/tools/health.js +23 -0
  198. package/dist/tools/health.js.map +1 -0
  199. package/dist/tools/health.test.d.ts +2 -0
  200. package/dist/tools/health.test.d.ts.map +1 -0
  201. package/dist/tools/health.test.js +119 -0
  202. package/dist/tools/health.test.js.map +1 -0
  203. package/dist/tools/index.d.ts +18 -0
  204. package/dist/tools/index.d.ts.map +1 -0
  205. package/dist/tools/index.js +35 -0
  206. package/dist/tools/index.js.map +1 -0
  207. package/dist/tools/performance.d.ts +8 -0
  208. package/dist/tools/performance.d.ts.map +1 -0
  209. package/dist/tools/performance.js +25 -0
  210. package/dist/tools/performance.js.map +1 -0
  211. package/dist/tools/performance.test.d.ts +2 -0
  212. package/dist/tools/performance.test.d.ts.map +1 -0
  213. package/dist/tools/performance.test.js +176 -0
  214. package/dist/tools/performance.test.js.map +1 -0
  215. package/dist/tools/version-compare.d.ts +8 -0
  216. package/dist/tools/version-compare.d.ts.map +1 -0
  217. package/dist/tools/version-compare.js +17 -0
  218. package/dist/tools/version-compare.js.map +1 -0
  219. package/dist/tools/version-compare.test.d.ts +2 -0
  220. package/dist/tools/version-compare.test.d.ts.map +1 -0
  221. package/dist/tools/version-compare.test.js +82 -0
  222. package/dist/tools/version-compare.test.js.map +1 -0
  223. package/dist/toolsets.d.ts +17 -0
  224. package/dist/toolsets.d.ts.map +1 -0
  225. package/dist/toolsets.js +47 -0
  226. package/dist/toolsets.js.map +1 -0
  227. package/dist/toolsets.test.d.ts +2 -0
  228. package/dist/toolsets.test.d.ts.map +1 -0
  229. package/dist/toolsets.test.js +91 -0
  230. package/dist/toolsets.test.js.map +1 -0
  231. package/dist/view-title.test.d.ts +2 -0
  232. package/dist/view-title.test.d.ts.map +1 -0
  233. package/dist/view-title.test.js +91 -0
  234. package/dist/view-title.test.js.map +1 -0
  235. package/dist/widget-tools/comparisons.d.ts +13 -0
  236. package/dist/widget-tools/comparisons.d.ts.map +1 -0
  237. package/dist/widget-tools/comparisons.js +177 -0
  238. package/dist/widget-tools/comparisons.js.map +1 -0
  239. package/dist/widget-tools/comparisons.test.d.ts +2 -0
  240. package/dist/widget-tools/comparisons.test.d.ts.map +1 -0
  241. package/dist/widget-tools/comparisons.test.js +123 -0
  242. package/dist/widget-tools/comparisons.test.js.map +1 -0
  243. package/dist/widget-tools/shared.d.ts +36 -0
  244. package/dist/widget-tools/shared.d.ts.map +1 -0
  245. package/dist/widget-tools/shared.js +39 -0
  246. package/dist/widget-tools/shared.js.map +1 -0
  247. package/dist/widget-tools.d.ts +25 -0
  248. package/dist/widget-tools.d.ts.map +1 -0
  249. package/dist/widget-tools.js +269 -0
  250. package/dist/widget-tools.js.map +1 -0
  251. package/dist/widget-tools.test.d.ts +2 -0
  252. package/dist/widget-tools.test.d.ts.map +1 -0
  253. package/dist/widget-tools.test.js +272 -0
  254. package/dist/widget-tools.test.js.map +1 -0
  255. package/package.json +91 -5
  256. package/src/bpmn-name-lookup.test.ts +333 -0
  257. package/src/bpmn-name-lookup.ts +197 -0
  258. package/src/bpmn-names.ts +51 -0
  259. package/src/brand-gates.test.ts +69 -0
  260. package/src/builder-texts.test.ts +40 -0
  261. package/src/builder-texts.ts +15 -0
  262. package/src/definition.ts +181 -0
  263. package/src/engine-ids.ts +85 -0
  264. package/src/engine-scope.test.ts +324 -0
  265. package/src/heatmap-data.ts +14 -0
  266. package/src/index.ts +4 -0
  267. package/src/instructions.ts +33 -0
  268. package/src/messages/GLOSSARY.md +88 -0
  269. package/src/messages/de.ask-ai.ts +28 -0
  270. package/src/messages/de.builder.ts +77 -0
  271. package/src/messages/de.server.ts +39 -0
  272. package/src/messages/de.sweep.ts +244 -0
  273. package/src/messages/en.ask-ai.ts +34 -0
  274. package/src/messages/en.builder.ts +76 -0
  275. package/src/messages/en.server.ts +39 -0
  276. package/src/messages/en.sweep.ts +240 -0
  277. package/src/messages/glossary.test.ts +122 -0
  278. package/src/messages/glossary.ts +62 -0
  279. package/src/messages/index.ts +24 -0
  280. package/src/messages/plural.ts +18 -0
  281. package/src/messages/use-t.ts +12 -0
  282. package/src/module.test.ts +319 -0
  283. package/src/module.ts +211 -0
  284. package/src/named-views.test.ts +141 -0
  285. package/src/named-views.ts +97 -0
  286. package/src/plugin.ts +94 -0
  287. package/src/prometheus-wiring.test.ts +174 -0
  288. package/src/server-locale.ts +59 -0
  289. package/src/settings-tools.ts +170 -0
  290. package/src/settings.test.ts +402 -0
  291. package/src/settings.ts +114 -0
  292. package/src/steps/app-config.ts +75 -0
  293. package/src/steps/dashboard.ts +73 -0
  294. package/src/steps/failure-dashboard.ts +38 -0
  295. package/src/steps/index.ts +2 -0
  296. package/src/steps/steps.test.ts +216 -0
  297. package/src/tool-names.ts +26 -0
  298. package/src/tools/cluster-compare.ts +28 -0
  299. package/src/tools/element.ts +35 -0
  300. package/src/tools/engine-compare.test.ts +210 -0
  301. package/src/tools/engine-compare.ts +30 -0
  302. package/src/tools/engine-landscape.test.ts +138 -0
  303. package/src/tools/engine-landscape.ts +21 -0
  304. package/src/tools/failures.ts +19 -0
  305. package/src/tools/health.test.ts +156 -0
  306. package/src/tools/health.ts +29 -0
  307. package/src/tools/index.ts +44 -0
  308. package/src/tools/performance.test.ts +210 -0
  309. package/src/tools/performance.ts +38 -0
  310. package/src/tools/version-compare.test.ts +97 -0
  311. package/src/tools/version-compare.ts +28 -0
  312. package/src/toolsets.test.ts +107 -0
  313. package/src/toolsets.ts +56 -0
  314. package/src/view-title.test.ts +123 -0
  315. package/src/widget-tools/comparisons.test.ts +170 -0
  316. package/src/widget-tools/comparisons.ts +229 -0
  317. package/src/widget-tools/shared.ts +67 -0
  318. package/src/widget-tools.test.ts +306 -0
  319. package/src/widget-tools.ts +375 -0
  320. package/src/widgets/analytics-dashboard/activity-bottleneck-table.tsx +179 -0
  321. package/src/widgets/analytics-dashboard/definition-breakdown.tsx +108 -0
  322. package/src/widgets/analytics-dashboard/execution-performance-kpi.tsx +94 -0
  323. package/src/widgets/analytics-dashboard/execution-summary-kpi.tsx +122 -0
  324. package/src/widgets/analytics-dashboard/lib.ts +43 -0
  325. package/src/widgets/bpmn-heatmap.test.tsx +75 -0
  326. package/src/widgets/bpmn-heatmap.tsx +127 -0
  327. package/src/widgets/catalogue-sync.test.ts +16 -0
  328. package/src/widgets/cluster-compare.tsx +148 -0
  329. package/src/widgets/comparison-shared.test.ts +237 -0
  330. package/src/widgets/comparison-shared.tsx +371 -0
  331. package/src/widgets/comparison-widgets.test.tsx +307 -0
  332. package/src/widgets/dashboard-widgets.test.tsx +397 -0
  333. package/src/widgets/engine-compare.tsx +87 -0
  334. package/src/widgets/engine-landscape.tsx +352 -0
  335. package/src/widgets/failure-dashboard/error-patterns-table.tsx +122 -0
  336. package/src/widgets/failure-dashboard/failure-rate-table.test.ts +80 -0
  337. package/src/widgets/failure-dashboard/failure-rate-table.tsx +170 -0
  338. package/src/widgets/failure-dashboard/lib.ts +32 -0
  339. package/src/widgets/failure-dashboard/summary-kpi.tsx +122 -0
  340. package/src/widgets/failure-landscape-widgets.test.tsx +393 -0
  341. package/src/widgets/figure.tsx +79 -0
  342. package/src/widgets/hand-off.test.ts +126 -0
  343. package/src/widgets/hand-off.ts +102 -0
  344. package/src/widgets/index.ts +124 -0
  345. package/src/widgets/model-descriptions.dashboard.test.ts +280 -0
  346. package/src/widgets/model-descriptions.test.ts +251 -0
  347. package/src/widgets/model-descriptions.ts +428 -0
  348. package/src/widgets/names.test.ts +32 -0
  349. package/src/widgets/names.ts +39 -0
  350. package/src/widgets/query-gate.test.tsx +57 -0
  351. package/src/widgets/query-gate.tsx +50 -0
  352. package/src/widgets/settings-section.test.tsx +174 -0
  353. package/src/widgets/settings-section.tsx +244 -0
  354. package/src/widgets/version-compare.test.ts +68 -0
  355. package/src/widgets/version-compare.tsx +96 -0
  356. package/src/widgets/view-meta.ts +18 -0
  357. package/src/widgets/widget-render.test-support.tsx +103 -0
@@ -0,0 +1,110 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { namedDashboard, namedFailureDashboard, namedLandscape } from "./named-views.js";
3
+ import { createNameLookup } from "./bpmn-name-lookup.js";
4
+ import { elementNameOf, processNameOf } from "./bpmn-names.js";
5
+ /**
6
+ * Every view asks for the names of exactly the ids it lists, no more, by
7
+ * priority, on the engines its rows come from.
8
+ */
9
+ describe("named views", () => {
10
+ const lookup = () => vi.fn(() => Promise.resolve({}));
11
+ it("the dashboard: its scope, the elements of its activities, then its definitions", async () => {
12
+ const namesFor = lookup();
13
+ const data = {
14
+ processDefinitionKey: "order",
15
+ engines: ["prod-b", "prod-a", "prod-c"],
16
+ reportingEngines: ["prod-a", "prod-b"],
17
+ definitionBreakdown: [{ processDefinitionKey: "order" }, { processDefinitionKey: "refund" }],
18
+ activityBreakdown: [
19
+ { processDefinitionKey: "order", activityId: "Task_A" },
20
+ { processDefinitionKey: "order", activityId: "Task_B" },
21
+ ],
22
+ };
23
+ const named = await namedDashboard(data, namesFor);
24
+ expect(named.names).toEqual({});
25
+ const [keys, request] = namesFor.mock.calls[0];
26
+ expect([...keys]).toEqual(["order", "order", "order", "order", "refund"]);
27
+ expect(request?.elementIds).toEqual({ order: ["Task_A", "Task_B"], refund: [] });
28
+ // The reporting engines, in the scope's (configuration) order; a silent one has no rows.
29
+ expect(request?.engines).toEqual(["prod-b", "prod-a"]);
30
+ });
31
+ it("the dashboard reads on its whole scope when the payload does not say which engines report", async () => {
32
+ const namesFor = lookup();
33
+ await namedDashboard({
34
+ processDefinitionKey: null,
35
+ engines: ["prod-a", "prod-b"],
36
+ definitionBreakdown: [],
37
+ activityBreakdown: [],
38
+ }, namesFor);
39
+ expect(namesFor.mock.calls[0][1]?.engines).toEqual(["prod-a", "prod-b"]);
40
+ });
41
+ it("names a process key such as constructor like any other", async () => {
42
+ const namesFor = lookup();
43
+ await namedDashboard({
44
+ processDefinitionKey: null,
45
+ engines: null,
46
+ definitionBreakdown: [{ processDefinitionKey: "constructor" }],
47
+ activityBreakdown: [{ processDefinitionKey: "constructor", activityId: "Task_A" }],
48
+ }, namesFor);
49
+ expect(namesFor.mock.calls[0][1]?.elementIds).toEqual({ constructor: ["Task_A"] });
50
+ expect(namesFor.mock.calls[0][1]?.engines).toBeNull();
51
+ });
52
+ // The lookup reads at most 40 models per view: a fleet with more
53
+ // definitions must not lose the names of its bottleneck activities to the
54
+ // long tail of the breakdown (sorted by starts).
55
+ it("keeps the activities' names when the fleet has more than 40 definitions", async () => {
56
+ const fetchBpmnXml = vi.fn((key) => Promise.resolve(`<process id="${key}" name="Process ${key}"><userTask id="Task_Slow" name="Review"/></process>`));
57
+ const definitions = Array.from({ length: 45 }, (_, i) => ({ processDefinitionKey: `p${i}` }));
58
+ const data = {
59
+ processDefinitionKey: null,
60
+ engines: ["prod-a"],
61
+ reportingEngines: ["prod-a"],
62
+ definitionBreakdown: definitions,
63
+ // A long-running, low-volume process: the last of the breakdown.
64
+ activityBreakdown: [{ processDefinitionKey: "p44", activityId: "Task_Slow" }],
65
+ };
66
+ const { names } = await namedDashboard(data, createNameLookup(fetchBpmnXml));
67
+ expect(elementNameOf(names, "p44", "Task_Slow")).toBe("Review");
68
+ expect(processNameOf(names, "p44")).toBe("Process p44");
69
+ expect(fetchBpmnXml).toHaveBeenCalledTimes(40);
70
+ // The cap falls on the end of the breakdown instead.
71
+ expect(processNameOf(names, "p0")).toBe("Process p0");
72
+ expect(processNameOf(names, "p40")).toBeNull();
73
+ });
74
+ it("the failure dashboard: process names only, its most affected first, on its engines", async () => {
75
+ const failures = lookup();
76
+ await namedFailureDashboard({
77
+ engines: ["prod-a", "prod-b"],
78
+ errorPatterns: [{ processDefinitionKey: "a" }],
79
+ processBreakdown: [{ processDefinitionKey: "b" }],
80
+ mostAffectedProcess: "b",
81
+ }, failures);
82
+ expect([...failures.mock.calls[0][0]]).toEqual(["b", "a", "b"]);
83
+ expect(failures.mock.calls[0][1]).toEqual({
84
+ elementIds: { a: [], b: [] },
85
+ engines: ["prod-a", "prod-b"],
86
+ });
87
+ const none = lookup();
88
+ await namedFailureDashboard({
89
+ engines: ["prod-a"],
90
+ errorPatterns: [],
91
+ processBreakdown: [],
92
+ mostAffectedProcess: null,
93
+ }, none);
94
+ expect([...none.mock.calls[0][0]]).toEqual([]);
95
+ });
96
+ it("the landscape: each process read on the engines it runs on", async () => {
97
+ const landscape = lookup();
98
+ await namedLandscape({
99
+ processes: [
100
+ { processDefinitionKey: "c", engineIds: ["prod-b", "prod-c"] },
101
+ { processDefinitionKey: "d", engineIds: ["prod-a"] },
102
+ ],
103
+ }, landscape);
104
+ expect(landscape.mock.calls[0][1]).toEqual({
105
+ elementIds: { c: [], d: [] },
106
+ enginesByKey: { c: ["prod-b", "prod-c"], d: ["prod-a"] },
107
+ });
108
+ });
109
+ });
110
+ //# sourceMappingURL=named-views.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"named-views.test.js","sourceRoot":"","sources":["../src/named-views.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { AppPlugin } from "@miragon/mcp-toolkit-core";
2
+ import type { MCPServer } from "mcp-use";
3
+ import { type PrometheusConfig } from "@miragon/pulse-analytics-client";
4
+ import { type FetchBpmnXml } from "./bpmn-name-lookup.js";
5
+ import type { ProfileSource } from "./server-locale.js";
6
+ /**
7
+ * `PrometheusConfig` carries the connection: the base URL (e.g.
8
+ * http://localhost:9090), optional bearer/basic auth + extra headers, and the
9
+ * per-query deadline (`timeoutMs`).
10
+ */
11
+ export interface AnalyticsPluginConfig extends PrometheusConfig {
12
+ /**
13
+ * Optional BPMN-XML lookup used by widget tools that enrich metric data with
14
+ * engine lookups — the BPMN heatmap's diagram, and the process and activity
15
+ * names the dashboards, the failure dashboard and the landscape show in
16
+ * place of ids. Injected by the host app (which owns the engine client) so
17
+ * this module stays free of engine SDKs. When absent, the heatmap degrades
18
+ * to a non-diagram fallback and the views show ids.
19
+ */
20
+ fetchBpmnXml?: FetchBpmnXml;
21
+ /**
22
+ * Profile store (shared with camunda7): locale for model-facing summaries,
23
+ * plus this module's own settings slice (`modules.analytics`) — read for
24
+ * period/minBucketSize defaults, written by `analytics_save_settings`.
25
+ */
26
+ profileStore?: ProfileSource;
27
+ /**
28
+ * The module's toolset (`analyticsModule` passes the one the composition
29
+ * root resolved). `"read-only"` — also what an ABSENT or unknown toolset
30
+ * resolves to (an unknown name warns) — registers no settings save tool;
31
+ * `"standard"` registers it, given a writable `profileStore`. Typed `string`
32
+ * like camunda7's, so callers can pass a configured value through; it is
33
+ * resolved fail-closed here.
34
+ */
35
+ toolset?: string;
36
+ /**
37
+ * The engine ids analytics may read — the server's configured engines.
38
+ * Empty or absent: every engine-reading tool refuses (fail-closed), see
39
+ * `engine-ids.ts`.
40
+ */
41
+ engineIds?: readonly string[];
42
+ }
43
+ export declare function createPlugin(config: AnalyticsPluginConfig): AppPlugin<MCPServer>;
44
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAExC,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAI/F,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAE3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAKvD;;;;GAIG;AACH,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;;;OAIG;IACH,YAAY,CAAC,EAAE,aAAa,CAAA;IAC5B;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,qBAAqB,GAAG,SAAS,CAAC,SAAS,CAAC,CAyChF"}
package/dist/plugin.js ADDED
@@ -0,0 +1,52 @@
1
+ import { installMcpRequestContext } from "@miragon/pulse-widget-shell/server";
2
+ import { createPrometheusClient } from "@miragon/pulse-analytics-client";
3
+ import { registerTools } from "./tools/index.js";
4
+ import { registerSettingsTools } from "./settings-tools.js";
5
+ import { registerWidgetTools } from "./widget-tools.js";
6
+ import { createNameLookup } from "./bpmn-name-lookup.js";
7
+ import { definition } from "./definition.js";
8
+ import { analyticsToolsets } from "./toolsets.js";
9
+ import { createEngineScope } from "./engine-ids.js";
10
+ export function createPlugin(config) {
11
+ const client = createPrometheusClient({
12
+ url: config.url,
13
+ bearerToken: config.bearerToken,
14
+ username: config.username,
15
+ password: config.password,
16
+ headers: config.headers,
17
+ timeoutMs: config.timeoutMs,
18
+ });
19
+ const engineScope = createEngineScope(config.engineIds);
20
+ // ONE name lookup (and its per-caller cache) for the tools, the feeds and the steps.
21
+ const namesFor = createNameLookup(config.fetchBpmnXml);
22
+ // The steps get the profile store too: a step's omitted period resolves to
23
+ // the caller's saved default, like every tool's.
24
+ const appConfig = {
25
+ client,
26
+ engineScope,
27
+ profileStore: config.profileStore,
28
+ namesFor,
29
+ };
30
+ return {
31
+ definition,
32
+ appConfig,
33
+ // Tools and feeds resolve the caller (saved defaults, summary locale) from
34
+ // the handler ctx. The pipeline steps get none, so their saved-period
35
+ // lookup reads the ambient request info — installed here like camunda7
36
+ // does (idempotent; the host installs it too).
37
+ registerTools: (server) => {
38
+ installMcpRequestContext(server);
39
+ registerTools(server, client, engineScope, config.profileStore);
40
+ },
41
+ registerWidgetTools: (server) => {
42
+ registerWidgetTools(server, client, {
43
+ fetchBpmnXml: config.fetchBpmnXml,
44
+ namesFor,
45
+ profileStore: config.profileStore,
46
+ engineScope,
47
+ });
48
+ registerSettingsTools(server, config.profileStore, analyticsToolsets.resolve(config.toolset));
49
+ },
50
+ };
51
+ }
52
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E,OAAO,EAAE,sBAAsB,EAAyB,MAAM,iCAAiC,CAAA;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAqB,MAAM,uBAAuB,CAAA;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAyCnD,MAAM,UAAU,YAAY,CAAC,MAA6B;IACxD,MAAM,MAAM,GAAG,sBAAsB,CAAC;QACpC,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAA;IACF,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACvD,qFAAqF;IACrF,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACtD,2EAA2E;IAC3E,iDAAiD;IACjD,MAAM,SAAS,GAAG;QAChB,MAAM;QACN,WAAW;QACX,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,QAAQ;KACoB,CAAA;IAC9B,OAAO;QACL,UAAU;QACV,SAAS;QACT,2EAA2E;QAC3E,sEAAsE;QACtE,uEAAuE;QACvE,+CAA+C;QAC/C,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE;YACxB,wBAAwB,CAAC,MAAM,CAAC,CAAA;YAChC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;QACjE,CAAC;QACD,mBAAmB,EAAE,CAAC,MAAM,EAAE,EAAE;YAC9B,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE;gBAClC,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,QAAQ;gBACR,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,WAAW;aACZ,CAAC,CAAA;YACF,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;QAC/F,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prometheus-wiring.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prometheus-wiring.test.d.ts","sourceRoot":"","sources":["../src/prometheus-wiring.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,142 @@
1
+ import http from "node:http";
2
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
+ import { analyticsModule } from "./module.js";
4
+ import { ANALYTICS_ENGINE_LANDSCAPE_DATA } from "./tool-names.js";
5
+ const seenAuth = [];
6
+ const seenTenant = [];
7
+ let hang = false;
8
+ const prometheus = http.createServer((req, res) => {
9
+ seenAuth.push(req.headers.authorization);
10
+ seenTenant.push(req.headers["x-scope-orgid"]);
11
+ if (hang)
12
+ return;
13
+ res.writeHead(200, { "Content-Type": "application/json" });
14
+ res.end(JSON.stringify({ status: "success", data: { resultType: "vector", result: [] } }));
15
+ });
16
+ let url = "";
17
+ beforeAll(async () => {
18
+ await new Promise((resolve) => prometheus.listen(0, "127.0.0.1", resolve));
19
+ url = `http://127.0.0.1:${prometheus.address().port}`;
20
+ });
21
+ afterAll(async () => {
22
+ prometheus.closeAllConnections();
23
+ await new Promise((resolve) => prometheus.close(() => resolve()));
24
+ });
25
+ /** A standalone analytics boot names the engines it may read (`engine-ids.ts`). */
26
+ const ENGINES = { ANALYTICS_ENGINE_IDS: "prod-a,prod-b" };
27
+ /** Boots the module from env the way the composition root does; returns its tools. */
28
+ function boot(env) {
29
+ const tools = new Map();
30
+ const server = {
31
+ tool: (definition, callback) => {
32
+ tools.set(definition.name, callback);
33
+ },
34
+ use: () => { },
35
+ };
36
+ const plugin = analyticsModule.createPlugin({
37
+ ...analyticsModule.configFromEnv({ PROMETHEUS_URL: url, ...ENGINES, ...env }),
38
+ toolset: "read-only",
39
+ }, {});
40
+ plugin.registerTools?.(server);
41
+ plugin.registerWidgetTools?.(server);
42
+ return tools;
43
+ }
44
+ describe("Prometheus config reaches the wire", () => {
45
+ it("PROMETHEUS_BEARER_TOKEN authenticates every query of a registrar tool", async () => {
46
+ hang = false;
47
+ seenAuth.length = 0;
48
+ const tools = boot({ PROMETHEUS_BEARER_TOKEN: "tok-123" });
49
+ const result = await tools.get("analytics_engine_landscape")({});
50
+ expect(result.isError).toBeFalsy();
51
+ expect(seenAuth.length).toBeGreaterThan(0);
52
+ expect(seenAuth.every((auth) => auth === "Bearer tok-123")).toBe(true);
53
+ });
54
+ it("PROMETHEUS_HEADERS and PROMETHEUS_USERNAME/PROMETHEUS_PASSWORD reach every query", async () => {
55
+ hang = false;
56
+ seenAuth.length = 0;
57
+ seenTenant.length = 0;
58
+ const tools = boot({
59
+ PROMETHEUS_HEADERS: '{"X-Scope-OrgID":"tenant-a"}',
60
+ PROMETHEUS_USERNAME: "grafana",
61
+ PROMETHEUS_PASSWORD: "hunter2-pass",
62
+ });
63
+ const result = await tools.get("analytics_engine_landscape")({});
64
+ expect(result.isError).toBeFalsy();
65
+ expect(seenTenant.length).toBeGreaterThan(0);
66
+ expect(seenTenant.every((tenant) => tenant === "tenant-a")).toBe(true);
67
+ const basic = `Basic ${Buffer.from("grafana:hunter2-pass").toString("base64")}`;
68
+ expect(seenAuth.every((auth) => auth === basic)).toBe(true);
69
+ });
70
+ it("PROMETHEUS_TIMEOUT_MS bounds a hung Prometheus", async () => {
71
+ hang = true;
72
+ const tools = boot({ PROMETHEUS_TIMEOUT_MS: "60" });
73
+ const result = await tools.get("analytics_engine_landscape")({});
74
+ expect(result.isError).toBe(true);
75
+ expect(result.content[0].text).toBe("Prometheus did not respond within 60 ms (timeout)");
76
+ });
77
+ it("EVERY widget tool and feed hands ctx.signal to its queries", async () => {
78
+ hang = false;
79
+ const tools = new Map();
80
+ const server = {
81
+ tool: (definition, callback) => {
82
+ tools.set(definition.name, callback);
83
+ },
84
+ };
85
+ analyticsModule
86
+ .createPlugin({
87
+ ...analyticsModule.configFromEnv({ PROMETHEUS_URL: url, ...ENGINES }),
88
+ toolset: "read-only",
89
+ }, {})
90
+ .registerWidgetTools?.(server);
91
+ // Each handler runs twice with args every tool accepts: unsignalled it
92
+ // must reach Prometheus, with an already-aborted ctx.signal it must not —
93
+ // a handler that drops ctx would still query. Tools that never query are
94
+ // named.
95
+ const args = {
96
+ processDefinitionKey: "order",
97
+ // Handlers called directly get no schema defaults: the compare windows.
98
+ windowDays: 7,
99
+ windowBeforeDays: 3,
100
+ windowAfterDays: 3,
101
+ // Relative to now: compare windows are held inside the retention.
102
+ deploymentTimestamp: new Date(Date.now() - 3 * 86_400_000).toISOString(),
103
+ engineA: "prod-a",
104
+ engineB: "prod-b",
105
+ };
106
+ const queriesOf = async (name, ctx) => {
107
+ const before = seenAuth.length;
108
+ await tools.get(name)(args, ctx);
109
+ return seenAuth.length - before;
110
+ };
111
+ const neverQuery = [];
112
+ for (const name of tools.keys()) {
113
+ if ((await queriesOf(name, {})) === 0) {
114
+ neverQuery.push(name);
115
+ continue;
116
+ }
117
+ expect({ name, queries: await queriesOf(name, { signal: AbortSignal.abort() }) }).toEqual({
118
+ name,
119
+ queries: 0,
120
+ });
121
+ }
122
+ // The settings and the heatmap's diagram (read from the engine) never ask Prometheus.
123
+ expect(neverQuery.sort()).toEqual([
124
+ "analytics_bpmn_xml_data",
125
+ "analytics_settings_data",
126
+ "analytics_show_settings",
127
+ ]);
128
+ expect(tools.size - neverQuery.length).toBeGreaterThanOrEqual(11);
129
+ });
130
+ it("a widget feed's ctx.signal cancels its queries before the deadline", async () => {
131
+ hang = true;
132
+ const tools = boot({ PROMETHEUS_TIMEOUT_MS: "10000" });
133
+ const controller = new AbortController();
134
+ setTimeout(() => controller.abort(), 30);
135
+ const started = Date.now();
136
+ const result = await tools.get(ANALYTICS_ENGINE_LANDSCAPE_DATA)({}, { signal: controller.signal });
137
+ expect(Date.now() - started).toBeLessThan(5_000);
138
+ expect(result.isError).toBe(true);
139
+ expect(result.content[0].text).toBe("Prometheus query cancelled by the caller");
140
+ });
141
+ });
142
+ //# sourceMappingURL=prometheus-wiring.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prometheus-wiring.test.js","sourceRoot":"","sources":["../src/prometheus-wiring.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { resolveAuthUserId, resolveProfileKey } from "@miragon/pulse-widget-shell/server";
2
+ /**
3
+ * The profile port + key resolution come from the shared server kit, NOT from a
4
+ * module-local copy: every module reads and writes the same profile record, so
5
+ * a divergent key precedence (or a differently-spelled anonymous fallback)
6
+ * would silently split a user's settings across two records. Re-exported under
7
+ * this module's names so the call sites read in analytics vocabulary.
8
+ *
9
+ * `ProfileSource` is the minimal read/write view a module needs — the locale
10
+ * plus its own slice under `modules.analytics`. camunda7's `ProfileStore`
11
+ * satisfies it structurally, without analytics depending on the camunda7
12
+ * module; `save` merges per module key on the store side, so writing
13
+ * `modules.analytics` never touches other modules' slices.
14
+ */
15
+ export type { ProfileSlice, ProfileSource } from "@miragon/pulse-widget-shell/server";
16
+ /**
17
+ * Resolve the profile key for the in-flight request: the OAuth caller (off the
18
+ * tool-handler `ctx`), else `anonymous` for an explicitly declared local
19
+ * caller (stdio, tests). A request without OAuth resolves `undefined` — reads
20
+ * fall back to defaults, saves fail visibly, so unrelated callers never
21
+ * cross-share one record.
22
+ */
23
+ export declare const resolveSettingsKey: typeof resolveProfileKey;
24
+ /**
25
+ * Just the OAuth half of {@link resolveSettingsKey} — the save path stamps it
26
+ * onto the record as its owner (`opts.userId`).
27
+ */
28
+ export declare const resolveSettingsAuthUserId: typeof resolveAuthUserId;
29
+ /** A locale-bound translate for summaries; a show tool's summary translate + view title. */
30
+ export type { ServerT, ViewLocale } from "@miragon/pulse-widget-shell/server";
31
+ /**
32
+ * Resolve the request locale and return a translate bound to it + the analytics
33
+ * catalogs — `const t = await localizeFor(store, ctx); … summary: t("key", { … })`.
34
+ * Pass the tool-handler `ctx` so an auth user id resolves the same record the
35
+ * save path writes. Locale resolution + the fail-soft rules (no store, no key,
36
+ * store OUTAGE → English) come from the shared `createLocalizeFor`.
37
+ */
38
+ export declare const localizeFor: (store?: import("@miragon/pulse-widget-shell/server").ProfileSource, ctx?: unknown) => Promise<import("@miragon/pulse-widget-shell/server").ServerT>;
39
+ /**
40
+ * {@link localizeFor} plus the view title, from ONE profile read — the kit's
41
+ * one title rule for every module's show tools: a view is titled only in a
42
+ * language the profile names; with "system" (the default), no caller or a
43
+ * store outage it carries no title, and the widget's own heading names it in
44
+ * the host's language (#322 U3). Summaries stay `t`:
45
+ * `const { t, title } = await localizeViewFor(store, ctx); … title: title("key")`.
46
+ */
47
+ export declare const localizeViewFor: (store?: import("@miragon/pulse-widget-shell/server").ProfileSource, ctx?: unknown) => Promise<import("@miragon/pulse-widget-shell/server").ViewLocale>;
48
+ //# sourceMappingURL=server-locale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-locale.d.ts","sourceRoot":"","sources":["../src/server-locale.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,oCAAoC,CAAA;AAG3C;;;;;;;;;;;;GAYG;AACH,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAA;AAErF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,0BAAoB,CAAA;AAEnD;;;GAGG;AACH,eAAO,MAAM,yBAAyB,0BAAoB,CAAA;AAE1D,4FAA4F;AAC5F,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAE7E;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,sJAAgC,CAAA;AAExD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,yJAAoC,CAAA"}
@@ -0,0 +1,33 @@
1
+ import { createLocalizeFor, createLocalizeViewFor, resolveAuthUserId, resolveProfileKey, } from "@miragon/pulse-widget-shell/server";
2
+ import { translator } from "./messages/index.js";
3
+ /**
4
+ * Resolve the profile key for the in-flight request: the OAuth caller (off the
5
+ * tool-handler `ctx`), else `anonymous` for an explicitly declared local
6
+ * caller (stdio, tests). A request without OAuth resolves `undefined` — reads
7
+ * fall back to defaults, saves fail visibly, so unrelated callers never
8
+ * cross-share one record.
9
+ */
10
+ export const resolveSettingsKey = resolveProfileKey;
11
+ /**
12
+ * Just the OAuth half of {@link resolveSettingsKey} — the save path stamps it
13
+ * onto the record as its owner (`opts.userId`).
14
+ */
15
+ export const resolveSettingsAuthUserId = resolveAuthUserId;
16
+ /**
17
+ * Resolve the request locale and return a translate bound to it + the analytics
18
+ * catalogs — `const t = await localizeFor(store, ctx); … summary: t("key", { … })`.
19
+ * Pass the tool-handler `ctx` so an auth user id resolves the same record the
20
+ * save path writes. Locale resolution + the fail-soft rules (no store, no key,
21
+ * store OUTAGE → English) come from the shared `createLocalizeFor`.
22
+ */
23
+ export const localizeFor = createLocalizeFor(translator);
24
+ /**
25
+ * {@link localizeFor} plus the view title, from ONE profile read — the kit's
26
+ * one title rule for every module's show tools: a view is titled only in a
27
+ * language the profile names; with "system" (the default), no caller or a
28
+ * store outage it carries no title, and the widget's own heading names it in
29
+ * the host's language (#322 U3). Summaries stay `t`:
30
+ * `const { t, title } = await localizeViewFor(store, ctx); … title: title("key")`.
31
+ */
32
+ export const localizeViewFor = createLocalizeViewFor(translator);
33
+ //# sourceMappingURL=server-locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-locale.js","sourceRoot":"","sources":["../src/server-locale.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAiBhD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,iBAAiB,CAAA;AAEnD;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAA;AAK1D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAA;AAExD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAA"}
@@ -0,0 +1,23 @@
1
+ import type { MCPServer } from "mcp-use";
2
+ import { type ProfileSource } from "./server-locale.js";
3
+ import { type AnalyticsSettings } from "./settings.js";
4
+ import { type AnalyticsToolset } from "./toolsets.js";
5
+ /**
6
+ * The analytics module's settings section — its own show/data/save tool triple
7
+ * (the three render paths), so the module plugs into the settings page without
8
+ * camunda7 owning any analytics vocabulary. The slice persists under
9
+ * `modules.analytics` in the shared profile record; the shared store merges
10
+ * per module key, so this never touches other modules' slices.
11
+ */
12
+ /** What the settings widget renders: the effective slice + whether saving is wired. */
13
+ export interface AnalyticsSettingsView {
14
+ settings: AnalyticsSettings;
15
+ /**
16
+ * False without a writable store, in the `read-only` toolset (also what a
17
+ * missing toolset resolves to), or when the request carries no caller
18
+ * identity (no OAuth — see `resolveProfileKey`) — the widget hides Save.
19
+ */
20
+ canSave: boolean;
21
+ }
22
+ export declare function registerSettingsTools(server: MCPServer, profileStore?: ProfileSource, toolset?: AnalyticsToolset): void;
23
+ //# sourceMappingURL=settings-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-tools.d.ts","sourceRoot":"","sources":["../src/settings-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAYxC,OAAO,EAKL,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAKL,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAE1E;;;;;;GAMG;AAEH,uFAAuF;AACvF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,YAAY,CAAC,EAAE,aAAa,EAC5B,OAAO,CAAC,EAAE,gBAAgB,GACzB,IAAI,CAqHN"}
@@ -0,0 +1,100 @@
1
+ import { appOnly, buildDataFeedResult, buildSingleWidgetView, requireProfileKey, saveModuleSlice, showToolBinding, withToolErrors, strictToolInput, } from "@miragon/pulse-widget-shell/server";
2
+ import { ANALYTICS_SAVE_SETTINGS, ANALYTICS_SETTINGS_DATA } from "./tool-names.js";
3
+ import { localizeFor, localizeViewFor, resolveSettingsAuthUserId, resolveSettingsKey, } from "./server-locale.js";
4
+ import { ANALYTICS_MODULE_KEY, analyticsSettingsSaveInput, parseAnalyticsSettings, settingsFor, } from "./settings.js";
5
+ import { allowsDurableWrites } from "./toolsets.js";
6
+ export function registerSettingsTools(server, profileStore, toolset) {
7
+ // The save tool is a durable write registered OUTSIDE the tool registrar, so
8
+ // it gates itself against the module's toolset (see `allowsDurableWrites`):
9
+ // only `standard` saves. A missing toolset resolves to the `read-only`
10
+ // floor, and an unknown name from an untyped caller warns and degrades to it.
11
+ const store = profileStore;
12
+ const save = allowsDurableWrites(toolset) ? store?.save?.bind(store) : undefined;
13
+ const loadView = async (ctx) => ({
14
+ settings: await settingsFor(store, ctx),
15
+ // Store/toolset gate AND per-request identity: without a profile key the
16
+ // save tool refuses, so the section must render read-only instead of a
17
+ // Save button whose click errors.
18
+ canSave: Boolean(save) && resolveSettingsKey(ctx) !== undefined,
19
+ });
20
+ const summarize = (t, view) => t("aSum.settings", {
21
+ period: view.settings.defaultPeriod,
22
+ minBucketSize: view.settings.minBucketSize,
23
+ changeHint: view.canSave ? t("aSum.settingsChangeHint") : "",
24
+ });
25
+ server.tool({
26
+ name: "analytics_show_settings",
27
+ title: "Analytics Settings",
28
+ description: "Open the analytics settings section: the default look-back period and the minimum comparison bucket size applied when analytics calls omit them.",
29
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
30
+ inputSchema: strictToolInput({}),
31
+ ...showToolBinding("analytics_show_settings", "Analytics Settings"),
32
+ }, withToolErrors(async (_params, ctx) => {
33
+ const view = await loadView(ctx);
34
+ const { t, title } = await localizeViewFor(store, ctx);
35
+ return buildSingleWidgetView({
36
+ widget: "analytics:settings",
37
+ app: "analytics",
38
+ dataType: "analytics:settings",
39
+ data: { ...view },
40
+ // The view title in the language the profile names (the section
41
+ // heading's own key); none with "system", where the heading names it.
42
+ title: title("aSettings.heading"),
43
+ summary: summarize(t, view),
44
+ });
45
+ }));
46
+ server.tool({
47
+ name: ANALYTICS_SETTINGS_DATA,
48
+ title: "Analytics settings data (internal)",
49
+ description: "Internal JSON feed (no UI) for the analytics settings section's self-fetch. Prefer analytics_show_settings.",
50
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
51
+ inputSchema: strictToolInput({}),
52
+ ...appOnly,
53
+ }, withToolErrors(async (_params, ctx) => buildDataFeedResult({ ...(await loadView(ctx)) })));
54
+ // Without a writable store (or on the `read-only` floor) there is nothing to
55
+ // save into — the section stays read-only (canSave: false) and the tool
56
+ // surface honestly reflects that.
57
+ if (!save || !store)
58
+ return;
59
+ server.tool({
60
+ name: ANALYTICS_SAVE_SETTINGS,
61
+ title: "Save analytics settings",
62
+ description: "Update the caller's analytics defaults. Only the provided fields change; omitted fields keep their value. The saved defaults apply whenever an analytics call omits `period` or `minBucketSize`.",
63
+ // The module's only non-read-only tool, and explicitly NOT destructive
64
+ // (MCP presumes a write destructive unless told otherwise): it merges
65
+ // the caller's own slice, nothing is deleted or overwritten wholesale.
66
+ annotations: {
67
+ readOnlyHint: false,
68
+ destructiveHint: false,
69
+ idempotentHint: true,
70
+ openWorldHint: false,
71
+ },
72
+ inputSchema: strictToolInput(analyticsSettingsSaveInput.shape),
73
+ // No view binding / app visibility: a normal model-visible tool; the
74
+ // settings widget also calls it and reads the saved slice back from
75
+ // structuredContent.
76
+ }, withToolErrors(async (params, ctx) => {
77
+ // Keyless refusal + a patch-only slice save are the shared slice-write
78
+ // contract (`@miragon/pulse-widget-shell/server`) — every module's save
79
+ // tool uses the same pair. The store merges the patch under its per-key
80
+ // lock, so a concurrent save of the other field is never reverted.
81
+ const key = requireProfileKey(ctx);
82
+ // The OAuth caller is stamped as the record's owner.
83
+ const savedSlice = await saveModuleSlice({ get: (k) => store.get(k), save }, key, ANALYTICS_MODULE_KEY, params, { userId: resolveSettingsAuthUserId(ctx) });
84
+ const effective = parseAnalyticsSettings({ [ANALYTICS_MODULE_KEY]: savedSlice });
85
+ const t = await localizeFor(store, ctx);
86
+ return {
87
+ content: [
88
+ {
89
+ type: "text",
90
+ text: t("aSum.settingsSaved", {
91
+ period: effective.defaultPeriod,
92
+ minBucketSize: effective.minBucketSize,
93
+ }),
94
+ },
95
+ ],
96
+ structuredContent: effective,
97
+ };
98
+ }));
99
+ }
100
+ //# sourceMappingURL=settings-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-tools.js","sourceRoot":"","sources":["../src/settings-tools.ts"],"names":[],"mappings":"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"}