Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 4 additions & 176 deletions docs/reference/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1859,28 +1859,6 @@
}
}
},
"/api/v1/events/health": {
"get": {
"tags": [
"sse"
],
"summary": "Sse Health",
"description": "Get SSE service health status.",
"operationId": "sse_health_api_v1_events_health_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SSEHealthResponse"
}
}
}
}
}
}
},
"/api/v1/events/executions/{execution_id}/events": {
"get": {
"tags": [
Expand Down Expand Up @@ -9068,14 +9046,7 @@
"title": "Exit Code"
},
"error_type": {
"anyOf": [
{
"$ref": "#/components/schemas/ExecutionErrorType"
},
{
"type": "null"
}
]
"$ref": "#/components/schemas/ExecutionErrorType"
},
"error_message": {
"type": "string",
Expand Down Expand Up @@ -9896,7 +9867,6 @@
"saga_commands",
"dead_letter_queue",
"dlq_events",
"event_bus_stream",
"websocket_events"
],
"title": "KafkaTopic",
Expand Down Expand Up @@ -13104,10 +13074,7 @@
"enum": [
"connected",
"subscribed",
"heartbeat",
"shutdown",
"status",
"error"
"status"
],
"title": "SSEControlEvent",
"description": "Control events for execution SSE streams (not from Kafka)."
Expand Down Expand Up @@ -13178,31 +13145,7 @@
}
],
"title": "Message",
"description": "Human-readable message (heartbeat, shutdown)"
},
"grace_period": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Grace Period",
"description": "Shutdown grace period in seconds"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Error",
"description": "Error message (error event)"
"description": "Human-readable message (subscribed event)"
},
"status": {
"anyOf": [
Expand Down Expand Up @@ -13294,71 +13237,6 @@
"title": "SSEExecutionEventData",
"description": "Typed model for SSE execution stream event payload.\n\nThis represents the JSON data sent inside each SSE message for execution streams.\nAll fields except event_type and execution_id are optional since different\nevent types carry different data."
},
"SSEHealthResponse": {
"properties": {
"status": {
"$ref": "#/components/schemas/SSEHealthStatus",
"description": "Health status: healthy or draining"
},
"kafka_enabled": {
"type": "boolean",
"title": "Kafka Enabled",
"description": "Whether Kafka features are enabled",
"default": true
},
"active_connections": {
"type": "integer",
"title": "Active Connections",
"description": "Total number of active SSE connections"
},
"active_executions": {
"type": "integer",
"title": "Active Executions",
"description": "Number of executions being monitored"
},
"active_consumers": {
"type": "integer",
"title": "Active Consumers",
"description": "Number of active Kafka consumers"
},
"max_connections_per_user": {
"type": "integer",
"title": "Max Connections Per User",
"description": "Maximum connections allowed per user"
},
"shutdown": {
"$ref": "#/components/schemas/ShutdownStatusResponse",
"description": "Shutdown status information"
},
"timestamp": {
"type": "string",
"format": "date-time",
"title": "Timestamp",
"description": "Health check timestamp"
}
},
"type": "object",
"required": [
"status",
"active_connections",
"active_executions",
"active_consumers",
"max_connections_per_user",
"shutdown",
"timestamp"
],
"title": "SSEHealthResponse",
"description": "Response model for SSE health check."
},
"SSEHealthStatus": {
"type": "string",
"enum": [
"healthy",
"draining"
],
"title": "SSEHealthStatus",
"description": "Health status for SSE service."
},
"SagaCancellationResponse": {
"properties": {
"success": {
Expand Down Expand Up @@ -14782,57 +14660,6 @@
"title": "SettingsHistoryResponse",
"description": "Response model for settings history (limited snapshot of recent changes)"
},
"ShutdownStatusResponse": {
"properties": {
"phase": {
"type": "string",
"title": "Phase",
"description": "Current shutdown phase"
},
"initiated": {
"type": "boolean",
"title": "Initiated",
"description": "Whether shutdown has been initiated"
},
"complete": {
"type": "boolean",
"title": "Complete",
"description": "Whether shutdown is complete"
},
"active_connections": {
"type": "integer",
"title": "Active Connections",
"description": "Number of active connections"
},
"draining_connections": {
"type": "integer",
"title": "Draining Connections",
"description": "Number of connections being drained"
},
"duration": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Duration",
"description": "Duration of shutdown in seconds"
}
},
"type": "object",
"required": [
"phase",
"initiated",
"complete",
"active_connections",
"draining_connections"
],
"title": "ShutdownStatusResponse",
"description": "Response model for shutdown status."
},
"SortOrder": {
"type": "string",
"enum": [
Expand Down Expand Up @@ -15984,6 +15811,7 @@
"title": "Reason"
}
},
"additionalProperties": true,
"type": "object",
"required": [
"event_id",
Expand Down
8 changes: 6 additions & 2 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default [
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
project: './tsconfig.json',
},
globals: {
...globals.browser,
Expand All @@ -37,9 +38,12 @@ export default [
'@typescript-eslint': tseslint,
},
rules: {
...tseslint.configs.recommended.rules,
...tseslint.configs['strict-type-checked'].rules,
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'off', // Too noisy for generated code
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/only-throw-error': 'off', // API client returns unknown errors
'@typescript-eslint/no-non-null-assertion': 'off', // Needed with noUncheckedIndexedAccess
'@typescript-eslint/restrict-template-expressions': ['error', { allowNumber: true }],
'no-unused-vars': 'off',
},
},
Expand Down
33 changes: 9 additions & 24 deletions frontend/src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount } from 'svelte';
import { Router, goto } from "@mateothegreat/svelte5-router";
import { Toaster } from 'svelte-sonner';
import Header from "$components/Header.svelte";
import Footer from "$components/Footer.svelte";
import Spinner from "$components/Spinner.svelte";
import ErrorDisplay from "$components/ErrorDisplay.svelte";
import { theme } from '$stores/theme';
import { initializeAuth, AuthInitializer } from '$lib/auth-init';
import { appError } from '$stores/errorStore';
import { isAuthenticated } from '$stores/auth';
import { get } from 'svelte/store';
import { themeStore } from '$stores/theme.svelte';
Comment thread
HardMax71 marked this conversation as resolved.
import { appError } from '$stores/errorStore.svelte';
import { authStore } from '$stores/auth.svelte';

// Page components
import Home from "$routes/Home.svelte";
Expand All @@ -25,25 +23,12 @@
import AdminUsers from "$routes/admin/AdminUsers.svelte";
import AdminSettings from "$routes/admin/AdminSettings.svelte";

// Theme value derived from store with proper cleanup
let themeValue = $state('auto');
const unsubscribeTheme = theme.subscribe(value => { themeValue = value; });

// Global error state
let globalError = $state<{ error: Error | string; title?: string } | null>(null);
const unsubscribeError = appError.subscribe(value => { globalError = value; });

onDestroy(() => {
unsubscribeTheme();
unsubscribeError();
});

let authInitialized = $state(false);

// Initialize auth before rendering routes
onMount(async () => {
try {
await initializeAuth();
await authStore.initialize();
console.log('[App] Authentication initialized');
} catch (err) {
console.error('[App] Auth initialization failed:', err);
Expand All @@ -54,8 +39,8 @@

// Auth hook for protected routes
const requireAuth = async () => {
await AuthInitializer.waitForInit();
if (!get(isAuthenticated)) {
await authStore.waitForInit();
if (!authStore.isAuthenticated) {
const currentPath = window.location.pathname + window.location.search;
if (currentPath !== '/login' && currentPath !== '/register') {
sessionStorage.setItem('redirectAfterLogin', currentPath);
Expand Down Expand Up @@ -85,8 +70,8 @@
];
</script>

{#if globalError}
<ErrorDisplay error={globalError.error} title={globalError.title} />
{#if appError.current}
<ErrorDisplay error={appError.current.error} title={appError.current.title} />
{:else}
<div class="flex flex-col min-h-screen bg-bg-default dark:bg-dark-bg-default pt-16">
<Header/>
Expand Down
Loading
Loading