Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
155 lines
4.8 KiB
JavaScript
155 lines
4.8 KiB
JavaScript
import { PrismaClient } from "@prisma/client"
|
|
import { ConvexHttpClient } from "convex/browser"
|
|
|
|
const prisma = new PrismaClient()
|
|
|
|
function toMillis(date) {
|
|
return date instanceof Date ? date.getTime() : date ? new Date(date).getTime() : undefined
|
|
}
|
|
|
|
function normalizeString(value, fallback = "") {
|
|
if (!value) return fallback
|
|
return value.trim()
|
|
}
|
|
|
|
function slugify(value) {
|
|
return normalizeString(value)
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9\s-]/g, "")
|
|
.replace(/\s+/g, "-")
|
|
.replace(/-+/g, "-") || undefined
|
|
}
|
|
|
|
async function main() {
|
|
const tenantId = process.env.SYNC_TENANT_ID || "tenant-atlas"
|
|
const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL || "http://127.0.0.1:3210"
|
|
const secret = process.env.CONVEX_SYNC_SECRET
|
|
|
|
if (!secret) {
|
|
console.error("CONVEX_SYNC_SECRET não configurado. Configure no .env.")
|
|
process.exit(1)
|
|
}
|
|
|
|
const [users, queues, tickets, companies] = await Promise.all([
|
|
prisma.user.findMany({
|
|
include: {
|
|
teams: {
|
|
include: { team: true },
|
|
},
|
|
company: true,
|
|
},
|
|
}),
|
|
prisma.queue.findMany(),
|
|
prisma.ticket.findMany({
|
|
include: {
|
|
requester: true,
|
|
assignee: true,
|
|
queue: true,
|
|
company: true,
|
|
comments: {
|
|
include: {
|
|
author: true,
|
|
},
|
|
},
|
|
events: true,
|
|
},
|
|
orderBy: { createdAt: "asc" },
|
|
}),
|
|
prisma.company.findMany(),
|
|
])
|
|
|
|
const userSnapshot = users.map((user) => ({
|
|
email: user.email,
|
|
name: normalizeString(user.name, user.email),
|
|
role: user.role,
|
|
avatarUrl: user.avatarUrl ?? undefined,
|
|
teams: user.teams
|
|
.map((membership) => membership.team?.name)
|
|
.filter((name) => Boolean(name) && typeof name === "string"),
|
|
companySlug: user.company?.slug ?? undefined,
|
|
}))
|
|
|
|
const queueSnapshot = queues.map((queue) => ({
|
|
name: normalizeString(queue.name, queue.slug ?? queue.id),
|
|
slug: queue.slug ? queue.slug : normalizeString(queue.name, queue.id).toLowerCase().replace(/\s+/g, "-"),
|
|
}))
|
|
|
|
const referenceFallbackStart = 41000
|
|
let referenceCounter = referenceFallbackStart
|
|
|
|
const ticketSnapshot = tickets.map((ticket) => {
|
|
const reference = ticket.reference && ticket.reference > 0 ? ticket.reference : ++referenceCounter
|
|
const requesterEmail = ticket.requester?.email ?? userSnapshot[0]?.email ?? "unknown@example.com"
|
|
const assigneeEmail = ticket.assignee?.email ?? undefined
|
|
const queueSlug = ticket.queue?.slug ?? slugify(ticket.queue?.name)
|
|
const companySlug = ticket.company?.slug ?? ticket.requester?.company?.slug ?? undefined
|
|
|
|
return {
|
|
reference,
|
|
subject: normalizeString(ticket.subject, `Ticket ${reference}`),
|
|
summary: ticket.summary ?? undefined,
|
|
status: ticket.status,
|
|
priority: ticket.priority,
|
|
channel: ticket.channel,
|
|
queueSlug: queueSlug ?? undefined,
|
|
requesterEmail,
|
|
assigneeEmail,
|
|
companySlug,
|
|
dueAt: toMillis(ticket.dueAt) ?? undefined,
|
|
firstResponseAt: toMillis(ticket.firstResponseAt) ?? undefined,
|
|
resolvedAt: toMillis(ticket.resolvedAt) ?? undefined,
|
|
closedAt: toMillis(ticket.closedAt) ?? undefined,
|
|
createdAt: toMillis(ticket.createdAt) ?? Date.now(),
|
|
updatedAt: toMillis(ticket.updatedAt) ?? Date.now(),
|
|
tags: Array.isArray(ticket.tags) ? ticket.tags : undefined,
|
|
comments: ticket.comments.map((comment) => ({
|
|
authorEmail: comment.author?.email ?? requesterEmail,
|
|
visibility: comment.visibility,
|
|
body: comment.body,
|
|
createdAt: toMillis(comment.createdAt) ?? Date.now(),
|
|
updatedAt: toMillis(comment.updatedAt) ?? Date.now(),
|
|
})),
|
|
events: ticket.events.map((event) => ({
|
|
type: event.type,
|
|
payload: event.payload ?? {},
|
|
createdAt: toMillis(event.createdAt) ?? Date.now(),
|
|
})),
|
|
}
|
|
})
|
|
|
|
const companySnapshot = companies.map((company) => ({
|
|
slug: company.slug ?? slugify(company.name),
|
|
name: company.name,
|
|
cnpj: company.cnpj ?? undefined,
|
|
domain: company.domain ?? undefined,
|
|
phone: company.phone ?? undefined,
|
|
description: company.description ?? undefined,
|
|
address: company.address ?? undefined,
|
|
createdAt: toMillis(company.createdAt) ?? Date.now(),
|
|
updatedAt: toMillis(company.updatedAt) ?? Date.now(),
|
|
}))
|
|
|
|
const client = new ConvexHttpClient(convexUrl)
|
|
|
|
const result = await client.mutation("migrations:importPrismaSnapshot", {
|
|
secret,
|
|
snapshot: {
|
|
tenantId,
|
|
companies: companySnapshot,
|
|
users: userSnapshot,
|
|
queues: queueSnapshot,
|
|
tickets: ticketSnapshot,
|
|
},
|
|
})
|
|
|
|
console.log("Sincronização concluída:", result)
|
|
}
|
|
|
|
main()
|
|
.catch((error) => {
|
|
console.error(error)
|
|
process.exitCode = 1
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect()
|
|
})
|