Files
calendar/packages/features/webhooks/lib/infrastructure/mappers/WebhookOutputMapper.ts
T
Syed Ali ShahbazandGitHub 056922b6ee feat: add webhook versioning (#23861)
* add webhook version schema

* version the code

* update version from numeric to date val

* migration

* update schema and build factory

* update string

* move version picker

* tooltip instead of infobadge

* --

* fix type

* --

* fix type

* fix type

* --

* fix messed up merge

* improvements to payloadfactory

* extract version off of DB and instead keep it in IWebhookRepository

* fix webhookform

* fix type safety and routing ambiguity

* scalable with easier factory extensions and base definition

* fix types

* --

* --

* clean up prisma/client type imports

* fix

* type fix

* type fix

* cleanup

* add tests and registry changes

* unintended file inclusion

* type-fix

* select in repo

* --

* explicit return type

* --

* fix type

* fixes

* feedback 1

* feedback 2

* use enum instead of string

* fixes
2025-12-18 09:36:22 +02:00

135 lines
4.2 KiB
TypeScript

import type { TimeUnit, WebhookTriggerEvents } from "@calcom/prisma/enums";
import type { Webhook, WebhookSubscriber } from "../../dto/types";
import { parseWebhookVersion } from "../../interface/IWebhookRepository";
/**
* Full webhook from Prisma (for CRUD operations)
*/
type PrismaWebhookFull = {
id: string;
subscriberUrl: string;
payloadTemplate: string | null;
appId: string | null;
secret: string | null;
active: boolean;
eventTriggers: WebhookTriggerEvents[];
eventTypeId: number | null;
teamId: number | null;
userId: number | null;
time: number | null;
timeUnit: TimeUnit | null;
version: string;
createdAt: Date;
platform: boolean;
platformOAuthClientId: string | null;
};
/**
* Minimal webhook from Prisma (for delivery/subscribers)
*/
type PrismaWebhookMinimal = {
id: string;
subscriberUrl: string;
payloadTemplate: string | null;
appId: string | null;
secret: string | null;
eventTriggers: WebhookTriggerEvents[];
time: number | null;
timeUnit: TimeUnit | null;
version: string;
};
export class WebhookOutputMapper {
/**
* Map full Prisma webhook to domain Webhook (for UI/CRUD)
*/
static toWebhook(prismaWebhook: PrismaWebhookFull): Webhook {
return {
id: prismaWebhook.id,
subscriberUrl: prismaWebhook.subscriberUrl,
payloadTemplate: prismaWebhook.payloadTemplate,
appId: prismaWebhook.appId,
secret: prismaWebhook.secret,
active: prismaWebhook.active,
eventTriggers: prismaWebhook.eventTriggers,
eventTypeId: prismaWebhook.eventTypeId,
teamId: prismaWebhook.teamId,
userId: prismaWebhook.userId,
time: prismaWebhook.time,
timeUnit: prismaWebhook.timeUnit,
version: parseWebhookVersion(prismaWebhook.version),
createdAt: prismaWebhook.createdAt,
platform: prismaWebhook.platform,
platformOAuthClientId: prismaWebhook.platformOAuthClientId,
};
}
static toWebhookList(prismaWebhooks: PrismaWebhookFull[]): Webhook[] {
return prismaWebhooks.map(WebhookOutputMapper.toWebhook);
}
/**
* Map minimal Prisma webhook to WebhookSubscriber (for delivery)
*/
static toSubscriber(prismaWebhook: PrismaWebhookMinimal): WebhookSubscriber {
return {
id: prismaWebhook.id,
subscriberUrl: prismaWebhook.subscriberUrl,
payloadTemplate: prismaWebhook.payloadTemplate,
appId: prismaWebhook.appId,
secret: prismaWebhook.secret,
eventTriggers: prismaWebhook.eventTriggers,
time: prismaWebhook.time ?? undefined,
timeUnit: prismaWebhook.timeUnit ?? undefined,
version: parseWebhookVersion(prismaWebhook.version),
};
}
static toSubscriberList(prismaWebhooks: PrismaWebhookMinimal[]): WebhookSubscriber[] {
return prismaWebhooks.map(WebhookOutputMapper.toSubscriber);
}
/**
* Legacy method - kept for backward compatibility
* @deprecated Use toWebhook() or toSubscriber() based on context
*/
static toDomain(prismaWebhook: PrismaWebhookMinimal): WebhookSubscriber {
return WebhookOutputMapper.toSubscriber(prismaWebhook);
}
/**
* Legacy method - kept for backward compatibility
* @deprecated Use toWebhookList() or toSubscriberList() based on context
*/
static toDomainList(prismaWebhooks: PrismaWebhookMinimal[]): WebhookSubscriber[] {
return WebhookOutputMapper.toSubscriberList(prismaWebhooks);
}
static toSubscriberPartial(prismaWebhook: {
id: string;
subscriberUrl: string;
eventTriggers: string[];
version: string;
payloadTemplate?: string | null;
appId?: string | null;
secret?: string | null;
time?: number | null;
timeUnit?: string | null;
}): WebhookSubscriber {
return {
id: prismaWebhook.id,
subscriberUrl: prismaWebhook.subscriberUrl,
payloadTemplate: prismaWebhook.payloadTemplate ?? null,
appId: prismaWebhook.appId ?? null,
secret: prismaWebhook.secret ?? null,
// Enums are just strings at runtime - Prisma validates them
eventTriggers: prismaWebhook.eventTriggers as unknown as WebhookSubscriber["eventTriggers"],
time: prismaWebhook.time ?? undefined,
timeUnit: prismaWebhook.timeUnit as unknown as WebhookSubscriber["timeUnit"],
version: parseWebhookVersion(prismaWebhook.version),
};
}
}