diff --git a/flake.nix b/flake.nix
index 9f01d57..0072096 100644
--- a/flake.nix
+++ b/flake.nix
@@ -35,6 +35,7 @@
pkg-config
sqlite
gemini-cli
+ biome
];
buildInputs = [ ];
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath (nativeBuildInputs ++ buildInputs);
diff --git a/frontend/biome.json b/frontend/biome.json
new file mode 100644
index 0000000..fa60a6c
--- /dev/null
+++ b/frontend/biome.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "https://biomejs.dev/schemas/2.3.6/schema.json",
+ "vcs": {
+ "enabled": true,
+ "clientKind": "git",
+ "useIgnoreFile": true
+ },
+ "files": {
+ "includes": ["**", "!!**/dist"]
+ },
+ "formatter": {
+ "enabled": true,
+ "formatWithErrors": true,
+ "attributePosition": "auto",
+ "indentStyle": "space",
+ "indentWidth": 2,
+ "lineWidth": 110,
+ "lineEnding": "lf"
+ },
+ "javascript": {
+ "formatter": {
+ "arrowParentheses": "always",
+ "bracketSameLine": false,
+ "bracketSpacing": true,
+ "jsxQuoteStyle": "double",
+ "quoteProperties": "asNeeded",
+ "semicolons": "always",
+ "trailingCommas": "all"
+ }
+ },
+ "json": {
+ "formatter": {
+ "trailingCommas": "none"
+ }
+ },
+ "css": {
+ "parser": {
+ "tailwindDirectives": true
+ }
+ }
+}
diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js
index 2e7af2b..2aa7205 100644
--- a/frontend/postcss.config.js
+++ b/frontend/postcss.config.js
@@ -3,4 +3,4 @@ export default {
tailwindcss: {},
autoprefixer: {},
},
-}
+};
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 7445af5..e941b74 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,13 +1,13 @@
-import { Component, createSignal, onMount, Show } from 'solid-js';
-import RulesList from './components/RulesList';
-import CommandQueue from './components/CommandQueue';
-import Login from './components/Login';
-import ChangePassword from './components/ChangePassword';
-import RequestLog from './components/RequestLog';
-import { authStore } from './api/auth';
+import { Component, createSignal, onMount, Show } from "solid-js";
+import RulesList from "./components/RulesList";
+import CommandQueue from "./components/CommandQueue";
+import Login from "./components/Login";
+import ChangePassword from "./components/ChangePassword";
+import RequestLog from "./components/RequestLog";
+import { authStore } from "./api/auth";
const App: Component = () => {
- const [activeTab, setActiveTab] = createSignal<'rules' | 'commands' | 'logs'>('rules');
+ const [activeTab, setActiveTab] = createSignal<"rules" | "commands" | "logs">("rules");
const [isAuthenticated, setIsAuthenticated] = createSignal(false);
const [showChangePassword, setShowChangePassword] = createSignal(false);
@@ -31,9 +31,7 @@ const App: Component = () => {
-
- My Linspirer Control Panel
-
+
My Linspirer Control Panel
- }>
+
No commands in queue }
+ >
{(cmd) => (
-
+
{cmd.status}
-
- {formatDate(cmd.received_at)}
-
+ {formatDate(cmd.received_at)}
{JSON.stringify(cmd.command, null, 2)}
@@ -56,19 +57,19 @@ const CommandQueue: Component = () => {
-
+
updateCommandStatus(cmd.id, 'verified')}
+ onClick={() => updateCommandStatus(cmd.id, "verified")}
>
Verify
updateCommandStatus(cmd.id, 'rejected')}
+ onClick={() => updateCommandStatus(cmd.id, "rejected")}
>
Reject
diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx
index 2fb8654..23b946b 100644
--- a/frontend/src/components/Login.tsx
+++ b/frontend/src/components/Login.tsx
@@ -1,40 +1,40 @@
-import { Component, createSignal } from 'solid-js';
-import { Button } from './ui/Button';
-import { Card } from './ui/Card';
-import { Input } from './ui/Input';
+import { Component, createSignal } from "solid-js";
+import { Button } from "./ui/Button";
+import { Card } from "./ui/Card";
+import { Input } from "./ui/Input";
interface LoginProps {
onLoginSuccess: (token: string) => void;
}
const Login: Component
= (props) => {
- const [password, setPassword] = createSignal('');
- const [error, setError] = createSignal('');
+ const [password, setPassword] = createSignal("");
+ const [error, setError] = createSignal("");
const [isLoading, setIsLoading] = createSignal(false);
const handleSubmit = async (e: Event) => {
e.preventDefault();
- setError('');
+ setError("");
setIsLoading(true);
try {
- const response = await fetch('/admin/api/login', {
- method: 'POST',
+ const response = await fetch("/admin/api/login", {
+ method: "POST",
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
body: JSON.stringify({ password: password() }),
});
if (!response.ok) {
- const errorData = await response.json().catch(() => ({ error: 'Login failed' }));
- throw new Error(errorData.error || 'Invalid password');
+ const errorData = await response.json().catch(() => ({ error: "Login failed" }));
+ throw new Error(errorData.error || "Invalid password");
}
const data = await response.json();
props.onLoginSuccess(data.token);
} catch (err) {
- setError(err instanceof Error ? err.message : 'Login failed');
+ setError(err instanceof Error ? err.message : "Login failed");
} finally {
setIsLoading(false);
}
@@ -43,9 +43,7 @@ const Login: Component = (props) => {
return (
-
- My Linspirer Admin Login
-
+ My Linspirer Admin Login
diff --git a/frontend/src/components/RequestDetails.tsx b/frontend/src/components/RequestDetails.tsx
index b09e505..3618fdb 100644
--- a/frontend/src/components/RequestDetails.tsx
+++ b/frontend/src/components/RequestDetails.tsx
@@ -1,8 +1,8 @@
-import { Component, createSignal, For, Show } from 'solid-js';
-import type { RequestLog } from '../types';
-import { Button } from './ui/Button';
-import { CardContent, CardFooter, CardHeader } from './ui/Card';
-import { Modal, ModalContent } from './ui/Modal';
+import { Component, createSignal, For, Show } from "solid-js";
+import type { RequestLog } from "../types";
+import { Button } from "./ui/Button";
+import { CardContent, CardFooter, CardHeader } from "./ui/Card";
+import { Modal, ModalContent } from "./ui/Modal";
interface TreeViewProps {
data: any;
@@ -12,17 +12,17 @@ interface TreeViewProps {
const TreeView: Component = (props) => {
const [isOpen, setIsOpen] = createSignal(props.isRoot ?? false);
- const isObject = typeof props.data === 'object' && props.data !== null;
+ const isObject = typeof props.data === "object" && props.data !== null;
const renderValue = (value: any) => {
switch (typeof value) {
- case 'string':
+ case "string":
return "{value}";
- case 'number':
+ case "number":
return {value};
- case 'boolean':
+ case "boolean":
return {String(value)};
- case 'object':
+ case "object":
if (value === null) return null;
// This case is handled by recursive TreeView
default:
@@ -36,9 +36,7 @@ const TreeView: Component = (props) => {
class="flex items-center cursor-pointer hover:bg-gray-100 rounded px-1"
onClick={() => setIsOpen(!isOpen())}
>
-
- {isObject ? (isOpen() ? '▼' : '►') : ''}
-
+ {isObject ? (isOpen() ? "▼" : "►") : ""}
{props.name}:
{renderValue(props.data)}
@@ -55,7 +53,6 @@ const TreeView: Component = (props) => {
);
};
-
interface RequestDetailsProps {
log: RequestLog;
onClose: () => void;
@@ -67,7 +64,9 @@ const RequestDetails: Component = (props) => {
Request Details
- {props.log.method} at {new Date(props.log.created_at).toLocaleString()}
+
+ {props.log.method} at {new Date(props.log.created_at).toLocaleString()}
+
@@ -88,11 +87,7 @@ const RequestDetails: Component = (props) => {
-
+
Close
diff --git a/frontend/src/components/RequestLog.tsx b/frontend/src/components/RequestLog.tsx
index 8b368a1..06c55ba 100644
--- a/frontend/src/components/RequestLog.tsx
+++ b/frontend/src/components/RequestLog.tsx
@@ -1,14 +1,14 @@
-import { Component, createMemo, createResource, createSignal, For, Show } from 'solid-js';
-import { logsApi } from '../api/client';
-import type { RequestLog as RequestLogType } from '../types';
-import { Card } from './ui/Card';
-import { Input } from './ui/Input';
-import { Select } from './ui/Select';
-import RequestDetails from './RequestDetails';
+import { Component, createMemo, createResource, createSignal, For, Show } from "solid-js";
+import { logsApi } from "../api/client";
+import type { RequestLog as RequestLogType } from "../types";
+import { Card } from "./ui/Card";
+import { Input } from "./ui/Input";
+import { Select } from "./ui/Select";
+import RequestDetails from "./RequestDetails";
const RequestLog: Component = () => {
- const [search, setSearch] = createSignal('');
- const [method, setMethod] = createSignal('');
+ const [search, setSearch] = createSignal("");
+ const [method, setMethod] = createSignal("");
const [selectedLog, setSelectedLog] = createSignal(null);
const [logs] = createResource(
@@ -17,12 +17,12 @@ const RequestLog: Component = () => {
// Solid's createResource refetches when the source accessor changes.
// We can add a debounce here if we want to avoid too many requests.
return logsApi.list(filters);
- }
+ },
);
const methods = createMemo(() => {
if (!logs()) return [];
- const allMethods = logs()!.map(log => log.method);
+ const allMethods = logs()!.map((log) => log.method);
return [...new Set(allMethods)];
});
@@ -38,7 +38,6 @@ const RequestLog: Component = () => {
return new Date(dateStr).toLocaleString();
};
-
return (
<>
@@ -61,9 +60,7 @@ const RequestLog: Component = () => {
class="min-w-[200px]"
>
-
- {(m) => }
-
+ {(m) => }
@@ -74,22 +71,40 @@ const RequestLog: Component = () => {
| Method |
Time |
- Request Body |
+
+ Request Body
+ |
- Loading... | }>
-
-
- No logs found.
+ |
+ Loading...
|
- }>
+ }
+ >
+
+
+ No logs found.
+ |
+
+ }
+ >
{(log) => (
handleLogClick(log)}>
- | {log.method} |
- {formatDate(log.created_at)} |
+
+ {log.method}
+ |
+
+ {formatDate(log.created_at)}
+ |
{JSON.stringify(log.request_body)}
|
@@ -102,9 +117,7 @@ const RequestLog: Component = () => {
-
- {(log) => }
-
+ {(log) => }
>
);
};
diff --git a/frontend/src/components/RulesList.tsx b/frontend/src/components/RulesList.tsx
index fa675fb..8ef9b9e 100644
--- a/frontend/src/components/RulesList.tsx
+++ b/frontend/src/components/RulesList.tsx
@@ -1,19 +1,19 @@
-import { Component, createSignal, createResource, For, Show } from 'solid-js';
-import { rulesApi } from '../api/client';
-import type { InterceptionRule } from '../types';
-import { Button } from './ui/Button';
-import { Card } from './ui/Card';
-import { Input } from './ui/Input';
-import { Select } from './ui/Select';
-import { Textarea } from './ui/Textarea';
+import { Component, createSignal, createResource, For, Show } from "solid-js";
+import { rulesApi } from "../api/client";
+import type { InterceptionRule } from "../types";
+import { Button } from "./ui/Button";
+import { Card } from "./ui/Card";
+import { Input } from "./ui/Input";
+import { Select } from "./ui/Select";
+import { Textarea } from "./ui/Textarea";
const RulesList: Component = () => {
const [rules, { refetch }] = createResource(rulesApi.list);
const [showEditor, setShowEditor] = createSignal(false);
const [editingId, setEditingId] = createSignal(null);
- const [editingMethod, setEditingMethod] = createSignal('');
- const [editingAction, setEditingAction] = createSignal<'passthrough' | 'modify' | 'replace'>('passthrough');
- const [editingResponse, setEditingResponse] = createSignal('');
+ const [editingMethod, setEditingMethod] = createSignal("");
+ const [editingAction, setEditingAction] = createSignal<"passthrough" | "modify" | "replace">("passthrough");
+ const [editingResponse, setEditingResponse] = createSignal("");
const toggleRule = async (rule: InterceptionRule) => {
try {
@@ -22,13 +22,13 @@ const RulesList: Component = () => {
});
refetch();
} catch (err) {
- console.error('Failed to toggle rule:', err);
+ console.error("Failed to toggle rule:", err);
alert(`Error: ${err}`);
}
};
const deleteRule = async (id: number) => {
- if (!confirm('Are you sure you want to delete this rule?')) return;
+ if (!confirm("Are you sure you want to delete this rule?")) return;
try {
if (id === editingId()) {
@@ -37,14 +37,14 @@ const RulesList: Component = () => {
await rulesApi.delete(id);
refetch();
} catch (err) {
- console.error('Failed to delete rule:', err);
+ console.error("Failed to delete rule:", err);
alert(`Error: ${err}`);
}
};
const createNewRule = async () => {
if (!editingMethod()) {
- alert('Please enter a method name');
+ alert("Please enter a method name");
return;
}
@@ -52,14 +52,14 @@ const RulesList: Component = () => {
await rulesApi.create({
method_name: editingMethod(),
action: editingAction(),
- custom_response: editingAction() === 'replace' ? editingResponse() : undefined,
+ custom_response: editingAction() === "replace" ? editingResponse() : undefined,
});
setShowEditor(false);
- setEditingMethod('');
- setEditingResponse('');
+ setEditingMethod("");
+ setEditingResponse("");
refetch();
} catch (err) {
- console.error('Failed to create rule:', err);
+ console.error("Failed to create rule:", err);
alert(`Error: ${err}`);
}
};
@@ -68,15 +68,15 @@ const RulesList: Component = () => {
setEditingId(rule.id);
setEditingMethod(rule.method_name);
setEditingAction(rule.action);
- setEditingResponse(rule.custom_response || '');
+ setEditingResponse(rule.custom_response || "");
setShowEditor(true);
};
const cancelEdit = () => {
setEditingId(null);
- setEditingMethod('');
- setEditingAction('passthrough');
- setEditingResponse('');
+ setEditingMethod("");
+ setEditingAction("passthrough");
+ setEditingResponse("");
setShowEditor(false);
};
@@ -88,7 +88,7 @@ const RulesList: Component = () => {
}
if (!editingMethod()) {
- alert('Please enter a method name');
+ alert("Please enter a method name");
return;
}
@@ -96,12 +96,12 @@ const RulesList: Component = () => {
await rulesApi.update(id, {
method_name: editingMethod(),
action: editingAction(),
- custom_response: editingAction() === 'replace' ? editingResponse() : undefined,
+ custom_response: editingAction() === "replace" ? editingResponse() : undefined,
});
cancelEdit();
refetch();
} catch (err) {
- console.error('Failed to update rule:', err);
+ console.error("Failed to update rule:", err);
alert(`Error: ${err}`);
}
};
@@ -119,20 +119,16 @@ const RulesList: Component = () => {
}
}}
>
- {showEditor() ? 'Cancel' : '+ New Rule'}
+ {showEditor() ? "Cancel" : "+ New Rule"}
-
- {editingId() !== null ? 'Edit Rule' : 'Create New Rule'}
-
+ {editingId() !== null ? "Edit Rule" : "Create New Rule"}
-
+
{
-
+
-
+
-
+
-
- {editingId() !== null ? 'Update Rule' : 'Create Rule'}
-
+ {editingId() !== null ? "Update Rule" : "Create Rule"}
@@ -182,65 +170,64 @@ const RulesList: Component = () => {
- |
- Method Name
- |
-
- Action
- |
-
- Status
- |
-
- Actions
- |
+ Method Name |
+ Action |
+ Status |
+ Actions |
- Loading... |
- }>
-
-
- No rules configured yet. Click "+ New Rule" to create one.
+ |
+ Loading...
|
- }>
+ }
+ >
+
+
+ No rules configured yet. Click "+ New Rule" to create one.
+ |
+
+ }
+ >
{(rule) => (
- |
- {rule.method_name}
- |
+ {rule.method_name} |
-
+
{rule.action}
|
toggleRule(rule)}
- class={`px-3 py-1 rounded-md text-sm font-medium ${rule.is_enabled
- ? 'bg-green-100 text-green-800'
- : 'bg-gray-100 text-gray-800'
- }`}>
- {rule.is_enabled ? '✓ Enabled' : '✗ Disabled'}
+ class={`px-3 py-1 rounded-md text-sm font-medium ${
+ rule.is_enabled ? "bg-green-100 text-green-800" : "bg-gray-100 text-gray-800"
+ }`}
+ >
+ {rule.is_enabled ? "✓ Enabled" : "✗ Disabled"}
|
- startEdit(rule)}
- class="mr-4">
+ startEdit(rule)} class="mr-4">
Edit
- deleteRule(rule.id)}
- >
+ deleteRule(rule.id)}>
Delete
|
diff --git a/frontend/src/components/ui/Button.tsx b/frontend/src/components/ui/Button.tsx
index 10c230c..e51ccf0 100644
--- a/frontend/src/components/ui/Button.tsx
+++ b/frontend/src/components/ui/Button.tsx
@@ -1,35 +1,37 @@
-import { Component, JSX, splitProps } from 'solid-js';
-import { cva, type VariantProps } from 'class-variance-authority';
+import { Component, JSX, splitProps } from "solid-js";
+import { cva, type VariantProps } from "class-variance-authority";
const buttonVariants = cva(
- 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed',
+ "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed",
{
variants: {
variant: {
- primary: 'bg-indigo-600 text-white hover:bg-indigo-700',
- secondary: 'bg-white text-gray-700 border border-gray-300 hover:bg-gray-50',
- danger: 'bg-red-600 text-white hover:bg-red-700',
- success: 'bg-green-600 text-white hover:bg-green-700',
- ghost: 'text-indigo-600 hover:text-indigo-900',
- link: 'text-red-600 hover:text-red-900',
+ primary: "bg-indigo-600 text-white hover:bg-indigo-700",
+ secondary: "bg-white text-gray-700 border border-gray-300 hover:bg-gray-50",
+ danger: "bg-red-600 text-white hover:bg-red-700",
+ success: "bg-green-600 text-white hover:bg-green-700",
+ ghost: "text-indigo-600 hover:text-indigo-900",
+ link: "text-red-600 hover:text-red-900",
},
size: {
- sm: 'px-3 py-1',
- md: 'px-4 py-2',
- lg: 'w-full px-4 py-2',
+ sm: "px-3 py-1",
+ md: "px-4 py-2",
+ lg: "w-full px-4 py-2",
},
},
defaultVariants: {
- variant: 'primary',
- size: 'md',
+ variant: "primary",
+ size: "md",
},
- }
+ },
);
-export interface ButtonProps extends JSX.ButtonHTMLAttributes, VariantProps {}
+export interface ButtonProps
+ extends JSX.ButtonHTMLAttributes,
+ VariantProps {}
const Button: Component = (props) => {
- const [local, others] = splitProps(props, ['variant', 'size', 'class']);
+ const [local, others] = splitProps(props, ["variant", "size", "class"]);
return (
, VariantProps {}
const Card: Component = (props) => {
- const [local, others] = splitProps(props, ['variant', 'class']);
- return (
-
- );
+ const [local, others] = splitProps(props, ["variant", "class"]);
+ return ;
};
const CardHeader: Component> = (props) => {
- const [local, others] = splitProps(props, ['class']);
- return (
-
- );
+ const [local, others] = splitProps(props, ["class"]);
+ return ;
};
const CardContent: Component> = (props) => {
- const [local, others] = splitProps(props, ['class']);
- return (
-
- );
+ const [local, others] = splitProps(props, ["class"]);
+ return ;
};
const CardFooter: Component> = (props) => {
- const [local, others] = splitProps(props, ['class']);
- return (
-
- );
+ const [local, others] = splitProps(props, ["class"]);
+ return ;
};
export { Card, CardHeader, CardContent, CardFooter, cardVariants };
diff --git a/frontend/src/components/ui/Input.tsx b/frontend/src/components/ui/Input.tsx
index 7a57a63..5911c3e 100644
--- a/frontend/src/components/ui/Input.tsx
+++ b/frontend/src/components/ui/Input.tsx
@@ -1,30 +1,27 @@
-import { Component, JSX, splitProps } from 'solid-js';
-import { cva, type VariantProps } from 'class-variance-authority';
+import { Component, JSX, splitProps } from "solid-js";
+import { cva, type VariantProps } from "class-variance-authority";
const inputVariants = cva(
- 'w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500',
+ "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500",
{
variants: {
variant: {
- primary: '',
+ primary: "",
},
},
defaultVariants: {
- variant: 'primary',
+ variant: "primary",
},
- }
+ },
);
-export interface InputProps extends JSX.InputHTMLAttributes, VariantProps {}
+export interface InputProps
+ extends JSX.InputHTMLAttributes,
+ VariantProps {}
const Input: Component = (props) => {
- const [local, others] = splitProps(props, ['variant', 'class']);
- return (
-
- );
+ const [local, others] = splitProps(props, ["variant", "class"]);
+ return ;
};
export { Input, inputVariants };
diff --git a/frontend/src/components/ui/Modal.tsx b/frontend/src/components/ui/Modal.tsx
index 4c9dae6..6e4d705 100644
--- a/frontend/src/components/ui/Modal.tsx
+++ b/frontend/src/components/ui/Modal.tsx
@@ -1,7 +1,7 @@
-import { Component, JSX, splitProps } from 'solid-js';
+import { Component, JSX, splitProps } from "solid-js";
const Modal: Component> = (props) => {
- const [local, others] = splitProps(props, ['class']);
+ const [local, others] = splitProps(props, ["class"]);
return (
> = (props) => {
};
const ModalContent: Component
> = (props) => {
- const [local, others] = splitProps(props, ['class']);
- return (
-
- );
+ const [local, others] = splitProps(props, ["class"]);
+ return ;
};
export { Modal, ModalContent };
diff --git a/frontend/src/components/ui/Select.tsx b/frontend/src/components/ui/Select.tsx
index ad0f40e..e368160 100644
--- a/frontend/src/components/ui/Select.tsx
+++ b/frontend/src/components/ui/Select.tsx
@@ -1,30 +1,24 @@
-import { Component, JSX, splitProps } from 'solid-js';
-import { cva, type VariantProps } from 'class-variance-authority';
+import { Component, JSX, splitProps } from "solid-js";
+import { cva, type VariantProps } from "class-variance-authority";
-const selectVariants = cva(
- 'w-full border border-gray-300 rounded-md px-3 py-2',
- {
- variants: {
- variant: {
- primary: '',
- },
+const selectVariants = cva("w-full border border-gray-300 rounded-md px-3 py-2", {
+ variants: {
+ variant: {
+ primary: "",
},
- defaultVariants: {
- variant: 'primary',
- },
- }
-);
+ },
+ defaultVariants: {
+ variant: "primary",
+ },
+});
-export interface SelectProps extends JSX.SelectHTMLAttributes, VariantProps {}
+export interface SelectProps
+ extends JSX.SelectHTMLAttributes,
+ VariantProps {}
const Select: Component = (props) => {
- const [local, others] = splitProps(props, ['variant', 'class']);
- return (
-
- );
+ const [local, others] = splitProps(props, ["variant", "class"]);
+ return ;
};
export { Select, selectVariants };
diff --git a/frontend/src/components/ui/Textarea.tsx b/frontend/src/components/ui/Textarea.tsx
index cc82573..9747e9a 100644
--- a/frontend/src/components/ui/Textarea.tsx
+++ b/frontend/src/components/ui/Textarea.tsx
@@ -1,30 +1,24 @@
-import { Component, JSX, splitProps } from 'solid-js';
-import { cva, type VariantProps } from 'class-variance-authority';
+import { Component, JSX, splitProps } from "solid-js";
+import { cva, type VariantProps } from "class-variance-authority";
-const textareaVariants = cva(
- 'w-full border border-gray-300 rounded-md px-3 py-2 font-mono text-sm',
- {
- variants: {
- variant: {
- primary: '',
- },
+const textareaVariants = cva("w-full border border-gray-300 rounded-md px-3 py-2 font-mono text-sm", {
+ variants: {
+ variant: {
+ primary: "",
},
- defaultVariants: {
- variant: 'primary',
- },
- }
-);
+ },
+ defaultVariants: {
+ variant: "primary",
+ },
+});
-export interface TextareaProps extends JSX.TextareaHTMLAttributes, VariantProps {}
+export interface TextareaProps
+ extends JSX.TextareaHTMLAttributes,
+ VariantProps {}
const Textarea: Component = (props) => {
- const [local, others] = splitProps(props, ['variant', 'class']);
- return (
-
- );
+ const [local, others] = splitProps(props, ["variant", "class"]);
+ return ;
};
export { Textarea, textareaVariants };
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index af3f3b2..e870f19 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -1,10 +1,10 @@
/* @refresh reload */
-import { render } from 'solid-js/web';
-import App from './App';
-import './styles/index.css';
+import { render } from "solid-js/web";
+import App from "./App";
+import "./styles/index.css";
-const root = document.getElementById('root');
+const root = document.getElementById("root");
-if (!root) throw new Error('Root element not found');
+if (!root) throw new Error("Root element not found");
render(() => , root);
diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts
index af585ca..2c67bee 100644
--- a/frontend/src/types/index.ts
+++ b/frontend/src/types/index.ts
@@ -1,7 +1,7 @@
export interface InterceptionRule {
id: number;
method_name: string;
- action: 'passthrough' | 'modify' | 'replace';
+ action: "passthrough" | "modify" | "replace";
custom_response: any | null;
is_enabled: boolean;
created_at: string;
@@ -11,7 +11,7 @@ export interface InterceptionRule {
export interface Command {
id: number;
command: any;
- status: 'unverified' | 'verified' | 'rejected';
+ status: "unverified" | "verified" | "rejected";
received_at: string;
processed_at?: string;
notes?: string;
@@ -36,21 +36,21 @@ export interface UpdateCommandRequest {
}
export interface Request {
- headers: Record;
- body: {value: any, modified: boolean};
+ headers: Record;
+ body: { value: any; modified: boolean };
}
export interface Response {
- headers: Record;
- body: {value: any, modified: boolean};
+ headers: Record;
+ body: { value: any; modified: boolean };
}
export interface RequestLog {
- id: number;
- method: string;
- request_body: object;
- response_body: object;
- request_interception_action: string,
- response_interception_action: string,
- created_at: string;
+ id: number;
+ method: string;
+ request_body: object;
+ response_body: object;
+ request_interception_action: string;
+ response_interception_action: string;
+ created_at: string;
}
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index dca8ba0..614c86b 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -1,11 +1,8 @@
/** @type {import('tailwindcss').Config} */
export default {
- content: [
- "./index.html",
- "./src/**/*.{js,ts,jsx,tsx}",
- ],
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
-}
+};
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 4e5a677..a208915 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -1,21 +1,21 @@
-import { defineConfig } from 'vite';
-import solid from 'vite-plugin-solid';
+import { defineConfig } from "vite";
+import solid from "vite-plugin-solid";
export default defineConfig({
plugins: [solid()],
- base: '/admin/',
+ base: "/admin/",
build: {
- outDir: 'dist',
- assetsDir: 'assets',
+ outDir: "dist",
+ assetsDir: "assets",
sourcemap: false,
- minify: 'terser',
+ minify: "terser",
},
server: {
proxy: {
- '/admin/api': {
- target: 'http://localhost:8080',
+ "/admin/api": {
+ target: "http://localhost:8080",
changeOrigin: true,
- }
- }
- }
+ },
+ },
+ },
});