@rahdar/plugin-sdk 2026.10.54 → 2026.10.58
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/package.json +1 -1
- package/types/kernel/actions/types.d.ts +35 -34
- package/types/kernel/api/paging.d.ts +5 -2
- package/types/kernel/api/request.d.ts +2 -2
- package/types/kernel/api/resourceId.d.ts +32 -0
- package/types/kernel/api/schema.d.ts +1470 -1713
- package/types/kernel/approvals/columns.d.ts +1 -1
- package/types/kernel/auth/api.d.ts +3 -3
- package/types/kernel/auth/useCan.d.ts +8 -8
- package/types/kernel/feature.d.ts +8 -2
- package/types/kernel/keyboard/useKeySequences.d.ts +3 -2
- package/types/kernel/nav/currentView.d.ts +5 -4
- package/types/kernel/registry.d.ts +3 -2
- package/types/kernel/routing/roots.d.ts +4 -1
- package/types/kernel/routing/search.d.ts +7 -0
- package/types/kernel/shell/CommandPalette.d.ts +1 -1
- package/types/kernel/shell/HomeView.d.ts +1 -5
- package/types/kernel/shell/lastPlace.d.ts +1 -1
- package/types/kernel/shell/useClusterSystem.d.ts +11 -0
- package/types/kernel/slots.d.ts +28 -23
- package/types/sdk/index.d.ts +2 -2
- package/types/ui/ConfirmDialog.d.ts +3 -3
- package/types/ui/DescriptionList.d.ts +1 -1
- package/types/ui/EmptyState.d.ts +1 -1
- package/types/ui/HoldToConfirm.d.ts +2 -2
- package/types/ui/LoadingState.d.ts +1 -1
- package/types/ui/NodeOutcomeSummary.d.ts +1 -1
- package/types/ui/Toolbar.d.ts +1 -1
- package/types/ui/capabilityGate.d.ts +7 -6
- package/types/ui/notify.d.ts +1 -1
- package/types/ui/table/DataTable.d.ts +1 -1
- package/types/ui/table/columns.d.ts +9 -0
- package/types/ui/table/index.d.ts +1 -1
|
@@ -3,7 +3,7 @@ import { type HeldDisplayRow, type HeldOperationSummary } from './api.ts';
|
|
|
3
3
|
/** A value as the change table shows it: a secret says it is hidden, and an absent value says which absence. */
|
|
4
4
|
export declare function valueText(value: string | null | undefined, absent: string): string;
|
|
5
5
|
/**
|
|
6
|
-
* Whether the rows only name what the request acts on (a
|
|
6
|
+
* Whether the rows only name what the request acts on (a subscription, a user) rather than change values: every row
|
|
7
7
|
* lacks a current value. Those read as a list of facts; rows with a current value read as a change table.
|
|
8
8
|
*/
|
|
9
9
|
export declare const namesTargets: (rows: readonly HeldDisplayRow[]) => boolean;
|
|
@@ -19,7 +19,7 @@ export declare const keys: {
|
|
|
19
19
|
export declare const accessKeys: {
|
|
20
20
|
all: readonly ["access"];
|
|
21
21
|
of: (clusterId?: string) => readonly ["access", string];
|
|
22
|
-
resource: (clusterId: string,
|
|
22
|
+
resource: (clusterId: string, type: string, name: string) => readonly ["access", "resource", string, string, string];
|
|
23
23
|
};
|
|
24
24
|
/**
|
|
25
25
|
* What the signed-in user holds, globally or on one cluster, as the server's resolver decides it: through role
|
|
@@ -53,8 +53,8 @@ export declare function accessQuery(clusterId?: string): import("@tanstack/query
|
|
|
53
53
|
teams: components["schemas"]["TeamMembership"][];
|
|
54
54
|
createPatterns: components["schemas"]["CreatePatterns"];
|
|
55
55
|
}, Error>;
|
|
56
|
-
/** What the signed-in user may do with one
|
|
57
|
-
export declare function resourceAccessQuery(clusterId: string,
|
|
56
|
+
/** What the signed-in user may do with one subscription or destination: the actions they hold on it, as the server decides. */
|
|
57
|
+
export declare function resourceAccessQuery(clusterId: string, type: 'SUBSCRIPTION' | 'DESTINATION', name: string): import("@tanstack/query-core").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<{
|
|
58
58
|
actions: string[];
|
|
59
59
|
}, Error, {
|
|
60
60
|
actions: string[];
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A
|
|
2
|
+
* A subscription or destination of a cluster, for a check on one resource. Pass the `allowedActions` a row already
|
|
3
3
|
* carries from the server to answer from it with no request.
|
|
4
4
|
*/
|
|
5
5
|
export interface ResourceWhere {
|
|
6
6
|
clusterId: string;
|
|
7
|
-
|
|
7
|
+
type: 'subscription' | 'destination';
|
|
8
8
|
name: string;
|
|
9
9
|
allowedActions?: AllowedActions;
|
|
10
10
|
}
|
|
@@ -17,16 +17,16 @@ export type AllowedActions = readonly string[];
|
|
|
17
17
|
* counted as the server counts them.
|
|
18
18
|
*
|
|
19
19
|
* <p>`can(permission)` is about the whole installation. `can(permission, clusterId)` is about one cluster, and
|
|
20
|
-
* `can(permission, { clusterId,
|
|
20
|
+
* `can(permission, { clusterId, type, name })` about one subscription or destination, with a team's or share's rights counted.
|
|
21
21
|
* Each is fetched the first time it is asked. Until it arrives the control is offered, as it is while grants load:
|
|
22
22
|
* blocking on an answer not yet known would lock out someone the server lets in. For a resource permission the
|
|
23
|
-
* cluster answer counts grants only; what a team or share gives on some
|
|
24
|
-
* `anywhere`, and on one named
|
|
23
|
+
* cluster answer counts grants only; what a team or share gives on some subscription or address is in the summary's
|
|
24
|
+
* `anywhere`, and on one named subscription or destination in its own answer, or in the row's `allowedActions`.
|
|
25
25
|
*
|
|
26
|
-
* <p>`canAnywhere` is the page-level right: held on the cluster by a grant, or on some
|
|
26
|
+
* <p>`canAnywhere` is the page-level right: held on the cluster by a grant, or on some subscription or address through a team
|
|
27
27
|
* or a share. A control is hidden only when it is false. `canOn` is the right on one row the server sent, from the
|
|
28
28
|
* row's `allowedActions`: false there is a control shown disabled, with its reason. `createPatterns` are the name
|
|
29
|
-
* patterns a team or share lets the caller create
|
|
29
|
+
* patterns a team or share lets the caller create subscriptions and destinations under.
|
|
30
30
|
*/
|
|
31
31
|
export declare function useCan(): {
|
|
32
32
|
can: (permission: string, where?: string | ResourceWhere) => boolean;
|
|
@@ -36,7 +36,7 @@ export declare function useCan(): {
|
|
|
36
36
|
canOn: (permission: string, resource: {
|
|
37
37
|
allowedActions: AllowedActions;
|
|
38
38
|
}) => boolean;
|
|
39
|
-
createPatterns: (clusterId: string,
|
|
39
|
+
createPatterns: (clusterId: string, type: "subscription" | "destination") => string[] | undefined;
|
|
40
40
|
/** The teams the caller belongs to, with their role in each. */
|
|
41
41
|
teams: {
|
|
42
42
|
teamId: string;
|
|
@@ -5,9 +5,9 @@ import type { AnyRoute } from '@tanstack/react-router';
|
|
|
5
5
|
import type { NavGroupId } from './nav/groups.ts';
|
|
6
6
|
import type { SlotContributions } from './slots.ts';
|
|
7
7
|
/** The extension contract version, shared with the backend's `Contract.VERSION` (ADR-0070). */
|
|
8
|
-
export declare const CONTRACT =
|
|
8
|
+
export declare const CONTRACT = 17;
|
|
9
9
|
/** The module ids the backend manifest reports. A frontend feature uses the same id as its backend module. */
|
|
10
|
-
export declare const FEATURE_IDS: readonly ["security", "audit", "auditfeed", "settings", "lifecycle", "stream", "inbox", "approvals", "broker", "clusters", "governance", "scrape", "artemis", "mcp", "
|
|
10
|
+
export declare const FEATURE_IDS: readonly ["security", "audit", "auditfeed", "settings", "lifecycle", "stream", "inbox", "approvals", "broker", "clusters", "governance", "scrape", "artemis", "mcp", "resources", "messages", "routing", "metrics", "alerting", "events", "rr", "sql", "brokerconfig", "flow", "triage", "bulk", "transfer", "setupreview", "diagnostics", "apitokens", "plugins", "identity-local", "identity-oidc"];
|
|
11
11
|
export type FeatureId = (typeof FEATURE_IDS)[number];
|
|
12
12
|
/**
|
|
13
13
|
* An installed plugin's id, as its `plugin.json` declares it: lowercase kebab-case, vendor first,
|
|
@@ -36,6 +36,12 @@ export interface NavContribution {
|
|
|
36
36
|
icon: Icon;
|
|
37
37
|
/** The view's path below `/clusters/$clusterId/`. */
|
|
38
38
|
path: string;
|
|
39
|
+
/**
|
|
40
|
+
* The id of the broker system the view is for (`artemis`). Without it the view applies to every system; with
|
|
41
|
+
* it, the navigation lists the view only for a cluster that runs that system, and its route is under
|
|
42
|
+
* `/clusters/$clusterId/<system>/`, which another system's cluster answers with the not-found page.
|
|
43
|
+
*/
|
|
44
|
+
system?: string;
|
|
39
45
|
/**
|
|
40
46
|
* The permission the view reads with. Without it the entry stays visible and disabled,
|
|
41
47
|
* and says why; the server enforces it regardless.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { type NavContribution } from '../feature.ts';
|
|
2
2
|
/**
|
|
3
3
|
* The views that have a `g` letter: built-in views only — a plugin's letter is ignored, so a plugin
|
|
4
|
-
* can never take a letter an operator already relies on (ADR-0109).
|
|
4
|
+
* can never take a letter an operator already relies on (ADR-0109). A system-only view has no letter on a
|
|
5
|
+
* cluster known to run another system; while the system is not known the letter is offered.
|
|
5
6
|
*/
|
|
6
7
|
export declare function viewHotkeys(features: {
|
|
7
8
|
id: string;
|
|
8
9
|
nav?: NavContribution[];
|
|
9
|
-
}[]): Map<string, NavContribution>;
|
|
10
|
+
}[], systemId?: string): Map<string, NavContribution>;
|
|
10
11
|
/**
|
|
11
12
|
* The single-key shortcuts (ADR-0109), as one document listener mounted by the shell:
|
|
12
13
|
* `g` then a view's letter goes to that view of the open cluster, `?` opens the list of shortcuts,
|
|
@@ -8,14 +8,15 @@ export interface CurrentView {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Which cluster view an address is under (ADR-0109): the navigation entry whose path is the longest
|
|
11
|
-
* prefix of the path after `/clusters/<id>/`, so a
|
|
11
|
+
* prefix of the path after `/clusters/<id>/`, so a subscription's message browser is under Subscriptions and a
|
|
12
12
|
* bulk run under Bulk runs. Null outside any cluster.
|
|
13
13
|
*/
|
|
14
14
|
export declare function matchView(pathname: string, features: RahdarFeature[]): CurrentView | null;
|
|
15
15
|
export declare function useCurrentView(): CurrentView | null;
|
|
16
16
|
/**
|
|
17
17
|
* The address of the same view on another cluster (ADR-0109): an operator comparing two clusters
|
|
18
|
-
* stays on
|
|
19
|
-
* that may not exist there. Without a current view, the cluster
|
|
18
|
+
* stays on Subscriptions. The view's search is not carried — its filter and its open resource name things
|
|
19
|
+
* that may not exist there. Without a current view, or when the view is for one system and the cluster runs
|
|
20
|
+
* another (`system`), the cluster's landing page.
|
|
20
21
|
*/
|
|
21
|
-
export declare function sameViewOn(clusterId: string, view: CurrentView | null): string;
|
|
22
|
+
export declare function sameViewOn(clusterId: string, view: CurrentView | null, system?: string): string;
|
|
@@ -7,6 +7,7 @@ export interface NavGroup {
|
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* The features' views under the kernel's groups (ADR-0070): groups in their fixed order, views in
|
|
10
|
-
* their declared order, and a group none of the features contributes to left out.
|
|
10
|
+
* their declared order, and a group none of the features contributes to left out. A system-only view is
|
|
11
|
+
* listed only for a cluster that runs that system (`systemId`).
|
|
11
12
|
*/
|
|
12
|
-
export declare function navGroups(features: RahdarFeature[]): NavGroup[];
|
|
13
|
+
export declare function navGroups(features: RahdarFeature[], systemId?: string): NavGroup[];
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { type ComponentType, type ReactElement } from 'react';
|
|
2
2
|
import type { ModuleId } from '../feature.ts';
|
|
3
|
+
import { type ResourceSearch } from './search.ts';
|
|
3
4
|
/** The root every page renders inside: the shell. A feature's `routes.root` are its children. */
|
|
4
5
|
export declare const rootRoute: import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>;
|
|
5
6
|
/** One cluster's layout. A feature's `routes.cluster` are its children. */
|
|
6
7
|
export declare const clusterRoute: import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "clusters/$clusterId", "/clusters/$clusterId", string, "/clusters/$clusterId", undefined, import("@tanstack/router-core").ResolveParams<"clusters/$clusterId">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>;
|
|
7
8
|
export declare const pluginClusterFallback: import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "clusters/$clusterId", "/clusters/$clusterId", string, "/clusters/$clusterId", undefined, import("@tanstack/router-core").ResolveParams<"clusters/$clusterId">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "p/$pluginId/$", "/clusters/$clusterId/p/$pluginId/$", string, "/clusters/$clusterId/p/$pluginId/$", undefined, import("@tanstack/router-core").ResolveParams<"p/$pluginId/$">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>;
|
|
8
9
|
/** The shell's own pages, beside the cluster layout. */
|
|
9
|
-
export declare const shellRoutes: (import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/", "/", string, "/",
|
|
10
|
+
export declare const shellRoutes: (import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "/", "/", string, "/", (raw: Record<string, unknown>) => ResourceSearch & {
|
|
11
|
+
cluster?: string;
|
|
12
|
+
}, import("@tanstack/router-core").ResolveParams<"/">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined> | import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "login", "/login", string, "/login", undefined, import("@tanstack/router-core").ResolveParams<"login">, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined> | import("@tanstack/react-router").Route<unknown, import("@tanstack/react-router").RootRoute<import("@tanstack/router-core").Register, undefined, {}, import("@tanstack/router-core").AnyContext, import("@tanstack/router-core").AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, "admin", "/admin", string, "/admin", (raw: Record<string, unknown>) => {
|
|
10
13
|
tab?: string;
|
|
11
14
|
plugin?: string;
|
|
12
15
|
upload?: string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** A listing's navigable state: filter, sort and page live in the URL, not in local state (non-negotiable #9). */
|
|
2
|
+
export interface ResourceSearch {
|
|
3
|
+
q?: string;
|
|
4
|
+
sort?: string;
|
|
5
|
+
page?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function validateResourceSearch(raw: Record<string, unknown>): ResourceSearch;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ⌘K navigation across the console: jump to a view, a recent place, a cluster, or a
|
|
2
|
+
* ⌘K navigation across the console: jump to a view, a recent place, a cluster, or a subscription by name, or
|
|
3
3
|
* search a live view (ADR-0109). Mounted once in the root layout; the shortcut is registered by
|
|
4
4
|
* {@link Spotlight}, and the header's Search button opens it too.
|
|
5
5
|
*
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The landing page, with no cluster open: what the features contribute for it. The clusters feature
|
|
3
|
-
* sends the operator to the first cluster, so the page is seen only while that is decided or while no
|
|
4
|
-
* cluster is registered, which is what it is titled for.
|
|
5
|
-
*/
|
|
1
|
+
/** The landing page, with no cluster open: the estate, which is what the features contribute for it. */
|
|
6
2
|
export declare function HomeView(): import("react").JSX.Element;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
export interface LastPlace {
|
|
7
7
|
clusterId: string;
|
|
8
8
|
clusterName: string;
|
|
9
|
-
/** The view the operator was in, such as "
|
|
9
|
+
/** The view the operator was in, such as "Subscriptions". */
|
|
10
10
|
label: string;
|
|
11
11
|
/** The address, and the search it was opened with. */
|
|
12
12
|
to: string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { components } from '../api/schema.d.ts';
|
|
2
|
+
type ClusterDetail = components['schemas']['ClusterDetail'];
|
|
3
|
+
/**
|
|
4
|
+
* What the cluster says about its broker system: the system itself and the kinds it offers, each with the verbs
|
|
5
|
+
* it supports. It reads the cluster the clusters feature already keeps fresh, under the same key, so it adds
|
|
6
|
+
* no request of its own. `undefined` until the cluster has loaded, and for no cluster.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useClusterKinds(clusterId: string | undefined): Pick<ClusterDetail, 'system' | 'kinds'> | undefined;
|
|
9
|
+
/** The id of the system the cluster runs (`artemis`), which decides whether a system-only view is offered. */
|
|
10
|
+
export declare function useClusterSystem(clusterId: string | undefined): string | undefined;
|
|
11
|
+
export {};
|
package/types/kernel/slots.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { ComponentType } from 'react';
|
|
2
|
-
import type { ActionProps, ActionSection,
|
|
2
|
+
import type { ActionProps, ActionSection, ChannelTarget, ClientTarget, ConnectionTarget, ConsumerTarget, DestinationTarget, LinkProps, MessageTarget, ProducerTarget, ResourceRef, RouteTarget, SubscriptionTarget } from './actions/types.ts';
|
|
3
3
|
import type { HeldOperationDetail } from './approvals/api.ts';
|
|
4
4
|
import type { MetricRange } from './time/ranges.ts';
|
|
5
|
-
/**
|
|
6
|
-
export type
|
|
5
|
+
/** Subscriptions picked by name, or every subscription matching the subscriptions screen's filter (`q`, blank for all). */
|
|
6
|
+
export type SubscriptionSelection = {
|
|
7
7
|
kind: 'names';
|
|
8
8
|
names: string[];
|
|
9
9
|
} | {
|
|
@@ -11,7 +11,7 @@ export type QueueSelection = {
|
|
|
11
11
|
q: string;
|
|
12
12
|
total: number;
|
|
13
13
|
};
|
|
14
|
-
/** Messages picked by id, every message matching the messages screen's selector, or the whole
|
|
14
|
+
/** Messages picked by id, every message matching the messages screen's selector, or the whole subscription. */
|
|
15
15
|
export type MessageSelection = {
|
|
16
16
|
kind: 'ids';
|
|
17
17
|
ids: number[];
|
|
@@ -34,7 +34,7 @@ export interface SlotProps {
|
|
|
34
34
|
collapsed: boolean;
|
|
35
35
|
};
|
|
36
36
|
/** The landing page, when no cluster is open. */
|
|
37
|
-
'home.
|
|
37
|
+
'home.estate': object;
|
|
38
38
|
/** Above every view of a cluster: what identifies it, and what needs saying about its state. */
|
|
39
39
|
'cluster.header': {
|
|
40
40
|
clusterId: string;
|
|
@@ -43,20 +43,20 @@ export interface SlotProps {
|
|
|
43
43
|
'cluster.registration.afterProbe': {
|
|
44
44
|
contributions: Record<string, unknown>;
|
|
45
45
|
};
|
|
46
|
-
/** In a
|
|
47
|
-
'
|
|
46
|
+
/** In a subscription's detail drawer, below its per-node breakdown. `onClose` closes the drawer before navigating. */
|
|
47
|
+
'subscription.detail.panels': {
|
|
48
48
|
clusterId: string;
|
|
49
|
-
|
|
49
|
+
subscription: ResourceRef;
|
|
50
50
|
onClose: () => void;
|
|
51
51
|
};
|
|
52
52
|
/**
|
|
53
|
-
* Beside the
|
|
53
|
+
* Beside the subscriptions screen's selection: what can be done to the selected subscriptions. `count` is how
|
|
54
54
|
* many are selected, and may be zero: an action then stays visible and disabled. `clear` empties
|
|
55
55
|
* the selection.
|
|
56
56
|
*/
|
|
57
|
-
'
|
|
57
|
+
'subscriptions.selection': {
|
|
58
58
|
clusterId: string;
|
|
59
|
-
selection:
|
|
59
|
+
selection: SubscriptionSelection;
|
|
60
60
|
count: number;
|
|
61
61
|
clear: () => void;
|
|
62
62
|
};
|
|
@@ -67,7 +67,7 @@ export interface SlotProps {
|
|
|
67
67
|
*/
|
|
68
68
|
'messages.selection': {
|
|
69
69
|
clusterId: string;
|
|
70
|
-
|
|
70
|
+
subscription: ResourceRef;
|
|
71
71
|
node?: string;
|
|
72
72
|
selection: MessageSelection;
|
|
73
73
|
total: number | null;
|
|
@@ -77,10 +77,10 @@ export interface SlotProps {
|
|
|
77
77
|
'metrics.panels': {
|
|
78
78
|
clusterId: string;
|
|
79
79
|
};
|
|
80
|
-
/** In the flow view's monitoring pane, when a
|
|
80
|
+
/** In the flow view's monitoring pane, when a subscription is selected: its history over `range`, per node. */
|
|
81
81
|
'flow.selection.panels': {
|
|
82
82
|
clusterId: string;
|
|
83
|
-
|
|
83
|
+
subscription: ResourceRef;
|
|
84
84
|
range: MetricRange;
|
|
85
85
|
};
|
|
86
86
|
/** Inside a box on the topology graph, after its name. `nodeIds` are the broker endpoints the box stands for. */
|
|
@@ -92,8 +92,8 @@ export interface SlotProps {
|
|
|
92
92
|
'settings.sections': {
|
|
93
93
|
clusterId: string;
|
|
94
94
|
};
|
|
95
|
-
/** A tab of a cluster's
|
|
96
|
-
'
|
|
95
|
+
/** A tab of a cluster's Routes page, after Routes, labelled with the contribution's title; its id is the tab's `?tab=`. */
|
|
96
|
+
'routes.tabs': {
|
|
97
97
|
clusterId: string;
|
|
98
98
|
};
|
|
99
99
|
/**
|
|
@@ -120,19 +120,19 @@ export interface SlotProps {
|
|
|
120
120
|
opened: boolean;
|
|
121
121
|
onClose: () => void;
|
|
122
122
|
};
|
|
123
|
-
'
|
|
124
|
-
'
|
|
123
|
+
'subscription.actions': ActionProps<SubscriptionTarget>;
|
|
124
|
+
'destination.actions': ActionProps<DestinationTarget>;
|
|
125
125
|
'connection.actions': ActionProps<ConnectionTarget>;
|
|
126
|
-
'
|
|
126
|
+
'channel.actions': ActionProps<ChannelTarget>;
|
|
127
127
|
'consumer.actions': ActionProps<ConsumerTarget>;
|
|
128
128
|
'producer.actions': ActionProps<ProducerTarget>;
|
|
129
129
|
'message.actions': ActionProps<MessageTarget>;
|
|
130
|
-
'
|
|
130
|
+
'route.actions': ActionProps<RouteTarget>;
|
|
131
131
|
'client.actions': ActionProps<ClientTarget>;
|
|
132
|
-
'
|
|
133
|
-
'
|
|
132
|
+
'subscription.link': LinkProps<SubscriptionTarget>;
|
|
133
|
+
'destination.link': LinkProps<DestinationTarget>;
|
|
134
134
|
'connection.link': LinkProps<ConnectionTarget>;
|
|
135
|
-
'
|
|
135
|
+
'channel.link': LinkProps<ChannelTarget>;
|
|
136
136
|
}
|
|
137
137
|
export type SlotName = keyof SlotProps;
|
|
138
138
|
/**
|
|
@@ -186,6 +186,11 @@ export interface SlotContribution<P> {
|
|
|
186
186
|
* (listed under Plugins without one), and an `AdminGroupId`, required, for `admin.tabs`.
|
|
187
187
|
*/
|
|
188
188
|
group?: string;
|
|
189
|
+
/**
|
|
190
|
+
* `routes.tabs` only: the id of the broker system the tab is for (`artemis`). The tab is listed only on a
|
|
191
|
+
* cluster that runs that system.
|
|
192
|
+
*/
|
|
193
|
+
system?: string;
|
|
189
194
|
/** `*.actions` only: the menu section the item is listed under. */
|
|
190
195
|
section?: ActionSection;
|
|
191
196
|
Component: ComponentType<P>;
|
package/types/sdk/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { StatusBadge } from '../ui/StatusBadge.tsx';
|
|
|
19
19
|
import { Toolbar } from '../ui/Toolbar.tsx';
|
|
20
20
|
export { CONTRACT } from '../kernel/feature.ts';
|
|
21
21
|
export type { NavContribution, PaletteSource, PluginId, RouteContributions, RahdarFeature, TopicHandler, } from '../kernel/feature.ts';
|
|
22
|
-
export { ADMIN_GROUPS, SETTINGS_GROUPS, type AdminGroupId, type MessageSelection, type
|
|
22
|
+
export { ADMIN_GROUPS, SETTINGS_GROUPS, type AdminGroupId, type MessageSelection, type SubscriptionSelection, type SettingsGroupId, type SlotContribution, type SlotContributions, type SlotEntry, type SlotName, type SlotProps, } from '../kernel/slots.ts';
|
|
23
23
|
export { NAV_GROUPS, type NavGroupId } from '../kernel/nav/groups.ts';
|
|
24
24
|
export { clusterRoute, rootRoute } from '../kernel/routing/roots.ts';
|
|
25
25
|
export { ApiError, clusterKey, heldOperationsKey, OperationHeldError, request, type HeldOperation, } from '../kernel/api/request.ts';
|
|
@@ -37,7 +37,7 @@ export { StepUpPrompt } from '../kernel/auth/StepUp.tsx';
|
|
|
37
37
|
*/
|
|
38
38
|
export { useUserStream } from '../kernel/stream/useUserStream.ts';
|
|
39
39
|
export type { StreamStatus } from '../kernel/stream/useClusterStream.ts';
|
|
40
|
-
export { ACTION_SECTIONS, type ActionHost, type ActionMode, type ActionProps, type ActionSection, type ActionTargets, type
|
|
40
|
+
export { ACTION_SECTIONS, type ActionHost, type ActionMode, type ActionProps, type ActionSection, type ActionTargets, type ChannelTarget, type ClientTarget, type ConnectionTarget, type ConsumerTarget, type DestinationTarget, type HostedDialogProps, type MessageTarget, type ProducerTarget, type ResourceRef, type RouteTarget, type SubscriptionTarget, } from '../kernel/actions/types.ts';
|
|
41
41
|
export { ActionMenuItem } from '../ui/ActionMenuItem.tsx';
|
|
42
42
|
export { CapabilityGate } from '../ui/CapabilityGate.tsx';
|
|
43
43
|
export { gateFor, type GateScope, type GateVerdict } from '../ui/capabilityGate.ts';
|
|
@@ -6,7 +6,7 @@ import { type ReactNode } from 'react';
|
|
|
6
6
|
* <ul>
|
|
7
7
|
* <li>With `tone="danger"` the action is confirmed by pressing and holding the button until it
|
|
8
8
|
* fills ({@link HoldToConfirm}), never by a click or by typing; use it for anything that removes
|
|
9
|
-
* or overwrites. The button names the action and its count, such as "Delete 37
|
|
9
|
+
* or overwrites. The button names the action and its count, such as "Delete 37 subscriptions".
|
|
10
10
|
* <li>Focus enters the dialog on Cancel, Escape closes it, and focus returns to the control that
|
|
11
11
|
* opened it.
|
|
12
12
|
* <li>While `pending` the button is busy and cannot be pressed again, and the dialog stays
|
|
@@ -22,11 +22,11 @@ export declare function ConfirmDialog({ opened, onClose, title, consequence, con
|
|
|
22
22
|
export type ConfirmDialogProps = Readonly<{
|
|
23
23
|
opened: boolean;
|
|
24
24
|
onClose: () => void;
|
|
25
|
-
/** The action as a plain line, such as "Delete
|
|
25
|
+
/** The action as a plain line, such as "Delete subscription". */
|
|
26
26
|
title: string;
|
|
27
27
|
/** What it affects: the resource, the nodes and how much data goes. */
|
|
28
28
|
consequence: ReactNode;
|
|
29
|
-
/** The exact action, such as "Delete
|
|
29
|
+
/** The exact action, such as "Delete subscription". */
|
|
30
30
|
confirmLabel: string;
|
|
31
31
|
/**
|
|
32
32
|
* The button that dismisses without acting; defaults to "Cancel". Name what is kept, such as "Keep
|
|
@@ -12,7 +12,7 @@ export type DescriptionItem = Readonly<{
|
|
|
12
12
|
* two term and value pairs side by side for a short list in a wide space. A `label` names the list
|
|
13
13
|
* for assistive technology.
|
|
14
14
|
*
|
|
15
|
-
* `oneLine` is for terms and values that are names a broker supplies (a
|
|
15
|
+
* `oneLine` is for terms and values that are names a broker supplies (a subscription, an address, a role), in
|
|
16
16
|
* a cell with a width of its own: each stays on one line, shortened in the middle when it does not fit
|
|
17
17
|
* and named in full on hover and focus, and neither track shrinks below a readable width, so a long
|
|
18
18
|
* name never squeezes its neighbour into a column of characters. A value that is not a string shortens
|
package/types/ui/EmptyState.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { type ReactNode } from 'react';
|
|
|
17
17
|
export declare function EmptyState(props: EmptyStateProps): import("react").JSX.Element;
|
|
18
18
|
export type EmptyStateProps = Readonly<{
|
|
19
19
|
kind: 'empty';
|
|
20
|
-
/** What is missing, such as "No
|
|
20
|
+
/** What is missing, such as "No subscriptions". */
|
|
21
21
|
title: string;
|
|
22
22
|
/** What the resource is and why there is none. */
|
|
23
23
|
description: ReactNode;
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* finger or a pen, or with Space or Enter on the keyboard; the hint under the button says so, and the
|
|
6
6
|
* outcome is announced.
|
|
7
7
|
*
|
|
8
|
-
* <p>`label` is the action ("Delete 37
|
|
8
|
+
* <p>`label` is the action ("Delete 37 subscriptions") and names the blast radius the button is for; the button
|
|
9
9
|
* reads exactly that, and the hint under it says to hold it. While `loading` it is busy and cannot be held again. Mouse and touch
|
|
10
10
|
* presses are Mantine's `useLongPress`; it has no keyboard, which is handled here.
|
|
11
11
|
*/
|
|
12
12
|
export declare function HoldToConfirm({ label, onConfirm, loading, disabled, describedBy, tone, }: Readonly<{
|
|
13
|
-
/** The exact action, such as "Delete
|
|
13
|
+
/** The exact action, such as "Delete subscription ORDERS" or "Apply to 2 nodes". */
|
|
14
14
|
label: string;
|
|
15
15
|
onConfirm: () => void;
|
|
16
16
|
loading?: boolean;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `loading` props, which hold their own size.
|
|
6
6
|
*/
|
|
7
7
|
export declare function LoadingState({ label, variant, blockSize, inlineSize, }: Readonly<{
|
|
8
|
-
/** What is loading, such as "Loading
|
|
8
|
+
/** What is loading, such as "Loading subscriptions". Read aloud, not shown. */
|
|
9
9
|
label: string;
|
|
10
10
|
/** `block` fills the width it is in; `inline` sits in a line of text. */
|
|
11
11
|
variant?: 'block' | 'inline';
|
|
@@ -23,7 +23,7 @@ export declare function NodeOutcomeSummary({ outcome, destructive, alreadyLabel,
|
|
|
23
23
|
*/
|
|
24
24
|
alreadyLabel?: string;
|
|
25
25
|
/**
|
|
26
|
-
* What the counts are counting, and the verb for them. Defaults to the
|
|
26
|
+
* What the counts are counting, and the verb for them. Defaults to the subscription
|
|
27
27
|
* delete's wording; a connection close affects consumers, not messages, and
|
|
28
28
|
* saying "destroyed" there would overstate what happened.
|
|
29
29
|
*/
|
package/types/ui/Toolbar.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { type ReactNode } from 'react';
|
|
|
8
8
|
* controls that belong together; a toolbar of one or two is better as plain tab stops.
|
|
9
9
|
*/
|
|
10
10
|
export declare function Toolbar({ label, start, end, arrowNavigation, }: Readonly<{
|
|
11
|
-
/** Names the toolbar for assistive technology, such as "
|
|
11
|
+
/** Names the toolbar for assistive technology, such as "Subscription filters". */
|
|
12
12
|
label: string;
|
|
13
13
|
/** Controls that act on the view, on the start side. */
|
|
14
14
|
start?: ReactNode;
|
|
@@ -10,25 +10,26 @@ export type GateVerdict = {
|
|
|
10
10
|
};
|
|
11
11
|
/** What a permission is held on: one cluster, or Rahdar itself. */
|
|
12
12
|
export type GateScope = 'cluster' | 'installation';
|
|
13
|
-
/** What is known of a refusal on one
|
|
13
|
+
/** What is known of a refusal on one subscription or destination: the permission, and who owns it, to say who can grant it. */
|
|
14
14
|
export interface ResourceDenial {
|
|
15
15
|
permission: string;
|
|
16
|
-
noun: '
|
|
16
|
+
noun: 'subscription' | 'destination';
|
|
17
17
|
/** The name of the team that owns the resource; none when no team does. */
|
|
18
18
|
owner?: string | null;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Whether a lifecycle control may act, and why not when it may not.
|
|
22
22
|
*
|
|
23
|
-
* <p>Two independent gates, in
|
|
23
|
+
* <p>Two independent gates, checked in this order (a kind that lacks the verb comes before both, in
|
|
24
|
+
* `useKindVerbRefusal`):
|
|
24
25
|
*
|
|
25
26
|
* <ul>
|
|
26
|
-
* <li><b>Permission</b> — the caller's own grants. The server is the
|
|
27
|
-
* enforcement point; this only explains, and never hides.
|
|
28
27
|
* <li><b>Capability</b> — whether the broker connection can write at all. Only
|
|
29
28
|
* a known refusal blocks. Since ADR-0049 D5 an unproven capability is
|
|
30
29
|
* reported as unknown, and blocking on the absence of evidence would stop
|
|
31
30
|
* an operator using a broker that works perfectly well.
|
|
31
|
+
* <li><b>Permission</b> — the caller's own grants. The server is the
|
|
32
|
+
* enforcement point; this only explains, and never hides.
|
|
32
33
|
* </ul>
|
|
33
34
|
*
|
|
34
35
|
* <p>`scope` is what the permission is held on, so the reason names the right place: `cluster` for
|
|
@@ -38,6 +39,6 @@ export interface ResourceDenial {
|
|
|
38
39
|
export declare function gateFor(permitted: boolean, permissionLabel: string, capability: CapabilityView | undefined,
|
|
39
40
|
/** True while the caller's grants are still being fetched. */
|
|
40
41
|
loading?: boolean, scope?: GateScope,
|
|
41
|
-
/** Given for a control on one
|
|
42
|
+
/** Given for a control on one subscription or destination the caller can see: the reason then names the permission and whom to ask. */
|
|
42
43
|
denial?: ResourceDenial): GateVerdict;
|
|
43
44
|
export {};
|
package/types/ui/notify.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type ActionVerb = Readonly<{
|
|
|
14
14
|
}>;
|
|
15
15
|
type Notice = Readonly<{
|
|
16
16
|
action: ActionVerb;
|
|
17
|
-
/** What the action acts on, such as `
|
|
17
|
+
/** What the action acts on, such as `subscription "orders"`. */
|
|
18
18
|
subject: string;
|
|
19
19
|
}>;
|
|
20
20
|
/** Settles a toast that {@link notify.pending} returned: it is replaced by the outcome. */
|
|
@@ -12,7 +12,7 @@ interface DataTableBaseProps<T> {
|
|
|
12
12
|
columns: Column<T>[];
|
|
13
13
|
data: T[];
|
|
14
14
|
rowKey: (row: T) => string;
|
|
15
|
-
/** What the table lists, as its accessible name: "
|
|
15
|
+
/** What the table lists, as its accessible name: "Subscriptions", "Connections". */
|
|
16
16
|
label: string;
|
|
17
17
|
/** Shown in place of the rows when there are none: an `EmptyState`. */
|
|
18
18
|
empty: ReactNode;
|
|
@@ -46,4 +46,13 @@ interface KindPreset {
|
|
|
46
46
|
mono: boolean;
|
|
47
47
|
}
|
|
48
48
|
export declare const KIND_PRESETS: Record<ColumnKind, KindPreset>;
|
|
49
|
+
/**
|
|
50
|
+
* The Kind column of a list of one role: what the row's system calls its kind ("Queue", "Divert"). It is
|
|
51
|
+
* `low` so a narrow table drops it first; the name still identifies the row.
|
|
52
|
+
*/
|
|
53
|
+
export declare function kindColumn<T extends {
|
|
54
|
+
kindLabel: string;
|
|
55
|
+
}>(): Column<T>;
|
|
56
|
+
/** The same column for rows that hold the label deeper, such as a dead-letter row's subscription. */
|
|
57
|
+
export declare function kindColumn<T>(label: (row: T) => string): Column<T>;
|
|
49
58
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { DataTable, STATIC_ROW_LIMIT, type DataTableProps, type TableToolbar } from './DataTable.tsx';
|
|
2
|
-
export { KIND_PRESETS, type Column, type ColumnKind, type ColumnPriority } from './columns.ts';
|
|
2
|
+
export { KIND_PRESETS, kindColumn, type Column, type ColumnKind, type ColumnPriority } from './columns.ts';
|
|
3
3
|
export { DENSITY_KEY, densityToggleLabel, useDensity, type Density } from './density.ts';
|
|
4
4
|
export type { RowMenu, RowMenuContext } from './GridTable.tsx';
|
|
5
5
|
export { MiddleTruncate } from './MiddleTruncate.tsx';
|