chore: reorganize project structure and ensure default queues

This commit is contained in:
Esdras Renan 2025-10-06 22:59:35 -03:00
parent 854887f499
commit 1cccb852a5
201 changed files with 417 additions and 838 deletions

View file

@ -1,173 +0,0 @@
import sanitizeHtml from "sanitize-html"
import { ConvexError, v } from "convex/values"
import { mutation, query } from "./_generated/server"
import { requireStaff } from "./rbac"
const SANITIZE_OPTIONS: sanitizeHtml.IOptions = {
allowedTags: [
"p",
"br",
"a",
"strong",
"em",
"u",
"s",
"blockquote",
"ul",
"ol",
"li",
"code",
"pre",
"span",
"h1",
"h2",
"h3",
],
allowedAttributes: {
a: ["href", "name", "target", "rel"],
span: ["style"],
code: ["class"],
pre: ["class"],
},
allowedSchemes: ["http", "https", "mailto"],
transformTags: {
a: sanitizeHtml.simpleTransform("a", { rel: "noopener noreferrer", target: "_blank" }, true),
},
allowVulnerableTags: false,
}
function sanitizeTemplateBody(body: string) {
const sanitized = sanitizeHtml(body || "", SANITIZE_OPTIONS).trim()
return sanitized
}
function normalizeTitle(title: string) {
return title?.trim()
}
export const list = query({
args: {
tenantId: v.string(),
viewerId: v.id("users"),
},
handler: async (ctx, { tenantId, viewerId }) => {
await requireStaff(ctx, viewerId, tenantId)
const templates = await ctx.db
.query("commentTemplates")
.withIndex("by_tenant", (q) => q.eq("tenantId", tenantId))
.collect()
return templates
.sort((a, b) => a.title.localeCompare(b.title, "pt-BR", { sensitivity: "base" }))
.map((template) => ({
id: template._id,
title: template.title,
body: template.body,
createdAt: template.createdAt,
updatedAt: template.updatedAt,
createdBy: template.createdBy,
updatedBy: template.updatedBy ?? null,
}))
},
})
export const create = mutation({
args: {
tenantId: v.string(),
actorId: v.id("users"),
title: v.string(),
body: v.string(),
},
handler: async (ctx, { tenantId, actorId, title, body }) => {
await requireStaff(ctx, actorId, tenantId)
const normalizedTitle = normalizeTitle(title)
if (!normalizedTitle || normalizedTitle.length < 3) {
throw new ConvexError("Informe um título válido para o template")
}
const sanitizedBody = sanitizeTemplateBody(body)
if (!sanitizedBody) {
throw new ConvexError("Informe o conteúdo do template")
}
const existing = await ctx.db
.query("commentTemplates")
.withIndex("by_tenant_title", (q) => q.eq("tenantId", tenantId).eq("title", normalizedTitle))
.first()
if (existing) {
throw new ConvexError("Já existe um template com este título")
}
const now = Date.now()
const id = await ctx.db.insert("commentTemplates", {
tenantId,
title: normalizedTitle,
body: sanitizedBody,
createdBy: actorId,
updatedBy: actorId,
createdAt: now,
updatedAt: now,
})
return id
},
})
export const update = mutation({
args: {
templateId: v.id("commentTemplates"),
tenantId: v.string(),
actorId: v.id("users"),
title: v.string(),
body: v.string(),
},
handler: async (ctx, { templateId, tenantId, actorId, title, body }) => {
await requireStaff(ctx, actorId, tenantId)
const template = await ctx.db.get(templateId)
if (!template || template.tenantId !== tenantId) {
throw new ConvexError("Template não encontrado")
}
const normalizedTitle = normalizeTitle(title)
if (!normalizedTitle || normalizedTitle.length < 3) {
throw new ConvexError("Informe um título válido para o template")
}
const sanitizedBody = sanitizeTemplateBody(body)
if (!sanitizedBody) {
throw new ConvexError("Informe o conteúdo do template")
}
const duplicate = await ctx.db
.query("commentTemplates")
.withIndex("by_tenant_title", (q) => q.eq("tenantId", tenantId).eq("title", normalizedTitle))
.first()
if (duplicate && duplicate._id !== templateId) {
throw new ConvexError("Já existe um template com este título")
}
const now = Date.now()
await ctx.db.patch(templateId, {
title: normalizedTitle,
body: sanitizedBody,
updatedBy: actorId,
updatedAt: now,
})
},
})
export const remove = mutation({
args: {
templateId: v.id("commentTemplates"),
tenantId: v.string(),
actorId: v.id("users"),
},
handler: async (ctx, { templateId, tenantId, actorId }) => {
await requireStaff(ctx, actorId, tenantId)
const template = await ctx.db.get(templateId)
if (!template || template.tenantId !== tenantId) {
throw new ConvexError("Template não encontrado")
}
await ctx.db.delete(templateId)
},
})