Files
cal.diy/packages/prisma/index.ts
T
c2472cc05a feat: add createdAt and updatedAt fields to EventType model (#23949)
* feat: add createdAt and updatedAt fields to EventType model

- Add timestamp fields to EventType schema with backward compatibility
- Update all EventType select statements across API v1, v2, and tRPC
- Update platform API output types to include timestamp fields
- Generate migration for existing database records
- Fix test files to handle new timestamp fields properly

The timestamp fields are added as optional (DateTime?) to ensure backward
compatibility - existing EventType records will have null values for these
fields, while new records will automatically get timestamps.

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* fix: remove @default(now()) from EventType createdAt to prevent existing records from getting current timestamp

- Remove @default(now()) from createdAt field in schema to ensure backward compatibility
- Create migration that only drops DEFAULT constraint without updating existing records
- Existing EventType records will keep null timestamps
- New records will get timestamps via application logic

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* feat: add createdAt and updatedAt timestamps to all EventType creation locations

- Update all seed scripts to set timestamps for new EventType records
- Ensure consistency across all EventType creation patterns
- Maintain backward compatibility with nullable timestamp fields

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* feat: add timestamps to remaining EventType creation locations in test files

- Update integration test files to include createdAt and updatedAt
- Ensure consistency across all EventType creation patterns
- Complete comprehensive update of all EventType creation locations

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* add migration

* few left

* feat: implement Prisma extension for automatic EventType timestamps

- Create eventTypeTimestampsExtension to automatically set createdAt and updatedAt
- Handle both eventType.create and eventType.createMany operations
- Revert all manual timestamp setting from application code
- Extension only sets timestamps if not already provided
- Maintains backward compatibility - existing records keep null timestamps
- New records get automatic timestamps via Prisma extension
- Follows existing Cal.com extension patterns and architecture

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* feat: remove hardcoded timestamp settings from test files

- Remove manual createdAt/updatedAt settings from routing forms controller test
- Remove manual timestamp settings from event types repository fixture
- Prisma extension now handles timestamps automatically for all EventType operations

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* update

* Update event-type.output.ts

* fix test

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2025-09-24 06:59:46 +01:00

95 lines
3.8 KiB
TypeScript

import { PrismaClient, type Prisma } from "@calcom/prisma/client";
import { bookingIdempotencyKeyExtension } from "./extensions/booking-idempotency-key";
import { disallowUndefinedDeleteUpdateManyExtension } from "./extensions/disallow-undefined-delete-update-many";
import { eventTypeTimestampsExtension } from "./extensions/event-type-timestamps";
import { excludeLockedUsersExtension } from "./extensions/exclude-locked-users";
import { excludePendingPaymentsExtension } from "./extensions/exclude-pending-payment-teams";
import { usageTrackingExtention } from "./extensions/usage-tracking";
import { bookingReferenceMiddleware } from "./middleware";
const prismaOptions: Prisma.PrismaClientOptions = {};
const globalForPrisma = global as unknown as {
baseClient: PrismaClient;
};
const loggerLevel = parseInt(process.env.NEXT_PUBLIC_LOGGER_LEVEL ?? "", 10);
if (!isNaN(loggerLevel)) {
switch (loggerLevel) {
case 5:
case 6:
prismaOptions.log = ["error"];
break;
case 4:
prismaOptions.log = ["warn", "error"];
break;
case 3:
prismaOptions.log = ["info", "error", "warn"];
break;
default:
// For values 0, 1, 2 (or anything else below 3)
prismaOptions.log = ["query", "info", "error", "warn"];
break;
}
}
const baseClient = globalForPrisma.baseClient || new PrismaClient(prismaOptions);
export const customPrisma = (options?: Prisma.PrismaClientOptions) =>
new PrismaClient({ ...prismaOptions, ...options })
.$extends(usageTrackingExtention(baseClient))
.$extends(excludeLockedUsersExtension())
.$extends(excludePendingPaymentsExtension())
.$extends(bookingIdempotencyKeyExtension())
.$extends(eventTypeTimestampsExtension())
.$extends(disallowUndefinedDeleteUpdateManyExtension()) as unknown as PrismaClient;
// If any changed on middleware server restart is required
// TODO: Migrate it to $extends
bookingReferenceMiddleware(baseClient);
// FIXME: Due to some reason, there are types failing in certain places due to the $extends. Fix it and then enable it
// Specifically we get errors like `Type 'string | Date | null | undefined' is not assignable to type 'Exact<string | Date | null | undefined, string | Date | null | undefined>'`
// Explanation why we cast as PrismaClient. When we leave Prisma to its devices it tries to infer logic based on the extensions, but this is not a simple extends.
// this makes the PrismaClient export type-hint impossible and it also is a massive hit on Prisma type hinting performance.
export const prisma: PrismaClient = baseClient
.$extends(usageTrackingExtention(baseClient))
.$extends(excludeLockedUsersExtension())
.$extends(excludePendingPaymentsExtension())
.$extends(bookingIdempotencyKeyExtension())
.$extends(eventTypeTimestampsExtension())
.$extends(disallowUndefinedDeleteUpdateManyExtension()) as unknown as PrismaClient;
// This prisma instance is meant to be used only for READ operations.
// If self hosting, feel free to leave INSIGHTS_DATABASE_URL as empty and `readonlyPrisma` will default to `prisma`.
export const readonlyPrisma = process.env.INSIGHTS_DATABASE_URL
? customPrisma({
datasources: { db: { url: process.env.INSIGHTS_DATABASE_URL } },
})
: prisma;
if (process.env.NODE_ENV !== "production") {
globalForPrisma.baseClient = baseClient;
}
type OmitPrismaClient = Omit<
PrismaClient,
"$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends"
>;
// we cant pass tx to functions as types miss match since we have a custom prisma client https://github.com/prisma/prisma/discussions/20924#discussioncomment-10077649
export type {
OmitPrismaClient as PrismaTransaction,
// we re-export the native PrismaClient type for backwards-compatibility.
PrismaClient,
};
/**
* @deprecated Use named export `prisma` instead
*/
export default prisma;
export * from "./selects";