refactor: Migrate trpc routers in App store package to Trpc package (#23536)

* migrate trpc routers in app package to trpc package

* delete

* delete

* delete

* fix

* fix

* fix

* format

* format

* fix

* fix

* fix

* fix

* remove unused file

* fix

* fix

* wip
This commit is contained in:
Benny Joo
2025-09-07 22:17:33 -03:00
committed by GitHub
parent a1fca56aac
commit 92eb41c117
32 changed files with 266 additions and 279 deletions
@@ -1,4 +1,4 @@
import appBasecamp3 from "@calcom/app-store/basecamp3/trpc-router";
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
import appBasecamp3 from "@calcom/trpc/server/routers/apps/basecamp3/_router";
export default createNextApiHandler(appBasecamp3);
@@ -1,4 +1,4 @@
import appRoutingForms from "@calcom/app-store/routing-forms/trpc-router";
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
import appRoutingForms from "@calcom/trpc/server/routers/apps/routing-forms/_router";
export default createNextApiHandler(appRoutingForms);
@@ -1 +0,0 @@
export { default } from "./trpc/_router";
@@ -6,7 +6,7 @@ import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
import { sendGenericWebhookPayload } from "@calcom/features/webhooks/lib/sendPayload";
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
import { _onFormSubmission } from "./utils";
import { _onFormSubmission } from "./formSubmissionUtils";
// Mock dependencies
vi.mock("@calcom/lib/getOrgIdFromMemberOrTeamId", () => ({
@@ -1,13 +1,244 @@
import type { Prisma } from "@prisma/client";
import type { App_RoutingForms_Form, User } from "@prisma/client";
import dayjs from "@calcom/dayjs";
import type { Tasker } from "@calcom/features/tasker/tasker";
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
import { sendGenericWebhookPayload } from "@calcom/features/webhooks/lib/sendPayload";
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
import logger from "@calcom/lib/logger";
import { withReporting } from "@calcom/lib/sentryWrapper";
import { prisma } from "@calcom/prisma";
import type { App_RoutingForms_Form } from "@calcom/prisma/client";
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
import { RoutingFormSettings } from "@calcom/prisma/zod-utils";
import type { Ensure } from "@calcom/types/utils";
import { TRPCError } from "@trpc/server";
import { onFormSubmission } from "../trpc/utils";
import type { FormResponse, SerializableForm } from "../types/types";
import type { FormResponse, SerializableForm, SerializableField, OrderedResponses } from "../types/types";
const moduleLogger = logger.getSubLogger({ prefix: ["routing-forms/lib/formSubmissionUtils"] });
type SelectFieldWebhookResponse = string | number | string[] | { label: string; id: string | null };
export type FORM_SUBMITTED_WEBHOOK_RESPONSES = Record<
string,
{
/**
* Deprecates `value` prop as it now has both the id(that doesn't change) and the label(that can change but is human friendly)
*/
response: number | string | string[] | SelectFieldWebhookResponse | SelectFieldWebhookResponse[];
/**
* @deprecated Use `response` instead
*/
value: FormResponse[keyof FormResponse]["value"];
}
>;
function isOptionsField(field: Pick<SerializableField, "type" | "options">) {
return (field.type === "select" || field.type === "multiselect") && field.options;
}
export function getFieldResponse({
field,
fieldResponseValue,
}: {
fieldResponseValue: FormResponse[keyof FormResponse]["value"];
field: Pick<SerializableField, "type" | "options">;
}) {
if (!isOptionsField(field)) {
return {
value: fieldResponseValue,
response: fieldResponseValue,
};
}
if (!field.options) {
return {
value: fieldResponseValue,
response: fieldResponseValue,
};
}
const valueArray = fieldResponseValue instanceof Array ? fieldResponseValue : [fieldResponseValue];
const chosenOptions = valueArray.map((idOrLabel) => {
const foundOptionById = field.options?.find((option) => {
return option.id === idOrLabel;
});
if (foundOptionById) {
return {
label: foundOptionById.label,
id: foundOptionById.id,
};
} else {
return {
label: idOrLabel.toString(),
id: null,
};
}
});
return {
// value is a legacy prop that is just sending the labels which can change
value: chosenOptions.map((option) => option.label),
// response is new prop that is sending the label along with id(which doesn't change)
response: chosenOptions,
};
}
export const sendResponseEmail = async (
form: Pick<App_RoutingForms_Form, "id" | "name" | "fields">,
orderedResponses: OrderedResponses,
toAddresses: string[]
) => {
try {
if (typeof window === "undefined") {
const { default: ResponseEmail } = await import("../emails/templates/response-email");
const email = new ResponseEmail({ form: form, toAddresses, orderedResponses });
await email.sendEmail();
}
} catch (e) {
moduleLogger.error("Error sending response email", e);
}
};
function getWebhookTargetEntity(form: { teamId?: number | null; user: { id: number } }) {
// If it's a team form, the target must be team webhook
// If it's a user form, the target must be user webhook
const isTeamForm = form.teamId;
return { userId: isTeamForm ? null : form.user.id, teamId: isTeamForm ? form.teamId : null };
}
/**
* Not called in preview mode or dry run mode
* It takes care of sending webhooks and emails for form submissions
*/
export async function _onFormSubmission(
form: Ensure<
SerializableForm<App_RoutingForms_Form> & { user: Pick<User, "id" | "email">; userWithEmails?: string[] },
"fields"
>,
response: FormResponse,
responseId: number,
chosenAction?: {
type: "customPageMessage" | "externalRedirectUrl" | "eventTypeRedirectUrl";
value: string;
}
) {
const fieldResponsesByIdentifier: FORM_SUBMITTED_WEBHOOK_RESPONSES = {};
for (const [fieldId, fieldResponse] of Object.entries(response)) {
const field = form.fields.find((f) => f.id === fieldId);
if (!field) {
throw new Error(`Field with id ${fieldId} not found`);
}
// Use the label lowercased as the key to identify a field.
// TODO: We seem to be using label from the response, Can we not use the field.label
const key =
form.fields.find((f) => f.id === fieldId)?.identifier ||
(fieldResponse.label as keyof typeof fieldResponsesByIdentifier);
fieldResponsesByIdentifier[key] = getFieldResponse({
fieldResponseValue: fieldResponse.value,
field,
});
}
const { userId, teamId } = getWebhookTargetEntity(form);
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: userId, teamId });
const subscriberOptionsFormSubmitted = {
userId,
teamId,
orgId,
triggerEvent: WebhookTriggerEvents.FORM_SUBMITTED,
};
const subscriberOptionsFormSubmittedNoEvent = {
userId,
teamId,
orgId,
triggerEvent: WebhookTriggerEvents.FORM_SUBMITTED_NO_EVENT,
};
const webhooksFormSubmitted = await getWebhooks(subscriberOptionsFormSubmitted);
const webhooksFormSubmittedNoEvent = await getWebhooks(subscriberOptionsFormSubmittedNoEvent);
const promisesFormSubmitted = webhooksFormSubmitted.map((webhook) => {
sendGenericWebhookPayload({
secretKey: webhook.secret,
triggerEvent: "FORM_SUBMITTED",
createdAt: new Date().toISOString(),
webhook,
data: {
formId: form.id,
formName: form.name,
teamId: form.teamId,
responses: fieldResponsesByIdentifier,
},
rootData: {
// Send responses unwrapped at root level for backwards compatibility
...Object.entries(fieldResponsesByIdentifier).reduce((acc, [key, value]) => {
acc[key] = value.value;
return acc;
}, {} as Record<string, FormResponse[keyof FormResponse]["value"]>),
},
}).catch((e) => {
console.error(`Error executing routing form webhook`, webhook, e);
});
});
if (typeof window === "undefined") {
try {
const tasker: Tasker = await (await import("@calcom/features/tasker")).default;
const promisesFormSubmittedNoEvent = webhooksFormSubmittedNoEvent.map((webhook) => {
const scheduledAt = dayjs().add(15, "minute").toDate();
return tasker.create(
"triggerFormSubmittedNoEventWebhook",
{
responseId,
form: {
id: form.id,
name: form.name,
teamId: form.teamId ?? null,
},
responses: fieldResponsesByIdentifier,
redirect: chosenAction,
webhook,
},
{ scheduledAt }
);
});
const promises = [...promisesFormSubmitted, ...promisesFormSubmittedNoEvent];
await Promise.all(promises);
const orderedResponses = form.fields.reduce((acc, field) => {
acc.push(response[field.id]);
return acc;
}, [] as OrderedResponses);
if (form.teamId) {
if (form.userWithEmails?.length) {
moduleLogger.debug(
`Preparing to send Form Response email for Form:${form.id} to users: ${form.userWithEmails.join(
","
)}`
);
await sendResponseEmail(form, orderedResponses, form.userWithEmails);
}
} else if (form.settings?.emailOwnerOnSubmission) {
moduleLogger.debug(
`Preparing to send Form Response email for Form:${form.id} to form owner: ${form.user.email}`
);
await sendResponseEmail(form, orderedResponses, [form.user.email]);
}
} catch (e) {
moduleLogger.error("Error triggering routing form response side effects", e);
}
}
}
export const onFormSubmission = withReporting(_onFormSubmission, "onFormSubmission");
export type TargetRoutingFormForResponse = SerializableForm<
App_RoutingForms_Form & {
@@ -1 +0,0 @@
export { default } from "./trpc/_router";
@@ -1,237 +0,0 @@
import type { App_RoutingForms_Form, User } from "@prisma/client";
import dayjs from "@calcom/dayjs";
import type { Tasker } from "@calcom/features/tasker/tasker";
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
import { sendGenericWebhookPayload } from "@calcom/features/webhooks/lib/sendPayload";
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
import logger from "@calcom/lib/logger";
import { withReporting } from "@calcom/lib/sentryWrapper";
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
import type { Ensure } from "@calcom/types/utils";
import type { SerializableField, OrderedResponses } from "../types/types";
import type { FormResponse, SerializableForm } from "../types/types";
const moduleLogger = logger.getSubLogger({ prefix: ["routing-forms/trpc/utils"] });
type SelectFieldWebhookResponse = string | number | string[] | { label: string; id: string | null };
export type FORM_SUBMITTED_WEBHOOK_RESPONSES = Record<
string,
{
/**
* Deprecates `value` prop as it now has both the id(that doesn't change) and the label(that can change but is human friendly)
*/
response: number | string | string[] | SelectFieldWebhookResponse | SelectFieldWebhookResponse[];
/**
* @deprecated Use `response` instead
*/
value: FormResponse[keyof FormResponse]["value"];
}
>;
function isOptionsField(field: Pick<SerializableField, "type" | "options">) {
return (field.type === "select" || field.type === "multiselect") && field.options;
}
export function getFieldResponse({
field,
fieldResponseValue,
}: {
fieldResponseValue: FormResponse[keyof FormResponse]["value"];
field: Pick<SerializableField, "type" | "options">;
}) {
if (!isOptionsField(field)) {
return {
value: fieldResponseValue,
response: fieldResponseValue,
};
}
if (!field.options) {
return {
value: fieldResponseValue,
response: fieldResponseValue,
};
}
const valueArray = fieldResponseValue instanceof Array ? fieldResponseValue : [fieldResponseValue];
const chosenOptions = valueArray.map((idOrLabel) => {
const foundOptionById = field.options?.find((option) => {
return option.id === idOrLabel;
});
if (foundOptionById) {
return {
label: foundOptionById.label,
id: foundOptionById.id,
};
} else {
return {
label: idOrLabel.toString(),
id: null,
};
}
});
return {
// value is a legacy prop that is just sending the labels which can change
value: chosenOptions.map((option) => option.label),
// response is new prop that is sending the label along with id(which doesn't change)
response: chosenOptions,
};
}
/**
* Not called in preview mode or dry run mode
* It takes care of sending webhooks and emails for form submissions
*/
export async function _onFormSubmission(
form: Ensure<
SerializableForm<App_RoutingForms_Form> & { user: Pick<User, "id" | "email">; userWithEmails?: string[] },
"fields"
>,
response: FormResponse,
responseId: number,
chosenAction?: {
type: "customPageMessage" | "externalRedirectUrl" | "eventTypeRedirectUrl";
value: string;
}
) {
const fieldResponsesByIdentifier: FORM_SUBMITTED_WEBHOOK_RESPONSES = {};
for (const [fieldId, fieldResponse] of Object.entries(response)) {
const field = form.fields.find((f) => f.id === fieldId);
if (!field) {
throw new Error(`Field with id ${fieldId} not found`);
}
// Use the label lowercased as the key to identify a field.
// TODO: We seem to be using label from the response, Can we not use the field.label
const key =
form.fields.find((f) => f.id === fieldId)?.identifier ||
(fieldResponse.label as keyof typeof fieldResponsesByIdentifier);
fieldResponsesByIdentifier[key] = getFieldResponse({
fieldResponseValue: fieldResponse.value,
field,
});
}
const { userId, teamId } = getWebhookTargetEntity(form);
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: userId, teamId });
const subscriberOptionsFormSubmitted = {
userId,
teamId,
orgId,
triggerEvent: WebhookTriggerEvents.FORM_SUBMITTED,
};
const subscriberOptionsFormSubmittedNoEvent = {
userId,
teamId,
orgId,
triggerEvent: WebhookTriggerEvents.FORM_SUBMITTED_NO_EVENT,
};
const webhooksFormSubmitted = await getWebhooks(subscriberOptionsFormSubmitted);
const webhooksFormSubmittedNoEvent = await getWebhooks(subscriberOptionsFormSubmittedNoEvent);
const promisesFormSubmitted = webhooksFormSubmitted.map((webhook) => {
sendGenericWebhookPayload({
secretKey: webhook.secret,
triggerEvent: "FORM_SUBMITTED",
createdAt: new Date().toISOString(),
webhook,
data: {
formId: form.id,
formName: form.name,
teamId: form.teamId,
responses: fieldResponsesByIdentifier,
},
rootData: {
// Send responses unwrapped at root level for backwards compatibility
...Object.entries(fieldResponsesByIdentifier).reduce((acc, [key, value]) => {
acc[key] = value.value;
return acc;
}, {} as Record<string, FormResponse[keyof FormResponse]["value"]>),
},
}).catch((e) => {
console.error(`Error executing routing form webhook`, webhook, e);
});
});
if (typeof window === "undefined") {
try {
const tasker: Tasker = await (await import("@calcom/features/tasker")).default;
const promisesFormSubmittedNoEvent = webhooksFormSubmittedNoEvent.map((webhook) => {
const scheduledAt = dayjs().add(15, "minute").toDate();
return tasker.create(
"triggerFormSubmittedNoEventWebhook",
{
responseId,
form: {
id: form.id,
name: form.name,
teamId: form.teamId ?? null,
},
responses: fieldResponsesByIdentifier,
redirect: chosenAction,
webhook,
},
{ scheduledAt }
);
});
const promises = [...promisesFormSubmitted, ...promisesFormSubmittedNoEvent];
await Promise.all(promises);
const orderedResponses = form.fields.reduce((acc, field) => {
acc.push(response[field.id]);
return acc;
}, [] as OrderedResponses);
if (form.teamId) {
if (form.userWithEmails?.length) {
moduleLogger.debug(
`Preparing to send Form Response email for Form:${form.id} to users: ${form.userWithEmails.join(
","
)}`
);
await sendResponseEmail(form, orderedResponses, form.userWithEmails);
}
} else if (form.settings?.emailOwnerOnSubmission) {
moduleLogger.debug(
`Preparing to send Form Response email for Form:${form.id} to form owner: ${form.user.email}`
);
await sendResponseEmail(form, orderedResponses, [form.user.email]);
}
} catch (e) {
moduleLogger.error("Error triggering routing form response side effects", e);
}
}
}
export const onFormSubmission = withReporting(_onFormSubmission, "onFormSubmission");
export const sendResponseEmail = async (
form: Pick<App_RoutingForms_Form, "id" | "name" | "fields">,
orderedResponses: OrderedResponses,
toAddresses: string[]
) => {
try {
if (typeof window === "undefined") {
const { default: ResponseEmail } = await import("../emails/templates/response-email");
const email = new ResponseEmail({ form: form, toAddresses, orderedResponses });
await email.sendEmail();
}
} catch (e) {
moduleLogger.error("Error sending response email", e);
}
};
function getWebhookTargetEntity(form: { teamId?: number | null; user: { id: number } }) {
// If it's a team form, the target must be team webhook
// If it's a user form, the target must be user webhook
const isTeamForm = form.teamId;
return { userId: isTeamForm ? null : form.user.id, teamId: isTeamForm ? form.teamId : null };
}
@@ -1,7 +1,7 @@
import { z } from "zod";
import type { FORM_SUBMITTED_WEBHOOK_RESPONSES } from "@calcom/app-store/routing-forms/lib/formSubmissionUtils";
import incompleteBookingActionFunctions from "@calcom/app-store/routing-forms/lib/incompleteBooking/actionFunctions";
import type { FORM_SUBMITTED_WEBHOOK_RESPONSES } from "@calcom/app-store/routing-forms/trpc/utils";
import { sendGenericWebhookPayload } from "@calcom/features/webhooks/lib/sendPayload";
import prisma from "@calcom/prisma";
@@ -1,12 +1,12 @@
import getAppKeysFromSlug from "@calcom/app-store/_utils/getAppKeysFromSlug";
import { refreshAccessToken } from "@calcom/app-store/basecamp3/lib/helpers";
import type { BasecampToken } from "@calcom/app-store/basecamp3/lib/types";
import type { PrismaClient } from "@calcom/prisma/client";
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug";
import { refreshAccessToken } from "../lib/helpers";
import type { BasecampToken } from "../lib/types";
import type { TProjectMutationInputSchema } from "./projectMutation.schema";
interface ProjectMutationHandlerOptions {
@@ -1,13 +1,12 @@
import getAppKeysFromSlug from "@calcom/app-store/_utils/getAppKeysFromSlug";
import { refreshAccessToken } from "@calcom/app-store/basecamp3/lib/helpers";
import type { BasecampToken } from "@calcom/app-store/basecamp3/lib/types";
import type { PrismaClient } from "@calcom/prisma/client";
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug";
import { refreshAccessToken } from "../lib/helpers";
import type { BasecampToken } from "../lib/types";
interface ProjectsHandlerOptions {
ctx: {
prisma: PrismaClient;
@@ -1,3 +1,4 @@
import getConnectedForms from "@calcom/app-store/routing-forms/lib/getConnectedForms";
import { entityPrismaWhereClause } from "@calcom/lib/entityPermissionUtils.server";
import type { PrismaClient } from "@calcom/prisma";
import { MembershipRole } from "@calcom/prisma/enums";
@@ -5,7 +6,6 @@ import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import getConnectedForms from "../lib/getConnectedForms";
import type { TDeleteFormInputSchema } from "./deleteForm.schema";
import { checkPermissionOnExistingRoutingForm } from "./permissions";
@@ -1,6 +1,13 @@
import type { App_RoutingForms_Form } from "@prisma/client";
import { Prisma } from "@prisma/client";
import { createFallbackRoute } from "@calcom/app-store/routing-forms/lib/createFallbackRoute";
import { getSerializableForm } from "@calcom/app-store/routing-forms/lib/getSerializableForm";
import { isFallbackRoute } from "@calcom/app-store/routing-forms/lib/isFallbackRoute";
import isRouter from "@calcom/app-store/routing-forms/lib/isRouter";
import isRouterLinkedField from "@calcom/app-store/routing-forms/lib/isRouterLinkedField";
import type { SerializableForm } from "@calcom/app-store/routing-forms/types/types";
import { zodFields, zodRouterRoute, zodRoutes } from "@calcom/app-store/routing-forms/zod";
import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service";
import { entityPrismaWhereClause, canEditEntity } from "@calcom/lib/entityPermissionUtils.server";
import type { PrismaClient } from "@calcom/prisma";
@@ -9,14 +16,6 @@ import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import { createFallbackRoute } from "../lib/createFallbackRoute";
import { getSerializableForm } from "../lib/getSerializableForm";
import { isFallbackRoute } from "../lib/isFallbackRoute";
import { isFormCreateEditAllowed } from "../lib/isFormCreateEditAllowed";
import isRouter from "../lib/isRouter";
import isRouterLinkedField from "../lib/isRouterLinkedField";
import type { SerializableForm } from "../types/types";
import { zodFields, zodRouterRoute, zodRoutes } from "../zod";
import type { TFormMutationInputSchema } from "./formMutation.schema";
import { checkPermissionOnExistingRoutingForm } from "./permissions";
@@ -69,8 +68,8 @@ export const formMutationHandler = async ({ ctx, input }: FormMutationHandlerOpt
inputFields = inputFields || [];
inputRoutes = inputRoutes || [];
type InputFields = typeof inputFields;
type InputRoutes = typeof inputRoutes;
type InputFields = NonNullable<typeof inputFields>;
type InputRoutes = NonNullable<typeof inputRoutes>;
let routes: InputRoutes;
let fields: InputFields;
type DuplicateFrom = NonNullable<typeof duplicateFrom>;
@@ -1,9 +1,8 @@
import z from "zod";
import { zodFields, zodRoutes } from "@calcom/app-store/routing-forms/zod";
import { RoutingFormSettings } from "@calcom/prisma/zod-utils";
import { zodFields, zodRoutes } from "../zod";
export const ZFormMutationInputSchema = z.object({
id: z.string(),
name: z.string(),
@@ -1,11 +1,9 @@
import { getSerializableForm } from "@calcom/app-store/routing-forms/lib/getSerializableForm";
import { entityPrismaWhereClause } from "@calcom/lib/entityPermissionUtils.server";
import type { PrismaClient } from "@calcom/prisma";
import { MembershipRole } from "@calcom/prisma/enums";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import { getSerializableForm } from "../lib/getSerializableForm";
import type { TFormQueryInputSchema } from "./formQuery.schema";
import { checkPermissionOnExistingRoutingForm } from "./permissions";
@@ -1,5 +1,7 @@
import type { z } from "zod";
import { getSerializableForm } from "@calcom/app-store/routing-forms/lib/getSerializableForm";
import type { zodFields, zodRoutes } from "@calcom/app-store/routing-forms/zod";
import { hasFilter } from "@calcom/features/filters/lib/hasFilter";
import { entityPrismaWhereClause, canEditEntity } from "@calcom/lib/entityPermissionUtils.server";
import logger from "@calcom/lib/logger";
@@ -9,8 +11,6 @@ import type { Prisma } from "@calcom/prisma/client";
import { entries } from "@calcom/prisma/zod-utils";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { getSerializableForm } from "../lib/getSerializableForm";
import type { zodFields, zodRoutes } from "../zod";
import type { TFormSchema } from "./forms.schema";
interface FormsHandlerOptions {
@@ -1,10 +1,10 @@
import { enabledIncompleteBookingApps } from "@calcom/app-store/routing-forms/lib/enabledIncompleteBookingApps";
import type { PrismaClient } from "@calcom/prisma";
import { safeCredentialSelect } from "@calcom/prisma/selects/credential";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import { enabledIncompleteBookingApps } from "../lib/enabledIncompleteBookingApps";
import type { TGetIncompleteBookingSettingsInputSchema } from "./getIncompleteBookingSettings.schema";
interface GetIncompleteBookingSettingsOptions {
@@ -1,5 +1,8 @@
import type { z } from "zod";
import { enrichFormWithMigrationData } from "@calcom/app-store/routing-forms/enrichFormWithMigrationData";
import { getSerializableForm } from "@calcom/app-store/routing-forms/lib/getSerializableForm";
import type { FormResponse } from "@calcom/app-store/routing-forms/types/types";
import { canAccessEntity } from "@calcom/lib/entityPermissionUtils.server";
import { getTranslation } from "@calcom/lib/server/i18n";
import { prisma } from "@calcom/prisma";
@@ -7,9 +10,6 @@ import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import { enrichFormWithMigrationData } from "../enrichFormWithMigrationData";
import { getSerializableForm } from "../lib/getSerializableForm";
import type { FormResponse } from "../types/types";
import type { ZFormByResponseIdInputSchema } from "./_router";
type GetResponseWithFormFieldsOptions = {
@@ -1,10 +1,10 @@
import incompleteBookingActionDataSchemas from "@calcom/app-store/routing-forms/lib/incompleteBooking/actionDataSchemas";
import logger from "@calcom/lib/logger";
import type { PrismaClient } from "@calcom/prisma";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import incompleteBookingActionDataSchemas from "../lib/incompleteBooking/actionDataSchemas";
import type { TSaveIncompleteBookingSettingsInputSchema } from "./saveIncompleteBookingSettings.schema";
const log = logger.getSubLogger({ prefix: ["incomplete-booking"] });
@@ -1,10 +1,10 @@
import app_Basecamp3 from "@calcom/app-store/basecamp3/trpc-router";
import app_RoutingForms from "@calcom/app-store/routing-forms/trpc-router";
import { userAdminRouter } from "@calcom/features/ee/users/server/trpc-router";
import { featureFlagRouter } from "@calcom/features/flags/server/router";
import { insightsRouter } from "@calcom/features/insights/server/trpc-router";
import { router } from "../../trpc";
import app_Basecamp3 from "../apps/basecamp3/_router";
import app_RoutingForms from "../apps/routing-forms/_router";
import { loggedInViewerRouter } from "../loggedInViewer/_router";
import { publicViewerRouter } from "../publicViewer/_router";
import { timezonesRouter } from "../publicViewer/timezones/_router";
@@ -1,4 +1,3 @@
import type { TFormSchema } from "@calcom/app-store/routing-forms/trpc/forms.schema";
import { hasFilter } from "@calcom/features/filters/lib/hasFilter";
import { prisma } from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client";
@@ -7,6 +6,7 @@ import type { TrpcSessionUser } from "@calcom/trpc/server/types";
import { TRPCError } from "@trpc/server";
import type { TFormSchema } from "../../apps/routing-forms/forms.schema";
import type { TWorkflowOrderInputSchema } from "./workflowOrder.schema";
type RoutingFormOrderOptions = {