Extract alert overrides projection model owner

This commit is contained in:
rcourtman
2026-03-22 22:14:31 +00:00
parent f02fc8455b
commit d19c5dbf06
7 changed files with 465 additions and 326 deletions
@@ -328,8 +328,10 @@ ownership,
`frontend-modern/src/features/alerts/alertsConfigurationModel.ts` for backend
config normalization, factory defaults, docker-gap validation, and save-payload
serialization,
`frontend-modern/src/features/alerts/useAlertOverridesState.ts` for raw
override normalization plus resource-backed override projection, and
`frontend-modern/src/features/alerts/alertOverridesModel.ts` for raw override
normalization plus resource-backed override projection, and
`frontend-modern/src/features/alerts/useAlertOverridesState.ts` for reactive
override state, derived resource lists, and overview handoff, and
`frontend-modern/src/features/alerts/useAlertDestinationsState.ts` for
notification destination reload and persistence.
`frontend-modern/src/features/alerts/useAlertWebhookDestinationsState.ts` now
@@ -498,8 +498,10 @@ for the default-backed mutable configuration snapshot plus apply/capture/reset
ownership,
`frontend-modern/src/features/alerts/alertsConfigurationModel.ts` for config
normalization, factory defaults, docker-gap validation, and payload
serialization, `frontend-modern/src/features/alerts/useAlertOverridesState.ts`
for override projection and thresholds-facing resource selectors, and
serialization, `frontend-modern/src/features/alerts/alertOverridesModel.ts`
for override normalization and resource-backed projection, and
`frontend-modern/src/features/alerts/useAlertOverridesState.ts`
for reactive override state and thresholds-facing resource selectors, and
`frontend-modern/src/features/alerts/useAlertDestinationsState.ts` for
notification destination reload and persistence.
`frontend-modern/src/features/alerts/useAlertWebhookDestinationsState.ts` now
@@ -0,0 +1,75 @@
import { describe, expect, it } from 'vitest';
import type { Resource } from '@/types/resource';
import {
buildProjectedOverrides,
normalizeRawOverridesConfig,
} from '../alertOverridesModel';
const makeResource = (overrides: Partial<Resource>): Resource =>
({
id: 'resource-1',
name: 'resource-1',
type: 'vm',
...overrides,
}) as Resource;
describe('alertOverridesModel', () => {
it('normalizes disk override ids into canonical agent disk keys', () => {
expect(
normalizeRawOverridesConfig({
'agent:agent-1/disk:NVMe 0n1': {
disk: { trigger: 90, clear: 85 },
} as any,
}),
).toEqual({
'agent:agent-1/disk:nvme-0n1': {
disk: { trigger: 90, clear: 85 },
},
});
});
it('projects guest overrides without requiring agent-backed resources', () => {
const guest = makeResource({
id: 'vm-100',
name: 'db-01',
type: 'vm',
platformId: 'qemu/100',
platformData: {
vmid: 100,
node: 'pve-1',
instance: 'qemu/100',
},
});
expect(
buildProjectedOverrides({
rawConfig: {
'vm-100': {
cpu: { trigger: 95, clear: 90 },
disabled: true,
} as any,
},
nodeResources: [],
vmResources: [guest],
containerResources: [],
storageResources: [],
agentResourceList: [],
dockerHostResources: [],
getChildren: () => [],
pbsInstanceById: new Map(),
}),
).toEqual([
expect.objectContaining({
id: 'vm-100',
type: 'guest',
resourceType: 'VM',
disabled: true,
thresholds: {
cpu: 95,
},
}),
]);
});
});
@@ -0,0 +1,352 @@
import type { PBSInstance } from '@/types/api';
import type { RawOverrideConfig } from '@/types/alerts';
import type { Resource } from '@/types/resource';
import { getActionableAgentIdFromResource } from '@/utils/agentResources';
import { isAppContainerDiscoveryResourceType } from '@/utils/discoveryTarget';
import {
extractTriggerValues,
getAlertResourceDisplayLabel,
guessNumericId,
platformData,
} from './helpers';
import type { Override } from './types';
const asRecord = (value: unknown): Record<string, unknown> | undefined =>
value && typeof value === 'object' ? (value as Record<string, unknown>) : undefined;
const asString = (value: unknown): string | undefined =>
typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
const uniqueIds = (...values: unknown[]): string[] => {
const ids: string[] = [];
const seen = new Set<string>();
values.forEach((value) => {
const normalized = asString(value);
if (!normalized || seen.has(normalized)) return;
seen.add(normalized);
ids.push(normalized);
});
return ids;
};
export const normalizeRawOverridesConfig = (
rawOverrides: Record<string, RawOverrideConfig>,
): Record<string, RawOverrideConfig> => {
const cleanedOverrides: Record<string, RawOverrideConfig> = {};
for (const [key, value] of Object.entries(rawOverrides)) {
const diskMatch = key.match(/^(agent:.+\/disk:)(.+)$/);
if (diskMatch) {
const normalized =
diskMatch[2]
.toLowerCase()
.replace(/[^a-z0-9]/g, '-')
.replace(/-{2,}/g, '-')
.replace(/^-|-$/g, '') || 'unknown';
cleanedOverrides[diskMatch[1] + normalized] = value;
continue;
}
cleanedOverrides[key] = value;
}
return cleanedOverrides;
};
export const hostOverrideIdCandidates = (resource: Resource): string[] => {
const data = platformData(resource);
const agent = asRecord(data?.agent);
return uniqueIds(
getActionableAgentIdFromResource(resource),
resource.discoveryTarget?.agentId,
resource.agent?.agentId,
agent?.agentId,
data?.agentId,
resource.id,
);
};
export const dockerHostOverrideIdCandidates = (resource: Resource): string[] => {
const data = platformData(resource);
const docker = asRecord(data?.docker);
const discoveryTarget = resource.discoveryTarget;
return uniqueIds(
isAppContainerDiscoveryResourceType(discoveryTarget?.resourceType)
? discoveryTarget?.resourceId
: undefined,
docker?.hostSourceId,
data?.hostSourceId,
discoveryTarget?.agentId,
resource.id,
);
};
export const dockerContainerOverrideIdCandidates = (
host: Resource,
shortId: string,
): string[] =>
uniqueIds(
...dockerHostOverrideIdCandidates(host).map((hostId) => `docker:${hostId}/${shortId}`),
);
interface BuildProjectedOverridesArgs {
rawConfig: Record<string, RawOverrideConfig>;
nodeResources: Resource[];
vmResources: Resource[];
containerResources: Resource[];
storageResources: Resource[];
agentResourceList: Resource[];
dockerHostResources: Resource[];
getChildren: (resourceId: string) => Resource[];
pbsInstanceById: Map<string, PBSInstance>;
}
export const buildProjectedOverrides = ({
rawConfig,
nodeResources,
vmResources,
containerResources,
storageResources,
agentResourceList,
dockerHostResources,
getChildren,
pbsInstanceById,
}: BuildProjectedOverridesArgs): Override[] => {
const overridesList: Override[] = [];
const dockerHostMap = new Map<string, Resource>();
const dockerContainerMap = new Map<
string,
{ host: Resource; container: Resource; containerShortId: string }
>();
const agentMap = new Map<string, Resource>();
const storageCoords = (resource: Resource): { node: string; instance: string } => {
const data = platformData(resource);
if (resource.type === 'datastore') {
const instance =
(data?.pbsInstanceId as string | undefined) ||
resource.parentId ||
resource.platformId ||
'pbs';
const node = (data?.pbsInstanceName as string | undefined) || instance;
return { node, instance };
}
return {
node: (data?.node as string | undefined) || '',
instance: (data?.instance as string | undefined) || resource.platformId || '',
};
};
dockerHostResources.forEach((host) => {
dockerHostOverrideIdCandidates(host).forEach((id) => {
dockerHostMap.set(id, host);
});
const containers = getChildren(host.id).filter((resource) => resource.type === 'app-container');
containers.forEach((container) => {
const shortId = container.id.includes('/') ? container.id.split('/').pop()! : container.id;
dockerContainerOverrideIdCandidates(host, shortId).forEach((resourceId) => {
dockerContainerMap.set(resourceId, { host, container, containerShortId: shortId });
});
});
});
agentResourceList.forEach((agentResource) => {
hostOverrideIdCandidates(agentResource).forEach((id) => {
agentMap.set(id, agentResource);
});
});
Object.entries(rawConfig).forEach(([key, thresholds]) => {
const dockerHost = dockerHostMap.get(key);
if (dockerHost) {
overridesList.push({
id: key,
name: getAlertResourceDisplayLabel(dockerHost),
type: 'dockerHost',
resourceType: 'Container Runtime',
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const dockerContainer = dockerContainerMap.get(key);
if (dockerContainer) {
const { host, container, containerShortId } = dockerContainer;
const containerName = getAlertResourceDisplayLabel(container, containerShortId);
overridesList.push({
id: key,
name: containerName,
type: 'dockerContainer',
resourceType: 'Container',
node: getAlertResourceDisplayLabel(host),
instance: getAlertResourceDisplayLabel(host),
disabled: thresholds.disabled || false,
disableConnectivity: thresholds.disableConnectivity || false,
poweredOffSeverity:
thresholds.poweredOffSeverity === 'critical'
? 'critical'
: thresholds.poweredOffSeverity === 'warning'
? 'warning'
: undefined,
thresholds: extractTriggerValues(thresholds),
});
return;
}
if (key.startsWith('docker:')) {
const [, rest] = key.split(':', 2);
const [hostId, containerId] = (rest || '').split('/', 2);
if (containerId) {
overridesList.push({
id: key,
name: containerId,
type: 'dockerContainer',
resourceType: 'Container',
node: hostId,
disabled: thresholds.disabled || false,
disableConnectivity: thresholds.disableConnectivity || false,
poweredOffSeverity:
thresholds.poweredOffSeverity === 'critical'
? 'critical'
: thresholds.poweredOffSeverity === 'warning'
? 'warning'
: undefined,
thresholds: extractTriggerValues(thresholds),
});
return;
}
overridesList.push({
id: key,
name: hostId || key,
type: 'dockerHost',
resourceType: 'Container Runtime',
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const diskMatch = key.match(/^agent:(.+)\/disk:(.+)$/);
if (diskMatch) {
const [, agentId, diskLabel] = diskMatch;
const agent = agentMap.get(agentId);
overridesList.push({
id: key,
name: diskLabel.replace(/-/g, '/'),
type: 'agentDisk',
resourceType: 'Agent Disk',
node: agent ? getAlertResourceDisplayLabel(agent) : agentId,
disabled: thresholds.disabled || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const agentResource = agentMap.get(key);
if (agentResource) {
const displayName = getAlertResourceDisplayLabel(agentResource);
const data = platformData(agentResource);
const agent = asRecord(data?.agent);
overridesList.push({
id: key,
name: displayName,
type: 'agent',
resourceType: 'Agent',
node: displayName,
instance:
asString(agent?.platform) ||
asString(agent?.osName) ||
asString(data?.platform) ||
asString(data?.osName) ||
'',
disabled: thresholds.disabled || false,
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
if (key.startsWith('pbs-')) {
const pbs = pbsInstanceById.get(key);
if (pbs) {
overridesList.push({
id: key,
name: pbs.name,
type: 'pbs',
resourceType: 'PBS',
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
}
return;
}
const node = nodeResources.find((resource) => resource.id === key);
if (node) {
overridesList.push({
id: key,
name: getAlertResourceDisplayLabel(node),
type: 'agent',
resourceType: 'Agent',
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const storage = storageResources.find((resource) => resource.id === key);
if (storage) {
const coords = storageCoords(storage);
overridesList.push({
id: key,
name: getAlertResourceDisplayLabel(storage),
type: 'storage',
resourceType: 'Storage',
node: coords.node,
instance: coords.instance,
disabled: thresholds.disabled || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const guest =
vmResources.find((resource) => resource.id === key) ||
containerResources.find((resource) => resource.id === key);
if (!guest) {
return;
}
const data = platformData(guest);
overridesList.push({
id: key,
name: getAlertResourceDisplayLabel(guest),
type: 'guest',
resourceType: guest.type === 'vm' ? 'VM' : 'Container',
vmid: (data?.vmid as number | undefined) ?? guessNumericId(guest.id),
node: (data?.node as string | undefined) ?? '',
instance: (data?.instance as string | undefined) ?? guest.platformId,
disabled: thresholds.disabled || false,
disableConnectivity: thresholds.disableConnectivity || false,
poweredOffSeverity:
thresholds.poweredOffSeverity === 'critical'
? 'critical'
: thresholds.poweredOffSeverity === 'warning'
? 'warning'
: undefined,
thresholds: extractTriggerValues(thresholds),
backup: thresholds.backup,
snapshot: thresholds.snapshot,
});
});
return overridesList;
};
@@ -3,16 +3,10 @@ import { createEffect, createMemo, createSignal, type Accessor } from 'solid-js'
import type { PBSInstance, PMGInstance } from '@/types/api';
import type { RawOverrideConfig } from '@/types/alerts';
import type { Resource, ResourceType } from '@/types/resource';
import { getActionableAgentIdFromResource, hasAgentFacet } from '@/utils/agentResources';
import { isAppContainerDiscoveryResourceType } from '@/utils/discoveryTarget';
import { hasAgentFacet } from '@/utils/agentResources';
import { pbsInstanceFromResource, pmgInstanceFromResource } from '@/utils/resourceStateAdapters';
import {
extractTriggerValues,
getAlertResourceDisplayLabel,
guessNumericId,
platformData,
} from './helpers';
import { buildProjectedOverrides, normalizeRawOverridesConfig } from './alertOverridesModel';
import type { Override } from './types';
export interface AlertOverridesStateProps {
@@ -23,91 +17,12 @@ export interface AlertOverridesStateProps {
setOverviewOverrides: (value: Override[]) => void;
}
const asRecord = (value: unknown): Record<string, unknown> | undefined =>
value && typeof value === 'object' ? (value as Record<string, unknown>) : undefined;
const asString = (value: unknown): string | undefined =>
typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
const uniqueIds = (...values: unknown[]): string[] => {
const ids: string[] = [];
const seen = new Set<string>();
values.forEach((value) => {
const normalized = asString(value);
if (!normalized || seen.has(normalized)) return;
seen.add(normalized);
ids.push(normalized);
});
return ids;
};
const normalizeRawOverridesConfig = (
rawOverrides: Record<string, RawOverrideConfig>,
): Record<string, RawOverrideConfig> => {
const cleanedOverrides: Record<string, RawOverrideConfig> = {};
for (const [key, value] of Object.entries(rawOverrides)) {
const diskMatch = key.match(/^(agent:.+\/disk:)(.+)$/);
if (diskMatch) {
const normalized =
diskMatch[2]
.toLowerCase()
.replace(/[^a-z0-9]/g, '-')
.replace(/-{2,}/g, '-')
.replace(/^-|-$/g, '') || 'unknown';
cleanedOverrides[diskMatch[1] + normalized] = value;
continue;
}
cleanedOverrides[key] = value;
}
return cleanedOverrides;
};
export function useAlertOverridesState(props: AlertOverridesStateProps) {
const [overrides, setOverrides] = createSignal<Override[]>([]);
const [rawOverridesConfig, setRawOverridesConfig] = createSignal<
Record<string, RawOverrideConfig>
>({});
const pd = platformData;
const hostOverrideIdCandidates = (resource: Resource): string[] => {
const data = pd(resource);
const agent = asRecord(data?.agent);
return uniqueIds(
getActionableAgentIdFromResource(resource),
resource.discoveryTarget?.agentId,
resource.agent?.agentId,
agent?.agentId,
data?.agentId,
resource.id,
);
};
const dockerHostOverrideIdCandidates = (resource: Resource): string[] => {
const data = pd(resource);
const docker = asRecord(data?.docker);
const discoveryTarget = resource.discoveryTarget;
return uniqueIds(
isAppContainerDiscoveryResourceType(discoveryTarget?.resourceType)
? discoveryTarget?.resourceId
: undefined,
docker?.hostSourceId,
data?.hostSourceId,
discoveryTarget?.agentId,
resource.id,
);
};
const dockerContainerOverrideIdCandidates = (host: Resource, shortId: string): string[] =>
uniqueIds(
...dockerHostOverrideIdCandidates(host).map((hostId) => `docker:${hostId}/${shortId}`),
);
const allGuests = createMemo(
() => [
...props.byType('vm'),
@@ -180,239 +95,16 @@ export function useAlertOverridesState(props: AlertOverridesStateProps) {
.filter((resource) => resource.type === 'storage' || resource.type === 'datastore');
const agentResourceList = agentResources();
const dockerHostResources = props.byType('docker-host');
const overridesList: Override[] = [];
const dockerHostMap = new Map<string, Resource>();
const dockerContainerMap = new Map<
string,
{ host: Resource; container: Resource; containerShortId: string }
>();
const agentMap = new Map<string, Resource>();
const storageCoords = (resource: Resource): { node: string; instance: string } => {
const data = pd(resource);
if (resource.type === 'datastore') {
const instance =
(data?.pbsInstanceId as string | undefined) ||
resource.parentId ||
resource.platformId ||
'pbs';
const node = (data?.pbsInstanceName as string | undefined) || instance;
return { node, instance };
}
return {
node: (data?.node as string | undefined) || '',
instance: (data?.instance as string | undefined) || resource.platformId || '',
};
};
dockerHostResources.forEach((host) => {
dockerHostOverrideIdCandidates(host).forEach((id) => {
dockerHostMap.set(id, host);
});
const containers = props
.children(host.id)
.filter((resource) => resource.type === 'app-container');
containers.forEach((container) => {
const shortId = container.id.includes('/') ? container.id.split('/').pop()! : container.id;
dockerContainerOverrideIdCandidates(host, shortId).forEach((resourceId) => {
dockerContainerMap.set(resourceId, { host, container, containerShortId: shortId });
});
});
});
agentResourceList.forEach((agentResource) => {
hostOverrideIdCandidates(agentResource).forEach((id) => {
agentMap.set(id, agentResource);
});
});
Object.entries(rawConfig).forEach(([key, thresholds]) => {
const dockerHost = dockerHostMap.get(key);
if (dockerHost) {
overridesList.push({
id: key,
name: getAlertResourceDisplayLabel(dockerHost),
type: 'dockerHost',
resourceType: 'Container Runtime',
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const dockerContainer = dockerContainerMap.get(key);
if (dockerContainer) {
const { host, container, containerShortId } = dockerContainer;
const containerName = getAlertResourceDisplayLabel(container, containerShortId);
overridesList.push({
id: key,
name: containerName,
type: 'dockerContainer',
resourceType: 'Container',
node: getAlertResourceDisplayLabel(host),
instance: getAlertResourceDisplayLabel(host),
disabled: thresholds.disabled || false,
disableConnectivity: thresholds.disableConnectivity || false,
poweredOffSeverity:
thresholds.poweredOffSeverity === 'critical'
? 'critical'
: thresholds.poweredOffSeverity === 'warning'
? 'warning'
: undefined,
thresholds: extractTriggerValues(thresholds),
});
return;
}
if (key.startsWith('docker:')) {
const [, rest] = key.split(':', 2);
const [hostId, containerId] = (rest || '').split('/', 2);
if (containerId) {
overridesList.push({
id: key,
name: containerId,
type: 'dockerContainer',
resourceType: 'Container',
node: hostId,
disabled: thresholds.disabled || false,
disableConnectivity: thresholds.disableConnectivity || false,
poweredOffSeverity:
thresholds.poweredOffSeverity === 'critical'
? 'critical'
: thresholds.poweredOffSeverity === 'warning'
? 'warning'
: undefined,
thresholds: extractTriggerValues(thresholds),
});
return;
}
overridesList.push({
id: key,
name: hostId || key,
type: 'dockerHost',
resourceType: 'Container Runtime',
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const diskMatch = key.match(/^agent:(.+)\/disk:(.+)$/);
if (diskMatch) {
const [, agentId, diskLabel] = diskMatch;
const agent = agentMap.get(agentId);
overridesList.push({
id: key,
name: diskLabel.replace(/-/g, '/'),
type: 'agentDisk',
resourceType: 'Agent Disk',
node: agent ? getAlertResourceDisplayLabel(agent) : agentId,
disabled: thresholds.disabled || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const agentResource = agentMap.get(key);
if (agentResource) {
const displayName = getAlertResourceDisplayLabel(agentResource);
const data = pd(agentResource);
const agent = asRecord(data?.agent);
overridesList.push({
id: key,
name: displayName,
type: 'agent',
resourceType: 'Agent',
node: displayName,
instance:
asString(agent?.platform) ||
asString(agent?.osName) ||
asString(data?.platform) ||
asString(data?.osName) ||
'',
disabled: thresholds.disabled || false,
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
if (key.startsWith('pbs-')) {
const pbs = pbsInstanceById().get(key);
if (pbs) {
overridesList.push({
id: key,
name: pbs.name,
type: 'pbs',
resourceType: 'PBS',
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
}
return;
}
const node = nodeResources.find((resource) => resource.id === key);
if (node) {
overridesList.push({
id: key,
name: getAlertResourceDisplayLabel(node),
type: 'agent',
resourceType: 'Agent',
disableConnectivity: thresholds.disableConnectivity || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const storage = storageResources.find((resource) => resource.id === key);
if (storage) {
const coords = storageCoords(storage);
overridesList.push({
id: key,
name: getAlertResourceDisplayLabel(storage),
type: 'storage',
resourceType: 'Storage',
node: coords.node,
instance: coords.instance,
disabled: thresholds.disabled || false,
thresholds: extractTriggerValues(thresholds),
});
return;
}
const guest =
vmResources.find((resource) => resource.id === key) ||
containerResources.find((resource) => resource.id === key);
if (!guest) {
return;
}
const data = pd(guest);
overridesList.push({
id: key,
name: getAlertResourceDisplayLabel(guest),
type: 'guest',
resourceType: guest.type === 'vm' ? 'VM' : 'Container',
vmid: (data?.vmid as number | undefined) ?? guessNumericId(guest.id),
node: (data?.node as string | undefined) ?? '',
instance: (data?.instance as string | undefined) ?? guest.platformId,
disabled: thresholds.disabled || false,
disableConnectivity: thresholds.disableConnectivity || false,
poweredOffSeverity:
thresholds.poweredOffSeverity === 'critical'
? 'critical'
: thresholds.poweredOffSeverity === 'warning'
? 'warning'
: undefined,
thresholds: extractTriggerValues(thresholds),
backup: thresholds.backup,
snapshot: thresholds.snapshot,
});
const overridesList = buildProjectedOverrides({
rawConfig,
nodeResources,
vmResources,
containerResources,
storageResources,
agentResourceList,
dockerHostResources,
getChildren: props.children,
pbsInstanceById: pbsInstanceById(),
});
const currentOverrides = overrides();
@@ -4,6 +4,7 @@ import alertsConfigurationSurfaceSource from '@/features/alerts/AlertsConfigurat
import alertsConfigurationStateSource from '@/features/alerts/useAlertsConfigurationState.ts?raw';
import alertsConfigurationSnapshotStateSource from '@/features/alerts/useAlertsConfigurationSnapshotState.ts?raw';
import alertsConfigurationModelSource from '@/features/alerts/alertsConfigurationModel.ts?raw';
import alertOverridesModelSource from '@/features/alerts/alertOverridesModel.ts?raw';
import alertOverridesStateSource from '@/features/alerts/useAlertOverridesState.ts?raw';
import alertDestinationsStateSource from '@/features/alerts/useAlertDestinationsState.ts?raw';
import alertDestinationsTabStateSource from '@/features/alerts/useAlertDestinationsTabState.ts?raw';
@@ -278,9 +279,16 @@ describe('tab path helpers', () => {
expect(alertsConfigurationModelSource).toContain('const createHysteresisThreshold =');
expect(alertsConfigurationModelSource).toContain('const normalizeGap =');
expect(alertOverridesStateSource).toContain('export function useAlertOverridesState');
expect(alertOverridesStateSource).toContain('getActionableAgentIdFromResource');
expect(alertOverridesStateSource).toContain('pbsInstanceFromResource');
expect(alertOverridesStateSource).toContain('buildProjectedOverrides');
expect(alertOverridesStateSource).not.toContain('getActionableAgentIdFromResource');
expect(alertOverridesStateSource).not.toContain('const hostOverrideIdCandidates =');
expect(alertOverridesStateSource).toContain('props.setOverviewOverrides(overrides())');
expect(alertOverridesModelSource).toContain('export const normalizeRawOverridesConfig =');
expect(alertOverridesModelSource).toContain('export const hostOverrideIdCandidates =');
expect(alertOverridesModelSource).toContain('export const dockerHostOverrideIdCandidates =');
expect(alertOverridesModelSource).toContain('export const buildProjectedOverrides =');
expect(alertOverridesModelSource).toContain('getActionableAgentIdFromResource');
expect(alertDestinationsStateSource).toContain('export function useAlertDestinationsState');
expect(alertDestinationsStateSource).toContain('NotificationsAPI.getEmailConfig');
expect(alertDestinationsStateSource).toContain('NotificationsAPI.updateEmailConfig');
@@ -328,6 +328,7 @@ import alertsConfigurationSurfaceSource from '@/features/alerts/AlertsConfigurat
import alertsConfigurationStateSource from '@/features/alerts/useAlertsConfigurationState.ts?raw';
import alertsConfigurationSnapshotStateSource from '@/features/alerts/useAlertsConfigurationSnapshotState.ts?raw';
import alertsConfigurationModelSource from '@/features/alerts/alertsConfigurationModel.ts?raw';
import alertOverridesModelSource from '@/features/alerts/alertOverridesModel.ts?raw';
import alertOverridesStateSource from '@/features/alerts/useAlertOverridesState.ts?raw';
import alertDestinationsStateSource from '@/features/alerts/useAlertDestinationsState.ts?raw';
import alertDestinationsTabStateSource from '@/features/alerts/useAlertDestinationsTabState.ts?raw';
@@ -2862,9 +2863,16 @@ describe('frontend resource type boundaries', () => {
expect(alertsConfigurationModelSource).toContain('const createHysteresisThreshold =');
expect(alertsConfigurationModelSource).toContain('const normalizeGap =');
expect(alertOverridesStateSource).toContain('export function useAlertOverridesState');
expect(alertOverridesStateSource).toContain('getActionableAgentIdFromResource');
expect(alertOverridesStateSource).toContain('pbsInstanceFromResource');
expect(alertOverridesStateSource).toContain('buildProjectedOverrides');
expect(alertOverridesStateSource).not.toContain('getActionableAgentIdFromResource');
expect(alertOverridesStateSource).not.toContain('const hostOverrideIdCandidates =');
expect(alertOverridesStateSource).toContain('props.setOverviewOverrides(overrides())');
expect(alertOverridesModelSource).toContain('export const normalizeRawOverridesConfig =');
expect(alertOverridesModelSource).toContain('export const hostOverrideIdCandidates =');
expect(alertOverridesModelSource).toContain('export const dockerHostOverrideIdCandidates =');
expect(alertOverridesModelSource).toContain('export const buildProjectedOverrides =');
expect(alertOverridesModelSource).toContain('getActionableAgentIdFromResource');
expect(alertDestinationsStateSource).toContain('getAlertDestinationsConfigLoadError');
expect(alertDestinationsStateSource).toContain('NotificationsAPI.getEmailConfig');
expect(alertDestinationsStateSource).toContain('NotificationsAPI.updateEmailConfig');