mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
fix: backend none templates (#241)
This commit is contained in:
5
.changeset/fair-pigs-wash.md
Normal file
5
.changeset/fair-pigs-wash.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"create-better-t-stack": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix templates when backend is none
|
||||||
@@ -20,9 +20,7 @@ export function displayConfig(config: Partial<ProjectConfig>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.backend !== undefined) {
|
if (config.backend !== undefined) {
|
||||||
configDisplay.push(
|
configDisplay.push(`${pc.blue("Backend:")} ${String(config.backend)}`);
|
||||||
`${pc.blue("Backend Framework:")} ${String(config.backend)}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.runtime !== undefined) {
|
if (config.runtime !== undefined) {
|
||||||
|
|||||||
@@ -3,40 +3,19 @@ import type { ProjectConfig } from "../types";
|
|||||||
export function generateReproducibleCommand(config: ProjectConfig): string {
|
export function generateReproducibleCommand(config: ProjectConfig): string {
|
||||||
const flags: string[] = [];
|
const flags: string[] = [];
|
||||||
|
|
||||||
if (config.database === "none") {
|
|
||||||
flags.push("--database none");
|
|
||||||
} else {
|
|
||||||
flags.push(`--database ${config.database}`);
|
|
||||||
|
|
||||||
if (config.orm) {
|
|
||||||
flags.push(`--orm ${config.orm}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.dbSetup) {
|
|
||||||
flags.push(`--db-setup ${config.dbSetup}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.api) {
|
|
||||||
flags.push(`--api ${config.api}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
flags.push(config.auth ? "--auth" : "--no-auth");
|
|
||||||
flags.push(config.git ? "--git" : "--no-git");
|
|
||||||
flags.push(config.install ? "--install" : "--no-install");
|
|
||||||
|
|
||||||
if (config.runtime) {
|
|
||||||
flags.push(`--runtime ${config.runtime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.backend) {
|
|
||||||
flags.push(`--backend ${config.backend}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.frontend && config.frontend.length > 0) {
|
if (config.frontend && config.frontend.length > 0) {
|
||||||
flags.push(`--frontend ${config.frontend.join(" ")}`);
|
flags.push(`--frontend ${config.frontend.join(" ")}`);
|
||||||
|
} else {
|
||||||
|
flags.push("--frontend none");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flags.push(`--backend ${config.backend}`);
|
||||||
|
flags.push(`--runtime ${config.runtime}`);
|
||||||
|
flags.push(`--database ${config.database}`);
|
||||||
|
flags.push(`--orm ${config.orm}`);
|
||||||
|
flags.push(`--api ${config.api}`);
|
||||||
|
flags.push(config.auth ? "--auth" : "--no-auth");
|
||||||
|
|
||||||
if (config.addons && config.addons.length > 0) {
|
if (config.addons && config.addons.length > 0) {
|
||||||
flags.push(`--addons ${config.addons.join(" ")}`);
|
flags.push(`--addons ${config.addons.join(" ")}`);
|
||||||
} else {
|
} else {
|
||||||
@@ -49,9 +28,10 @@ export function generateReproducibleCommand(config: ProjectConfig): string {
|
|||||||
flags.push("--examples none");
|
flags.push("--examples none");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.packageManager) {
|
flags.push(`--db-setup ${config.dbSetup}`);
|
||||||
flags.push(`--package-manager ${config.packageManager}`);
|
flags.push(config.git ? "--git" : "--no-git");
|
||||||
}
|
flags.push(`--package-manager ${config.packageManager}`);
|
||||||
|
flags.push(config.install ? "--install" : "--no-install");
|
||||||
|
|
||||||
let baseCommand = "";
|
let baseCommand = "";
|
||||||
const pkgManager = config.packageManager;
|
const pkgManager = config.packageManager;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{{#if (includes frontend 'next')}}
|
{{#if (includes frontend 'next')}}
|
||||||
{{!-- Next.js tRPC Client Setup --}}
|
|
||||||
import { QueryCache, QueryClient } from '@tanstack/react-query';
|
import { QueryCache, QueryClient } from '@tanstack/react-query';
|
||||||
import { createTRPCClient, httpBatchLink } from '@trpc/client';
|
import { createTRPCClient, httpBatchLink } from '@trpc/client';
|
||||||
import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query';
|
import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query';
|
||||||
@@ -47,16 +46,14 @@ export const trpc = createTRPCOptionsProxy<AppRouter>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
{{else if (includes frontend 'tanstack-start')}}
|
{{else if (includes frontend 'tanstack-start')}}
|
||||||
{{!-- TanStack Start tRPC Client Setup --}}
|
|
||||||
import { createTRPCContext } from "@trpc/tanstack-react-query";
|
import { createTRPCContext } from "@trpc/tanstack-react-query";
|
||||||
import type { AppRouter } from "../../../server/src/routers"; {{! Adjust path if necessary }}
|
import type { AppRouter } from "../../../server/src/routers";
|
||||||
|
|
||||||
export const { TRPCProvider, useTRPC, useTRPCClient } =
|
export const { TRPCProvider, useTRPC, useTRPCClient } =
|
||||||
createTRPCContext<AppRouter>();
|
createTRPCContext<AppRouter>();
|
||||||
|
|
||||||
{{else}}
|
{{else}}
|
||||||
{{!-- Default Web tRPC Client Setup (TanStack Router, React Router, etc.) --}}
|
import type { AppRouter } from "../../../server/src/routers";
|
||||||
import type { AppRouter } from "../../../server/src/routers"; {{! Adjust path if necessary }}
|
|
||||||
import { QueryCache, QueryClient } from "@tanstack/react-query";
|
import { QueryCache, QueryClient } from "@tanstack/react-query";
|
||||||
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
||||||
import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
|
import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
|
||||||
|
|||||||
@@ -12,20 +12,48 @@ import { Checkbox } from "@/components/ui/checkbox";
|
|||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Loader2, Trash2 } from "lucide-react";
|
import { Loader2, Trash2 } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
{{#if (eq api "orpc")}}
|
{{#if (eq backend "convex")}}
|
||||||
|
import { useMutation, useQuery } from "convex/react";
|
||||||
|
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
||||||
|
import type { Id } from "@{{projectName}}/backend/convex/_generated/dataModel.d.ts";
|
||||||
|
{{else}}
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
import { orpc } from "@/utils/orpc";
|
import { orpc } from "@/utils/orpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
import { trpc } from "@/utils/trpc";
|
import { trpc } from "@/utils/trpc";
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
||||||
export default function TodosPage() {
|
export default function TodosPage() {
|
||||||
const [newTodoText, setNewTodoText] = useState("");
|
const [newTodoText, setNewTodoText] = useState("");
|
||||||
|
|
||||||
{{#if (eq api "orpc")}}
|
{{#if (eq backend "convex")}}
|
||||||
|
const todos = useQuery(api.todos.getAll);
|
||||||
|
const createTodoMutation = useMutation(api.todos.create);
|
||||||
|
const toggleTodoMutation = useMutation(api.todos.toggle);
|
||||||
|
const deleteTodoMutation = useMutation(api.todos.deleteTodo);
|
||||||
|
|
||||||
|
const handleAddTodo = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const text = newTodoText.trim();
|
||||||
|
if (!text) return;
|
||||||
|
await createTodoMutation({ text });
|
||||||
|
setNewTodoText("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleToggleTodo = (id: Id<"todos">, currentCompleted: boolean) => {
|
||||||
|
toggleTodoMutation({ id, completed: !currentCompleted });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteTodo = (id: Id<"todos">) => {
|
||||||
|
deleteTodoMutation({ id });
|
||||||
|
};
|
||||||
|
{{else}}
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
const todos = useQuery(orpc.todo.getAll.queryOptions());
|
const todos = useQuery(orpc.todo.getAll.queryOptions());
|
||||||
const createMutation = useMutation(
|
const createMutation = useMutation(
|
||||||
orpc.todo.create.mutationOptions({
|
orpc.todo.create.mutationOptions({
|
||||||
@@ -45,8 +73,8 @@ export default function TodosPage() {
|
|||||||
onSuccess: () => todos.refetch(),
|
onSuccess: () => todos.refetch(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
const todos = useQuery(trpc.todo.getAll.queryOptions());
|
const todos = useQuery(trpc.todo.getAll.queryOptions());
|
||||||
const createMutation = useMutation(
|
const createMutation = useMutation(
|
||||||
trpc.todo.create.mutationOptions({
|
trpc.todo.create.mutationOptions({
|
||||||
@@ -66,7 +94,7 @@ export default function TodosPage() {
|
|||||||
onSuccess: () => todos.refetch(),
|
onSuccess: () => todos.refetch(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
const handleAddTodo = (e: React.FormEvent) => {
|
const handleAddTodo = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -82,6 +110,7 @@ export default function TodosPage() {
|
|||||||
const handleDeleteTodo = (id: number) => {
|
const handleDeleteTodo = (id: number) => {
|
||||||
deleteMutation.mutate({ id });
|
deleteMutation.mutate({ id });
|
||||||
};
|
};
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-md py-10">
|
<div className="mx-auto w-full max-w-md py-10">
|
||||||
@@ -99,20 +128,73 @@ export default function TodosPage() {
|
|||||||
value={newTodoText}
|
value={newTodoText}
|
||||||
onChange={(e) => setNewTodoText(e.target.value)}
|
onChange={(e) => setNewTodoText(e.target.value)}
|
||||||
placeholder="Add a new task..."
|
placeholder="Add a new task..."
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
|
{{else}}
|
||||||
disabled={createMutation.isPending}
|
disabled={createMutation.isPending}
|
||||||
|
{{/if}}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
|
disabled={!newTodoText.trim()}
|
||||||
|
{{else}}
|
||||||
disabled={createMutation.isPending || !newTodoText.trim()}
|
disabled={createMutation.isPending || !newTodoText.trim()}
|
||||||
|
{{/if}}
|
||||||
>
|
>
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
|
Add
|
||||||
|
{{else}}
|
||||||
{createMutation.isPending ? (
|
{createMutation.isPending ? (
|
||||||
<Loader2 className="h-4 w-4 animate-spin" />
|
<Loader2 className="h-4 w-4 animate-spin" />
|
||||||
) : (
|
) : (
|
||||||
"Add"
|
"Add"
|
||||||
)}
|
)}
|
||||||
|
{{/if}}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
|
{todos === undefined ? (
|
||||||
|
<div className="flex justify-center py-4">
|
||||||
|
<Loader2 className="h-6 w-6 animate-spin" />
|
||||||
|
</div>
|
||||||
|
) : todos.length === 0 ? (
|
||||||
|
<p className="py-4 text-center">No todos yet. Add one above!</p>
|
||||||
|
) : (
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{todos.map((todo) => (
|
||||||
|
<li
|
||||||
|
key={todo._id}
|
||||||
|
className="flex items-center justify-between rounded-md border p-2"
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Checkbox
|
||||||
|
checked={todo.completed}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
handleToggleTodo(todo._id, todo.completed)
|
||||||
|
}
|
||||||
|
id={`todo-${todo._id}`}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor={`todo-${todo._id}`}
|
||||||
|
className={`${todo.completed ? "line-through text-muted-foreground" : ""}`}
|
||||||
|
>
|
||||||
|
{todo.text}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => handleDeleteTodo(todo._id)}
|
||||||
|
aria-label="Delete todo"
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
{{else}}
|
||||||
{todos.isLoading ? (
|
{todos.isLoading ? (
|
||||||
<div className="flex justify-center py-4">
|
<div className="flex justify-center py-4">
|
||||||
<Loader2 className="h-6 w-6 animate-spin" />
|
<Loader2 className="h-6 w-6 animate-spin" />
|
||||||
@@ -155,6 +237,7 @@ export default function TodosPage() {
|
|||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
|
{{/if}}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ export default function Todos() {
|
|||||||
onChange={(e) => setNewTodoText(e.target.value)}
|
onChange={(e) => setNewTodoText(e.target.value)}
|
||||||
placeholder="Add a new task..."
|
placeholder="Add a new task..."
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
{{!-- Convex mutations don't have an easy isPending state here, disable based on text --}}
|
|
||||||
{{else}}
|
{{else}}
|
||||||
disabled={createMutation.isPending}
|
disabled={createMutation.isPending}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -33,40 +33,48 @@ export default function Home() {
|
|||||||
|
|
||||||
<View className="rounded-lg border border-foreground p-4">
|
<View className="rounded-lg border border-foreground p-4">
|
||||||
<Text className="mb-2 font-medium text-foreground">API Status</Text>
|
<Text className="mb-2 font-medium text-foreground">API Status</Text>
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
<View className="flex-row items-center gap-2">
|
<View className="flex-row items-center gap-2">
|
||||||
<View
|
<View
|
||||||
className={`h-2.5 w-2.5 rounded-full ${
|
className={`h-2.5 w-2.5 rounded-full ${
|
||||||
{{#if (or (eq api "orpc") (eq api "trpc"))}}
|
|
||||||
healthCheck.data ? "bg-green-500" : "bg-red-500"
|
|
||||||
{{else}}
|
|
||||||
healthCheck ? "bg-green-500" : "bg-red-500"
|
healthCheck ? "bg-green-500" : "bg-red-500"
|
||||||
{{/if}}
|
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
<Text className="text-sm text-foreground">
|
<Text className="text-sm text-foreground">
|
||||||
{{#if (eq api "orpc")}}
|
|
||||||
{healthCheck.isLoading
|
|
||||||
? "Checking..."
|
|
||||||
: healthCheck.data
|
|
||||||
? "Connected"
|
|
||||||
: "Disconnected"}
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
{healthCheck.isLoading
|
|
||||||
? "Checking..."
|
|
||||||
: healthCheck.data
|
|
||||||
? "Connected"
|
|
||||||
: "Disconnected"}
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
{healthCheck === undefined
|
{healthCheck === undefined
|
||||||
? "Checking..."
|
? "Checking..."
|
||||||
: healthCheck === "OK"
|
: healthCheck === "OK"
|
||||||
? "Connected"
|
? "Connected"
|
||||||
: "Error"}
|
: "Error"}
|
||||||
{{/if}}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
|
<View className="flex-row items-center gap-2">
|
||||||
|
<View
|
||||||
|
className={`h-2.5 w-2.5 rounded-full ${
|
||||||
|
healthCheck.data ? "bg-green-500" : "bg-red-500"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
<Text className="text-sm text-foreground">
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
|
{healthCheck.isLoading
|
||||||
|
? "Checking..."
|
||||||
|
: healthCheck.data
|
||||||
|
? "Connected"
|
||||||
|
: "Disconnected"}
|
||||||
|
{{/if}}
|
||||||
|
{{#if (eq api "trpc")}}
|
||||||
|
{healthCheck.isLoading
|
||||||
|
? "Checking..."
|
||||||
|
: healthCheck.data
|
||||||
|
? "Connected"
|
||||||
|
: "Disconnected"}
|
||||||
|
{{/if}}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
||||||
{{else}}
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
import { Stack } from "expo-router";
|
import { Stack } from "expo-router";
|
||||||
import {
|
import {
|
||||||
@@ -82,6 +84,7 @@ export default function RootLayout() {
|
|||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</ConvexProvider>
|
</ConvexProvider>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
|
<ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
|
||||||
<StatusBar style={isDarkColorScheme ? "light" : "dark"} />
|
<StatusBar style={isDarkColorScheme ? "light" : "dark"} />
|
||||||
@@ -96,6 +99,20 @@ export default function RootLayout() {
|
|||||||
</GestureHandlerRootView>
|
</GestureHandlerRootView>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
{{else}}
|
||||||
|
<ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
|
||||||
|
<StatusBar style={isDarkColorScheme ? "light" : "dark"} />
|
||||||
|
<GestureHandlerRootView style=\{{ flex: 1 }}>
|
||||||
|
<Stack>
|
||||||
|
<Stack.Screen name="(drawer)" options=\{{ headerShown: false }} />
|
||||||
|
<Stack.Screen
|
||||||
|
name="modal"
|
||||||
|
options=\{{ title: "Modal", presentation: "modal" }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</GestureHandlerRootView>
|
||||||
|
</ThemeProvider>
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,38 +33,54 @@ export default function Home() {
|
|||||||
|
|
||||||
<View style={styles.apiStatusCard}>
|
<View style={styles.apiStatusCard}>
|
||||||
<Text style={styles.cardTitle}>API Status</Text>
|
<Text style={styles.cardTitle}>API Status</Text>
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
<View style={styles.apiStatusRow}>
|
<View style={styles.apiStatusRow}>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.statusIndicatorDot,
|
styles.statusIndicatorDot,
|
||||||
{{#if (or (eq api "orpc") (eq api "trpc"))}}
|
|
||||||
healthCheck.data
|
|
||||||
? styles.statusIndicatorGreen
|
|
||||||
: styles.statusIndicatorRed,
|
|
||||||
{{else}}
|
|
||||||
healthCheck === "OK"
|
healthCheck === "OK"
|
||||||
? styles.statusIndicatorGreen
|
? styles.statusIndicatorGreen
|
||||||
: styles.statusIndicatorRed,
|
: styles.statusIndicatorRed,
|
||||||
{{/if}}
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Text style={styles.statusText}>
|
<Text style={styles.statusText}>
|
||||||
{{#if (or (eq api "orpc") (eq api "trpc"))}}
|
|
||||||
{healthCheck.isLoading
|
|
||||||
? "Checking..."
|
|
||||||
: healthCheck.data
|
|
||||||
? "Connected"
|
|
||||||
: "Disconnected"}
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
{healthCheck === undefined
|
{healthCheck === undefined
|
||||||
? "Checking..."
|
? "Checking..."
|
||||||
: healthCheck === "OK"
|
: healthCheck === "OK"
|
||||||
? "Connected"
|
? "Connected"
|
||||||
: "Error"}
|
: "Error"}
|
||||||
{{/if}}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
|
<View style={styles.apiStatusRow}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.statusIndicatorDot,
|
||||||
|
healthCheck.data
|
||||||
|
? styles.statusIndicatorGreen
|
||||||
|
: styles.statusIndicatorRed,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Text style={styles.statusText}>
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
|
{healthCheck.isLoading
|
||||||
|
? "Checking..."
|
||||||
|
: healthCheck.data
|
||||||
|
? "Connected"
|
||||||
|
: "Disconnected"}
|
||||||
|
{{/if}}
|
||||||
|
{{#if (eq api "trpc")}}
|
||||||
|
{healthCheck.isLoading
|
||||||
|
? "Checking..."
|
||||||
|
: healthCheck.data
|
||||||
|
? "Connected"
|
||||||
|
: "Disconnected"}
|
||||||
|
{{/if}}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import { queryClient } from "@/utils/orpc";
|
|||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
||||||
{{else}}
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
import { Stack } from "expo-router";
|
import { Stack } from "expo-router";
|
||||||
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
||||||
@@ -51,6 +53,7 @@ export default function RootLayout() {
|
|||||||
</GestureHandlerRootView>
|
</GestureHandlerRootView>
|
||||||
</ConvexProvider>
|
</ConvexProvider>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<GestureHandlerRootView style=\{{ flex: 1 }}>
|
<GestureHandlerRootView style=\{{ flex: 1 }}>
|
||||||
<Stack
|
<Stack
|
||||||
@@ -72,6 +75,27 @@ export default function RootLayout() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</GestureHandlerRootView>
|
</GestureHandlerRootView>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
{{else}}
|
||||||
|
<GestureHandlerRootView style=\{{ flex: 1 }}>
|
||||||
|
<Stack
|
||||||
|
screenOptions=\{{
|
||||||
|
headerStyle: {
|
||||||
|
backgroundColor: theme.colors.background,
|
||||||
|
},
|
||||||
|
headerTitleStyle: {
|
||||||
|
color: theme.colors.typography,
|
||||||
|
},
|
||||||
|
headerTintColor: theme.colors.typography,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack.Screen name="(drawer)" options=\{{ headerShown: false }} />
|
||||||
|
<Stack.Screen
|
||||||
|
name="modal"
|
||||||
|
options=\{{ title: "Modal", presentation: "modal" }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</GestureHandlerRootView>
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
const { $orpc } = useNuxtApp()
|
const { $orpc } = useNuxtApp()
|
||||||
import { useQuery } from '@tanstack/vue-query'
|
import { useQuery } from '@tanstack/vue-query'
|
||||||
|
{{/unless}}
|
||||||
|
|
||||||
const TITLE_TEXT = `
|
const TITLE_TEXT = `
|
||||||
██████╗ ███████╗████████╗████████╗███████╗██████╗
|
██████╗ ███████╗████████╗████████╗███████╗██████╗
|
||||||
@@ -18,14 +20,16 @@ const TITLE_TEXT = `
|
|||||||
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
|
╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
const healthCheck = useQuery($orpc.healthCheck.queryOptions())
|
const healthCheck = useQuery($orpc.healthCheck.queryOptions())
|
||||||
|
{{/unless}}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container mx-auto max-w-3xl px-4 py-2">
|
<div class="container mx-auto max-w-3xl px-4 py-2">
|
||||||
<pre class="overflow-x-auto font-mono text-sm whitespace-pre-wrap">{{ TITLE_TEXT }}</pre>
|
<pre class="overflow-x-auto font-mono text-sm whitespace-pre-wrap">{{ TITLE_TEXT }}</pre>
|
||||||
<div class="grid gap-6 mt-4">
|
<div class="grid gap-6 mt-4">
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
<section class="rounded-lg border p-4">
|
<section class="rounded-lg border p-4">
|
||||||
<h2 class="mb-2 font-medium">API Status</h2>
|
<h2 class="mb-2 font-medium">API Status</h2>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -58,6 +62,7 @@ const healthCheck = useQuery($orpc.healthCheck.queryOptions())
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
{{/unless}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -2,14 +2,14 @@
|
|||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
import { useQuery } from "convex/react";
|
import { useQuery } from "convex/react";
|
||||||
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
||||||
{{else}}
|
{{else if (or (eq api "orpc") (eq api "trpc"))}}
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
{{#if (eq api "orpc")}}
|
{{#if (eq api "orpc")}}
|
||||||
import { orpc } from "@/utils/orpc";
|
import { orpc } from "@/utils/orpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
import { trpc } from "@/utils/trpc";
|
import { trpc } from "@/utils/trpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
import { useQuery } from "@tanstack/react-query";
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
const TITLE_TEXT = `
|
const TITLE_TEXT = `
|
||||||
@@ -43,8 +43,8 @@ export default function Home() {
|
|||||||
<div className="grid gap-6">
|
<div className="grid gap-6">
|
||||||
<section className="rounded-lg border p-4">
|
<section className="rounded-lg border p-4">
|
||||||
<h2 className="mb-2 font-medium">API Status</h2>
|
<h2 className="mb-2 font-medium">API Status</h2>
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
<div
|
<div
|
||||||
className={`h-2 w-2 rounded-full ${healthCheck === "OK" ? "bg-green-500" : healthCheck === undefined ? "bg-orange-400" : "bg-red-500"}`}
|
className={`h-2 w-2 rounded-full ${healthCheck === "OK" ? "bg-green-500" : healthCheck === undefined ? "bg-orange-400" : "bg-red-500"}`}
|
||||||
/>
|
/>
|
||||||
@@ -55,19 +55,23 @@ export default function Home() {
|
|||||||
? "Connected"
|
? "Connected"
|
||||||
: "Error"}
|
: "Error"}
|
||||||
</span>
|
</span>
|
||||||
{{else}}
|
|
||||||
<div
|
|
||||||
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
|
||||||
/>
|
|
||||||
<span className="text-sm text-muted-foreground">
|
|
||||||
{healthCheck.isLoading
|
|
||||||
? "Checking..."
|
|
||||||
: healthCheck.data
|
|
||||||
? "Connected"
|
|
||||||
: "Disconnected"}
|
|
||||||
</span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div
|
||||||
|
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
||||||
|
/>
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
{healthCheck.isLoading
|
||||||
|
? "Checking..."
|
||||||
|
: healthCheck.data
|
||||||
|
? "Connected"
|
||||||
|
: "Disconnected"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,49 +1,50 @@
|
|||||||
"use client"
|
"use client"
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
||||||
{{else}}
|
{{else}}
|
||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
{{#unless (eq api "none")}}
|
||||||
{{#if (eq api "orpc")}}
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { orpc, ORPCContext, queryClient } from "@/utils/orpc";
|
{{#if (eq api "orpc")}}
|
||||||
{{/if}}
|
import { orpc, ORPCContext, queryClient } from "@/utils/orpc";
|
||||||
{{#if (eq api "trpc")}}
|
{{/if}}
|
||||||
import { queryClient } from "@/utils/trpc";
|
{{#if (eq api "trpc")}}
|
||||||
{{/if}}
|
import { queryClient } from "@/utils/trpc";
|
||||||
|
{{/if}}
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
import { ThemeProvider } from "./theme-provider";
|
import { ThemeProvider } from "./theme-provider";
|
||||||
import { Toaster } from "./ui/sonner";
|
import { Toaster } from "./ui/sonner";
|
||||||
|
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
|
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
export default function Providers({
|
export default function Providers({ children, }: { children: React.ReactNode })
|
||||||
children,
|
{ return (
|
||||||
}: {
|
<ThemeProvider
|
||||||
children: React.ReactNode
|
attribute="class"
|
||||||
}) {
|
defaultTheme="system"
|
||||||
return (
|
enableSystem
|
||||||
<ThemeProvider
|
disableTransitionOnChange
|
||||||
attribute="class"
|
>
|
||||||
defaultTheme="system"
|
{{#if (eq backend "convex")}}
|
||||||
enableSystem
|
<ConvexProvider client={convex}>{children}</ConvexProvider>
|
||||||
disableTransitionOnChange
|
{{else}}
|
||||||
>
|
{{#unless (eq api "none")}}
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
<ConvexProvider client={convex}>{children}</ConvexProvider>
|
|
||||||
{{else}}
|
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
{{#if (eq api "orpc")}}
|
{{#if (eq api "orpc")}}
|
||||||
<ORPCContext.Provider value={orpc}>
|
<ORPCContext.Provider value={orpc}>
|
||||||
{children}
|
{children}
|
||||||
</ORPCContext.Provider>
|
</ORPCContext.Provider>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
{children}
|
{children}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
{{/if}}
|
{{else}}
|
||||||
<Toaster richColors />
|
{children}
|
||||||
</ThemeProvider>
|
{{/unless}}
|
||||||
)
|
{{/if}}
|
||||||
}
|
<Toaster richColors />
|
||||||
|
</ThemeProvider>
|
||||||
|
) }
|
||||||
|
|||||||
@@ -13,20 +13,25 @@ import { ThemeProvider } from "./components/theme-provider";
|
|||||||
import { Toaster } from "./components/ui/sonner";
|
import { Toaster } from "./components/ui/sonner";
|
||||||
|
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
||||||
{{else}}
|
{{else}}
|
||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
{{#unless (eq api "none")}}
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
{{#if (eq api "orpc")}}
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
import { orpc, ORPCContext, queryClient } from "./utils/orpc";
|
{{#if (eq api "orpc")}}
|
||||||
{{/if}}
|
import { orpc, ORPCContext, queryClient } from "./utils/orpc";
|
||||||
{{#if (eq api "trpc")}}
|
{{/if}}
|
||||||
import { queryClient } from "./utils/trpc";
|
{{#if (eq api "trpc")}}
|
||||||
{{/if}}
|
import { queryClient } from "./utils/trpc";
|
||||||
|
{{/if}}
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
export const links: Route.LinksFunction = () => [
|
export const links: Route.LinksFunction = () => [
|
||||||
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
|
{
|
||||||
|
rel: "preconnect",
|
||||||
|
href: "https://fonts.googleapis.com",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
rel: "preconnect",
|
rel: "preconnect",
|
||||||
href: "https://fonts.gstatic.com",
|
href: "https://fonts.gstatic.com",
|
||||||
@@ -57,28 +62,12 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const convex = new ConvexReactClient(
|
const convex = new ConvexReactClient(
|
||||||
import.meta.env.VITE_CONVEX_URL as string,
|
import.meta.env.VITE_CONVEX_URL as string,
|
||||||
);
|
);
|
||||||
|
return (
|
||||||
return (
|
<ConvexProvider client={convex}>
|
||||||
<ConvexProvider client={convex}>
|
|
||||||
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
|
||||||
<div className="grid grid-rows-[auto_1fr] h-svh">
|
|
||||||
<Header />
|
|
||||||
<Outlet />
|
|
||||||
</div>
|
|
||||||
<Toaster richColors />
|
|
||||||
</ThemeProvider>
|
|
||||||
</ConvexProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
{{else if (eq api "orpc")}}
|
|
||||||
export default function App() {
|
|
||||||
return (
|
|
||||||
<QueryClientProvider client={queryClient}>
|
|
||||||
<ORPCContext.Provider value={orpc}>
|
|
||||||
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
||||||
<div className="grid grid-rows-[auto_1fr] h-svh">
|
<div className="grid grid-rows-[auto_1fr] h-svh">
|
||||||
<Header />
|
<Header />
|
||||||
@@ -86,15 +75,44 @@ export default function App() {
|
|||||||
</div>
|
</div>
|
||||||
<Toaster richColors />
|
<Toaster richColors />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</ORPCContext.Provider>
|
</ConvexProvider>
|
||||||
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
);
|
||||||
</QueryClientProvider>
|
}
|
||||||
);
|
{{else if (eq api "orpc")}}
|
||||||
}
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<ORPCContext.Provider value={orpc}>
|
||||||
|
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
||||||
|
<div className="grid grid-rows-[auto_1fr] h-svh">
|
||||||
|
<Header />
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
<Toaster richColors />
|
||||||
|
</ThemeProvider>
|
||||||
|
</ORPCContext.Provider>
|
||||||
|
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
{{else if (eq api "trpc")}}
|
{{else if (eq api "trpc")}}
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
||||||
|
<div className="grid grid-rows-[auto_1fr] h-svh">
|
||||||
|
<Header />
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
<Toaster richColors />
|
||||||
|
</ThemeProvider>
|
||||||
|
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{{else}}
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
||||||
<div className="grid grid-rows-[auto_1fr] h-svh">
|
<div className="grid grid-rows-[auto_1fr] h-svh">
|
||||||
<Header />
|
<Header />
|
||||||
@@ -102,10 +120,8 @@ export default function App() {
|
|||||||
</div>
|
</div>
|
||||||
<Toaster richColors />
|
<Toaster richColors />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
);
|
||||||
</QueryClientProvider>
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import type { Route } from "./+types/_index";
|
|||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
import { useQuery } from "convex/react";
|
import { useQuery } from "convex/react";
|
||||||
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
||||||
{{else}}
|
{{else if (or (eq api "orpc") (eq api "trpc"))}}
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
{{#if (eq api "orpc")}}
|
{{#if (eq api "orpc")}}
|
||||||
import { orpc } from "@/utils/orpc";
|
import { orpc } from "@/utils/orpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
import { trpc } from "@/utils/trpc";
|
import { trpc } from "@/utils/trpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
import { useQuery } from "@tanstack/react-query";
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
const TITLE_TEXT = `
|
const TITLE_TEXT = `
|
||||||
@@ -47,8 +47,8 @@ export default function Home() {
|
|||||||
<div className="grid gap-6">
|
<div className="grid gap-6">
|
||||||
<section className="rounded-lg border p-4">
|
<section className="rounded-lg border p-4">
|
||||||
<h2 className="mb-2 font-medium">API Status</h2>
|
<h2 className="mb-2 font-medium">API Status</h2>
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
<div
|
<div
|
||||||
className={`h-2 w-2 rounded-full ${healthCheck === "OK" ? "bg-green-500" : healthCheck === undefined ? "bg-orange-400" : "bg-red-500"}`}
|
className={`h-2 w-2 rounded-full ${healthCheck === "OK" ? "bg-green-500" : healthCheck === undefined ? "bg-orange-400" : "bg-red-500"}`}
|
||||||
/>
|
/>
|
||||||
@@ -59,21 +59,25 @@ export default function Home() {
|
|||||||
? "Connected"
|
? "Connected"
|
||||||
: "Error"}
|
: "Error"}
|
||||||
</span>
|
</span>
|
||||||
{{else}}
|
|
||||||
<div
|
|
||||||
className={`h-2 w-2 rounded-full ${
|
|
||||||
healthCheck.data ? "bg-green-500" : "bg-red-500"
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
<span className="text-sm text-muted-foreground">
|
|
||||||
{healthCheck.isLoading
|
|
||||||
? "Checking..."
|
|
||||||
: healthCheck.data
|
|
||||||
? "Connected"
|
|
||||||
: "Disconnected"}
|
|
||||||
</span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div
|
||||||
|
className={`h-2 w-2 rounded-full ${
|
||||||
|
healthCheck.data ? "bg-green-500" : "bg-red-500"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
{healthCheck.isLoading
|
||||||
|
? "Checking..."
|
||||||
|
: healthCheck.data
|
||||||
|
? "Connected"
|
||||||
|
: "Disconnected"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,57 +2,51 @@ import { RouterProvider, createRouter } from "@tanstack/react-router";
|
|||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import Loader from "./components/loader";
|
import Loader from "./components/loader";
|
||||||
import { routeTree } from "./routeTree.gen";
|
import { routeTree } from "./routeTree.gen";
|
||||||
|
|
||||||
{{#if (eq api "orpc")}}
|
{{#if (eq api "orpc")}}
|
||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { orpc, queryClient } from "./utils/orpc";
|
import { orpc, queryClient } from "./utils/orpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
import { QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { queryClient, trpc } from "./utils/trpc";
|
import { queryClient, trpc } from "./utils/trpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
||||||
|
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);
|
||||||
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if (eq api "orpc")}}
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
routeTree,
|
routeTree,
|
||||||
defaultPreload: "intent",
|
defaultPreload: "intent",
|
||||||
defaultPendingComponent: () => <Loader />,
|
defaultPendingComponent: () => <Loader />,
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
context: { orpc, queryClient },
|
context: { orpc, queryClient },
|
||||||
Wrap: function WrapComponent({ children }) {
|
Wrap: function WrapComponent({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
<QueryClientProvider client={queryClient}>
|
||||||
|
{children}
|
||||||
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
{{else if (eq api "trpc")}}
|
||||||
{{/if}}
|
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
const router = createRouter({
|
|
||||||
routeTree,
|
|
||||||
defaultPreload: "intent",
|
|
||||||
defaultPendingComponent: () => <Loader />,
|
|
||||||
context: { trpc, queryClient },
|
context: { trpc, queryClient },
|
||||||
Wrap: function WrapComponent({ children }) {
|
Wrap: function WrapComponent({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
<QueryClientProvider client={queryClient}>
|
||||||
|
{children}
|
||||||
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
{{else if (eq backend "convex")}}
|
||||||
{{/if}}
|
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
const router = createRouter({
|
|
||||||
routeTree,
|
|
||||||
defaultPreload: "intent",
|
|
||||||
defaultPendingComponent: () => <Loader />,
|
|
||||||
context: {},
|
context: {},
|
||||||
Wrap: function WrapComponent({ children }) {
|
Wrap: function WrapComponent({ children }: { children: React.ReactNode }) {
|
||||||
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
|
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
|
||||||
},
|
},
|
||||||
|
{{else}}
|
||||||
|
context: {},
|
||||||
|
{{/if}}
|
||||||
});
|
});
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
declare module "@tanstack/react-router" {
|
declare module "@tanstack/react-router" {
|
||||||
interface Register {
|
interface Register {
|
||||||
@@ -61,7 +55,10 @@ declare module "@tanstack/react-router" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const rootElement = document.getElementById("app");
|
const rootElement = document.getElementById("app");
|
||||||
if (!rootElement) throw new Error("Root element not found");
|
|
||||||
|
if (!rootElement) {
|
||||||
|
throw new Error("Root element not found");
|
||||||
|
}
|
||||||
|
|
||||||
if (!rootElement.innerHTML) {
|
if (!rootElement.innerHTML) {
|
||||||
const root = ReactDOM.createRoot(rootElement);
|
const root = ReactDOM.createRoot(rootElement);
|
||||||
|
|||||||
@@ -31,14 +31,12 @@ export interface RouterAppContext {
|
|||||||
orpc: typeof orpc;
|
orpc: typeof orpc;
|
||||||
queryClient: QueryClient;
|
queryClient: QueryClient;
|
||||||
}
|
}
|
||||||
{{/if}}
|
{{else if (eq api "trpc")}}
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
export interface RouterAppContext {
|
export interface RouterAppContext {
|
||||||
trpc: typeof trpc;
|
trpc: typeof trpc;
|
||||||
queryClient: QueryClient;
|
queryClient: QueryClient;
|
||||||
}
|
}
|
||||||
{{/if}}
|
{{else}}
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
export interface RouterAppContext {}
|
export interface RouterAppContext {}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
@@ -63,18 +61,21 @@ export const Route = createRootRouteWithContext<RouterAppContext>()({
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
{{#if (eq api "orpc")}}
|
|
||||||
function RootComponent() {
|
function RootComponent() {
|
||||||
const [client] = useState<RouterClient<typeof appRouter>>(() => createORPCClient(link))
|
|
||||||
const [orpc] = useState(() => createORPCReactQueryUtils(client))
|
|
||||||
|
|
||||||
const isFetching = useRouterState({
|
const isFetching = useRouterState({
|
||||||
select: (s) => s.isLoading,
|
select: (s) => s.isLoading,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
|
const [client] = useState<RouterClient<typeof appRouter>>(() => createORPCClient(link));
|
||||||
|
const [orpcUtils] = useState(() => createORPCReactQueryUtils(client));
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<HeadContent />
|
<HeadContent />
|
||||||
<ORPCContext.Provider value={orpc}>
|
{{#if (eq api "orpc")}}
|
||||||
|
<ORPCContext.Provider value={orpcUtils}>
|
||||||
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
||||||
<div className="grid grid-rows-[auto_1fr] h-svh">
|
<div className="grid grid-rows-[auto_1fr] h-svh">
|
||||||
<Header />
|
<Header />
|
||||||
@@ -83,20 +84,7 @@ function RootComponent() {
|
|||||||
<Toaster richColors />
|
<Toaster richColors />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</ORPCContext.Provider>
|
</ORPCContext.Provider>
|
||||||
<TanStackRouterDevtools position="bottom-left" />
|
{{else}}
|
||||||
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
function RootComponent() {
|
|
||||||
const isFetching = useRouterState({
|
|
||||||
select: (s) => s.isLoading,
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<HeadContent />
|
|
||||||
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
||||||
<div className="grid grid-rows-[auto_1fr] h-svh">
|
<div className="grid grid-rows-[auto_1fr] h-svh">
|
||||||
<Header />
|
<Header />
|
||||||
@@ -104,29 +92,11 @@ function RootComponent() {
|
|||||||
</div>
|
</div>
|
||||||
<Toaster richColors />
|
<Toaster richColors />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
{{/if}}
|
||||||
<TanStackRouterDevtools position="bottom-left" />
|
<TanStackRouterDevtools position="bottom-left" />
|
||||||
|
{{#if (or (eq api "orpc") (eq api "trpc"))}}
|
||||||
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
||||||
|
{{/if}}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
{{/if}}
|
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
function RootComponent() {
|
|
||||||
const isFetching = useRouterState({
|
|
||||||
select: (s) => s.isLoading,
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<HeadContent />
|
|
||||||
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
|
||||||
<div className="grid grid-rows-[auto_1fr] h-svh">
|
|
||||||
<Header />
|
|
||||||
{isFetching ? <Loader /> : <Outlet />}
|
|
||||||
</div>
|
|
||||||
<Toaster richColors />
|
|
||||||
</ThemeProvider>
|
|
||||||
<TanStackRouterDevtools position="bottom-left" />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
{{/if}}
|
|
||||||
|
|||||||
@@ -49,20 +49,8 @@ function HomeComponent() {
|
|||||||
<div className="grid gap-6">
|
<div className="grid gap-6">
|
||||||
<section className="rounded-lg border p-4">
|
<section className="rounded-lg border p-4">
|
||||||
<h2 className="mb-2 font-medium">API Status</h2>
|
<h2 className="mb-2 font-medium">API Status</h2>
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{{#if (or (eq api "orpc") (eq api "trpc"))}}
|
|
||||||
<div
|
|
||||||
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
|
||||||
/>
|
|
||||||
<span className="text-sm text-muted-foreground">
|
|
||||||
{healthCheck.isLoading
|
|
||||||
? "Checking..."
|
|
||||||
: healthCheck.data
|
|
||||||
? "Connected"
|
|
||||||
: "Disconnected"}
|
|
||||||
</span>
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
<div
|
<div
|
||||||
className={`h-2 w-2 rounded-full ${healthCheck === "OK" ? "bg-green-500" : healthCheck === undefined ? "bg-orange-400" : "bg-red-500"}`}
|
className={`h-2 w-2 rounded-full ${healthCheck === "OK" ? "bg-green-500" : healthCheck === undefined ? "bg-orange-400" : "bg-red-500"}`}
|
||||||
/>
|
/>
|
||||||
@@ -73,8 +61,23 @@ function HomeComponent() {
|
|||||||
? "Connected"
|
? "Connected"
|
||||||
: "Error"}
|
: "Error"}
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div
|
||||||
|
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
||||||
|
/>
|
||||||
|
<span className="text-sm text-muted-foreground">
|
||||||
|
{healthCheck.isLoading
|
||||||
|
? "Checking..."
|
||||||
|
: healthCheck.data
|
||||||
|
? "Connected"
|
||||||
|
: "Disconnected"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,24 +8,20 @@ import { routeTree } from "./routeTree.gen";
|
|||||||
import Loader from "./components/loader";
|
import Loader from "./components/loader";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
{{else}}
|
{{else}}
|
||||||
import {
|
|
||||||
QueryCache,
|
|
||||||
QueryClient,
|
|
||||||
QueryClientProvider,
|
|
||||||
} from "@tanstack/react-query";
|
|
||||||
import { createRouter as createTanstackRouter } from "@tanstack/react-router";
|
import { createRouter as createTanstackRouter } from "@tanstack/react-router";
|
||||||
import Loader from "./components/loader";
|
import Loader from "./components/loader";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { routeTree } from "./routeTree.gen";
|
import { routeTree } from "./routeTree.gen";
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
|
import { QueryCache, QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
||||||
import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
|
import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import type { AppRouter } from "../../server/src/routers";
|
import type { AppRouter } from "../../server/src/routers";
|
||||||
import { TRPCProvider } from "./utils/trpc";
|
import { TRPCProvider } from "./utils/trpc";
|
||||||
{{/if}}
|
{{else if (eq api "orpc")}}
|
||||||
{{#if (eq api "orpc")}}
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { orpc, ORPCContext, queryClient } from "./utils/orpc";
|
import { orpc, ORPCContext, queryClient as orpcQueryClient } from "./utils/orpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
@@ -62,7 +58,6 @@ export function createRouter() {
|
|||||||
}),
|
}),
|
||||||
queryClient,
|
queryClient,
|
||||||
);
|
);
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
}
|
}
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -103,6 +98,8 @@ const trpc = createTRPCOptionsProxy({
|
|||||||
client: trpcClient,
|
client: trpcClient,
|
||||||
queryClient: queryClient,
|
queryClient: queryClient,
|
||||||
});
|
});
|
||||||
|
{{else if (eq api "orpc")}}
|
||||||
|
const queryClient = orpcQueryClient;
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
export const createRouter = () => {
|
export const createRouter = () => {
|
||||||
@@ -112,33 +109,37 @@ export const createRouter = () => {
|
|||||||
defaultPreloadStaleTime: 0,
|
defaultPreloadStaleTime: 0,
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
context: { trpc, queryClient },
|
context: { trpc, queryClient },
|
||||||
{{/if}}
|
{{else if (eq api "orpc")}}
|
||||||
{{#if (eq api "orpc")}}
|
|
||||||
context: { orpc, queryClient },
|
context: { orpc, queryClient },
|
||||||
|
{{else}}
|
||||||
|
context: { },
|
||||||
{{/if}}
|
{{/if}}
|
||||||
defaultPendingComponent: () => <Loader />,
|
defaultPendingComponent: () => <Loader />,
|
||||||
defaultNotFoundComponent: () => <div>Not Found</div>,
|
defaultNotFoundComponent: () => <div>Not Found</div>,
|
||||||
|
{{#if (eq api "trpc")}}
|
||||||
Wrap: ({ children }) => (
|
Wrap: ({ children }) => (
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
<TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
|
<TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
|
||||||
{children}
|
{children}
|
||||||
</TRPCProvider>
|
</TRPCProvider>
|
||||||
{{/if}}
|
</QueryClientProvider>
|
||||||
{{#if (eq api "orpc")}}
|
),
|
||||||
|
{{else if (eq api "orpc")}}
|
||||||
|
Wrap: ({ children }) => (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
<ORPCContext.Provider value={orpc}>
|
<ORPCContext.Provider value={orpc}>
|
||||||
{children}
|
{children}
|
||||||
</ORPCContext.Provider>
|
</ORPCContext.Provider>
|
||||||
{{/if}}
|
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
),
|
),
|
||||||
|
{{else}}
|
||||||
|
Wrap: ({ children }) => <>{children}</>,
|
||||||
|
{{/if}}
|
||||||
});
|
});
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
};
|
};
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
// Register the router instance for type safety
|
|
||||||
declare module "@tanstack/react-router" {
|
declare module "@tanstack/react-router" {
|
||||||
interface Register {
|
interface Register {
|
||||||
router: ReturnType<typeof createRouter>;
|
router: ReturnType<typeof createRouter>;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Toaster } from "@/components/ui/sonner";
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
|
{{#unless (eq backend "convex")}} {{#unless (eq api "none")}}
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
|
{{/unless}} {{/unless}}
|
||||||
import {
|
import {
|
||||||
HeadContent,
|
HeadContent,
|
||||||
Outlet,
|
Outlet,
|
||||||
@@ -10,7 +12,9 @@ import {
|
|||||||
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
|
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
|
||||||
import Header from "../components/header";
|
import Header from "../components/header";
|
||||||
import appCss from "../index.css?url";
|
import appCss from "../index.css?url";
|
||||||
|
{{#unless (and (eq api "none") (not (eq backend "convex"))}}
|
||||||
import type { QueryClient } from "@tanstack/react-query";
|
import type { QueryClient } from "@tanstack/react-query";
|
||||||
|
{{/unless}}
|
||||||
import Loader from "@/components/loader";
|
import Loader from "@/components/loader";
|
||||||
|
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
@@ -25,12 +29,14 @@ export interface RouterAppContext {
|
|||||||
trpc: TRPCOptionsProxy<AppRouter>;
|
trpc: TRPCOptionsProxy<AppRouter>;
|
||||||
queryClient: QueryClient;
|
queryClient: QueryClient;
|
||||||
}
|
}
|
||||||
{{/if}}
|
{{else if (eq api "orpc")}}
|
||||||
{{#if (eq api "orpc")}}
|
|
||||||
import type { orpc } from "@/utils/orpc";
|
import type { orpc } from "@/utils/orpc";
|
||||||
export interface RouterAppContext {
|
export interface RouterAppContext {
|
||||||
orpc: typeof orpc;
|
orpc: typeof orpc;
|
||||||
queryClient: QueryClient;
|
queryClient: QueryClient;
|
||||||
|
}
|
||||||
|
{{else}}
|
||||||
|
export interface RouterAppContext {
|
||||||
}
|
}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -75,7 +81,11 @@ function RootDocument() {
|
|||||||
</div>
|
</div>
|
||||||
<Toaster richColors />
|
<Toaster richColors />
|
||||||
<TanStackRouterDevtools position="bottom-left" />
|
<TanStackRouterDevtools position="bottom-left" />
|
||||||
|
{{#unless (eq backend "convex")}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
|
||||||
|
{{/unless}}
|
||||||
|
{{/unless}}
|
||||||
<Scripts />
|
<Scripts />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ import { createFileRoute } from "@tanstack/react-router";
|
|||||||
import { convexQuery } from "@convex-dev/react-query";
|
import { convexQuery } from "@convex-dev/react-query";
|
||||||
import { useSuspenseQuery } from "@tanstack/react-query";
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
||||||
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
||||||
{{else}}
|
{{else if (or (eq api "trpc") (eq api "orpc"))}}
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
{{#if (eq api "trpc")}}
|
{{#if (eq api "trpc")}}
|
||||||
import { useTRPC } from "@/utils/trpc";
|
import { useTRPC } from "@/utils/trpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq api "orpc")}}
|
{{#if (eq api "orpc")}}
|
||||||
import { useORPC } from "@/utils/orpc";
|
import { useORPC } from "@/utils/orpc";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
import { useQuery } from "@tanstack/react-query";
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
export const Route = createFileRoute("/")({
|
export const Route = createFileRoute("/")({
|
||||||
@@ -36,15 +36,12 @@ const TITLE_TEXT = `
|
|||||||
function HomeComponent() {
|
function HomeComponent() {
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
const healthCheck = useSuspenseQuery(convexQuery(api.healthCheck.get, {}));
|
const healthCheck = useSuspenseQuery(convexQuery(api.healthCheck.get, {}));
|
||||||
{{else}}
|
{{else if (eq api "trpc")}}
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
const trpc = useTRPC();
|
const trpc = useTRPC();
|
||||||
const healthCheck = useQuery(trpc.healthCheck.queryOptions());
|
const healthCheck = useQuery(trpc.healthCheck.queryOptions());
|
||||||
{{/if}}
|
{{else if (eq api "orpc")}}
|
||||||
{{#if (eq api "orpc")}}
|
|
||||||
const orpc = useORPC();
|
const orpc = useORPC();
|
||||||
const healthCheck = useQuery(orpc.healthCheck.queryOptions());
|
const healthCheck = useQuery(orpc.healthCheck.queryOptions());
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -53,8 +50,8 @@ function HomeComponent() {
|
|||||||
<div className="grid gap-6">
|
<div className="grid gap-6">
|
||||||
<section className="rounded-lg border p-4">
|
<section className="rounded-lg border p-4">
|
||||||
<h2 className="mb-2 font-medium">API Status</h2>
|
<h2 className="mb-2 font-medium">API Status</h2>
|
||||||
|
{{#if (eq backend "convex")}}
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{{#if (eq backend "convex")}}
|
|
||||||
<div
|
<div
|
||||||
className={`h-2 w-2 rounded-full ${healthCheck.data === "OK" ? "bg-green-500" : healthCheck.isLoading ? "bg-orange-400" : "bg-red-500"}`}
|
className={`h-2 w-2 rounded-full ${healthCheck.data === "OK" ? "bg-green-500" : healthCheck.isLoading ? "bg-orange-400" : "bg-red-500"}`}
|
||||||
/>
|
/>
|
||||||
@@ -65,19 +62,23 @@ function HomeComponent() {
|
|||||||
? "Connected"
|
? "Connected"
|
||||||
: "Error"}
|
: "Error"}
|
||||||
</span>
|
</span>
|
||||||
{{else}}
|
|
||||||
<div
|
|
||||||
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
|
||||||
/>
|
|
||||||
<span className="text-muted-foreground text-sm">
|
|
||||||
{healthCheck.isLoading
|
|
||||||
? "Checking..."
|
|
||||||
: healthCheck.data
|
|
||||||
? "Connected"
|
|
||||||
: "Disconnected"}
|
|
||||||
</span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
{{#unless (eq api "none")}}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div
|
||||||
|
className={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
||||||
|
/>
|
||||||
|
<span className="text-muted-foreground text-sm">
|
||||||
|
{healthCheck.isLoading
|
||||||
|
? "Checking..."
|
||||||
|
: healthCheck.data
|
||||||
|
? "Connected"
|
||||||
|
: "Disconnected"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import { RouterProvider, createRouter } from "@tanstack/solid-router";
|
|||||||
import { render } from "solid-js/web";
|
import { render } from "solid-js/web";
|
||||||
import { routeTree } from "./routeTree.gen";
|
import { routeTree } from "./routeTree.gen";
|
||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
import { QueryClientProvider } from "@tanstack/solid-query";
|
import { QueryClientProvider } from "@tanstack/solid-query";
|
||||||
import { queryClient } from "./utils/orpc";
|
import { queryClient } from "./utils/orpc";
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
routeTree,
|
routeTree,
|
||||||
@@ -20,9 +22,13 @@ declare module "@tanstack/solid-router" {
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
|
{{/if}}
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
{{/if}}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
import Header from "@/components/header";
|
import Header from "@/components/header";
|
||||||
import { Outlet, createRootRouteWithContext } from "@tanstack/solid-router";
|
import { Outlet, createRootRouteWithContext } from "@tanstack/solid-router";
|
||||||
import { TanStackRouterDevtools } from "@tanstack/solid-router-devtools";
|
import { TanStackRouterDevtools } from "@tanstack/solid-router-devtools";
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
import { SolidQueryDevtools } from "@tanstack/solid-query-devtools";
|
import { SolidQueryDevtools } from "@tanstack/solid-query-devtools";
|
||||||
|
import type { QueryClient } from "@tanstack/solid-query";
|
||||||
|
import type { orpc } from "../utils/orpc";
|
||||||
|
|
||||||
export const Route = createRootRouteWithContext()({
|
export interface RouterContext {
|
||||||
|
orpc: typeof orpc;
|
||||||
|
queryClient: QueryClient;
|
||||||
|
}
|
||||||
|
{{else}}
|
||||||
|
export interface RouterContext {}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
export const Route = createRootRouteWithContext<RouterContext>()({
|
||||||
component: RootComponent,
|
component: RootComponent,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -14,7 +25,9 @@ function RootComponent() {
|
|||||||
<Header />
|
<Header />
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
<SolidQueryDevtools />
|
<SolidQueryDevtools />
|
||||||
|
{{/if}}
|
||||||
<TanStackRouterDevtools />
|
<TanStackRouterDevtools />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { createFileRoute } from "@tanstack/solid-router";
|
import { createFileRoute } from "@tanstack/solid-router";
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
import { useQuery } from "@tanstack/solid-query";
|
import { useQuery } from "@tanstack/solid-query";
|
||||||
import { orpc } from "../utils/orpc";
|
import { orpc } from "../utils/orpc";
|
||||||
import { Match, Switch } from "solid-js";
|
import { Match, Switch } from "solid-js";
|
||||||
|
{{else}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
export const Route = createFileRoute("/")({
|
export const Route = createFileRoute("/")({
|
||||||
component: App,
|
component: App,
|
||||||
@@ -24,12 +27,15 @@ const TITLE_TEXT = `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
const healthCheck = useQuery(() => orpc.healthCheck.queryOptions());
|
const healthCheck = useQuery(() => orpc.healthCheck.queryOptions());
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="container mx-auto max-w-3xl px-4 py-2">
|
<div class="container mx-auto max-w-3xl px-4 py-2">
|
||||||
<pre class="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
|
<pre class="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
|
||||||
<div class="grid gap-6">
|
<div class="grid gap-6">
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
<section class="rounded-lg border p-4">
|
<section class="rounded-lg border p-4">
|
||||||
<h2 class="mb-2 font-medium">API Status</h2>
|
<h2 class="mb-2 font-medium">API Status</h2>
|
||||||
<Switch>
|
<Switch>
|
||||||
@@ -53,12 +59,13 @@ function App() {
|
|||||||
<span class="text-sm text-muted-foreground">
|
<span class="text-sm text-muted-foreground">
|
||||||
{healthCheck.data
|
{healthCheck.data
|
||||||
? "Connected"
|
? "Connected"
|
||||||
: "Disconnected (Success but no data)"}
|
: "Disconnected"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
</section>
|
</section>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,16 +16,12 @@
|
|||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { QueryClientProvider } from '@tanstack/svelte-query';
|
import { QueryClientProvider } from '@tanstack/svelte-query';
|
||||||
import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
|
import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
{{#if (eq api "orpc")}}
|
|
||||||
import { queryClient } from '$lib/orpc';
|
import { queryClient } from '$lib/orpc';
|
||||||
{{/if}}
|
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
import { queryClient } from '$lib/trpc';
|
|
||||||
{{/if}}
|
|
||||||
import Header from '../components/Header.svelte';
|
import Header from '../components/Header.svelte';
|
||||||
|
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
@@ -40,4 +36,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<SvelteQueryDevtools />
|
<SvelteQueryDevtools />
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
{{else}}
|
||||||
|
<script lang="ts">
|
||||||
|
import '../app.css';
|
||||||
|
import Header from '../components/Header.svelte';
|
||||||
|
|
||||||
|
let { children } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="grid h-svh grid-rows-[auto_1fr]">
|
||||||
|
<Header />
|
||||||
|
<main class="overflow-y-auto">
|
||||||
|
{@render children()}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -3,10 +3,8 @@
|
|||||||
import { useQuery } from 'convex-svelte';
|
import { useQuery } from 'convex-svelte';
|
||||||
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
import { api } from "@{{projectName}}/backend/convex/_generated/api.js";
|
||||||
|
|
||||||
|
|
||||||
const healthCheck = useQuery(api.healthCheck.get, {});
|
const healthCheck = useQuery(api.healthCheck.get, {});
|
||||||
|
|
||||||
|
|
||||||
const TITLE_TEXT = `
|
const TITLE_TEXT = `
|
||||||
██████╗ ███████╗████████╗████████╗███████╗██████╗
|
██████╗ ███████╗████████╗████████╗███████╗██████╗
|
||||||
██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
|
██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
|
||||||
@@ -28,7 +26,7 @@ const TITLE_TEXT = `
|
|||||||
<pre class="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
|
<pre class="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
|
||||||
<div class="grid gap-6">
|
<div class="grid gap-6">
|
||||||
<section class="rounded-lg border p-4">
|
<section class="rounded-lg border p-4">
|
||||||
<h2 class="mb-2 font-medium">API Status (Convex)</h2>
|
<h2 class="mb-2 font-medium">API Status</h2>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
class={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
class={`h-2 w-2 rounded-full ${healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
||||||
@@ -48,19 +46,9 @@ const TITLE_TEXT = `
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
{{#if (eq api "orpc")}}
|
{{#if (eq api "orpc")}}
|
||||||
import { orpc } from "$lib/orpc";
|
import { orpc } from "$lib/orpc";
|
||||||
{{/if}}
|
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
import { trpc } from "$lib/trpc";
|
|
||||||
{{/if}}
|
|
||||||
import { createQuery } from "@tanstack/svelte-query";
|
import { createQuery } from "@tanstack/svelte-query";
|
||||||
|
|
||||||
{{#if (eq api "orpc")}}
|
|
||||||
const healthCheck = createQuery(orpc.healthCheck.queryOptions());
|
const healthCheck = createQuery(orpc.healthCheck.queryOptions());
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq api "trpc")}}
|
|
||||||
const healthCheck = createQuery(trpc.healthCheck.queryOptions());
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
|
|
||||||
const TITLE_TEXT = `
|
const TITLE_TEXT = `
|
||||||
██████╗ ███████╗████████╗████████╗███████╗██████╗
|
██████╗ ███████╗████████╗████████╗███████╗██████╗
|
||||||
@@ -82,8 +70,9 @@ const TITLE_TEXT = `
|
|||||||
<div class="container mx-auto max-w-3xl px-4 py-2">
|
<div class="container mx-auto max-w-3xl px-4 py-2">
|
||||||
<pre class="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
|
<pre class="overflow-x-auto font-mono text-sm">{TITLE_TEXT}</pre>
|
||||||
<div class="grid gap-6">
|
<div class="grid gap-6">
|
||||||
|
{{#if (eq api "orpc")}}
|
||||||
<section class="rounded-lg border p-4">
|
<section class="rounded-lg border p-4">
|
||||||
<h2 class="mb-2 font-medium">API Status{{#if (eq api "trpc")}} (tRPC){{/if}}{{#if (eq api "orpc")}} (oRPC){{/if}}</h2>
|
<h2 class="mb-2 font-medium">API Status</h2>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div
|
<div
|
||||||
class={`h-2 w-2 rounded-full ${$healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
class={`h-2 w-2 rounded-full ${$healthCheck.data ? "bg-green-500" : "bg-red-500"}`}
|
||||||
@@ -97,6 +86,7 @@ const TITLE_TEXT = `
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
22
bun.lock
22
bun.lock
@@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
"apps/cli": {
|
"apps/cli": {
|
||||||
"name": "create-better-t-stack",
|
"name": "create-better-t-stack",
|
||||||
"version": "2.9.0",
|
"version": "2.9.2",
|
||||||
"bin": {
|
"bin": {
|
||||||
"create-better-t-stack": "dist/index.js",
|
"create-better-t-stack": "dist/index.js",
|
||||||
},
|
},
|
||||||
@@ -43,9 +43,9 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-dialog": "^1.1.13",
|
"@radix-ui/react-dialog": "^1.1.13",
|
||||||
"@radix-ui/react-scroll-area": "^1.2.6",
|
"@radix-ui/react-scroll-area": "^1.2.8",
|
||||||
"@radix-ui/react-switch": "^1.2.2",
|
"@radix-ui/react-switch": "^1.2.4",
|
||||||
"@radix-ui/react-tooltip": "^1.2.4",
|
"@radix-ui/react-tooltip": "^1.2.6",
|
||||||
"babel-plugin-react-compiler": "^19.1.0-rc.1",
|
"babel-plugin-react-compiler": "^19.1.0-rc.1",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"fumadocs-mdx": "11.6.1",
|
"fumadocs-mdx": "11.6.1",
|
||||||
"fumadocs-ui": "15.2.10",
|
"fumadocs-ui": "15.2.10",
|
||||||
"lucide-react": "^0.503.0",
|
"lucide-react": "^0.503.0",
|
||||||
"motion": "^12.8.0",
|
"motion": "^12.10.5",
|
||||||
"next": "15.3.1",
|
"next": "15.3.1",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"nuqs": "^2.4.3",
|
"nuqs": "^2.4.3",
|
||||||
@@ -64,16 +64,16 @@
|
|||||||
"tailwind-merge": "^3.2.0",
|
"tailwind-merge": "^3.2.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4.1.4",
|
"@tailwindcss/postcss": "^4.1.5",
|
||||||
"@types/mdx": "^2.0.13",
|
"@types/mdx": "^2.0.13",
|
||||||
"@types/node": "22.14.1",
|
"@types/node": "22.14.1",
|
||||||
"@types/react": "^19.1.2",
|
"@types/react": "^19.1.3",
|
||||||
"@types/react-dom": "^19.1.2",
|
"@types/react-dom": "^19.1.3",
|
||||||
"eslint": "^9.25.1",
|
"eslint": "^9.26.0",
|
||||||
"eslint-config-next": "15.3.1",
|
"eslint-config-next": "15.3.1",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"tailwindcss": "^4.1.4",
|
"tailwindcss": "^4.1.5",
|
||||||
"tw-animate-css": "^1.2.8",
|
"tw-animate-css": "^1.2.9",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user