refactor: improve code formatting and readability across multiple files
This commit is contained in:
@@ -3,10 +3,14 @@ from __future__ import annotations
|
|||||||
from fastapi import FastAPI, HTTPException
|
from fastapi import FastAPI, HTTPException
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
|
|
||||||
from app.core.error_handling import REQUEST_ID_HEADER, _error_payload, _get_request_id, install_error_handling
|
from app.core.error_handling import (
|
||||||
|
REQUEST_ID_HEADER,
|
||||||
|
_error_payload,
|
||||||
|
_get_request_id,
|
||||||
|
install_error_handling,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_request_validation_error_includes_request_id():
|
def test_request_validation_error_includes_request_id():
|
||||||
|
|||||||
@@ -46,7 +46,9 @@ async def test_request_id_middleware_ignores_blank_client_header_and_generates_o
|
|||||||
|
|
||||||
assert isinstance(captured_request_id, str) and captured_request_id
|
assert isinstance(captured_request_id, str) and captured_request_id
|
||||||
# Header should reflect the generated id, not the blank one.
|
# Header should reflect the generated id, not the blank one.
|
||||||
values = [v for k, v in response_headers if k.lower() == REQUEST_ID_HEADER.lower().encode("latin-1")]
|
values = [
|
||||||
|
v for k, v in response_headers if k.lower() == REQUEST_ID_HEADER.lower().encode("latin-1")
|
||||||
|
]
|
||||||
assert values == [captured_request_id.encode("latin-1")]
|
assert values == [captured_request_id.encode("latin-1")]
|
||||||
|
|
||||||
|
|
||||||
@@ -81,5 +83,7 @@ async def test_request_id_middleware_does_not_duplicate_existing_header() -> Non
|
|||||||
assert start_headers is not None
|
assert start_headers is not None
|
||||||
|
|
||||||
# Ensure the middleware did not append a second copy.
|
# Ensure the middleware did not append a second copy.
|
||||||
values = [v for k, v in start_headers if k.lower() == REQUEST_ID_HEADER.lower().encode("latin-1")]
|
values = [
|
||||||
|
v for k, v in start_headers if k.lower() == REQUEST_ID_HEADER.lower().encode("latin-1")
|
||||||
|
]
|
||||||
assert values == [b"already"]
|
assert values == [b"already"]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ This package is the **Next.js** web UI for OpenClaw Mission Control.
|
|||||||
|
|
||||||
- Talks to the Mission Control **backend** over HTTP (typically `http://localhost:8000`).
|
- Talks to the Mission Control **backend** over HTTP (typically `http://localhost:8000`).
|
||||||
- Uses **React Query** for data fetching.
|
- Uses **React Query** for data fetching.
|
||||||
- Can optionally enable **Clerk** authentication (disabled by default unless you provide a *real* Clerk publishable key).
|
- Can optionally enable **Clerk** authentication (disabled by default unless you provide a _real_ Clerk publishable key).
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ Implementation detail: we gate on a conservative regex (`pk_test_...` / `pk_live
|
|||||||
- `NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL`
|
- `NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL`
|
||||||
|
|
||||||
**Important:** `frontend/.env.example` contains placeholder values like `YOUR_PUBLISHABLE_KEY`.
|
**Important:** `frontend/.env.example` contains placeholder values like `YOUR_PUBLISHABLE_KEY`.
|
||||||
Those placeholders are *not* valid keys and are intentionally treated as “Clerk disabled”.
|
Those placeholders are _not_ valid keys and are intentionally treated as “Clerk disabled”.
|
||||||
|
|
||||||
## How the frontend talks to the backend
|
## How the frontend talks to the backend
|
||||||
|
|
||||||
@@ -161,4 +161,4 @@ Clerk should be **off** unless you set a real `pk_test_...` or `pk_live_...` pub
|
|||||||
|
|
||||||
- `allowedDevOrigins: ["192.168.1.101"]`
|
- `allowedDevOrigins: ["192.168.1.101"]`
|
||||||
|
|
||||||
If you’re developing from a different hostname/IP, you may need to update `allowedDevOrigins` (or use `npm run dev` on localhost).
|
If you’re developing from a different hostname/IP, you may need to update `allowedDevOrigins` (or use `npm run dev` on localhost).
|
||||||
|
|||||||
@@ -26,15 +26,23 @@ vi.mock("next/link", () => {
|
|||||||
// wrappers still render <SignedOut/> from @clerk/nextjs (which crashes in real builds).
|
// wrappers still render <SignedOut/> from @clerk/nextjs (which crashes in real builds).
|
||||||
vi.mock("@clerk/nextjs", () => {
|
vi.mock("@clerk/nextjs", () => {
|
||||||
return {
|
return {
|
||||||
ClerkProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
ClerkProvider: ({ children }: { children: React.ReactNode }) => (
|
||||||
|
<>{children}</>
|
||||||
|
),
|
||||||
SignedIn: () => {
|
SignedIn: () => {
|
||||||
throw new Error("@clerk/nextjs SignedIn rendered (unexpected in secretless mode)");
|
throw new Error(
|
||||||
|
"@clerk/nextjs SignedIn rendered (unexpected in secretless mode)",
|
||||||
|
);
|
||||||
},
|
},
|
||||||
SignedOut: () => {
|
SignedOut: () => {
|
||||||
throw new Error("@clerk/nextjs SignedOut rendered without ClerkProvider");
|
throw new Error("@clerk/nextjs SignedOut rendered without ClerkProvider");
|
||||||
},
|
},
|
||||||
SignInButton: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
SignInButton: ({ children }: { children: React.ReactNode }) => (
|
||||||
SignOutButton: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
<>{children}</>
|
||||||
|
),
|
||||||
|
SignOutButton: ({ children }: { children: React.ReactNode }) => (
|
||||||
|
<>{children}</>
|
||||||
|
),
|
||||||
useAuth: () => ({ isLoaded: true, isSignedIn: false }),
|
useAuth: () => ({ isLoaded: true, isSignedIn: false }),
|
||||||
useUser: () => ({ isLoaded: true, isSignedIn: false, user: null }),
|
useUser: () => ({ isLoaded: true, isSignedIn: false, user: null }),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -135,7 +135,11 @@ const SSE_RECONNECT_BACKOFF = {
|
|||||||
|
|
||||||
type HeartbeatUnit = "s" | "m" | "h" | "d";
|
type HeartbeatUnit = "s" | "m" | "h" | "d";
|
||||||
|
|
||||||
const HEARTBEAT_PRESETS: Array<{ label: string; amount: number; unit: HeartbeatUnit }> = [
|
const HEARTBEAT_PRESETS: Array<{
|
||||||
|
label: string;
|
||||||
|
amount: number;
|
||||||
|
unit: HeartbeatUnit;
|
||||||
|
}> = [
|
||||||
{ label: "30s", amount: 30, unit: "s" },
|
{ label: "30s", amount: 30, unit: "s" },
|
||||||
{ label: "1m", amount: 1, unit: "m" },
|
{ label: "1m", amount: 1, unit: "m" },
|
||||||
{ label: "2m", amount: 2, unit: "m" },
|
{ label: "2m", amount: 2, unit: "m" },
|
||||||
@@ -781,22 +785,22 @@ export default function BoardGroupDetailPage() {
|
|||||||
{HEARTBEAT_PRESETS.map((preset) => {
|
{HEARTBEAT_PRESETS.map((preset) => {
|
||||||
const value = `${preset.amount}${preset.unit}`;
|
const value = `${preset.amount}${preset.unit}`;
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={value}
|
key={value}
|
||||||
type="button"
|
type="button"
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-md px-2.5 py-1 text-xs font-semibold transition-colors",
|
"rounded-md px-2.5 py-1 text-xs font-semibold transition-colors",
|
||||||
heartbeatEvery === value
|
heartbeatEvery === value
|
||||||
? "bg-slate-900 text-white"
|
? "bg-slate-900 text-white"
|
||||||
: "text-slate-600 hover:bg-slate-100 hover:text-slate-900",
|
: "text-slate-600 hover:bg-slate-100 hover:text-slate-900",
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setHeartbeatAmount(String(preset.amount));
|
setHeartbeatAmount(String(preset.amount));
|
||||||
setHeartbeatUnit(preset.unit);
|
setHeartbeatUnit(preset.unit);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{preset.label}
|
{preset.label}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
// IMPORTANT: keep this file dependency-free (no `"use client"`, no React, no Clerk imports)
|
// IMPORTANT: keep this file dependency-free (no `"use client"`, no React, no Clerk imports)
|
||||||
// so it can be used from both client and server/edge entrypoints.
|
// so it can be used from both client and server/edge entrypoints.
|
||||||
|
|
||||||
export function isLikelyValidClerkPublishableKey(key: string | undefined): key is string {
|
export function isLikelyValidClerkPublishableKey(
|
||||||
|
key: string | undefined,
|
||||||
|
): key is string {
|
||||||
if (!key) return false;
|
if (!key) return false;
|
||||||
|
|
||||||
// Clerk publishable keys look like: pk_test_... or pk_live_...
|
// Clerk publishable keys look like: pk_test_... or pk_live_...
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import { clerkMiddleware } from "@clerk/nextjs/server";
|
|||||||
import { isLikelyValidClerkPublishableKey } from "@/auth/clerkKey";
|
import { isLikelyValidClerkPublishableKey } from "@/auth/clerkKey";
|
||||||
|
|
||||||
const isClerkEnabled = () =>
|
const isClerkEnabled = () =>
|
||||||
isLikelyValidClerkPublishableKey(process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY);
|
isLikelyValidClerkPublishableKey(
|
||||||
|
process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
|
||||||
|
);
|
||||||
|
|
||||||
export default isClerkEnabled() ? clerkMiddleware() : () => NextResponse.next();
|
export default isClerkEnabled() ? clerkMiddleware() : () => NextResponse.next();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user