refactor: remove @calcom/features dependency from @calcom/prisma (#23820)

This commit is contained in:
Benny Joo
2025-09-18 12:40:39 -04:00
committed by GitHub
parent f41aa234d7
commit 4011733271
30 changed files with 239 additions and 241 deletions
@@ -4,8 +4,8 @@ import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { z } from "zod";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { validPassword } from "@calcom/features/auth/lib/validPassword";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import prisma from "@calcom/prisma";
import { IdentityProvider } from "@calcom/prisma/enums";
+2 -2
View File
@@ -4,8 +4,8 @@ import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import z from "zod";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { isPasswordValid } from "@calcom/features/auth/lib/isPasswordValid";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { isPasswordValid } from "@calcom/lib/auth/isPasswordValid";
import { emailRegex } from "@calcom/lib/emailSchema";
import { HttpError } from "@calcom/lib/http-error";
import slugify from "@calcom/lib/slugify";
+1 -1
View File
@@ -5,7 +5,7 @@ import React from "react";
import { Controller, FormProvider, useForm } from "react-hook-form";
import { z } from "zod";
import { isPasswordValid } from "@calcom/features/auth/lib/isPasswordValid";
import { isPasswordValid } from "@calcom/lib/auth/isPasswordValid";
import { WEBSITE_URL } from "@calcom/lib/constants";
import { emailRegex } from "@calcom/lib/emailSchema";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -2,13 +2,13 @@ import type { GetServerSidePropsContext } from "next";
import { z } from "zod";
import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData";
import type { LocationObject } from "@calcom/app-store/locations";
import { isConferencing as isConferencingApp } from "@calcom/app-store/utils";
import { getLocale } from "@calcom/features/auth/lib/getLocale";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { AppOnboardingSteps } from "@calcom/lib/apps/appOnboardingSteps";
import { CAL_URL } from "@calcom/lib/constants";
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
import type { LocationObject } from "@calcom/app-store/locations";
import { UserRepository } from "@calcom/lib/server/repository/user";
import prisma from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client";
+1
View File
@@ -86,6 +86,7 @@
"devDependencies": {
"@changesets/changelog-github": "^0.5.1",
"@changesets/cli": "2.29.4",
"@faker-js/faker": "9.2.0",
"@jetstreamapp/soql-parser-js": "^6.1.0",
"@playwright/test": "^1.45.3",
"@snaplet/copycat": "^4.1.0",
@@ -16,6 +16,7 @@ import createUsersAndConnectToOrg from "@calcom/features/ee/dsync/lib/users/crea
import ImpersonationProvider from "@calcom/features/ee/impersonation/lib/ImpersonationProvider";
import { getOrgFullOrigin, subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
import { clientSecretVerifier, hostedCal, isSAMLLoginEnabled } from "@calcom/features/ee/sso/lib/saml";
import { isPasswordValid } from "@calcom/lib/auth/isPasswordValid";
import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError";
import {
GOOGLE_CALENDAR_SCOPES,
@@ -46,7 +47,6 @@ import { teamMetadataSchema, userMetadata } from "@calcom/prisma/zod-utils";
import { getOrgUsernameFromEmail } from "../signup/utils/getOrgUsernameFromEmail";
import { ErrorCode } from "./ErrorCode";
import { dub } from "./dub";
import { isPasswordValid } from "./isPasswordValid";
import CalComAdapter from "./next-auth-custom-adapter";
import { verifyPassword } from "./verifyPassword";
@@ -2,12 +2,12 @@ import { cookies, headers } from "next/headers";
import { NextResponse } from "next/server";
import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { sendEmailVerification } from "@calcom/features/auth/lib/verifyEmail";
import { createOrUpdateMemberships } from "@calcom/features/auth/signup/utils/createOrUpdateMemberships";
import { prefillAvatar } from "@calcom/features/auth/signup/utils/prefillAvatar";
import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billling-service";
import { checkIfEmailIsBlockedInWatchlistController } from "@calcom/features/watchlist/operations/check-if-email-in-watchlist.controller";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { getLocaleFromRequest } from "@calcom/lib/getLocaleFromRequest";
import { HttpError } from "@calcom/lib/http-error";
@@ -1,9 +1,9 @@
import { NextResponse } from "next/server";
import { checkPremiumUsername } from "@calcom/ee/common/lib/checkPremiumUsername";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { sendEmailVerification } from "@calcom/features/auth/lib/verifyEmail";
import { createOrUpdateMemberships } from "@calcom/features/auth/signup/utils/createOrUpdateMemberships";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants";
import logger from "@calcom/lib/logger";
import { isUsernameReservedDueToMigration } from "@calcom/lib/server/username";
@@ -3,6 +3,7 @@ import type { Dispatch, SetStateAction } from "react";
import { Controller, useFormContext } from "react-hook-form";
import type { z } from "zod";
import { getPaymentAppData } from "@calcom/app-store/_utils/payments/getPaymentAppData";
import { useAtomsContext } from "@calcom/atoms/hooks/useAtomsContext";
import { useIsPlatform } from "@calcom/atoms/hooks/useIsPlatform";
import {
@@ -31,8 +32,6 @@ import type {
SettingsToggleClassNames,
} from "@calcom/features/eventtypes/lib/types";
import { FormBuilder } from "@calcom/features/form-builder/FormBuilder";
import type { fieldSchema } from "@calcom/features/form-builder/schema";
import type { EditableSchema } from "@calcom/features/form-builder/schema";
import { BookerLayoutSelector } from "@calcom/features/settings/BookerLayoutSelector";
import {
DEFAULT_LIGHT_BRAND_COLOR,
@@ -42,11 +41,12 @@ import {
} from "@calcom/lib/constants";
import { generateHashedLink } from "@calcom/lib/generateHashedLink";
import { checkWCAGContrastColor } from "@calcom/lib/getBrandColours";
import { getPaymentAppData } from "@calcom/app-store/_utils/payments/getPaymentAppData";
import { extractHostTimezone } from "@calcom/lib/hashedLinksUtils";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { Prisma } from "@calcom/prisma/client";
import { SchedulingType } from "@calcom/prisma/enums";
import type { EditableSchema } from "@calcom/prisma/zod-utils";
import type { fieldSchema } from "@calcom/prisma/zod-utils";
import type { RouterOutputs } from "@calcom/trpc/react";
import classNames from "@calcom/ui/classNames";
import { Alert } from "@calcom/ui/components/alert";
@@ -8,6 +8,7 @@ import type {
import Widgets from "@calcom/app-store/routing-forms/components/react-awesome-query-builder/widgets";
import PhoneInput from "@calcom/features/components/phone-input";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { fieldSchema, variantsConfigSchema, FieldType } from "@calcom/prisma/zod-utils";
import { AddressInput } from "@calcom/ui/components/address";
import { InfoBadge } from "@calcom/ui/components/badge";
import { Button } from "@calcom/ui/components/button";
@@ -18,7 +19,6 @@ import { Tooltip } from "@calcom/ui/components/tooltip";
import { ComponentForField } from "./FormBuilderField";
import { propsTypes } from "./propsTypes";
import type { fieldSchema, FieldType, variantsConfigSchema } from "./schema";
import { preprocessNameFieldDataWithVariant } from "./utils";
export const isValidValueProp: Record<Component["propsType"], (val: unknown) => boolean> = {
@@ -11,6 +11,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { md } from "@calcom/lib/markdownIt";
import { markdownToSafeHTMLClient } from "@calcom/lib/markdownToSafeHTMLClient";
import turndown from "@calcom/lib/turndownService";
import { excludeOrRequireEmailSchema } from "@calcom/prisma/zod-utils";
import classNames from "@calcom/ui/classNames";
import { Badge } from "@calcom/ui/components/badge";
import { Button } from "@calcom/ui/components/button";
@@ -31,7 +32,7 @@ import { showToast } from "@calcom/ui/components/toast";
import { fieldTypesConfigMap } from "./fieldTypes";
import { fieldsThatSupportLabelAsSafeHtml } from "./fieldsThatSupportLabelAsSafeHtml";
import { type fieldsSchema, excludeOrRequireEmailSchema } from "./schema";
import type { fieldsSchema } from "./schema";
import { getFieldIdentifier } from "./utils/getFieldIdentifier";
import { getConfig as getVariantsConfig } from "./utils/variantsConfig";
+3 -1
View File
@@ -1,7 +1,9 @@
import type z from "zod";
import type { FieldType } from "@calcom/prisma/zod-utils";
import { propsTypes } from "./propsTypes";
import type { FieldType, fieldTypeConfigSchema } from "./schema";
import type { fieldTypeConfigSchema } from "./schema";
const configMap: Record<FieldType, Omit<z.infer<typeof fieldTypeConfigSchema>, "propsType">> = {
// This won't be stored in DB. It allows UI to be configured from the codebase for all existing booking fields stored in DB as well
@@ -1,4 +1,4 @@
import type { FieldType } from "./schema";
import type { FieldType } from "@calcom/prisma/zod-utils";
/**
* Once a component supports `labelAsSafeHtml`, add it's field's type here
+1 -190
View File
@@ -1,6 +1,6 @@
import { z } from "zod";
import { getValidRhfFieldName } from "@calcom/lib/getValidRhfFieldName";
import { fieldSchema, fieldTypeEnum, variantsConfigSchema, type FieldType } from "@calcom/prisma/zod-utils";
import { fieldTypesConfigMap } from "./fieldTypes";
import { preprocessNameFieldDataWithVariant } from "./utils";
@@ -8,154 +8,6 @@ import { getConfig as getVariantsConfig } from "./utils/variantsConfig";
const nonEmptyString = () => z.string().refine((value: string) => value.trim().length > 0);
const fieldTypeEnum = z.enum([
"name",
"text",
"textarea",
"number",
"email",
"phone",
"address",
"multiemail",
"select",
"multiselect",
"checkbox",
"radio",
"radioInput",
"boolean",
"url",
]);
export type FieldType = z.infer<typeof fieldTypeEnum>;
export const EditableSchema = z.enum([
"system", // Can't be deleted, can't be hidden, name can't be edited, can't be marked optional
"system-but-optional", // Can't be deleted. Name can't be edited. But can be hidden or be marked optional
"system-but-hidden", // Can't be deleted, name can't be edited, will be shown
"user", // Fully editable
"user-readonly", // All fields are readOnly.
]);
export const excludeOrRequireEmailSchema = z.string().superRefine((val, ctx) => {
const allDomains = val.split(",").map((dom) => dom.trim());
const regex = /^(?:@?[a-z0-9-]+(?:\.[a-z]{2,})?)?(?:@[a-z0-9-]+\.[a-z]{2,})?$/;
/*
Valid patterns - [ example, example.anything, anyone@example.anything ]
Invalid patterns - Patterns involving capital letter [ Example, Example.anything, Anyone@example.anything ]
*/
const isValid = !allDomains.some((domain) => !regex.test(domain));
if (!isValid) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Enter valid domain or email",
});
}
});
const baseFieldSchema = z.object({
name: z.string().transform(getValidRhfFieldName),
type: fieldTypeEnum,
// TODO: We should make at least one of `defaultPlaceholder` and `placeholder` required. Do the same for label.
label: z.string().optional(),
labelAsSafeHtml: z.string().optional(),
/**
* It is the default label that will be used when a new field is created.
* Note: It belongs in FieldsTypeConfig, so that changing defaultLabel in code can work for existing fields as well(for fields that are using the default label).
* Supports translation
*/
defaultLabel: z.string().optional(),
placeholder: z.string().optional(),
/**
* It is the default placeholder that will be used when a new field is created.
* Note: Same as defaultLabel, it belongs in FieldsTypeConfig
* Supports translation
*/
defaultPlaceholder: z.string().optional(),
required: z.boolean().default(false).optional(),
/**
* It is the list of options that is valid for a certain type of fields.
*
*/
options: z
.array(
z.object({
label: z.string(),
value: z.string(),
price: z.coerce.number().min(0).optional(),
})
)
.optional(),
/**
* This is an alternate way to specify options when the options are stored elsewhere. Form Builder expects options to be present at `dataStore[getOptionsAt]`
* This allows keeping a single source of truth in DB.
*/
getOptionsAt: z.string().optional(),
/**
* For `radioInput` type of questions, it stores the input that is shown based on the user option selected.
* e.g. If user is given a list of locations and he selects "Phone", then he will be shown a phone input
*/
optionsInputs: z
.record(
z.object({
// Support all types as needed
// Must be a subset of `fieldTypeEnum`.TODO: Enforce it in TypeScript
type: z.enum(["address", "phone", "text"]),
required: z.boolean().optional(),
placeholder: z.string().optional(),
})
)
.optional(),
/**
* It is the minimum number of characters that can be entered in the field.
* It is used for types with `supportsLengthCheck= true`.
* @default 0
* @requires supportsLengthCheck = true
*/
minLength: z.number().optional(),
/**
* It is the maximum number of characters that can be entered in the field.
* It is used for types with `supportsLengthCheck= true`.
* @requires supportsLengthCheck = true
*/
maxLength: z.number().optional(),
// Emails that needs to be excluded
excludeEmails: excludeOrRequireEmailSchema.optional(),
// Emails that need to be required
requireEmails: excludeOrRequireEmailSchema.optional(),
// Price associated with the field which works like addons which users can add to the booking
price: z.coerce.number().min(0).optional(),
});
export const variantsConfigSchema = z.object({
variants: z.record(
z.object({
/**
* Variant Fields schema for a variant of the main field.
* It doesn't support non text fields as of now
**/
fields: baseFieldSchema
.omit({
defaultLabel: true,
defaultPlaceholder: true,
options: true,
getOptionsAt: true,
optionsInputs: true,
})
.array(),
})
),
});
export type ALL_VIEWS = "ALL_VIEWS";
// It is the config that is specific to a type and doesn't make sense in all fields individually. Any field with the type will automatically inherit this config.
@@ -238,47 +90,6 @@ export const fieldTypeConfigSchema = z
return true;
});
/**
* Main field Schema
*/
export const fieldSchema = baseFieldSchema.merge(
z.object({
variant: z.string().optional(),
variantsConfig: variantsConfigSchema.optional(),
views: z
.object({
label: z.string(),
id: z.string(),
description: z.string().optional(),
})
.array()
.optional(),
/**
* It is used to hide fields such as location when there are less than two options
*/
hideWhenJustOneOption: z.boolean().default(false).optional(),
hidden: z.boolean().optional(),
editable: EditableSchema.default("user").optional(),
sources: z
.array(
z.object({
// Unique ID for the `type`. If type is workflow, it's the workflow ID
id: z.string(),
type: z.union([z.literal("user"), z.literal("system"), z.string()]),
label: z.string(),
editUrl: z.string().optional(),
// Mark if a field is required by this source or not. This allows us to set `field.required` based on all the sources' fieldRequired value
fieldRequired: z.boolean().optional(),
})
)
.optional(),
disableOnPrefill: z.boolean().default(false).optional(),
})
);
export const fieldsSchema = z.array(fieldSchema);
export const fieldTypesSchemaMap: Partial<
@@ -1,9 +1,9 @@
import type z from "zod";
import type { useLocale } from "@calcom/lib/hooks/useLocale";
import type { fieldSchema } from "@calcom/prisma/zod-utils";
import { fieldTypesConfigMap } from "../fieldTypes";
import type { fieldSchema } from "../schema";
type ConfigVariants = NonNullable<ReturnType<typeof getConfig>>["variants"];
type Field = z.infer<typeof fieldSchema>;
@@ -2,8 +2,8 @@ import prismock from "../../../../tests/libs/__mocks__/prisma";
import { describe, test, expect, vi, beforeEach } from "vitest";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { checkIfEmailIsBlockedInWatchlistController } from "@calcom/features/watchlist/operations/check-if-email-in-watchlist.controller";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { CreationSource } from "@calcom/prisma/enums";
import { UserRepository } from "../repository/user";
@@ -20,7 +20,7 @@ vi.mock("@calcom/lib/server/i18n", () => {
};
});
vi.mock("@calcom/features/auth/lib/hashPassword", () => ({
vi.mock("@calcom/lib/auth/hashPassword", () => ({
hashPassword: vi.fn().mockResolvedValue("hashed-password"),
}));
@@ -1,5 +1,5 @@
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { checkIfEmailIsBlockedInWatchlistController } from "@calcom/features/watchlist/operations/check-if-email-in-watchlist.controller";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import logger from "@calcom/lib/logger";
import prisma from "@calcom/prisma";
import type { CreationSource, UserPermissionRole, IdentityProvider } from "@calcom/prisma/enums";
+3 -4
View File
@@ -18,11 +18,10 @@
"post-install": "yarn generate-schemas",
"seed-app-store": "ts-node --transpile-only ../../scripts/seed-app-store.ts",
"delete-app": "ts-node --transpile-only ./delete-app.ts",
"seed-insights": "ts-node --transpile-only ./seed-insights.ts",
"seed-pbac": "ts-node --transpile-only ./seed-pbac-organization.ts"
"seed-insights": "ts-node --transpile-only ../../scripts/seed-insights.ts",
"seed-pbac": "ts-node --transpile-only ../../scripts/seed-pbac-organization.ts"
},
"devDependencies": {
"@faker-js/faker": "9.2.0",
"npm-run-all": "^4.1.5"
},
"dependencies": {
@@ -46,4 +45,4 @@
"prisma": {
"seed": "ts-node --transpile-only ../../scripts/seed.ts"
}
}
}
+192 -7
View File
@@ -11,10 +11,9 @@ import type {
ZodTypeAny,
} from "zod";
import { isPasswordValid } from "@calcom/features/auth/lib/isPasswordValid";
import type { FieldType as FormBuilderFieldType } from "@calcom/features/form-builder/schema";
import { fieldsSchema as formBuilderFieldsSchema } from "@calcom/features/form-builder/schema";
import { isPasswordValid } from "@calcom/lib/auth/isPasswordValid";
import { emailSchema as emailRegexSchema, emailRegex } from "@calcom/lib/emailSchema";
import { getValidRhfFieldName } from "@calcom/lib/getValidRhfFieldName";
import type { IntervalLimit } from "@calcom/lib/intervalLimits/intervalLimitSchema";
import { zodAttributesQueryValue } from "@calcom/lib/raqb/zod";
import { slugify } from "@calcom/lib/slugify";
@@ -135,10 +134,6 @@ export const eventTypeMetaDataSchemaWithoutApps = _eventTypeMetaDataSchemaWithou
export type EventTypeMetadata = z.infer<typeof EventTypeMetaDataSchema>;
export const eventTypeBookingFields = formBuilderFieldsSchema;
export const BookingFieldTypeEnum = eventTypeBookingFields.element.shape.type.Enum;
export type BookingFieldType = FormBuilderFieldType;
// Validation of user added bookingFields' responses happen using `getBookingResponsesSchema` which requires `eventType`.
// So it is a dynamic validation and thus entire validation can't exist here
// Note that this validation runs to validate prefill params as well, so it should consider that partial values can be there. e.g. `name` might be empty string
@@ -768,3 +763,193 @@ export const serviceAccountKeySchema = z
export type TServiceAccountKeySchema = z.infer<typeof serviceAccountKeySchema>;
export const rrSegmentQueryValueSchema = zodAttributesQueryValue.nullish();
// Routing Form Fields
export const fieldTypeEnum = z.enum([
"name",
"text",
"textarea",
"number",
"email",
"phone",
"address",
"multiemail",
"select",
"multiselect",
"checkbox",
"radio",
"radioInput",
"boolean",
"url",
]);
export type FieldType = z.infer<typeof fieldTypeEnum>;
export const excludeOrRequireEmailSchema = z.string().superRefine((val, ctx) => {
const allDomains = val.split(",").map((dom) => dom.trim());
const regex = /^(?:@?[a-z0-9-]+(?:\.[a-z]{2,})?)?(?:@[a-z0-9-]+\.[a-z]{2,})?$/;
/*
Valid patterns - [ example, example.anything, anyone@example.anything ]
Invalid patterns - Patterns involving capital letter [ Example, Example.anything, Anyone@example.anything ]
*/
const isValid = !allDomains.some((domain) => !regex.test(domain));
if (!isValid) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Enter valid domain or email",
});
}
});
export const EditableSchema = z.enum([
"system", // Can't be deleted, can't be hidden, name can't be edited, can't be marked optional
"system-but-optional", // Can't be deleted. Name can't be edited. But can be hidden or be marked optional
"system-but-hidden", // Can't be deleted, name can't be edited, will be shown
"user", // Fully editable
"user-readonly", // All fields are readOnly.
]);
export const baseFieldSchema = z.object({
name: z.string().transform(getValidRhfFieldName),
type: fieldTypeEnum,
// TODO: We should make at least one of `defaultPlaceholder` and `placeholder` required. Do the same for label.
label: z.string().optional(),
labelAsSafeHtml: z.string().optional(),
/**
* It is the default label that will be used when a new field is created.
* Note: It belongs in FieldsTypeConfig, so that changing defaultLabel in code can work for existing fields as well(for fields that are using the default label).
* Supports translation
*/
defaultLabel: z.string().optional(),
placeholder: z.string().optional(),
/**
* It is the default placeholder that will be used when a new field is created.
* Note: Same as defaultLabel, it belongs in FieldsTypeConfig
* Supports translation
*/
defaultPlaceholder: z.string().optional(),
required: z.boolean().default(false).optional(),
/**
* It is the list of options that is valid for a certain type of fields.
*
*/
options: z
.array(
z.object({
label: z.string(),
value: z.string(),
price: z.coerce.number().min(0).optional(),
})
)
.optional(),
/**
* This is an alternate way to specify options when the options are stored elsewhere. Form Builder expects options to be present at `dataStore[getOptionsAt]`
* This allows keeping a single source of truth in DB.
*/
getOptionsAt: z.string().optional(),
/**
* For `radioInput` type of questions, it stores the input that is shown based on the user option selected.
* e.g. If user is given a list of locations and he selects "Phone", then he will be shown a phone input
*/
optionsInputs: z
.record(
z.object({
// Support all types as needed
// Must be a subset of `fieldTypeEnum`.TODO: Enforce it in TypeScript
type: z.enum(["address", "phone", "text"]),
required: z.boolean().optional(),
placeholder: z.string().optional(),
})
)
.optional(),
/**
* It is the minimum number of characters that can be entered in the field.
* It is used for types with `supportsLengthCheck= true`.
* @default 0
* @requires supportsLengthCheck = true
*/
minLength: z.number().optional(),
/**
* It is the maximum number of characters that can be entered in the field.
* It is used for types with `supportsLengthCheck= true`.
* @requires supportsLengthCheck = true
*/
maxLength: z.number().optional(),
// Emails that needs to be excluded
excludeEmails: excludeOrRequireEmailSchema.optional(),
// Emails that need to be required
requireEmails: excludeOrRequireEmailSchema.optional(),
// Price associated with the field which works like addons which users can add to the booking
price: z.coerce.number().min(0).optional(),
});
export const variantsConfigSchema = z.object({
variants: z.record(
z.object({
/**
* Variant Fields schema for a variant of the main field.
* It doesn't support non text fields as of now
**/
fields: baseFieldSchema
.omit({
defaultLabel: true,
defaultPlaceholder: true,
options: true,
getOptionsAt: true,
optionsInputs: true,
})
.array(),
})
),
});
export const fieldSchema = baseFieldSchema.merge(
z.object({
variant: z.string().optional(),
variantsConfig: variantsConfigSchema.optional(),
views: z
.object({
label: z.string(),
id: z.string(),
description: z.string().optional(),
})
.array()
.optional(),
/**
* It is used to hide fields such as location when there are less than two options
*/
hideWhenJustOneOption: z.boolean().default(false).optional(),
hidden: z.boolean().optional(),
editable: EditableSchema.default("user").optional(),
sources: z
.array(
z.object({
// Unique ID for the `type`. If type is workflow, it's the workflow ID
id: z.string(),
type: z.union([z.literal("user"), z.literal("system"), z.string()]),
label: z.string(),
editUrl: z.string().optional(),
// Mark if a field is required by this source or not. This allows us to set `field.required` based on all the sources' fieldRequired value
fieldRequired: z.boolean().optional(),
})
)
.optional(),
disableOnPrefill: z.boolean().default(false).optional(),
})
);
export const eventTypeBookingFields = z.array(fieldSchema);
export const BookingFieldTypeEnum = eventTypeBookingFields.element.shape.type.Enum;
@@ -1,6 +1,6 @@
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { validPassword } from "@calcom/features/auth/lib/validPassword";
import { verifyPassword } from "@calcom/features/auth/lib/verifyPassword";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { prisma } from "@calcom/prisma";
import { IdentityProvider } from "@calcom/prisma/enums";
@@ -1,7 +1,7 @@
import { createHash } from "crypto";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { verifyPassword } from "@calcom/features/auth/lib/verifyPassword";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { prisma } from "@calcom/prisma";
import { TRPCError } from "@trpc/server";
@@ -2,11 +2,11 @@ import { faker } from "@faker-js/faker";
import { v4 as uuidv4 } from "uuid";
import dayjs from "@calcom/dayjs";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import type { Prisma } from "@calcom/prisma/client";
import { PrismaClient } from "@calcom/prisma/client";
import { BookingStatus, AssignmentReasonEnum } from "@calcom/prisma/enums";
import type { Prisma } from "./client";
import { PrismaClient } from "./client";
import { seedAttributes, seedRoutingFormResponses, seedRoutingForms } from "./seed-utils";
function getRandomRatingFeedback() {
@@ -1,11 +1,10 @@
import { uuid } from "short-uuid";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
import prisma from "@calcom/prisma";
import { MembershipRole, RoleType } from "@calcom/prisma/enums";
import prisma from ".";
/**
* Creates an organization with custom roles and PBAC (Permission-Based Access Control) enabled
* This demonstrates how to set up fine-grained permissions for team members
+2 -2
View File
@@ -11,7 +11,7 @@ import zoomMeta from "@calcom/app-store/zoomvideo/_metadata";
import dayjs from "@calcom/dayjs";
import { BookingStatus } from "@calcom/prisma/enums";
import { createUserAndEventType } from "../packages/prisma/seed-utils";
import { createUserAndEventType } from "./seed-utils";
async function _createManyDifferentUsersWithDifferentEventTypesAndBookings({
tillUser,
@@ -322,4 +322,4 @@ async function createAUserWithManyBookings() {
// startFrom: 10000,
// });
createAUserWithManyBookings();
createAUserWithManyBookings();
@@ -4,13 +4,12 @@ import { uuid } from "short-uuid";
import type z from "zod";
import dayjs from "@calcom/dayjs";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
import prisma from "@calcom/prisma";
import type { Prisma, UserPermissionRole } from "@calcom/prisma/client";
import { MembershipRole } from "@calcom/prisma/enums";
import prisma from ".";
import type { Prisma, UserPermissionRole } from "./client";
import type { teamMetadataSchema } from "./zod-utils";
import type { teamMetadataSchema } from "@calcom/prisma/zod-utils";
export async function createUserAndEventType({
user,
+3 -3
View File
@@ -6,7 +6,7 @@ import googleMeetMeta from "@calcom/app-store/googlevideo/_metadata";
import zoomMeta from "@calcom/app-store/zoomvideo/_metadata";
import dayjs from "@calcom/dayjs";
import { getOrgFullOrigin } from "@calcom/ee/organizations/lib/orgDomains";
import { hashPassword } from "@calcom/features/auth/lib/hashPassword";
import { hashPassword } from "@calcom/lib/auth/hashPassword";
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
import prisma from "@calcom/prisma";
import type { Membership, Team, User, UserPermissionRole } from "@calcom/prisma/client";
@@ -14,10 +14,10 @@ import { Prisma } from "@calcom/prisma/client";
import { BookingStatus, MembershipRole, RedirectType, SchedulingType } from "@calcom/prisma/enums";
import type { Ensure } from "@calcom/types/utils";
import mainHugeEventTypesSeed from "../packages/prisma/seed-huge-event-types";
import { createUserAndEventType } from "../packages/prisma/seed-utils";
import type { teamMetadataSchema } from "../packages/prisma/zod-utils";
import mainAppStore from "./seed-app-store";
import mainHugeEventTypesSeed from "./seed-huge-event-types";
import { createUserAndEventType } from "./seed-utils";
type PlatformUser = {
email: string;
+4 -3
View File
@@ -6032,9 +6032,9 @@ __metadata:
linkType: hard
"@faker-js/faker@npm:^7.3.0":
version: 7.4.0
resolution: "@faker-js/faker@npm:7.4.0"
checksum: 1acebb84bfb142c08e6ba2942910d16bd92ea147fa585fa2fa9ce9983f7a8c7c016002beb7fc20ef6f7aef6c4ae9cb3fa680b275823402e34802b8489d2b980d
version: 7.6.0
resolution: "@faker-js/faker@npm:7.6.0"
checksum: 942af6221774e8c98a0eb6bc75265e05fb81a941170377666c3439aab9495dd321d6beedc5406f07e6ad44262b3e43c20961f666d116ad150b78e7437dd1bb2b
languageName: node
linkType: hard
@@ -21669,6 +21669,7 @@ __metadata:
"@changesets/cli": 2.29.4
"@daily-co/daily-js": ^0.83.1
"@evyweb/ioctopus": ^1.2.0
"@faker-js/faker": 9.2.0
"@jetstreamapp/soql-parser-js": ^6.1.0
"@next/third-parties": ^14.2.5
"@playwright/test": ^1.45.3