feat(service-integrations): phase 1 — integration architecture foundation

- Add Integration interfaces, registry, cache, encryption, and base helpers
- Add integrationType, integrationConfig, integrationEnabled to App model
- Add integration widget type to constants and validators
- Add integration fields to AppRecord, CreateAppInput, UpdateAppInput
- Update appService with encryption/decryption for integration config
- Add API routes: list integrations, test connection, fetch endpoint data
This commit is contained in:
2026-03-25 22:02:34 +03:00
parent c62ca79adb
commit 114dee57a8
12 changed files with 445 additions and 6 deletions
+16 -3
View File
@@ -74,7 +74,10 @@ export const createAppSchema = z.object({
healthcheckInterval: z.number().int().min(30).max(86400).optional(),
healthcheckMethod: z.enum([HealthcheckMethod.GET, HealthcheckMethod.HEAD]).optional(),
healthcheckExpectedStatus: z.number().int().min(100).max(599).optional(),
healthcheckTimeout: z.number().int().min(1000).max(30000).optional()
healthcheckTimeout: z.number().int().min(1000).max(30000).optional(),
integrationType: z.string().max(50).nullable().optional(),
integrationConfig: z.string().max(10000).nullable().optional(),
integrationEnabled: z.boolean().optional()
});
export const updateAppSchema = z.object({
@@ -89,7 +92,10 @@ export const updateAppSchema = z.object({
healthcheckInterval: z.number().int().min(30).max(86400).optional(),
healthcheckMethod: z.enum([HealthcheckMethod.GET, HealthcheckMethod.HEAD]).optional(),
healthcheckExpectedStatus: z.number().int().min(100).max(599).optional(),
healthcheckTimeout: z.number().int().min(1000).max(30000).optional()
healthcheckTimeout: z.number().int().min(1000).max(30000).optional(),
integrationType: z.string().max(50).nullable().optional(),
integrationConfig: z.string().max(10000).nullable().optional(),
integrationEnabled: z.boolean().optional()
});
// --- Board ---
@@ -185,7 +191,8 @@ const allWidgetTypes = [
WidgetType.MARKDOWN,
WidgetType.METRIC,
WidgetType.LINK_GROUP,
WidgetType.CAMERA
WidgetType.CAMERA,
WidgetType.INTEGRATION
] as const;
export const createWidgetSchema = z.object({
@@ -371,6 +378,12 @@ export const cameraWidgetConfigSchema = z.object({
aspectRatio: z.string().max(20).optional()
});
export const integrationWidgetConfigSchema = z.object({
appId: z.string().min(1, 'App ID is required'),
endpointId: z.string().min(1, 'Endpoint ID is required'),
refreshInterval: z.number().int().min(5).max(3600).optional()
});
// --- New entity schemas for Phases 4-7 ---
export const createTagSchema = z.object({