Skip to content
This repository was archived by the owner on Mar 5, 2026. It is now read-only.

feat: refactor routes and components for functions and triggers#16

Merged
andersonleal merged 1 commit intomainfrom
feat/fixes
Feb 17, 2026
Merged

feat: refactor routes and components for functions and triggers#16
andersonleal merged 1 commit intomainfrom
feat/fixes

Conversation

@andersonleal
Copy link
Copy Markdown
Contributor

@andersonleal andersonleal commented Feb 17, 2026

feat: refactor routes and components for functions and triggers

Summary

Splits the combined Handlers page into dedicated Functions and Triggers routes, improves the Sidebar with an engine health popover, and updates navigation and route structure across the console.

Key Changes

  • Route split: handlers.tsxfunctions.tsx + triggers.tsx
    • /handlers replaced by /functions and /triggers
    • Each route has its own loader, state, and UI tailored to functions vs triggers
  • Sidebar enhancements:
    • Engine health popover with component status (logs, metrics, spans, otel)
    • Uses TanStack Query (healthQuery) instead of manual fetch polling
    • Click-outside and Escape to close health panel
    • New Triggers nav item with Zap icon
  • Navigation: Functions href updated from /handlers to /functions; Triggers added
  • Route updates: config, logs, states, streams, traces, and index routes adjusted for new structure
  • Console-rust bridge: Additional function/trigger registration support

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Refactoring (no functional changes)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Checklist

  • My code follows the project's style guidelines (Biome)
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Additional Context

Files changed (15):

  • Sidebar.tsx — Health popover, nav items, TanStack Query
  • functions.tsx — New route (from handlers)
  • triggers.tsx — New route (from handlers)
  • handlers.tsx — Removed
  • index.tsx, routeTree.gen.ts, config.tsx, logs.tsx, states.tsx, streams.tsx, traces.tsx — Route/config updates
  • globals.css — Minor style addition
  • bridge/functions.rs, bridge/triggers.rs — Rust bridge updates

Summary by CodeRabbit

  • New Features

    • Added engine health monitoring panel in sidebar showing component status.
    • Introduced new Triggers page for managing and testing triggers (HTTP, Cron, Event).
    • New Functions page with searchable function list, details panel, and direct invocation capability.
    • Dashboard metric cards now link directly to Functions, Triggers, and Streams pages.
  • Navigation Changes

    • Renamed Functions route from /handlers to /functions.
    • Added new Triggers navigation item in sidebar.
  • UI Improvements

    • Removed connection status indicators from multiple pages for cleaner interface.
    • Enhanced keyboard accessibility with Escape key support.
    • Updated sidebar logo styling with rounded corners.

- Introduced new routes for Functions and Triggers, replacing the previous Handlers route.
- Updated Sidebar and routeTree to reflect the new structure, including the addition of Triggers.
- Enhanced the Functions page with improved UI for function invocation and management.
- Removed deprecated Handlers route and adjusted related components for consistency.
- Updated various components to improve layout and styling across the application.

feat: add /_console/invoke endpoint for direct function invocation

Registers engine::console::invoke bridge function and POST /_console/invoke
HTTP trigger, enabling the frontend to invoke any function by ID via the
bridge SDK (same mechanism iii-tui uses).

feat: add invoke play button to function list cards

feat: add direct invoke UI for CORE and non-HTTP functions

fix: strip leading slash from api_path to prevent double-slash in URLs

When HTTP triggers return api_path with a leading slash (e.g. /todo),
the UI was producing double-slashes like http://host:port//todo.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

The PR introduces health-based engine status UI with a detailed monitoring panel in the Sidebar, restructures routing by renaming /handlers to /functions and adding a new /triggers route, implements new comprehensive pages for managing functions and triggers with search/grouping/invocation capabilities, refactors the dashboard with navigation links, adds backend Rust handlers for function invocation, and removes connection status indicators from various pages.

Changes

Cohort / File(s) Summary
Health Monitoring UI
packages/console-frontend/src/components/layout/Sidebar.tsx
Integrated health query data to display engine status with a detailed popover panel showing component health indicators. Added health-driven online status, local state for panel visibility, outside-click dismissal, and keyboard accessibility (Escape key). Updated status pill to show online/offline with health count. Adjusted layout padding and expanded header styling.
Route System Refactoring
packages/console-frontend/src/routeTree.gen.ts
Migrated route from /handlers to /functions with new FunctionsRoute constant and type declarations. Added new /triggers route with TriggersRoute constant. Updated all public interfaces (FileRoutesByFullPath, FileRoutesByTo, FileRoutesById, FileRouteTypes, RootRouteChildren) and TanStack Router module augmentations to reflect route changes.
Route Config & Header Styling
packages/console-frontend/src/routes/config.tsx, packages/console-frontend/src/routes/states.tsx, packages/console-frontend/src/routes/streams.tsx, packages/console-frontend/src/routes/traces.tsx
Increased vertical header padding from py-2 md:py-3 to py-3 md:py-4 across multiple route files for consistent spacing adjustments.
Functions Management Page
packages/console-frontend/src/routes/functions.tsx
New route component implementing searchable, grouped list of functions with filtering by internal/system scope. Includes function selection with detail panel, request template generation from schema, editable JSON input, function invocation with error handling, and copy-to-clipboard support. Prefetches functions and worker data in loader.
Triggers Management Page
packages/console-frontend/src/routes/triggers.tsx
Comprehensive new route component for trigger management with grouping by trigger type (HTTP, Cron, Event, Other). Features include per-trigger detail panels, HTTP testing UI with path/query parameters and request body, cron schedule display with manual run, event payload editor, invocation result display via JsonViewer, copy utilities, and responsive layout.
Removed Handlers Page
packages/console-frontend/src/routes/handlers.tsx
Removed entire file containing legacy /handlers route and HandlersPage component with complex function/trigger browsing and invocation logic. Functionality split into new /functions and /triggers routes.
Dashboard Refactoring
packages/console-frontend/src/routes/index.tsx
Refactored dashboard layout: removed stream connection state and WifiOff icons; enhanced MetricsChart with optional href prop for clickable navigation to /functions, /triggers, and /streams; introduced more compact, dense grid layouts; removed verbose multi-column blocks; simplified system status display; added last-update timestamp rendering; adjusted typography, spacing, and border styles.
Connection Status Cleanup
packages/console-frontend/src/routes/logs.tsx
Removed isConnected state and Live/Offline badge rendering. Replaced dynamic connection indicators with simplified Paused badge logic. Removed Wifi icon imports and related connected state updates in otelLogsData effect.
Stylesheet Update
packages/console-frontend/src/styles/globals.css
Added single blank line before Table styles section with no functional changes.
Backend Function Invocation
packages/console-rust/src/bridge/functions.rs
Added new internal handler handle_invoke that extracts function_id, defaults input data, and calls target function with 30-second timeout. Registered new public engine::console::invoke function in register_functions, exposing invocation via external API.
Backend Trigger Registration
packages/console-rust/src/bridge/triggers.rs
Added new API trigger mapping for engine::console::invoke routed to POST _console/invoke, enabling HTTP-based function invocation without modifying existing triggers or registration flow.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant UI as Functions/Triggers Page
    participant API as Console API
    participant Handler as Rust Handler
    participant Engine as Engine

    User->>UI: Select function/trigger & enter params
    UI->>UI: Parse JSON request body
    alt Valid JSON
        UI->>API: POST /invoke with function_id & params
        API->>Handler: handle_invoke(function_id, input)
        Handler->>Handler: Extract function_id & default data
        Handler->>Engine: Call function with 30s timeout
        Engine-->>Handler: Return result
        Handler-->>API: Success/Error response
        API-->>UI: Invocation result
        UI->>UI: Display result & duration
        User-->>UI: View result in JsonViewer
    else Invalid JSON
        UI-->>User: Show JSON validation error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • iii-hq/console#3 — Overlaps on refactoring bridge functions file signatures and type changes that interact with the new invoke handler registration.
  • iii-hq/console#13 — Aligns on Rust bridge naming convention migration to engine::console::* style for the new invoke endpoint.
  • iii-hq/console#5 — Shares changes to functions/triggers query parameterization and prefetch/useQuery usage patterns across frontend routes.

Suggested reviewers

  • sergiofilhowz
  • guibeira
  • ytallo

🐰 A rabbit hops through the code with glee,
Health panels gleam and routes flow free!
Functions grouped, triggers arranged,
Invocation flows—oh, how things have changed!
The console now dances with triggers and grace,
A speedier, healthier interface space. 🏃‍♂️

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: refactor routes and components for functions and triggers' directly summarizes the main changes: splitting the handlers route into separate functions and triggers pages, updating navigation, and refactoring related components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/fixes

Comment @coderabbitai help to get the list of available commands and usage tips.

@andersonleal andersonleal merged commit 919af32 into main Feb 17, 2026
1 check was pending
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (8)
packages/console-frontend/src/routes/triggers.tsx (1)

158-162: Consider handling clipboard API errors.

navigator.clipboard.writeText can reject on certain browsers or when the page doesn't have focus. A try-catch or .catch() would prevent unhandled promise rejections.

♻️ Proposed fix
 const copyToClipboard = (text: string, key: string) => {
-    navigator.clipboard.writeText(text)
-    setCopied(key)
-    setTimeout(() => setCopied(null), 2000)
+    navigator.clipboard.writeText(text).then(() => {
+      setCopied(key)
+      setTimeout(() => setCopied(null), 2000)
+    }).catch(() => {
+      // Clipboard API failed, ignore silently
+    })
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/triggers.tsx` around lines 158 - 162,
The copyToClipboard function calls navigator.clipboard.writeText without
handling rejections; update copyToClipboard to await or attach a .catch() to
navigator.clipboard.writeText so any errors are handled, only call
setCopied(key) on success, and on failure log the error (or show a user-facing
notification) and avoid calling setCopied; reference the copyToClipboard
function and navigator.clipboard.writeText when making the change.
packages/console-frontend/src/routes/functions.tsx (1)

110-114: Consider handling clipboard API errors.

Same pattern as triggers.tsx - navigator.clipboard.writeText can reject. Consider extracting this into a shared utility with error handling.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/functions.tsx` around lines 110 - 114,
The copyToClipboard function currently calls navigator.clipboard.writeText
without handling rejections; update it to await or attach .then/.catch to
navigator.clipboard.writeText(text), only call setCopied(key) and schedule
clearing on success, and log or surface errors on failure. Extract this logic
into a shared utility (e.g., export a safeCopyToClipboard or
writeTextToClipboard helper) and replace the inline copyToClipboard in
functions.tsx (and mirror the change in triggers.tsx) so both components reuse
the promise-handling, error-logging, and success-only setCopied behavior.
packages/console-rust/src/bridge/functions.rs (1)

579-609: Consider applying format validation to the function_id parameter.

The handle_invoke function accepts a user-provided function identifier without validation, unlike other handlers which use hardcoded function names. While the function properly handles invocation errors, applying format validation (similar to the existing validate_flow_id pattern) would improve robustness and prevent unexpected invocations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-rust/src/bridge/functions.rs` around lines 579 - 609, The
handle_invoke function accepts an unvalidated function_id string; add format
validation similar to validate_flow_id to reject malformed IDs before calling
bridge.call_with_timeout. Modify handle_invoke to call an existing
validate_flow_id-like helper (or add validate_function_id) on the extracted
function_id and return error_response(IIIError::Handler(...)) when validation
fails, and only proceed to call bridge.call_with_timeout(&function_id, ...) when
the ID passes validation; reference the function name handle_invoke, the
variable function_id, and the call bridge.call_with_timeout in your changes.
packages/console-frontend/src/routes/index.tsx (5)

485-510: Same issue: repeated streams.filter((s) => !s.internal) calls.

This filter is called 5 times in this section alone. Apply the same memoization pattern:

♻️ Suggested refactor
const userStreams = useMemo(
  () => streams.filter((s) => !s.internal),
  [streams],
)

Then use userStreams instead of inline filters.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/index.tsx` around lines 485 - 510, The
code repeatedly calls streams.filter((s) => !s.internal) causing redundant
computation; create a memoized variable (e.g., userStreams) using useMemo(() =>
streams.filter(s => !s.internal), [streams]) and replace all inline filter calls
in this JSX block (the map, length checks, slice, and "+N more" calculation)
with userStreams to avoid repeated filtering; ensure you import/use React's
useMemo in the component and update references like s.id, slice(0,2), and
length-based conditional rendering to reference userStreams instead of
streams.filter(...).

351-419: Memoize repeated filter operations to avoid redundant iterations.

The same filters are called multiple times within the render:

  • userTriggers.filter((t) => t.trigger_type === 'http') — 5 times
  • userTriggers.filter((t) => t.trigger_type === 'cron') — 2 times
  • userTriggers.filter((t) => t.trigger_type === 'event') — 2 times

While not critical for small datasets, this is inefficient and harder to maintain.

♻️ Suggested refactor: memoize filtered arrays

Add these memoized values near the other useMemo calls (around line 233):

const httpTriggers = useMemo(
  () => userTriggers.filter((t) => t.trigger_type === 'http'),
  [userTriggers],
)
const cronTriggers = useMemo(
  () => userTriggers.filter((t) => t.trigger_type === 'cron'),
  [userTriggers],
)
const eventTriggers = useMemo(
  () => userTriggers.filter((t) => t.trigger_type === 'event'),
  [userTriggers],
)

Then replace inline filters with these variables throughout the component.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/index.tsx` around lines 351 - 419, The
render repeatedly calls userTriggers.filter(...) for 'http', 'cron', and
'event', causing redundant iterations; create memoized arrays using useMemo
(e.g., const httpTriggers = useMemo(() => userTriggers.filter(t =>
t.trigger_type === 'http'), [userTriggers]) and similarly cronTriggers and
eventTriggers) near the other useMemo calls, then replace all inline
userTriggers.filter(...) usages in the component with httpTriggers,
cronTriggers, and eventTriggers (also update counts, .slice(0,4), .map and the
"+N more" calculation to use these variables).

146-181: Apply cursor-pointer only when href is provided.

The content div always has cursor-pointer (line 148), but when no href is passed, the card isn't clickable. This creates a misleading affordance for users.

♻️ Suggested fix
 function MetricsChart({ title, value, data, color, icon: Icon, trend, href }: MetricsChartProps) {
   const content = (
-    <div className="bg-dark-gray/40 rounded-xl border border-border p-4 transition-all duration-200 group-hover:border-muted/40 group-hover:-translate-y-0.5 cursor-pointer">
+    <div className={`bg-dark-gray/40 rounded-xl border border-border p-4 transition-all duration-200 ${href ? 'group-hover:border-muted/40 group-hover:-translate-y-0.5 cursor-pointer' : ''}`}>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/index.tsx` around lines 146 - 181, The
MetricsChart component currently applies "cursor-pointer" on the content div
regardless of clickability; update MetricsChart so the "cursor-pointer" class is
only present when href is provided (either remove it from the static content div
and add it to the Link wrapper when rendering the link, or conditionally include
it in the content div's className based on href). Locate the MetricsChart
function and adjust the className on the div that currently contains
"cursor-pointer" (and/or the Link element) so non-link cards do not show a
pointer cursor while linked cards retain it.

53-97: Consider using unique gradient IDs to prevent SVG ID collisions.

The hardcoded id="skeleton-pulse" gradient will be duplicated in the DOM if multiple MiniChart components render with insufficient data simultaneously. While the visual impact is minimal since all skeletons share the same animation, SVG ID collisions can cause unexpected behavior in some browsers.

♻️ Suggested fix using React's useId
+import { useId } from 'react'
+
 function MiniChart({ data, color, height = 40 }: MiniChartProps) {
+  const gradientId = useId()
+
   if (data.length < 2) {
     return (
       <svg viewBox={`0 0 100 ${height}`} className="w-full h-8" preserveAspectRatio="none">
         <defs>
-          <linearGradient id="skeleton-pulse" x1="0" y1="0" x2="1" y2="0">
+          <linearGradient id={gradientId} x1="0" y1="0" x2="1" y2="0">
             ...
           </linearGradient>
         </defs>
         ...
         <polygon
           points="0,32 0,28 12,22 25,26 37,18 50,20 62,14 75,18 87,12 100,16 100,32"
-          fill="url(`#skeleton-pulse`)"
+          fill={`url(#${gradientId})`}
         />
       </svg>
     )
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/index.tsx` around lines 53 - 97, The SVG
uses a hardcoded id="skeleton-pulse" which can collide when multiple MiniChart
instances render; change the component (e.g., MiniChart in routes/index.tsx) to
generate a unique gradient id (use React's useId or a uniqueId helper) and
substitute that id for the linearGradient id and the polygon fill url reference
(and any other url(#...) references) so each instance gets its own gradient id.

245-248: streamsChartData produces a flat line since it uses current count for all history points.

Unlike functionsChartData and triggersChartData which read from metricsHistory (m.functions_count, m.triggers_count), this maps every history entry to the current streams count. The resulting chart will always be a horizontal line.

If historical stream counts are available in the metrics data, consider using them. Otherwise, this is fine as-is, but the mini-chart won't show any meaningful trend.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/index.tsx` around lines 245 - 248,
streamsChartData is using the current streams.length for every metricsHistory
point, producing a flat line; change the mapping to read the historical stream
count from metricsHistory (e.g., use m.streams_count or the appropriate property
on each metrics entry) similar to how functionsChartData and triggersChartData
use m.functions_count and m.triggers_count, and fall back to streams.filter(s =>
!s.internal).length only if the historical value is undefined.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/console-frontend/src/routes/functions.tsx`:
- Around line 26-34: The loader passed to createFileRoute for Route (component:
FunctionsPage) starts prefetching with Promise.allSettled([...]) but doesn't
return that promise, so the router won't await it; update the loader to return
the Promise.allSettled(...) result (i.e., return Promise.allSettled([
queryClient.prefetchQuery(functionsQuery()),
queryClient.prefetchQuery(workersQuery) ])) so TanStack Router will await the
prefetches.

In `@packages/console-frontend/src/routes/triggers.tsx`:
- Around line 30-38: The loader for Route invokes Promise.allSettled([...]) but
doesn't return it, so TanStack Router won't wait for
queryClient.prefetchQuery(triggersQuery()) and
queryClient.prefetchQuery(functionsQuery()) to complete; fix by returning the
Promise from the loader (e.g., add a return before Promise.allSettled or make
the loader async and return/await the Promise.allSettled result) so Route.loader
returns the prefetch promise and the router will await the queries.

---

Nitpick comments:
In `@packages/console-frontend/src/routes/functions.tsx`:
- Around line 110-114: The copyToClipboard function currently calls
navigator.clipboard.writeText without handling rejections; update it to await or
attach .then/.catch to navigator.clipboard.writeText(text), only call
setCopied(key) and schedule clearing on success, and log or surface errors on
failure. Extract this logic into a shared utility (e.g., export a
safeCopyToClipboard or writeTextToClipboard helper) and replace the inline
copyToClipboard in functions.tsx (and mirror the change in triggers.tsx) so both
components reuse the promise-handling, error-logging, and success-only setCopied
behavior.

In `@packages/console-frontend/src/routes/index.tsx`:
- Around line 485-510: The code repeatedly calls streams.filter((s) =>
!s.internal) causing redundant computation; create a memoized variable (e.g.,
userStreams) using useMemo(() => streams.filter(s => !s.internal), [streams])
and replace all inline filter calls in this JSX block (the map, length checks,
slice, and "+N more" calculation) with userStreams to avoid repeated filtering;
ensure you import/use React's useMemo in the component and update references
like s.id, slice(0,2), and length-based conditional rendering to reference
userStreams instead of streams.filter(...).
- Around line 351-419: The render repeatedly calls userTriggers.filter(...) for
'http', 'cron', and 'event', causing redundant iterations; create memoized
arrays using useMemo (e.g., const httpTriggers = useMemo(() =>
userTriggers.filter(t => t.trigger_type === 'http'), [userTriggers]) and
similarly cronTriggers and eventTriggers) near the other useMemo calls, then
replace all inline userTriggers.filter(...) usages in the component with
httpTriggers, cronTriggers, and eventTriggers (also update counts, .slice(0,4),
.map and the "+N more" calculation to use these variables).
- Around line 146-181: The MetricsChart component currently applies
"cursor-pointer" on the content div regardless of clickability; update
MetricsChart so the "cursor-pointer" class is only present when href is provided
(either remove it from the static content div and add it to the Link wrapper
when rendering the link, or conditionally include it in the content div's
className based on href). Locate the MetricsChart function and adjust the
className on the div that currently contains "cursor-pointer" (and/or the Link
element) so non-link cards do not show a pointer cursor while linked cards
retain it.
- Around line 53-97: The SVG uses a hardcoded id="skeleton-pulse" which can
collide when multiple MiniChart instances render; change the component (e.g.,
MiniChart in routes/index.tsx) to generate a unique gradient id (use React's
useId or a uniqueId helper) and substitute that id for the linearGradient id and
the polygon fill url reference (and any other url(#...) references) so each
instance gets its own gradient id.
- Around line 245-248: streamsChartData is using the current streams.length for
every metricsHistory point, producing a flat line; change the mapping to read
the historical stream count from metricsHistory (e.g., use m.streams_count or
the appropriate property on each metrics entry) similar to how
functionsChartData and triggersChartData use m.functions_count and
m.triggers_count, and fall back to streams.filter(s => !s.internal).length only
if the historical value is undefined.

In `@packages/console-frontend/src/routes/triggers.tsx`:
- Around line 158-162: The copyToClipboard function calls
navigator.clipboard.writeText without handling rejections; update
copyToClipboard to await or attach a .catch() to navigator.clipboard.writeText
so any errors are handled, only call setCopied(key) on success, and on failure
log the error (or show a user-facing notification) and avoid calling setCopied;
reference the copyToClipboard function and navigator.clipboard.writeText when
making the change.

In `@packages/console-rust/src/bridge/functions.rs`:
- Around line 579-609: The handle_invoke function accepts an unvalidated
function_id string; add format validation similar to validate_flow_id to reject
malformed IDs before calling bridge.call_with_timeout. Modify handle_invoke to
call an existing validate_flow_id-like helper (or add validate_function_id) on
the extracted function_id and return error_response(IIIError::Handler(...)) when
validation fails, and only proceed to call
bridge.call_with_timeout(&function_id, ...) when the ID passes validation;
reference the function name handle_invoke, the variable function_id, and the
call bridge.call_with_timeout in your changes.

Comment on lines +26 to +34
export const Route = createFileRoute('/functions')({
component: FunctionsPage,
loader: ({ context: { queryClient } }) => {
Promise.allSettled([
queryClient.prefetchQuery(functionsQuery()),
queryClient.prefetchQuery(workersQuery),
])
},
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Loader should return the promise for proper data prefetching.

Same issue as in triggers.tsx - the loader doesn't return the promise, so TanStack Router won't await the prefetch.

🔧 Proposed fix
 loader: ({ context: { queryClient } }) => {
-    Promise.allSettled([
+    return Promise.allSettled([
       queryClient.prefetchQuery(functionsQuery()),
       queryClient.prefetchQuery(workersQuery),
     ])
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const Route = createFileRoute('/functions')({
component: FunctionsPage,
loader: ({ context: { queryClient } }) => {
Promise.allSettled([
queryClient.prefetchQuery(functionsQuery()),
queryClient.prefetchQuery(workersQuery),
])
},
})
export const Route = createFileRoute('/functions')({
component: FunctionsPage,
loader: ({ context: { queryClient } }) => {
return Promise.allSettled([
queryClient.prefetchQuery(functionsQuery()),
queryClient.prefetchQuery(workersQuery),
])
},
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/functions.tsx` around lines 26 - 34, The
loader passed to createFileRoute for Route (component: FunctionsPage) starts
prefetching with Promise.allSettled([...]) but doesn't return that promise, so
the router won't await it; update the loader to return the
Promise.allSettled(...) result (i.e., return Promise.allSettled([
queryClient.prefetchQuery(functionsQuery()),
queryClient.prefetchQuery(workersQuery) ])) so TanStack Router will await the
prefetches.

Comment on lines +30 to +38
export const Route = createFileRoute('/triggers')({
component: TriggersPage,
loader: ({ context: { queryClient } }) => {
Promise.allSettled([
queryClient.prefetchQuery(triggersQuery()),
queryClient.prefetchQuery(functionsQuery()),
])
},
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Loader should return the promise for proper data prefetching.

The loader calls Promise.allSettled but doesn't return it. While the queries will still fire, TanStack Router won't wait for them before rendering, potentially causing a flash of loading state.

🔧 Proposed fix
 loader: ({ context: { queryClient } }) => {
-    Promise.allSettled([
+    return Promise.allSettled([
       queryClient.prefetchQuery(triggersQuery()),
       queryClient.prefetchQuery(functionsQuery()),
     ])
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const Route = createFileRoute('/triggers')({
component: TriggersPage,
loader: ({ context: { queryClient } }) => {
Promise.allSettled([
queryClient.prefetchQuery(triggersQuery()),
queryClient.prefetchQuery(functionsQuery()),
])
},
})
export const Route = createFileRoute('/triggers')({
component: TriggersPage,
loader: ({ context: { queryClient } }) => {
return Promise.allSettled([
queryClient.prefetchQuery(triggersQuery()),
queryClient.prefetchQuery(functionsQuery()),
])
},
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/console-frontend/src/routes/triggers.tsx` around lines 30 - 38, The
loader for Route invokes Promise.allSettled([...]) but doesn't return it, so
TanStack Router won't wait for queryClient.prefetchQuery(triggersQuery()) and
queryClient.prefetchQuery(functionsQuery()) to complete; fix by returning the
Promise from the loader (e.g., add a return before Promise.allSettled or make
the loader async and return/await the Promise.allSettled result) so Route.loader
returns the prefetch promise and the router will await the queries.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant