fix(service-integrations): resolve type errors and test failures

- Fix CreateAppInput nullable types for integration fields
- Add type casts in IntegrationWidget renderer dispatching
- Guard decryptAppIntegration against missing fields in test mocks
This commit is contained in:
2026-03-25 22:19:56 +03:00
parent 55e220bc07
commit 44bbf7b410
3 changed files with 20 additions and 11 deletions
@@ -5,7 +5,15 @@
import ProgressRenderer from './ProgressRenderer.svelte'; import ProgressRenderer from './ProgressRenderer.svelte';
import AlertBannerRenderer from './AlertBannerRenderer.svelte'; import AlertBannerRenderer from './AlertBannerRenderer.svelte';
import ChartRenderer from './ChartRenderer.svelte'; import ChartRenderer from './ChartRenderer.svelte';
import type { IntegrationData } from '$lib/server/integrations/types.js'; import type {
IntegrationData,
StatCardData,
GaugeData,
ListData,
ProgressData,
AlertBannerData,
ChartData
} from '$lib/server/integrations/types.js';
interface Props { interface Props {
config: { config: {
@@ -61,17 +69,17 @@
</div> </div>
{:else if integrationData} {:else if integrationData}
{#if integrationData.renderer === 'stat-card'} {#if integrationData.renderer === 'stat-card'}
<StatCardRenderer data={integrationData.data} /> <StatCardRenderer data={integrationData.data as StatCardData} />
{:else if integrationData.renderer === 'gauge'} {:else if integrationData.renderer === 'gauge'}
<GaugeRenderer data={integrationData.data} /> <GaugeRenderer data={integrationData.data as GaugeData} />
{:else if integrationData.renderer === 'list'} {:else if integrationData.renderer === 'list'}
<ListRenderer data={integrationData.data} /> <ListRenderer data={integrationData.data as ListData} />
{:else if integrationData.renderer === 'progress'} {:else if integrationData.renderer === 'progress'}
<ProgressRenderer data={integrationData.data} /> <ProgressRenderer data={integrationData.data as ProgressData} />
{:else if integrationData.renderer === 'alert-banner'} {:else if integrationData.renderer === 'alert-banner'}
<AlertBannerRenderer data={integrationData.data} /> <AlertBannerRenderer data={integrationData.data as AlertBannerData} />
{:else if integrationData.renderer === 'chart'} {:else if integrationData.renderer === 'chart'}
<ChartRenderer data={integrationData.data} /> <ChartRenderer data={integrationData.data as ChartData} />
{:else} {:else}
<div class="p-4 text-sm text-muted-foreground">Unknown renderer: {integrationData.renderer}</div> <div class="p-4 text-sm text-muted-foreground">Unknown renderer: {integrationData.renderer}</div>
{/if} {/if}
+3 -2
View File
@@ -2,10 +2,11 @@ import { prisma } from '../prisma.js';
import type { CreateAppInput, UpdateAppInput } from '$lib/types/app.js'; import type { CreateAppInput, UpdateAppInput } from '$lib/types/app.js';
import { encrypt, tryDecrypt } from '../integrations/encryption.js'; import { encrypt, tryDecrypt } from '../integrations/encryption.js';
function decryptAppIntegration<T extends { integrationConfig: string | null }>(app: T): T { function decryptAppIntegration<T extends Record<string, unknown>>(app: T): T {
if (!('integrationConfig' in app) || !app.integrationConfig) return app;
return { return {
...app, ...app,
integrationConfig: tryDecrypt(app.integrationConfig) integrationConfig: tryDecrypt(app.integrationConfig as string)
}; };
} }
+2 -2
View File
@@ -35,8 +35,8 @@ export interface CreateAppInput {
readonly healthcheckMethod?: HealthcheckMethod; readonly healthcheckMethod?: HealthcheckMethod;
readonly healthcheckExpectedStatus?: number; readonly healthcheckExpectedStatus?: number;
readonly healthcheckTimeout?: number; readonly healthcheckTimeout?: number;
readonly integrationType?: string; readonly integrationType?: string | null;
readonly integrationConfig?: string; readonly integrationConfig?: string | null;
readonly integrationEnabled?: boolean; readonly integrationEnabled?: boolean;
readonly createdById?: string; readonly createdById?: string;
} }