Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/modules/sites/db/sites.db.server.ts
T

183 lines
4.7 KiB
TypeScript

import { Prisma, Site } from "@toolctrl/db/prisma-browser";
import { db, dbRead } from "~/utils/db.server";
export async function getSite({ id, tenantId }: { id: string; tenantId: string }) {
// Read-only site detail used by admin views and public renderers — replica-safe.
return dbRead.site.findFirst({
where: { id, tenantId },
include: { tenant: true, createdByUser: true },
});
}
// Get site by type and siteId (for API authentication)
export async function getSiteByTypeAndSiteId(type: string, siteId: string) {
return db.site.findUnique({
where: { type_siteId: { type, siteId } },
include: { tenant: true },
});
}
export async function getSiteNameByTypeAndSiteId(type: string, siteId: string) {
// Read-only public lookup (used by rendering, not auth). Replica-safe.
return dbRead.site.findUnique({
where: { type_siteId: { type, siteId } },
include: { tenant: { select: { name: true, slug: true } } },
// select: {
// id: true,
// tenantId: true,
// name: true,
// siteId: true,
// isActive: true,
// branding: true,
// copy: true,
// },
});
}
// Get all sites for a tenant
export async function getSitesByTenantId(tenantId: string) {
// Tenant site listing for admin/public rendering — read-only.
return dbRead.site.findMany({
where: { tenantId },
orderBy: { createdAt: "desc" },
include: { createdByUser: { select: { email: true, firstName: true, lastName: true } } },
});
}
// Get sites by type for a tenant
export async function getSitesByTenantIdAndType(tenantId: string, type: string) {
// Tenant site listing filtered by type — read-only.
return dbRead.site.findMany({
where: { tenantId, type },
orderBy: { createdAt: "desc" },
});
}
// Check if siteId is available for a type
export async function isSiteIdAvailable(type: string, siteId: string): Promise<boolean> {
const existing = await db.site.findUnique({
where: { type_siteId: { type, siteId } },
select: { id: true },
});
return !existing;
}
// Create a new site
export async function createSite(data: {
tenantId: string;
type: string;
siteId: string;
name: string;
serverName: string;
serverHost: string;
isActive: boolean;
serverResolution: string;
createdByUserId?: string;
branding?: string;
copy?: string;
}) {
return db.site.create({
data: {
tenantId: data.tenantId,
type: data.type,
siteId: data.siteId,
name: data.name,
serverName: data.serverName,
serverHost: data.serverHost,
serverResolution: data.serverResolution,
isActive: data.isActive,
createdByUserId: data.createdByUserId,
branding: data.branding ?? "{}",
copy: data.copy ?? "{}",
},
include: { tenant: true },
});
}
export async function updateSite(
scope: { id: string; tenantId: string },
data: {
name?: string;
siteId?: string;
isActive?: boolean;
branding?: string;
copy?: string;
}
) {
const result = await db.site.updateMany({
where: scope,
data,
});
if (result.count !== 1) {
throw new Error("Site not found for tenant scope.");
}
return db.site.findFirstOrThrow({
where: scope,
});
}
export async function deleteSite(scope: { id: string; tenantId: string }) {
const item = await db.site.findFirst({ where: scope });
if (!item) {
throw new Error("Site not found for tenant scope.");
}
const result = await db.site.deleteMany({ where: scope });
if (result.count !== 1) {
throw new Error("Site not found for tenant scope.");
}
return item;
}
// Get sites with pagination
export async function getSitesWithPagination({
tenantId,
type,
pagination,
filters,
}: {
tenantId: string;
type?: string;
pagination?: { page: number; pageSize: number };
filters?: { q?: string };
}) {
let where: Prisma.SiteWhereInput = { tenantId };
if (type) {
where.type = type;
}
if (filters?.q) {
where = {
...where,
OR: [{ name: { contains: filters.q, mode: "insensitive" } }, { siteId: { contains: filters.q, mode: "insensitive" } }],
};
}
// Paginated listing for admin grid — read-only, replica-safe.
const items = await dbRead.site.findMany({
take: pagination?.pageSize,
skip: pagination ? pagination.pageSize * (pagination.page - 1) : undefined,
where,
orderBy: { createdAt: "desc" },
include: {
createdByUser: { select: { email: true, firstName: true, lastName: true } },
},
});
if (!pagination) {
return { items };
}
const totalItems = await dbRead.site.count({ where });
return {
items,
pagination: {
page: pagination.page,
pageSize: pagination.pageSize,
totalItems,
totalPages: Math.ceil(totalItems / pagination.pageSize),
},
};
}