@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.
- package/LICENSE +21 -0
- package/README.md +86 -3
- package/dist/bpmn-name-lookup.d.ts +72 -0
- package/dist/bpmn-name-lookup.d.ts.map +1 -0
- package/dist/bpmn-name-lookup.js +123 -0
- package/dist/bpmn-name-lookup.js.map +1 -0
- package/dist/bpmn-name-lookup.test.d.ts +2 -0
- package/dist/bpmn-name-lookup.test.d.ts.map +1 -0
- package/dist/bpmn-name-lookup.test.js +287 -0
- package/dist/bpmn-name-lookup.test.js.map +1 -0
- package/dist/bpmn-names.d.ts +38 -0
- package/dist/bpmn-names.d.ts.map +1 -0
- package/dist/bpmn-names.js +22 -0
- package/dist/bpmn-names.js.map +1 -0
- package/dist/brand-gates.test.d.ts +2 -0
- package/dist/brand-gates.test.d.ts.map +1 -0
- package/dist/brand-gates.test.js +58 -0
- package/dist/brand-gates.test.js.map +1 -0
- package/dist/builder-texts.d.ts +4 -0
- package/dist/builder-texts.d.ts.map +1 -0
- package/dist/builder-texts.js +14 -0
- package/dist/builder-texts.js.map +1 -0
- package/dist/builder-texts.test.d.ts +2 -0
- package/dist/builder-texts.test.d.ts.map +1 -0
- package/dist/builder-texts.test.js +32 -0
- package/dist/builder-texts.test.js.map +1 -0
- package/dist/definition.d.ts +3 -0
- package/dist/definition.d.ts.map +1 -0
- package/dist/definition.js +151 -0
- package/dist/definition.js.map +1 -0
- package/dist/engine-ids.d.ts +42 -0
- package/dist/engine-ids.d.ts.map +1 -0
- package/dist/engine-ids.js +50 -0
- package/dist/engine-ids.js.map +1 -0
- package/dist/engine-scope.test.d.ts +2 -0
- package/dist/engine-scope.test.d.ts.map +1 -0
- package/dist/engine-scope.test.js +260 -0
- package/dist/engine-scope.test.js.map +1 -0
- package/dist/heatmap-data.d.ts +15 -0
- package/dist/heatmap-data.d.ts.map +1 -0
- package/dist/heatmap-data.js +2 -0
- package/dist/heatmap-data.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +8 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +33 -0
- package/dist/instructions.js.map +1 -0
- package/dist/messages/de.ask-ai.d.ts +9 -0
- package/dist/messages/de.ask-ai.d.ts.map +1 -0
- package/dist/messages/de.ask-ai.js +18 -0
- package/dist/messages/de.ask-ai.js.map +1 -0
- package/dist/messages/de.builder.d.ts +12 -0
- package/dist/messages/de.builder.d.ts.map +1 -0
- package/dist/messages/de.builder.js +53 -0
- package/dist/messages/de.builder.js.map +1 -0
- package/dist/messages/de.server.d.ts +8 -0
- package/dist/messages/de.server.d.ts.map +1 -0
- package/dist/messages/de.server.js +26 -0
- package/dist/messages/de.server.js.map +1 -0
- package/dist/messages/de.sweep.d.ts +10 -0
- package/dist/messages/de.sweep.d.ts.map +1 -0
- package/dist/messages/de.sweep.js +203 -0
- package/dist/messages/de.sweep.js.map +1 -0
- package/dist/messages/en.ask-ai.d.ts +25 -0
- package/dist/messages/en.ask-ai.d.ts.map +1 -0
- package/dist/messages/en.ask-ai.js +24 -0
- package/dist/messages/en.ask-ai.js.map +1 -0
- package/dist/messages/en.builder.d.ts +12 -0
- package/dist/messages/en.builder.d.ts.map +1 -0
- package/dist/messages/en.builder.js +53 -0
- package/dist/messages/en.builder.js.map +1 -0
- package/dist/messages/en.server.d.ts +8 -0
- package/dist/messages/en.server.d.ts.map +1 -0
- package/dist/messages/en.server.js +26 -0
- package/dist/messages/en.server.js.map +1 -0
- package/dist/messages/en.sweep.d.ts +11 -0
- package/dist/messages/en.sweep.d.ts.map +1 -0
- package/dist/messages/en.sweep.js +204 -0
- package/dist/messages/en.sweep.js.map +1 -0
- package/dist/messages/glossary.d.ts +26 -0
- package/dist/messages/glossary.d.ts.map +1 -0
- package/dist/messages/glossary.js +37 -0
- package/dist/messages/glossary.js.map +1 -0
- package/dist/messages/glossary.test.d.ts +2 -0
- package/dist/messages/glossary.test.d.ts.map +1 -0
- package/dist/messages/glossary.test.js +109 -0
- package/dist/messages/glossary.test.js.map +1 -0
- package/dist/messages/index.d.ts +12 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +23 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/plural.d.ts +10 -0
- package/dist/messages/plural.d.ts.map +1 -0
- package/dist/messages/plural.js +17 -0
- package/dist/messages/plural.js.map +1 -0
- package/dist/messages/use-t.d.ts +10 -0
- package/dist/messages/use-t.d.ts.map +1 -0
- package/dist/messages/use-t.js +10 -0
- package/dist/messages/use-t.js.map +1 -0
- package/dist/module.d.ts +48 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +174 -0
- package/dist/module.js.map +1 -0
- package/dist/module.test.d.ts +2 -0
- package/dist/module.test.d.ts.map +1 -0
- package/dist/module.test.js +230 -0
- package/dist/module.test.js.map +1 -0
- package/dist/named-views.d.ts +27 -0
- package/dist/named-views.d.ts.map +1 -0
- package/dist/named-views.js +73 -0
- package/dist/named-views.js.map +1 -0
- package/dist/named-views.test.d.ts +2 -0
- package/dist/named-views.test.d.ts.map +1 -0
- package/dist/named-views.test.js +110 -0
- package/dist/named-views.test.js.map +1 -0
- package/dist/plugin.d.ts +44 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +52 -0
- package/dist/plugin.js.map +1 -0
- package/dist/prometheus-wiring.test.d.ts +2 -0
- package/dist/prometheus-wiring.test.d.ts.map +1 -0
- package/dist/prometheus-wiring.test.js +142 -0
- package/dist/prometheus-wiring.test.js.map +1 -0
- package/dist/server-locale.d.ts +48 -0
- package/dist/server-locale.d.ts.map +1 -0
- package/dist/server-locale.js +33 -0
- package/dist/server-locale.js.map +1 -0
- package/dist/settings-tools.d.ts +23 -0
- package/dist/settings-tools.d.ts.map +1 -0
- package/dist/settings-tools.js +100 -0
- package/dist/settings-tools.js.map +1 -0
- package/dist/settings.d.ts +77 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +99 -0
- package/dist/settings.js.map +1 -0
- package/dist/settings.test.d.ts +2 -0
- package/dist/settings.test.d.ts.map +1 -0
- package/dist/settings.test.js +299 -0
- package/dist/settings.test.js.map +1 -0
- package/dist/steps/app-config.d.ts +30 -0
- package/dist/steps/app-config.d.ts.map +1 -0
- package/dist/steps/app-config.js +46 -0
- package/dist/steps/app-config.js.map +1 -0
- package/dist/steps/dashboard.d.ts +12 -0
- package/dist/steps/dashboard.d.ts.map +1 -0
- package/dist/steps/dashboard.js +58 -0
- package/dist/steps/dashboard.js.map +1 -0
- package/dist/steps/failure-dashboard.d.ts +10 -0
- package/dist/steps/failure-dashboard.d.ts.map +1 -0
- package/dist/steps/failure-dashboard.js +32 -0
- package/dist/steps/failure-dashboard.js.map +1 -0
- package/dist/steps/index.d.ts +3 -0
- package/dist/steps/index.d.ts.map +1 -0
- package/dist/steps/index.js +3 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/steps/steps.test.d.ts +2 -0
- package/dist/steps/steps.test.d.ts.map +1 -0
- package/dist/steps/steps.test.js +153 -0
- package/dist/steps/steps.test.js.map +1 -0
- package/dist/tool-names.d.ts +13 -0
- package/dist/tool-names.d.ts.map +1 -0
- package/dist/tool-names.js +27 -0
- package/dist/tool-names.js.map +1 -0
- package/dist/tools/cluster-compare.d.ts +8 -0
- package/dist/tools/cluster-compare.d.ts.map +1 -0
- package/dist/tools/cluster-compare.js +17 -0
- package/dist/tools/cluster-compare.js.map +1 -0
- package/dist/tools/element.d.ts +8 -0
- package/dist/tools/element.d.ts.map +1 -0
- package/dist/tools/element.js +25 -0
- package/dist/tools/element.js.map +1 -0
- package/dist/tools/engine-compare.d.ts +8 -0
- package/dist/tools/engine-compare.d.ts.map +1 -0
- package/dist/tools/engine-compare.js +18 -0
- package/dist/tools/engine-compare.js.map +1 -0
- package/dist/tools/engine-compare.test.d.ts +2 -0
- package/dist/tools/engine-compare.test.d.ts.map +1 -0
- package/dist/tools/engine-compare.test.js +166 -0
- package/dist/tools/engine-compare.test.js.map +1 -0
- package/dist/tools/engine-landscape.d.ts +7 -0
- package/dist/tools/engine-landscape.d.ts.map +1 -0
- package/dist/tools/engine-landscape.js +13 -0
- package/dist/tools/engine-landscape.js.map +1 -0
- package/dist/tools/engine-landscape.test.d.ts +2 -0
- package/dist/tools/engine-landscape.test.d.ts.map +1 -0
- package/dist/tools/engine-landscape.test.js +110 -0
- package/dist/tools/engine-landscape.test.js.map +1 -0
- package/dist/tools/failures.d.ts +7 -0
- package/dist/tools/failures.d.ts.map +1 -0
- package/dist/tools/failures.js +13 -0
- package/dist/tools/failures.js.map +1 -0
- package/dist/tools/health.d.ts +7 -0
- package/dist/tools/health.d.ts.map +1 -0
- package/dist/tools/health.js +23 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/health.test.d.ts +2 -0
- package/dist/tools/health.test.d.ts.map +1 -0
- package/dist/tools/health.test.js +119 -0
- package/dist/tools/health.test.js.map +1 -0
- package/dist/tools/index.d.ts +18 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +35 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/performance.d.ts +8 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js +25 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/tools/performance.test.d.ts +2 -0
- package/dist/tools/performance.test.d.ts.map +1 -0
- package/dist/tools/performance.test.js +176 -0
- package/dist/tools/performance.test.js.map +1 -0
- package/dist/tools/version-compare.d.ts +8 -0
- package/dist/tools/version-compare.d.ts.map +1 -0
- package/dist/tools/version-compare.js +17 -0
- package/dist/tools/version-compare.js.map +1 -0
- package/dist/tools/version-compare.test.d.ts +2 -0
- package/dist/tools/version-compare.test.d.ts.map +1 -0
- package/dist/tools/version-compare.test.js +82 -0
- package/dist/tools/version-compare.test.js.map +1 -0
- package/dist/toolsets.d.ts +17 -0
- package/dist/toolsets.d.ts.map +1 -0
- package/dist/toolsets.js +47 -0
- package/dist/toolsets.js.map +1 -0
- package/dist/toolsets.test.d.ts +2 -0
- package/dist/toolsets.test.d.ts.map +1 -0
- package/dist/toolsets.test.js +91 -0
- package/dist/toolsets.test.js.map +1 -0
- package/dist/view-title.test.d.ts +2 -0
- package/dist/view-title.test.d.ts.map +1 -0
- package/dist/view-title.test.js +91 -0
- package/dist/view-title.test.js.map +1 -0
- package/dist/widget-tools/comparisons.d.ts +13 -0
- package/dist/widget-tools/comparisons.d.ts.map +1 -0
- package/dist/widget-tools/comparisons.js +177 -0
- package/dist/widget-tools/comparisons.js.map +1 -0
- package/dist/widget-tools/comparisons.test.d.ts +2 -0
- package/dist/widget-tools/comparisons.test.d.ts.map +1 -0
- package/dist/widget-tools/comparisons.test.js +123 -0
- package/dist/widget-tools/comparisons.test.js.map +1 -0
- package/dist/widget-tools/shared.d.ts +36 -0
- package/dist/widget-tools/shared.d.ts.map +1 -0
- package/dist/widget-tools/shared.js +39 -0
- package/dist/widget-tools/shared.js.map +1 -0
- package/dist/widget-tools.d.ts +25 -0
- package/dist/widget-tools.d.ts.map +1 -0
- package/dist/widget-tools.js +269 -0
- package/dist/widget-tools.js.map +1 -0
- package/dist/widget-tools.test.d.ts +2 -0
- package/dist/widget-tools.test.d.ts.map +1 -0
- package/dist/widget-tools.test.js +272 -0
- package/dist/widget-tools.test.js.map +1 -0
- package/package.json +91 -5
- package/src/bpmn-name-lookup.test.ts +333 -0
- package/src/bpmn-name-lookup.ts +197 -0
- package/src/bpmn-names.ts +51 -0
- package/src/brand-gates.test.ts +69 -0
- package/src/builder-texts.test.ts +40 -0
- package/src/builder-texts.ts +15 -0
- package/src/definition.ts +181 -0
- package/src/engine-ids.ts +85 -0
- package/src/engine-scope.test.ts +324 -0
- package/src/heatmap-data.ts +14 -0
- package/src/index.ts +4 -0
- package/src/instructions.ts +33 -0
- package/src/messages/GLOSSARY.md +88 -0
- package/src/messages/de.ask-ai.ts +28 -0
- package/src/messages/de.builder.ts +77 -0
- package/src/messages/de.server.ts +39 -0
- package/src/messages/de.sweep.ts +244 -0
- package/src/messages/en.ask-ai.ts +34 -0
- package/src/messages/en.builder.ts +76 -0
- package/src/messages/en.server.ts +39 -0
- package/src/messages/en.sweep.ts +240 -0
- package/src/messages/glossary.test.ts +122 -0
- package/src/messages/glossary.ts +62 -0
- package/src/messages/index.ts +24 -0
- package/src/messages/plural.ts +18 -0
- package/src/messages/use-t.ts +12 -0
- package/src/module.test.ts +319 -0
- package/src/module.ts +211 -0
- package/src/named-views.test.ts +141 -0
- package/src/named-views.ts +97 -0
- package/src/plugin.ts +94 -0
- package/src/prometheus-wiring.test.ts +174 -0
- package/src/server-locale.ts +59 -0
- package/src/settings-tools.ts +170 -0
- package/src/settings.test.ts +402 -0
- package/src/settings.ts +114 -0
- package/src/steps/app-config.ts +75 -0
- package/src/steps/dashboard.ts +73 -0
- package/src/steps/failure-dashboard.ts +38 -0
- package/src/steps/index.ts +2 -0
- package/src/steps/steps.test.ts +216 -0
- package/src/tool-names.ts +26 -0
- package/src/tools/cluster-compare.ts +28 -0
- package/src/tools/element.ts +35 -0
- package/src/tools/engine-compare.test.ts +210 -0
- package/src/tools/engine-compare.ts +30 -0
- package/src/tools/engine-landscape.test.ts +138 -0
- package/src/tools/engine-landscape.ts +21 -0
- package/src/tools/failures.ts +19 -0
- package/src/tools/health.test.ts +156 -0
- package/src/tools/health.ts +29 -0
- package/src/tools/index.ts +44 -0
- package/src/tools/performance.test.ts +210 -0
- package/src/tools/performance.ts +38 -0
- package/src/tools/version-compare.test.ts +97 -0
- package/src/tools/version-compare.ts +28 -0
- package/src/toolsets.test.ts +107 -0
- package/src/toolsets.ts +56 -0
- package/src/view-title.test.ts +123 -0
- package/src/widget-tools/comparisons.test.ts +170 -0
- package/src/widget-tools/comparisons.ts +229 -0
- package/src/widget-tools/shared.ts +67 -0
- package/src/widget-tools.test.ts +306 -0
- package/src/widget-tools.ts +375 -0
- package/src/widgets/analytics-dashboard/activity-bottleneck-table.tsx +179 -0
- package/src/widgets/analytics-dashboard/definition-breakdown.tsx +108 -0
- package/src/widgets/analytics-dashboard/execution-performance-kpi.tsx +94 -0
- package/src/widgets/analytics-dashboard/execution-summary-kpi.tsx +122 -0
- package/src/widgets/analytics-dashboard/lib.ts +43 -0
- package/src/widgets/bpmn-heatmap.test.tsx +75 -0
- package/src/widgets/bpmn-heatmap.tsx +127 -0
- package/src/widgets/catalogue-sync.test.ts +16 -0
- package/src/widgets/cluster-compare.tsx +148 -0
- package/src/widgets/comparison-shared.test.ts +237 -0
- package/src/widgets/comparison-shared.tsx +371 -0
- package/src/widgets/comparison-widgets.test.tsx +307 -0
- package/src/widgets/dashboard-widgets.test.tsx +397 -0
- package/src/widgets/engine-compare.tsx +87 -0
- package/src/widgets/engine-landscape.tsx +352 -0
- package/src/widgets/failure-dashboard/error-patterns-table.tsx +122 -0
- package/src/widgets/failure-dashboard/failure-rate-table.test.ts +80 -0
- package/src/widgets/failure-dashboard/failure-rate-table.tsx +170 -0
- package/src/widgets/failure-dashboard/lib.ts +32 -0
- package/src/widgets/failure-dashboard/summary-kpi.tsx +122 -0
- package/src/widgets/failure-landscape-widgets.test.tsx +393 -0
- package/src/widgets/figure.tsx +79 -0
- package/src/widgets/hand-off.test.ts +126 -0
- package/src/widgets/hand-off.ts +102 -0
- package/src/widgets/index.ts +124 -0
- package/src/widgets/model-descriptions.dashboard.test.ts +280 -0
- package/src/widgets/model-descriptions.test.ts +251 -0
- package/src/widgets/model-descriptions.ts +428 -0
- package/src/widgets/names.test.ts +32 -0
- package/src/widgets/names.ts +39 -0
- package/src/widgets/query-gate.test.tsx +57 -0
- package/src/widgets/query-gate.tsx +50 -0
- package/src/widgets/settings-section.test.tsx +174 -0
- package/src/widgets/settings-section.tsx +244 -0
- package/src/widgets/version-compare.test.ts +68 -0
- package/src/widgets/version-compare.tsx +96 -0
- package/src/widgets/view-meta.ts +18 -0
- 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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"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -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 @@
|
|
|
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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"}
|