@checkstack/integration-frontend 0.4.4 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,223 @@
1
1
  # @checkstack/integration-frontend
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e2d6f25: feat(automation): connection picker for integration actions + restore Integrations menu
8
+
9
+ Connection-backed automation actions (Jira, Teams, Webex) now render a
10
+ working connection picker plus cascading provider dropdowns in the
11
+ visual editor, and the Integrations entry is back in the user menu.
12
+
13
+ **Contract.** `ActionDefinition` gained an optional
14
+ `connectionProviderId` (and it is surfaced on `ActionInfoSchema` and
15
+ mapped in the `listActions` router). It carries the integration
16
+ provider's fully-qualified id, derived from the provider plugin's own
17
+ `pluginMetadata.pluginId` (never a hardcoded string), so the editor
18
+ knows which provider backs an action's dropdowns and it matches the
19
+ `qualifiedId` the integration provider registry assigns.
20
+
21
+ **Providers.** Jira, Teams and Webex each export
22
+ `*_PROVIDER_LOCAL_ID` / `*_PROVIDER_QUALIFIED_ID`, register their
23
+ provider with the local id, and add a `CONNECTION_OPTIONS`
24
+ (`"connectionOptions"`) resolver name. Their `post_message` /
25
+ issue actions set `connectionProviderId` and expose `connectionId`
26
+ as an `x-options-resolver` dropdown instead of a hidden field.
27
+
28
+ **Frontend bridge.** A new `useConnectionOptionResolvers` hook
29
+ (`@checkstack/automation-frontend`, which now depends on
30
+ `@checkstack/integration-common`) turns an action's
31
+ `x-options-resolver` schema fields into live data: the
32
+ `connectionOptions` resolver lists the provider's connections via
33
+ `listConnections`, and every other resolver name is forwarded to
34
+ `getConnectionOptions` for the selected `connectionId`, passing the
35
+ live form values as `context` for dependent fields. `ProviderActionBody`
36
+ now passes this map to `DynamicForm` (it was previously missing
37
+ entirely, so connection-backed actions had no working dropdowns).
38
+
39
+ **frontend-api.** `usePluginClient` procedures now also expose a typed
40
+ imperative `.call(input)` alongside `.useQuery` / `.useMutation`, for
41
+ async callbacks that cannot host a hook (such as a `DynamicForm`
42
+ options resolver). Additive, non-breaking.
43
+
44
+ **Integrations menu.** Re-added `IntegrationMenuItem` and a new
45
+ `IntegrationsLandingPage`, wired into `integration-frontend` as a list
46
+ route and a `UserMenuItemsSlot` entry under the "Configuration" group.
47
+
48
+ **Action card polish.** The action editor's secondary metadata (id,
49
+ description, failure behaviour) is now grouped into one quiet settings
50
+ panel with consistent small uppercase "eyebrow" labels, so the action's
51
+ own configuration stays the focal point. The raw failure checkbox was
52
+ replaced with the standard `Checkbox` control, and the provider action
53
+ picker / configuration sections gained consistent section headers and a
54
+ divider. The per-step "type" dropdown was removed: an action's kind is
55
+ fixed at creation, so changing it now means adding a new step and
56
+ deleting the old one (avoids the surprising full-config reset that
57
+ switching kinds used to trigger).
58
+
59
+ **Add-step picker.** Adding a step now opens a Home-Assistant-style
60
+ dialog where the operator decides the step type up front: an "Actions"
61
+ tab lists the registered provider actions grouped by category
62
+ (searchable; picking one presets the step's `action`), and a "Blocks"
63
+ tab lists the structural building blocks (choose / parallel / repeat /
64
+ etc.). Because the concrete action is chosen here, the in-card action
65
+ switcher was removed - a step's action is fixed once created. Composite
66
+ blocks now start with an empty child list (filled via the nested
67
+ add-step picker) instead of seeding an unconfigurable empty action.
68
+
69
+ - 41c77f4: feat(automation): one-time migration of webhook subscriptions + remove legacy integration backend
70
+
71
+ **BREAKING CHANGES** (platform is in BETA — no major bump):
72
+
73
+ - `IntegrationProvider` no longer carries `config` (subscription
74
+ config) or `deliver`. The interface now models a connection provider
75
+ only: connection schema + `getConnectionOptions` + `testConnection`.
76
+ - The legacy subscription / delivery-log / event endpoints
77
+ (`listSubscriptions`, `createSubscription`, `getDeliveryLogs`,
78
+ `listEventTypes`, …) are removed from `integrationContract`.
79
+ - `delivery-coordinator`, `hook-subscriber`, `event-registry`, and the
80
+ `integrationEventExtensionPoint` are deleted. Plugins that
81
+ previously called `integrationEvents.registerEvent(...)` now
82
+ register their hooks as automation triggers via
83
+ `automationTriggerExtensionPoint.registerTrigger(...)`.
84
+ - Frontend pages `IntegrationsPage` and `DeliveryLogsPage` are gone;
85
+ the integration plugin's only remaining UI is connection
86
+ management. Subscription management lives under `/automation/...`.
87
+ - `webhook_subscriptions` and `delivery_logs` tables stay in the
88
+ database for one release as a safety net (no code reads or writes
89
+ them), and will be dropped in a follow-up migration.
90
+
91
+ **New**:
92
+
93
+ - `jira.create_issue`, `teams.post_message`, `webex.post_message`,
94
+ `webhook.send`, `integration-script.run_shell`, and
95
+ `integration-script.run_script` actions registered against the
96
+ Automation Platform with matching `*.message`, `*.delivery`,
97
+ `shell.result`, and `script.result` artifact types. The script
98
+ plugin exposes **two** actions — `run_shell` runs bash via the
99
+ shared `ShellScriptRunner` (Monaco `shell` editor), `run_script`
100
+ runs an ESM module in a Bun subprocess via `EsmScriptRunner`
101
+ (Monaco `typescript` editor + `defineIntegration` helper) — to
102
+ preserve the legacy provider split. `jira.create_issue` keeps the
103
+ dynamic field-mapping dropdown (driven by
104
+ `JIRA_RESOLVERS.FIELD_OPTIONS`).
105
+ - One-time data migration runs on boot in
106
+ `automation-backend.afterPluginsReady`. It reads
107
+ `webhook_subscriptions` via a new service RPC
108
+ `IntegrationApi.listLegacySubscriptions`, translates each row into
109
+ a single-trigger / single-action automation (marked with
110
+ `managed_by = "migrated-subscription:<id>"`), and is idempotent
111
+ across restarts.
112
+ - Failed translations are recorded in a new
113
+ `automation_migration_failures` table and surfaced via
114
+ `AutomationApi.listMigrationFailures` /
115
+ `acknowledgeMigrationFailure` so admins can review and re-create
116
+ failed entries by hand.
117
+
118
+ ### Patch Changes
119
+
120
+ - Updated dependencies [e2d6f25]
121
+ - Updated dependencies [41c77f4]
122
+ - Updated dependencies [41c77f4]
123
+ - Updated dependencies [41c77f4]
124
+ - Updated dependencies [41c77f4]
125
+ - Updated dependencies [41c77f4]
126
+ - Updated dependencies [4832e33]
127
+ - Updated dependencies [6d52276]
128
+ - Updated dependencies [35bc682]
129
+ - Updated dependencies [c39ee69]
130
+ - @checkstack/frontend-api@0.6.0
131
+ - @checkstack/ui@1.11.0
132
+ - @checkstack/integration-common@0.6.0
133
+ - @checkstack/common@0.12.0
134
+ - @checkstack/tips-frontend@0.2.6
135
+ - @checkstack/signal-frontend@0.1.5
136
+
137
+ ## 0.4.5
138
+
139
+ ### Patch Changes
140
+
141
+ - f23f3c9: Retrofit the highest-traffic configuration list tables
142
+ (`HealthCheckList`, `SloConfigPage`, and the integration
143
+ `DeliveryLogsPage`) onto the `ResponsiveTable` + `MobileCardList`
144
+ primitives from `@checkstack/ui`. On `sm` and up each page still
145
+ renders the unchanged 5- to 7-column table; below that breakpoint a
146
+ sibling stacked-card layout surfaces the same data with the resource
147
+ name + status badge at the top, secondary columns in a muted line, and
148
+ the existing action buttons in a right-aligned footer. The
149
+ `HealthCheckListSkeleton` placeholder mirrors both branches so the page
150
+ no longer jumps when data resolves. No business logic, column order,
151
+ or query inputs changed.
152
+ - f23f3c9: Sweep every paginated `*-common` contract onto the canonical
153
+ `PaginationInput` / `PaginatedResult` from `@checkstack/common` and
154
+ remove the now-unused legacy exports.
155
+
156
+ **BREAKING CHANGE** - `@checkstack/common` drops the deprecated
157
+ `PaginationInputSchema`, `paginatedOutput`, and `PaginatedResponse`
158
+ symbols. Callers must consume `PaginationInput` (input) and
159
+ `PaginatedResult(itemSchema)` (output) instead. The canonical input is
160
+ `{ limit (1-100, default 20), offset (>= 0, default 0) }`; the
161
+ canonical output envelope is
162
+ `{ items, total, limit, offset }`.
163
+
164
+ **BREAKING CHANGE** - `@checkstack/notification-common` migrates
165
+ `getNotifications` off the legacy `PaginationInputSchema`
166
+ (`{ limit, offset, unreadOnly }` with output `{ notifications, total }`)
167
+ onto `ListNotificationsInputSchema =
168
+ PaginationInput.extend({ unreadOnly })` and
169
+ `PaginatedResult(NotificationSchema)`. The output key changes from
170
+ `notifications` to `items`, and `limit` / `offset` are now echoed on
171
+ the response. The `PaginationInput` type alias previously exported
172
+ from `notification-common` is removed - use `ListNotificationsInput`
173
+ or the canonical `PaginationInput` from `@checkstack/common`.
174
+
175
+ **BREAKING CHANGE** - `@checkstack/integration-common` migrates
176
+ `listSubscriptions` (inline `{ page, pageSize, ... }` -> output
177
+ `{ subscriptions, total }`) and `getDeliveryLogs` (via
178
+ `DeliveryLogQueryInputSchema` `{ subscriptionId?, eventType?, status?,
179
+ page, pageSize }` -> output `{ logs, total }`) onto the canonical
180
+ `PaginationInput.extend({...})` input and
181
+ `PaginatedResult(itemSchema)` output. External callers must switch
182
+ from `{ page, pageSize }` to `{ limit, offset }` and read response
183
+ items from `data.items` (no more `data.subscriptions` / `data.logs`).
184
+
185
+ The matching `*-backend` handlers were updated to consume the new
186
+ input shape (`offset` arithmetic in lieu of `(page - 1) * pageSize`)
187
+ and to echo `limit` / `offset` on the response. The `*-frontend` call
188
+ sites in `NotificationsPage`, `NotificationBell`, `IntegrationsPage`,
189
+ and `DeliveryLogsPage` were updated to send the new input shape and
190
+ read `data.items`.
191
+
192
+ - f23f3c9: Gate decorative motion and blur effects behind
193
+ `usePerformance().isLowPower` on a focused set of high-traffic plugin
194
+ pages (Dashboard, Dependency map, System node, Notification bell,
195
+ Announcement banner / cards, Anomaly field overrides editor, SLO
196
+ attribution chart, Catalog droppable group). Hover scales, backdrop
197
+ blurs, `animate-pulse`/`animate-ping` accents, and entry transitions
198
+ now drop to static states on low-power devices; functional UX
199
+ transitions (Drawer/Dialog open-close, colour transitions) are left
200
+ alone.
201
+
202
+ Standardise the post-mutation error-toast voice on plugin pages by
203
+ migrating multi-clause `toast.error(extractErrorMessage(error, "Failed
204
+ to X"))` call sites onto the `toastError(toast, "Failed to X", error)`
205
+ helper from `@checkstack/ui`. The helper applies the canonical
206
+ `"action: message"` prefix and 100-character truncation in one place,
207
+ and the now-orphaned `extractErrorMessage` imports are dropped from
208
+ the affected files. No business logic or component APIs changed.
209
+
210
+ - Updated dependencies [f23f3c9]
211
+ - Updated dependencies [f23f3c9]
212
+ - Updated dependencies [f23f3c9]
213
+ - Updated dependencies [f23f3c9]
214
+ - @checkstack/common@0.11.0
215
+ - @checkstack/frontend-api@0.5.2
216
+ - @checkstack/integration-common@0.5.0
217
+ - @checkstack/ui@1.10.0
218
+ - @checkstack/tips-frontend@0.2.5
219
+ - @checkstack/signal-frontend@0.1.4
220
+
3
221
  ## 0.4.4
4
222
 
5
223
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/integration-frontend",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "license": "Elastic-2.0",
5
5
  "type": "module",
6
6
  "main": "src/index.tsx",
@@ -13,12 +13,12 @@
13
13
  "lint:code": "eslint . --max-warnings 0"
14
14
  },
15
15
  "dependencies": {
16
- "@checkstack/common": "0.10.0",
17
- "@checkstack/frontend-api": "0.5.1",
18
- "@checkstack/integration-common": "0.4.0",
19
- "@checkstack/signal-frontend": "0.1.3",
20
- "@checkstack/tips-frontend": "0.2.3",
21
- "@checkstack/ui": "1.8.3",
16
+ "@checkstack/common": "0.11.0",
17
+ "@checkstack/frontend-api": "0.5.2",
18
+ "@checkstack/integration-common": "0.5.0",
19
+ "@checkstack/signal-frontend": "0.1.4",
20
+ "@checkstack/tips-frontend": "0.2.5",
21
+ "@checkstack/ui": "1.10.0",
22
22
  "lucide-react": "^0.344.0",
23
23
  "react": "^18.2.0",
24
24
  "react-router-dom": "^6.22.0"
@@ -27,6 +27,6 @@
27
27
  "typescript": "^5.0.0",
28
28
  "@types/react": "^18.2.0",
29
29
  "@checkstack/tsconfig": "0.0.7",
30
- "@checkstack/scripts": "0.3.2"
30
+ "@checkstack/scripts": "0.3.3"
31
31
  }
32
32
  }
@@ -1,4 +1,5 @@
1
- import { useNavigate } from "react-router-dom";
1
+ import React from "react";
2
+ import { Link } from "react-router-dom";
2
3
  import { Webhook } from "lucide-react";
3
4
  import { DropdownMenuItem } from "@checkstack/ui";
4
5
  import type { UserMenuItemsContext } from "@checkstack/frontend-api";
@@ -8,12 +9,17 @@ import {
8
9
  integrationAccess,
9
10
  pluginMetadata,
10
11
  } from "@checkstack/integration-common";
11
- import React from "react";
12
12
 
13
+ /**
14
+ * "Integrations" entry in the user menu. Links to the integrations landing
15
+ * page (provider list); each provider links on to its connection-management
16
+ * page. Gated on `integration.manage` — mirrors the access check the routes
17
+ * themselves enforce, but hiding the link is the cleaner UX for users who
18
+ * can't manage connections.
19
+ */
13
20
  export const IntegrationMenuItem = ({
14
21
  accessRules: userPerms,
15
22
  }: UserMenuItemsContext) => {
16
- const navigate = useNavigate();
17
23
  const qualifiedId = `${pluginMetadata.pluginId}.${integrationAccess.manage.id}`;
18
24
  const allowed = userPerms.includes("*") || userPerms.includes(qualifiedId);
19
25
 
@@ -22,11 +28,10 @@ export const IntegrationMenuItem = ({
22
28
  }
23
29
 
24
30
  return (
25
- <DropdownMenuItem
26
- onClick={() => navigate(resolveRoute(integrationRoutes.routes.list))}
27
- icon={<Webhook className="h-4 w-4" />}
28
- >
29
- Integrations
30
- </DropdownMenuItem>
31
+ <Link to={resolveRoute(integrationRoutes.routes.list)}>
32
+ <DropdownMenuItem icon={<Webhook className="h-4 w-4" />}>
33
+ Integrations
34
+ </DropdownMenuItem>
35
+ </Link>
31
36
  );
32
37
  };
package/src/index.tsx CHANGED
@@ -8,27 +8,23 @@ import {
8
8
  pluginMetadata,
9
9
  integrationAccess,
10
10
  } from "@checkstack/integration-common";
11
- import { IntegrationsPage } from "./pages/IntegrationsPage";
12
- import { DeliveryLogsPage } from "./pages/DeliveryLogsPage";
11
+ import { IntegrationsLandingPage } from "./pages/IntegrationsLandingPage";
13
12
  import { ProviderConnectionsPage } from "./pages/ProviderConnectionsPage";
14
13
  import { IntegrationMenuItem } from "./components/IntegrationMenuItem";
15
14
 
15
+ /**
16
+ * Integration frontend — now scoped to connection management. The
17
+ * legacy subscription / delivery-log pages were removed when the
18
+ * platform moved to the Automation Platform model; operators manage
19
+ * automations in `/automation/...` instead. The landing page lists
20
+ * providers and links each to its connection-management page.
21
+ */
16
22
  export const integrationPlugin = createFrontendPlugin({
17
23
  metadata: pluginMetadata,
18
24
  routes: [
19
25
  {
20
26
  route: integrationRoutes.routes.list,
21
- element: <IntegrationsPage />,
22
- accessRule: integrationAccess.manage,
23
- },
24
- {
25
- route: integrationRoutes.routes.logs,
26
- element: <DeliveryLogsPage />,
27
- accessRule: integrationAccess.manage,
28
- },
29
- {
30
- route: integrationRoutes.routes.deliveryLogs,
31
- element: <DeliveryLogsPage />,
27
+ element: <IntegrationsLandingPage />,
32
28
  accessRule: integrationAccess.manage,
33
29
  },
34
30
  {
@@ -48,7 +44,6 @@ export const integrationPlugin = createFrontendPlugin({
48
44
 
49
45
  export default integrationPlugin;
50
46
 
51
- // Re-export registry and types for providers to register custom config components
52
47
  export {
53
48
  registerProviderConfigExtension,
54
49
  getProviderConfigExtension,
@@ -0,0 +1,116 @@
1
+ import { Link } from "react-router-dom";
2
+ import {
3
+ PageLayout,
4
+ Card,
5
+ CardContent,
6
+ EmptyState,
7
+ LoadingSpinner,
8
+ DynamicIcon,
9
+ Badge,
10
+ type LucideIconName,
11
+ } from "@checkstack/ui";
12
+ import { Webhook, ArrowRight } from "lucide-react";
13
+ import { usePluginClient } from "@checkstack/frontend-api";
14
+ import { resolveRoute } from "@checkstack/common";
15
+ import { IntegrationApi, integrationRoutes } from "@checkstack/integration-common";
16
+
17
+ /**
18
+ * Integrations landing page — lists every registered integration provider
19
+ * and links each to its connection-management page. This is the entry
20
+ * point reached from the "Integrations" user-menu item; the per-provider
21
+ * `ProviderConnectionsPage` lives at `/connections/:providerId`.
22
+ *
23
+ * Only providers that declare a `connectionSchema` (i.e. need site-wide
24
+ * credentials) are actionable here; others are shown disabled so operators
25
+ * understand why there's nothing to configure.
26
+ */
27
+ export const IntegrationsLandingPage = () => {
28
+ const client = usePluginClient(IntegrationApi);
29
+ const { data: providers = [], isLoading } = client.listProviders.useQuery({});
30
+
31
+ if (isLoading) {
32
+ return (
33
+ <PageLayout title="Integrations" icon={Webhook}>
34
+ <div className="flex items-center justify-center py-12">
35
+ <LoadingSpinner />
36
+ </div>
37
+ </PageLayout>
38
+ );
39
+ }
40
+
41
+ if (providers.length === 0) {
42
+ return (
43
+ <PageLayout title="Integrations" icon={Webhook}>
44
+ <EmptyState
45
+ icon={<Webhook className="h-12 w-12" />}
46
+ title="No integration providers"
47
+ description="Install an integration plugin (e.g. Jira, Teams, Webex) to manage its connections here."
48
+ />
49
+ </PageLayout>
50
+ );
51
+ }
52
+
53
+ return (
54
+ <PageLayout
55
+ title="Integrations"
56
+ subtitle="Manage site-wide connections for your integration providers"
57
+ icon={Webhook}
58
+ >
59
+ <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
60
+ {providers.map((provider) => {
61
+ const card = (
62
+ <Card
63
+ className={
64
+ provider.hasConnectionSchema
65
+ ? "transition-colors hover:border-primary/50"
66
+ : "opacity-60"
67
+ }
68
+ >
69
+ <CardContent className="flex items-start gap-3 p-4">
70
+ <DynamicIcon
71
+ name={(provider.icon as LucideIconName) ?? "Webhook"}
72
+ className="mt-0.5 h-5 w-5 shrink-0 text-muted-foreground"
73
+ />
74
+ <div className="min-w-0 flex-1">
75
+ <div className="flex items-center gap-2">
76
+ <span className="truncate text-sm font-semibold">
77
+ {provider.displayName}
78
+ </span>
79
+ {!provider.hasConnectionSchema && (
80
+ <Badge variant="outline" className="shrink-0 text-[10px]">
81
+ No connections
82
+ </Badge>
83
+ )}
84
+ </div>
85
+ {provider.description && (
86
+ <p className="mt-0.5 truncate text-xs text-muted-foreground">
87
+ {provider.description}
88
+ </p>
89
+ )}
90
+ </div>
91
+ {provider.hasConnectionSchema && (
92
+ <ArrowRight className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
93
+ )}
94
+ </CardContent>
95
+ </Card>
96
+ );
97
+
98
+ if (!provider.hasConnectionSchema) {
99
+ return <div key={provider.qualifiedId}>{card}</div>;
100
+ }
101
+
102
+ return (
103
+ <Link
104
+ key={provider.qualifiedId}
105
+ to={resolveRoute(integrationRoutes.routes.connections, {
106
+ providerId: provider.qualifiedId,
107
+ })}
108
+ >
109
+ {card}
110
+ </Link>
111
+ );
112
+ })}
113
+ </div>
114
+ </PageLayout>
115
+ );
116
+ };
@@ -42,10 +42,11 @@ import {
42
42
  useToast,
43
43
  ConfirmationModal,
44
44
  BackLink,
45
+ toastError,
45
46
  type LucideIconName,
46
47
  } from "@checkstack/ui";
47
48
  import { usePluginClient } from "@checkstack/frontend-api";
48
- import { resolveRoute, extractErrorMessage } from "@checkstack/common";
49
+ import { resolveRoute } from "@checkstack/common";
49
50
  import {
50
51
  IntegrationApi,
51
52
  integrationRoutes,
@@ -108,7 +109,7 @@ export const ProviderConnectionsPage = () => {
108
109
  setSaving(false);
109
110
  },
110
111
  onError: (error) => {
111
- toast.error(extractErrorMessage(error, "Failed to create connection"));
112
+ toastError(toast, "Failed to create connection", error);
112
113
  setSaving(false);
113
114
  },
114
115
  });
@@ -122,7 +123,7 @@ export const ProviderConnectionsPage = () => {
122
123
  setSaving(false);
123
124
  },
124
125
  onError: (error) => {
125
- toast.error(extractErrorMessage(error, "Failed to update connection"));
126
+ toastError(toast, "Failed to update connection", error);
126
127
  setSaving(false);
127
128
  },
128
129
  });
@@ -135,7 +136,7 @@ export const ProviderConnectionsPage = () => {
135
136
  toast.success("Connection deleted");
136
137
  },
137
138
  onError: (error) => {
138
- toast.error(extractErrorMessage(error, "Failed to delete connection"));
139
+ toastError(toast, "Failed to delete connection", error);
139
140
  },
140
141
  });
141
142
 
@@ -157,7 +158,7 @@ export const ProviderConnectionsPage = () => {
157
158
  ...prev,
158
159
  [variables.connectionId]: { success: false, message: "Test failed" },
159
160
  }));
160
- toast.error(extractErrorMessage(error, "Connection test failed"));
161
+ toastError(toast, "Connection test failed", error);
161
162
  setTestingId(undefined);
162
163
  },
163
164
  });