feat(db): mesh data model — meshes, members, invites, audit log

- pgSchema "mesh" with 4 tables isolating the peer mesh domain
- Enums: visibility, transport, tier, role
- audit_log is metadata-only (E2E encryption enforced at broker/client)
- Cascade on mesh delete, soft-delete via archivedAt/revokedAt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-04 21:19:32 +01:00
commit d3163a5bff
1384 changed files with 314925 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
"use client";
import { QueryClientProvider as TanstackQueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { createQueryClient } from "./utils";
import type { QueryClient } from "@tanstack/react-query";
let clientQueryClientSingleton: QueryClient | undefined = undefined;
export const getQueryClient = () => {
if (typeof window === "undefined") {
// Server: always make a new query client
return createQueryClient();
} else {
// Browser: use singleton pattern to keep the same query client
return (clientQueryClientSingleton ??= createQueryClient());
}
};
export function QueryClientProvider(props: { children: React.ReactNode }) {
const queryClient = getQueryClient();
return (
<TanstackQueryClientProvider client={queryClient}>
{props.children}
<ReactQueryDevtools />
</TanstackQueryClientProvider>
);
}

View File

@@ -0,0 +1,5 @@
import { cache } from "react";
import { createQueryClient } from "./utils";
export const getQueryClient = cache(createQueryClient);

View File

@@ -0,0 +1,33 @@
import {
QueryClient,
defaultShouldDehydrateQuery,
} from "@tanstack/react-query";
import { toast } from "sonner";
import { logger } from "@turbostarter/shared/logger";
export const createQueryClient = () =>
new QueryClient({
defaultOptions: {
queries: {
// With SSR, we usually want to set some default staleTime
// above 0 to avoid refetching immediately on the client
staleTime: 60 * 1000,
},
dehydrate: {
shouldDehydrateQuery: (query) =>
defaultShouldDehydrateQuery(query) ||
query.state.status === "pending",
},
mutations: {
onError: (error: Error | { error: Error }) => {
if ("error" in error) {
error = error.error;
}
logger.error(error);
toast.error(error.message);
},
},
},
});