mirror of
https://github.com/hanzo-apps/dataroom.git
synced 2026-10-30 14:47:36 +00:00
The last of it, all one shape: sqlite has no enum, so those columns read back as `string`, while hand-written prop and payload types restated the literals. Each now names the type the shim already exports — DownloadType, ViewType — so the column and the code that consumes it stay in step. `linkType` reaches an outgoing webhook, whose contract is a zod enum and should stay strict, so the assertion happens where the payload is built and LINK_TYPES lives with the schema that defines it. DocumentPage.embeddedLinks is the last postgres String[] that became Json; duplicating a document read it back out and wrote it straight into the copy. 99 errors -> 0. Verified from a clean `prisma generate`. Co-authored-by: Hanzo Dev <[email protected]>
176 lines
4.9 KiB
TypeScript
176 lines
4.9 KiB
TypeScript
import { z } from "zod";
|
|
|
|
import { WEBHOOK_TRIGGERS } from "@/lib/webhook/constants";
|
|
|
|
export const createWebhookSchema = z.object({
|
|
name: z.string().min(1).max(40),
|
|
url: z.string().url().max(190),
|
|
secret: z.string().startsWith("whsec_"),
|
|
triggers: z.array(z.enum(WEBHOOK_TRIGGERS)),
|
|
});
|
|
|
|
export const updateWebhookSchema = createWebhookSchema.partial();
|
|
|
|
// Base event schema
|
|
|
|
// The link kinds this payload can carry. sqlite has no enum, so the column
|
|
// reads back as a plain string and the value is asserted against this list
|
|
// where the payload is built.
|
|
export const LINK_TYPES = [
|
|
"DOCUMENT_LINK",
|
|
"DATAROOM_LINK",
|
|
"WORKFLOW_LINK",
|
|
] as const;
|
|
|
|
const baseEventSchema = z.object({
|
|
id: z.string().startsWith("evt_"),
|
|
event: z.enum(WEBHOOK_TRIGGERS),
|
|
createdAt: z.string().datetime(),
|
|
});
|
|
|
|
// View Event schema
|
|
const viewEventSchema = z.object({
|
|
viewedAt: z.string().datetime(),
|
|
viewId: z.string(),
|
|
email: z.string().email().nullable(),
|
|
emailVerified: z.boolean().default(false),
|
|
country: z.string().nullable(),
|
|
city: z.string().nullable(),
|
|
device: z.string().nullable(),
|
|
browser: z.string().nullable(),
|
|
os: z.string().nullable(),
|
|
ua: z.string().nullable(),
|
|
referer: z.string().nullable(),
|
|
});
|
|
|
|
// Link Event schema
|
|
const linkEventSchema = z.object({
|
|
id: z.string(),
|
|
url: z
|
|
.string()
|
|
.describe(
|
|
"This is the full URL of the link e.g. https://dataroom.hanzo.ai/view/1234566",
|
|
),
|
|
name: z.string().nullable(),
|
|
domain: z.string(),
|
|
key: z.string(),
|
|
expiresAt: z.string().datetime().nullable(),
|
|
hasPassword: z.boolean().default(false),
|
|
allowList: z.array(z.string()),
|
|
denyList: z.array(z.string()),
|
|
enabledEmailProtection: z.boolean().default(false),
|
|
enabledEmailVerification: z.boolean().default(false),
|
|
allowDownload: z.boolean().default(false),
|
|
isArchived: z.boolean().default(false),
|
|
enabledNotification: z.boolean().default(true),
|
|
enabledFeedback: z.boolean().default(false),
|
|
enabledQuestion: z.boolean().default(false),
|
|
enabledScreenshotProtection: z.boolean().default(false),
|
|
enabledAgreement: z.boolean().default(false),
|
|
enabledWatermark: z.boolean().default(false),
|
|
|
|
metaTitle: z.string().nullable(),
|
|
metaDescription: z.string().nullable(),
|
|
metaImage: z.string().nullable(),
|
|
metaFavicon: z.string().nullable(),
|
|
|
|
documentId: z.string().nullable(),
|
|
dataroomId: z.string().nullable(),
|
|
groupId: z.string().nullable(),
|
|
|
|
linkType: z.enum(LINK_TYPES),
|
|
teamId: z.string(),
|
|
createdAt: z.string().datetime(),
|
|
updatedAt: z.string().datetime(),
|
|
});
|
|
|
|
// Document Event schema
|
|
const documentEventSchema = z.object({
|
|
id: z.string(),
|
|
name: z.string(),
|
|
contentType: z.string().nullable(),
|
|
teamId: z.string(),
|
|
createdAt: z.string().datetime(),
|
|
});
|
|
|
|
// Dataroom Event schema
|
|
const dataroomEventSchema = z.object({
|
|
id: z.string(),
|
|
name: z.string(),
|
|
teamId: z.string(),
|
|
createdAt: z.string().datetime(),
|
|
});
|
|
|
|
// link.created
|
|
export const linkCreatedWebhookSchema = z.object({
|
|
id: z.string().startsWith("evt_"),
|
|
event: z.literal("link.created"),
|
|
createdAt: z.string().datetime(),
|
|
data: z.object({
|
|
link: linkEventSchema,
|
|
document: documentEventSchema.optional(),
|
|
dataroom: dataroomEventSchema.optional(),
|
|
}),
|
|
});
|
|
|
|
// document.created
|
|
export const documentCreatedWebhookSchema = z.object({
|
|
id: z.string().startsWith("evt_"),
|
|
event: z.literal("document.created"),
|
|
createdAt: z.string().datetime(),
|
|
data: z.object({
|
|
document: documentEventSchema,
|
|
}),
|
|
});
|
|
|
|
// dataroom.created
|
|
export const dataroomCreatedWebhookSchema = z.object({
|
|
id: z.string().startsWith("evt_"),
|
|
event: z.literal("dataroom.created"),
|
|
createdAt: z.string().datetime(),
|
|
data: z.object({
|
|
dataroom: dataroomEventSchema,
|
|
}),
|
|
});
|
|
|
|
// link.viewed
|
|
export const linkViewedWebhookSchema = z.object({
|
|
id: z.string().startsWith("evt_"),
|
|
event: z.literal("link.viewed"),
|
|
createdAt: z.string().datetime(),
|
|
data: z.object({
|
|
view: viewEventSchema,
|
|
link: linkEventSchema,
|
|
document: documentEventSchema.optional(),
|
|
dataroom: dataroomEventSchema.optional(),
|
|
}),
|
|
});
|
|
|
|
export const webhookPayloadSchema = z.discriminatedUnion("event", [
|
|
linkCreatedWebhookSchema,
|
|
documentCreatedWebhookSchema,
|
|
dataroomCreatedWebhookSchema,
|
|
linkViewedWebhookSchema,
|
|
]);
|
|
|
|
export type WebhookPayload = z.infer<typeof webhookPayloadSchema>;
|
|
export type LinkCreatedWebhookPayload = z.infer<
|
|
typeof linkCreatedWebhookSchema
|
|
>;
|
|
export type DocumentCreatedWebhookPayload = z.infer<
|
|
typeof documentCreatedWebhookSchema
|
|
>;
|
|
export type DataroomCreatedWebhookPayload = z.infer<
|
|
typeof dataroomCreatedWebhookSchema
|
|
>;
|
|
|
|
// Schema of the response posted to the webhook callback URL
|
|
export const webhookCallbackSchema = z.object({
|
|
status: z.number(),
|
|
url: z.string(),
|
|
createdAt: z.number(),
|
|
sourceMessageId: z.string(),
|
|
body: z.string().optional().default(""), // Response from the original webhook URL
|
|
sourceBody: z.string(), // Original request payload from Hanzo Dataroom
|
|
});
|