Skip to content

refactor: Remove trpc/server dependency from @calcom/atoms#94

Open
tomerqodo wants to merge 2 commits into
qodo_combined_20260121_qodo_grep_cursor_copilot_1_base_refactor_remove_trpc_server_dependency_from_calcom_atoms_pr716from
qodo_combined_20260121_qodo_grep_cursor_copilot_1_head_refactor_remove_trpc_server_dependency_from_calcom_atoms_pr716
Open

refactor: Remove trpc/server dependency from @calcom/atoms#94
tomerqodo wants to merge 2 commits into
qodo_combined_20260121_qodo_grep_cursor_copilot_1_base_refactor_remove_trpc_server_dependency_from_calcom_atoms_pr716from
qodo_combined_20260121_qodo_grep_cursor_copilot_1_head_refactor_remove_trpc_server_dependency_from_calcom_atoms_pr716

Conversation

@tomerqodo

Copy link
Copy Markdown

Benchmark PR from qodo-benchmark#716

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. validateCreateScheduleInput throws generic Error 📘 Rule violation ⛯ Reliability
Description
• The new validateCreateScheduleInput uses throw new Error(...) for validation failures, which
  provides no typed error code or structured context for downstream handling.
• This makes it harder to categorize, monitor, and map failures to appropriate responses, contrary
  to the required hierarchical error structure.
Code

packages/platform/atoms/hooks/schedules/types.ts[R38-47]

+export function validateCreateScheduleInput(input: unknown): CreateScheduleInput {
+  if (!input || typeof input !== 'object') {
+    throw new Error('Invalid input: must be an object');
+  }
+
+  const data = input as Record<string, unknown>;
+
+  if (typeof data.name !== 'string' || data.name.length === 0) {
+    throw new Error('Invalid input: name must be a non-empty string');
+  }
Evidence
PR Compliance ID 15 requires custom error classes with typed codes and structured context; the added
function throws plain Error instances instead.

AGENTS.md
packages/platform/atoms/hooks/schedules/types.ts[38-47]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`validateCreateScheduleInput` throws generic `Error` objects, which violates the requirement for hierarchical custom errors with typed codes and structured context.

## Issue Context
This validation utility will be used to reject invalid inputs; without typed codes/context, callers cannot reliably categorize and handle the failure.

## Fix Focus Areas
- packages/platform/atoms/hooks/schedules/types.ts[38-47]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. validateCreateScheduleInput returns cast 📘 Rule violation ⛨ Security
Description
• The new validation only checks name and then returns data as CreateScheduleInput, leaving
  schedule and eventTypeId effectively unvalidated.
• This allows malformed external input to flow through as trusted types, increasing the risk of
  runtime errors and unsafe data handling.
Code

packages/platform/atoms/hooks/schedules/types.ts[R32-49]

+export type CreateScheduleInput = {
+  name: string;
+  schedule?: { start: Date; end: Date }[][];
+  eventTypeId?: number;
+};
+
+export function validateCreateScheduleInput(input: unknown): CreateScheduleInput {
+  if (!input || typeof input !== 'object') {
+    throw new Error('Invalid input: must be an object');
+  }
+
+  const data = input as Record<string, unknown>;
+
+  if (typeof data.name !== 'string' || data.name.length === 0) {
+    throw new Error('Invalid input: name must be a non-empty string');
+  }
+
+  return data as CreateScheduleInput;
Evidence
PR Compliance IDs 6 and 3 require validation/sanitization and explicit edge-case handling for
external inputs; the added function performs minimal checks and then uses an unsafe type cast to
accept the full object.

Rule 6: Generic: Security-First Input Validation and Data Handling
Rule 3: Generic: Robust Error Handling and Edge Case Management
packages/platform/atoms/hooks/schedules/types.ts[32-49]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The validation helper returns an unsafe cast (`data as CreateScheduleInput`) after only partially validating the input.

## Issue Context
`input` is `unknown` and should be treated as external/untrusted; `schedule` and `eventTypeId` need explicit validation to prevent malformed data from being treated as valid.

## Fix Focus Areas
- packages/platform/atoms/hooks/schedules/types.ts[32-49]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Schedule days type wrong 🐞 Bug ✓ Correctness
Description
GetAvailabilityListHandlerReturn in atoms defines availability.days as string[], but the
  persisted/API shape uses numeric weekday values (Int[]).
• This can cause TS incompatibilities when passing schedules into existing schedule
  transformers/components that expect days: number[].
• Because these types are now “hand-copied” into atoms, they are likely to drift further from the
  server contract over time.
Code

packages/platform/atoms/hooks/schedules/types.ts[R16-29]

+export type GetAvailabilityListHandlerReturn = {
+  schedules: (Omit<Schedule, "userId"> & {
+    availability: {
+      id: number;
+      userId: number | null;
+      eventTypeId: number | null;
+      days: string[];
+      startTime: Date;
+      endTime: Date;
+      date: Date | null;
+      scheduleId: number | null;
+    }[];
+    isDefault: boolean;
+  })[];
Evidence
Atoms newly defines days as string[], but Prisma schema stores days as Int[] and the shared
schedule transformer expects number[]. This will break type compatibility where atoms UI passes
schedules to shared transformers/components.

packages/platform/atoms/hooks/schedules/types.ts[16-29]
packages/prisma/schema.prisma[935-947]
packages/lib/schedules/transformers/getScheduleListItemData.ts[1-15]
packages/platform/atoms/list-schedules/wrappers/ListSchedulesPlatformWrapper.tsx[75-85]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`packages/platform/atoms/hooks/schedules/types.ts` defines `availability.days` as `string[]`, but the real persisted/API shape uses numeric weekday values (`Int[]`). This mismatch breaks type compatibility with existing consumers (e.g., `getScheduleListItemData`) and is likely to drift.

### Issue Context
The atoms package is being decoupled from `@calcom/trpc` by recreating server types locally. These new local types must still match the actual REST response served by the atoms API.

### Fix Focus Areas
- packages/platform/atoms/hooks/schedules/types.ts[16-29]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
4. Slot userIds type drift 🐞 Bug ✓ Correctness
Description
• The new atoms Slot type defines userIds?: string[], but the server-side slot pipeline uses
  number[] for userIds and can include it in the slots returned to clients.
• This mismatch can cause subtle bugs when consumers treat userIds numerically (comparisons,
  lookups) or when TS types are used to derive other contracts.
• It also increases the risk that different parts of the system will disagree on what a “slot”
  contains.
Code

packages/platform/atoms/booker/types.ts[R17-23]

+export type Slot = {
+  time: string;
+  userIds?: string[];
+  attendees?: number;
+  bookingUid?: string;
+  users?: string[];
+};
Evidence
Atoms defines userIds as string[] while server code constructs slots that carry `userIds?:
number[]` and spreads them into the response objects that eventually get sent back (e.g., available
slots mapping).

packages/platform/atoms/booker/types.ts[17-23]
packages/trpc/server/routers/viewer/slots/util.ts[1358-1368]
packages/trpc/server/routers/viewer/slots/util.ts[1395-1419]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Atoms `Slot.userIds` is typed as `string[]`, but server slot generation uses numeric IDs (`number[]`) and can include them in slot objects returned to clients.

### Issue Context
This PR removes atoms’ imports from TRPC by redefining types locally. Local types must still mirror the actual REST responses.

### Fix Focus Areas
- packages/platform/atoms/booker/types.ts[17-23]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. SlotInfo fromUser id wrong 🐞 Bug ✓ Correctness
Description
SlotInfo.fromUser.id is typed as string, but server-side IFromUser.id is number.
• This creates inconsistent ID typing inside the same response shape (fromUser.id is string while
  toUser.id is number), increasing the chance of runtime bugs and incorrect client-side comparisons.
• The mismatch is especially risky in code paths dealing with out-of-office routing/host delegation
  where these IDs may be used to correlate users.
Code

packages/platform/atoms/booker/types.ts[R115-128]

+type SlotInfo = {
+  time: string;
+  attendees?: number;
+  bookingUid?: string;
+  away?: boolean;
+  fromUser?: {
+    id: string;
+    displayName: string | null;
+  };
+  toUser?: {
+    id: number;
+    username: string | null;
+    displayName: string | null;
+  };
Evidence
Atoms defines fromUser.id as string. The canonical type used by the available slots service
(IFromUser) defines it as number, and that’s what the server uses when populating slot metadata.

packages/platform/atoms/booker/types.ts[115-128]
packages/features/availability/lib/getUserAvailability.ts[176-185]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Atoms `SlotInfo.fromUser.id` is typed as `string`, but server-side `IFromUser.id` is numeric.

### Issue Context
This type is part of `GetAvailableSlotsResponse` and will be consumed by atoms clients. Mixed ID types (`fromUser.id` vs `toUser.id`) are error-prone.

### Fix Focus Areas
- packages/platform/atoms/booker/types.ts[115-128]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Removed booker subpath export 🐞 Bug ⛯ Reliability
Description
@calcom/atoms export map drops the ./booker subpath and only exports ./booker/types.
• While there are no in-repo imports of @calcom/atoms/booker, this is a breaking change for any
  external consumers relying on that path.
• If this package is published (it has a version and npm scripts), this should be treated as a
  compatibility break (restore export or bump major).
Code

packages/platform/atoms/package.json[58]

+    "./booker/types": "./booker/types.ts",
Evidence
The package export map no longer includes ./booker, which means `import ... from
"@calcom/atoms/booker"` will fail at runtime in Node/bundlers that honor package exports.

packages/platform/atoms/package.json[50-61]
packages/platform/atoms/index.ts[1-7]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`packages/platform/atoms/package.json` removed the `./booker` export, which can break external consumers relying on that subpath.

### Issue Context
Even if the monorepo doesn’t currently use this path, package exports are part of the published contract.

### Fix Focus Areas
- packages/platform/atoms/package.json[55-60]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



ⓘ The new review experience is currently in Beta. Learn more

Qodo Logo

Comment on lines +38 to +47
export function validateCreateScheduleInput(input: unknown): CreateScheduleInput {
if (!input || typeof input !== 'object') {
throw new Error('Invalid input: must be an object');
}

const data = input as Record<string, unknown>;

if (typeof data.name !== 'string' || data.name.length === 0) {
throw new Error('Invalid input: name must be a non-empty string');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. validatecreatescheduleinput throws generic error 📘 Rule violation ⛯ Reliability

• The new validateCreateScheduleInput uses throw new Error(...) for validation failures, which
  provides no typed error code or structured context for downstream handling.
• This makes it harder to categorize, monitor, and map failures to appropriate responses, contrary
  to the required hierarchical error structure.
Agent prompt
## Issue description
`validateCreateScheduleInput` throws generic `Error` objects, which violates the requirement for hierarchical custom errors with typed codes and structured context.

## Issue Context
This validation utility will be used to reject invalid inputs; without typed codes/context, callers cannot reliably categorize and handle the failure.

## Fix Focus Areas
- packages/platform/atoms/hooks/schedules/types.ts[38-47]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +32 to +49
export type CreateScheduleInput = {
name: string;
schedule?: { start: Date; end: Date }[][];
eventTypeId?: number;
};

export function validateCreateScheduleInput(input: unknown): CreateScheduleInput {
if (!input || typeof input !== 'object') {
throw new Error('Invalid input: must be an object');
}

const data = input as Record<string, unknown>;

if (typeof data.name !== 'string' || data.name.length === 0) {
throw new Error('Invalid input: name must be a non-empty string');
}

return data as CreateScheduleInput;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. validatecreatescheduleinput returns cast 📘 Rule violation ⛨ Security

• The new validation only checks name and then returns data as CreateScheduleInput, leaving
  schedule and eventTypeId effectively unvalidated.
• This allows malformed external input to flow through as trusted types, increasing the risk of
  runtime errors and unsafe data handling.
Agent prompt
## Issue description
The validation helper returns an unsafe cast (`data as CreateScheduleInput`) after only partially validating the input.

## Issue Context
`input` is `unknown` and should be treated as external/untrusted; `schedule` and `eventTypeId` need explicit validation to prevent malformed data from being treated as valid.

## Fix Focus Areas
- packages/platform/atoms/hooks/schedules/types.ts[32-49]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +16 to +29
export type GetAvailabilityListHandlerReturn = {
schedules: (Omit<Schedule, "userId"> & {
availability: {
id: number;
userId: number | null;
eventTypeId: number | null;
days: string[];
startTime: Date;
endTime: Date;
date: Date | null;
scheduleId: number | null;
}[];
isDefault: boolean;
})[];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Schedule days type wrong 🐞 Bug ✓ Correctness

GetAvailabilityListHandlerReturn in atoms defines availability.days as string[], but the
  persisted/API shape uses numeric weekday values (Int[]).
• This can cause TS incompatibilities when passing schedules into existing schedule
  transformers/components that expect days: number[].
• Because these types are now “hand-copied” into atoms, they are likely to drift further from the
  server contract over time.
Agent prompt
### Issue description
`packages/platform/atoms/hooks/schedules/types.ts` defines `availability.days` as `string[]`, but the real persisted/API shape uses numeric weekday values (`Int[]`). This mismatch breaks type compatibility with existing consumers (e.g., `getScheduleListItemData`) and is likely to drift.

### Issue Context
The atoms package is being decoupled from `@calcom/trpc` by recreating server types locally. These new local types must still match the actual REST response served by the atoms API.

### Fix Focus Areas
- packages/platform/atoms/hooks/schedules/types.ts[16-29]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +17 to +23
export type Slot = {
time: string;
userIds?: string[];
attendees?: number;
bookingUid?: string;
users?: string[];
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Slot userids type drift 🐞 Bug ✓ Correctness

• The new atoms Slot type defines userIds?: string[], but the server-side slot pipeline uses
  number[] for userIds and can include it in the slots returned to clients.
• This mismatch can cause subtle bugs when consumers treat userIds numerically (comparisons,
  lookups) or when TS types are used to derive other contracts.
• It also increases the risk that different parts of the system will disagree on what a “slot”
  contains.
Agent prompt
### Issue description
Atoms `Slot.userIds` is typed as `string[]`, but server slot generation uses numeric IDs (`number[]`) and can include them in slot objects returned to clients.

### Issue Context
This PR removes atoms’ imports from TRPC by redefining types locally. Local types must still mirror the actual REST responses.

### Fix Focus Areas
- packages/platform/atoms/booker/types.ts[17-23]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +115 to +128
type SlotInfo = {
time: string;
attendees?: number;
bookingUid?: string;
away?: boolean;
fromUser?: {
id: string;
displayName: string | null;
};
toUser?: {
id: number;
username: string | null;
displayName: string | null;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

5. Slotinfo fromuser id wrong 🐞 Bug ✓ Correctness

SlotInfo.fromUser.id is typed as string, but server-side IFromUser.id is number.
• This creates inconsistent ID typing inside the same response shape (fromUser.id is string while
  toUser.id is number), increasing the chance of runtime bugs and incorrect client-side comparisons.
• The mismatch is especially risky in code paths dealing with out-of-office routing/host delegation
  where these IDs may be used to correlate users.
Agent prompt
### Issue description
Atoms `SlotInfo.fromUser.id` is typed as `string`, but server-side `IFromUser.id` is numeric.

### Issue Context
This type is part of `GetAvailableSlotsResponse` and will be consumed by atoms clients. Mixed ID types (`fromUser.id` vs `toUser.id`) are error-prone.

### Fix Focus Areas
- packages/platform/atoms/booker/types.ts[115-128]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

"./add-members-switch/AddMembersWithSwitchPlatformWrapper": "./add-members-switch/AddMembersWithSwitchPlatformWrapper.tsx",
"./availability/AvailabilitySettings": "./availability/AvailabilitySettings.tsx",
"./booker": "./booker/index.ts",
"./booker/types": "./booker/types.ts",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

6. Removed booker subpath export 🐞 Bug ⛯ Reliability

@calcom/atoms export map drops the ./booker subpath and only exports ./booker/types.
• While there are no in-repo imports of @calcom/atoms/booker, this is a breaking change for any
  external consumers relying on that path.
• If this package is published (it has a version and npm scripts), this should be treated as a
  compatibility break (restore export or bump major).
Agent prompt
### Issue description
`packages/platform/atoms/package.json` removed the `./booker` export, which can break external consumers relying on that subpath.

### Issue Context
Even if the monorepo doesn’t currently use this path, package exports are part of the published contract.

### Fix Focus Areas
- packages/platform/atoms/package.json[55-60]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant