-
Notifications
You must be signed in to change notification settings - Fork 0
fix(companion): event type links for org user #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: coderabbit_combined_20260121_augment_sentry_coderabbit_1_base_fixcompanion_event_type_links_for_org_user_pr706
Are you sure you want to change the base?
Conversation
Addresses Cubic AI review feedback (confidence 9/10): The username was hardcoded to 'username' but still used by BasicsTab as a fallback for URL display when bookingUrl is unavailable. This restores the useEffect that fetches the actual username from CalComAPIService.getUsername(). Co-Authored-By: unknown <>
WalkthroughThis PR introduces a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
companion/extension/lib/linkedin.ts (1)
109-119: ValidatebookingUrlscheme before use.
bookingUrlis now used directly inwindow.open/clipboard flows. If it ever contains a non-http(s) scheme (e.g.,javascript:), it can become a security footgun. Consider whitelistinghttp/https(and optionally custom-domain logic) before using it.🔒 Suggested guard for URL scheme
function buildBookingUrl(eventType: EventType): string { - return ( - eventType.bookingUrl || - `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}` - ); + const bookingUrl = eventType.bookingUrl; + if (bookingUrl) { + try { + const parsed = new URL(bookingUrl); + if (parsed.protocol === "http:" || parsed.protocol === "https:") { + return bookingUrl; + } + } catch { + // Fall through to default URL + } + } + return `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`; }Also applies to: 667-671
companion/components/event-type-list-item/EventTypeListItemParts.tsx (1)
7-62: Handle scheme-lessbookingUrlin display helper.
new URL(bookingUrl)throws on values likecal.com/org/slugor/org/slug, causing the fallback to return/{username}/{slug}instead of attempting to display the actual bookingUrl. If a scheme-less bookingUrl reaches this function, consider normalizing it withhttps://prefix before parsing, or falling back to the raw bookingUrl string for display.🔧 Suggested normalization approach
function getDisplayUrl(bookingUrl?: string, username?: string, slug?: string): string { if (bookingUrl) { try { + const normalized = + /^https?:\/\//i.test(bookingUrl) ? bookingUrl : `https://${bookingUrl.replace(/^\/+/, "")}`; + const url = new URL(normalized); // Return domain + pathname (e.g., "i.cal.com/keith/30min") return url.hostname + url.pathname; } catch { - // fallback if URL parsing fails + return bookingUrl; } } - return username ? `/${username}/${slug}` : `/${slug}`; + return username && slug ? `/${username}/${slug}` : slug ? `/${slug}` : ""; }companion/app/(tabs)/(event-types)/index.tsx (1)
40-157: ValidatebookingUrlscheme before copy/share/preview operations.The handlers use
bookingUrldirectly from the API without validating the scheme. A malformed or non-http(s) URL could fail or expose security issues. Centralize validation using a helper that checks URL format and scheme.🔧 Suggested fix (centralize validation)
+ const getSafeBookingUrl = (bookingUrl?: string): string | null => { + if (!bookingUrl) return null; + try { + const url = new URL(bookingUrl); + if (!["http:", "https:"].includes(url.protocol)) return null; + return url.toString(); + } catch { + return null; + } + }; + const handleCopyLink = async (eventType: EventType) => { - if (!eventType.bookingUrl) { + const safeUrl = getSafeBookingUrl(eventType.bookingUrl); + if (!safeUrl) { showErrorAlert("Error", "Booking URL not available for this event type."); return; } try { - await Clipboard.setStringAsync(eventType.bookingUrl); + await Clipboard.setStringAsync(safeUrl); showSuccessAlert("Link Copied", "Event type link copied!"); } catch { showErrorAlert("Error", "Failed to copy link. Please try again."); } }; const _handleShare = async (eventType: EventType) => { - if (!eventType.bookingUrl) { + const safeUrl = getSafeBookingUrl(eventType.bookingUrl); + if (!safeUrl) { showErrorAlert("Error", "Booking URL not available for this event type."); return; } try { await Share.share({ message: `Book a meeting: ${eventType.title}`, - url: eventType.bookingUrl, + url: safeUrl, }); } catch { showErrorAlert("Error", "Failed to share link. Please try again."); } }; const handlePreview = async (eventType: EventType) => { - if (!eventType.bookingUrl) { + const safeUrl = getSafeBookingUrl(eventType.bookingUrl); + if (!safeUrl) { showErrorAlert("Error", "Booking URL not available for this event type."); return; } try { if (Platform.OS === "web") { - window.open(eventType.bookingUrl, "_blank"); + window.open(safeUrl, "_blank"); } else { - await openInAppBrowser(eventType.bookingUrl, "event type preview"); + await openInAppBrowser(safeUrl, "event type preview"); } } catch { console.error("Failed to open preview"); showErrorAlert("Error", "Failed to open preview. Please try again."); } };
🤖 Fix all issues with AI agents
In `@companion/app/`(tabs)/(event-types)/event-type-detail.tsx:
- Around line 180-181: The bookingUrl state is never set from the API payload so
guards always fall back to the default prefix; inside applyEventTypeData,
extract the booking URL (or its components) from the incoming eventType data and
call setBookingUrl(...) with that value (use the same key the API provides on
eventType), ensuring preview/copy and any guards use that populated bookingUrl
instead of defaulting to "cal.com/{username}".
In `@companion/components/event-type-detail/tabs/BasicsTab.tsx`:
- Around line 257-276: The displayed booking URL prefix in BasicsTab.tsx
currently uses url.hostname which drops ports (so http://localhost:3000 becomes
http://localhost); update the logic inside the IIFE that reads props.bookingUrl
to use url.host instead of url.hostname so ports are preserved, keeping the rest
of the logic (pathParts building, prefix construction, fallback to
`cal.com/${props.username}/`) intact and ensuring the returned string uses
`${url.protocol}//${url.host}${prefix}`.
In `@companion/extension/entrypoints/content.ts`:
- Around line 1125-1128: The copy button currently reconstructs the URL from
eventType.users?.[0]?.username and eventType.slug instead of reusing the
already-built bookingUrl; update the copy action (the copy button click handler
/ copy function in content.ts) to use the bookingUrl variable when writing to
the clipboard or setting the copied text so org/custom URLs are preserved,
rather than re-building via username/slug.
In `@companion/services/calcom.ts`:
- Around line 1654-1662: getUsername currently assumes profile.username exists
and can return undefined; modify getUsername to validate profile and
profile.username after calling getUserProfile() and throw a descriptive Error if
username is missing (e.g., "Missing username on user profile") instead of
returning undefined. Reference the getUsername function and the getUserProfile()
call and the profile.username property when adding the guard and error throw so
callers always receive a non-empty string or a clear failure.
🧹 Nitpick comments (2)
companion/components/event-type-detail/tabs/LimitsTab.tsx (1)
125-128: Redundant styling between className and inline style.The
flex-row items-centerclasses inclassNamealready provideflexDirection: "row"andalignItems: "center". The inlinestyleprop duplicates these values. Consider removing the redundant properties from the inline style to keep a single source of truth:♻️ Suggested fix
<View className={`flex-row items-center pr-4 ${!isLast ? "border-b border-[`#E5E5E5`]" : ""}`} - style={{ height: 44, flexDirection: "row", alignItems: "center" }} + style={{ height: 44 }} >companion/components/event-type-detail/tabs/RecurringTab.tsx (1)
90-93: Redundant styling between className and inline style.Similar to
LimitsTab.tsx, theflex-row items-centerclasses already provideflexDirection: "row"andalignItems: "center". Consider removing the duplicates from the inline style:♻️ Suggested fix
<View className={`flex-row items-center pr-4 ${!isLast ? "border-b border-[`#E5E5E5`]" : ""}`} - style={{ minHeight: 44, flexDirection: "row", alignItems: "center" }} + style={{ minHeight: 44 }} >Note: Using
minHeighthere (vsheight: 44inLimitsTab.tsx) is appropriate sinceSettingRowcontent here may vary in height.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
companion/app/(tabs)/(availability)/availability-detail.tsxcompanion/app/(tabs)/(bookings)/index.ios.tsxcompanion/app/(tabs)/(bookings)/index.tsxcompanion/app/(tabs)/(event-types)/event-type-detail.tsxcompanion/app/(tabs)/(event-types)/index.ios.tsxcompanion/app/(tabs)/(event-types)/index.tsxcompanion/app/profile-sheet.ios.tsxcompanion/app/profile-sheet.tsxcompanion/components/Header.tsxcompanion/components/event-type-detail/tabs/AdvancedTab.tsxcompanion/components/event-type-detail/tabs/BasicsTab.tsxcompanion/components/event-type-detail/tabs/LimitsTab.tsxcompanion/components/event-type-detail/tabs/RecurringTab.tsxcompanion/components/event-type-list-item/EventTypeListItem.ios.tsxcompanion/components/event-type-list-item/EventTypeListItem.tsxcompanion/components/event-type-list-item/EventTypeListItemParts.tsxcompanion/extension/entrypoints/background/index.tscompanion/extension/entrypoints/content.tscompanion/extension/lib/linkedin.tscompanion/services/calcom.tscompanion/services/types/event-types.types.ts
🧰 Additional context used
🧬 Code graph analysis (7)
companion/components/event-type-detail/tabs/RecurringTab.tsx (1)
packages/features/calendars/weeklyview/types/state.ts (1)
View(7-7)
companion/app/profile-sheet.ios.tsx (1)
packages/features/calendars/weeklyview/types/state.ts (1)
View(7-7)
companion/app/profile-sheet.tsx (1)
packages/features/calendars/weeklyview/types/state.ts (1)
View(7-7)
companion/components/Header.tsx (1)
companion/components/AppPressable.tsx (1)
AppPressable(48-104)
companion/app/(tabs)/(event-types)/index.ios.tsx (3)
companion/utils/alerts.ts (2)
showErrorAlert(36-51)showSuccessAlert(67-74)companion/utils/index.ts (3)
showErrorAlert(14-14)showSuccessAlert(14-14)openInAppBrowser(16-16)companion/services/types/event-types.types.ts (1)
EventType(173-284)
companion/app/(tabs)/(event-types)/event-type-detail.tsx (3)
companion/utils/alerts.ts (1)
showErrorAlert(36-51)companion/utils/index.ts (2)
showErrorAlert(14-14)openInAppBrowser(16-16)companion/components/AppPressable.tsx (1)
AppPressable(48-104)
companion/app/(tabs)/(event-types)/index.tsx (3)
companion/utils/alerts.ts (2)
showErrorAlert(36-51)showSuccessAlert(67-74)companion/services/types/event-types.types.ts (1)
EventType(173-284)companion/utils/browser.ts (1)
openInAppBrowser(44-68)
🔇 Additional comments (25)
companion/components/event-type-detail/tabs/LimitsTab.tsx (1)
143-150: LGTM on Switch alignment fix.Adding
justifyContent: "center"alongsidealignSelf: "center"ensures proper vertical centering of the Switch control within its container. This is a reasonable approach for cross-platform consistency.companion/app/profile-sheet.tsx (1)
127-127: LGTM on border removal.Removing the bottom border from the profile header aligns with the iOS-specific version and creates a cleaner visual presentation.
companion/app/profile-sheet.ios.tsx (1)
150-150: LGTM on border removal.Consistent with the change in
profile-sheet.tsx, maintaining visual parity across platform-specific implementations.companion/extension/entrypoints/background/index.ts (1)
278-283: LGTM on lint suppression documentation.The biome-ignore comment appropriately documents why the
anycast is necessary—Safari'sbrowserActionAPI (Manifest V2) isn't represented in Chrome's type definitions. This is a valid cross-browser compatibility pattern.companion/services/types/event-types.types.ts (1)
281-283: LGTM on bookingUrl field addition.The new optional
bookingUrlfield is properly typed and documented. This enables direct booking URL usage throughout the application, replacing the need for programmatic URL construction viaCalComAPIService.buildEventTypeLink.companion/components/event-type-detail/tabs/RecurringTab.tsx (1)
107-114: LGTM on Switch alignment fix.Consistent with the
LimitsTab.tsxchange, ensuring proper vertical centering of the Switch control.companion/components/Header.tsx (1)
106-114: Consistent active-state styling update.
The black active/selected treatment and trigger layout tweaks look consistent with the broader UI refresh.Also applies to: 149-154, 171-176, 212-218, 234-240, 256-262, 292-299, 313-320, 336-342, 361-369, 388-394
companion/extension/entrypoints/content.ts (1)
835-837: bookingUrl propagation looks good.
Types and URL construction now consistently preferbookingUrlwith safe fallbacks elsewhere.Also applies to: 878-879, 894-895, 1081-1086, 1291-1299, 1322-1327, 1585-1586, 1627-1628, 1643-1644, 1829-1832, 1871-1874, 2036-2044
companion/app/(tabs)/(availability)/availability-detail.tsx (1)
85-92: Simple styling update looks good.
Color change is consistent with the new active-state palette.companion/components/event-type-detail/tabs/AdvancedTab.tsx (1)
140-142: Layout alignment tweaks look solid.
Explicit row alignment/centering should improve cross-platform consistency.Also applies to: 157-158
companion/components/event-type-list-item/EventTypeListItem.ios.tsx (1)
99-104: bookingUrl propagation on iOS looks good.Cleanly forwards
item.bookingUrlto the title for consistent URL display.companion/app/(tabs)/(bookings)/index.ios.tsx (1)
63-66: Menu label color update looks good.Consistent with the black-on-active styling update.
Also applies to: 124-127
companion/app/(tabs)/(bookings)/index.tsx (1)
64-75: Filter trigger layout/text styling update looks good.Improves alignment while keeping behavior unchanged.
companion/components/event-type-list-item/EventTypeListItem.tsx (1)
50-55: bookingUrl propagation on list item (non‑iOS) looks good.Keeps URL display logic centralized in the title component.
companion/app/(tabs)/(event-types)/index.tsx (1)
450-453: “New” button alignment tweak looks good.The inline flex alignment is consistent and harmless.
Also applies to: 516-518
companion/components/event-type-detail/tabs/BasicsTab.tsx (2)
40-40: Optional bookingUrl prop is a safe API extension.
204-210: Row alignment tweak looks good.companion/app/(tabs)/(event-types)/event-type-detail.tsx (4)
948-962: Preview/copy guards are sensible.
1273-1276: Header trigger alignment looks good.
1430-1430: bookingUrl propagation into BasicsTab is correct.
2339-2350: Hidden switch centering is a nice polish.companion/app/(tabs)/(event-types)/index.ios.tsx (4)
1-3: Import cleanup aligns with direct bookingUrl usage.Also applies to: 31-31
113-120: Copy link now correctly guards on bookingUrl.
127-135: Share action uses bookingUrl directly — good.
235-241: Preview action now opens the bookingUrl — good.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| const [bookingUrl, setBookingUrl] = useState<string>(""); | ||
| const [saving, setSaving] = useState(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Populate bookingUrl from API data; otherwise preview/copy always fail.
bookingUrl is initialized but never set from eventType data, so the new guards will always fire and the URL prefix falls back to cal.com/{username}.
🛠️ Suggested fix (add inside applyEventTypeData)
const applyEventTypeData = useCallback((eventType: EventType) => {
setEventTypeData(eventType);
+ setBookingUrl(eventType.bookingUrl ?? "");🤖 Prompt for AI Agents
In `@companion/app/`(tabs)/(event-types)/event-type-detail.tsx around lines 180 -
181, The bookingUrl state is never set from the API payload so guards always
fall back to the default prefix; inside applyEventTypeData, extract the booking
URL (or its components) from the incoming eventType data and call
setBookingUrl(...) with that value (use the same key the API provides on
eventType), ensuring preview/copy and any guards use that populated bookingUrl
instead of defaulting to "cal.com/{username}".
| {(() => { | ||
| // Parse bookingUrl to get domain prefix (e.g., "i.cal.com/" or "cal.com/username/") | ||
| if (props.bookingUrl) { | ||
| try { | ||
| const url = new URL(props.bookingUrl); | ||
| // Get path without the last segment (slug) | ||
| const pathParts = url.pathname.split("/").filter(Boolean); | ||
| pathParts.pop(); // Remove slug | ||
| // Compute prefix outside try/catch for React Compiler | ||
| let prefix = "/"; | ||
| if (pathParts.length > 0) { | ||
| prefix = `/${pathParts.join("/")}/`; | ||
| } | ||
| return `${url.protocol}//${url.hostname}${prefix}`; | ||
| } catch { | ||
| // fallback | ||
| } | ||
| } | ||
| return `cal.com/${props.username}/`; | ||
| })()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
node <<'EOF'
// Test URL.hostname vs URL.host behavior
const testUrls = [
"http://localhost:3000/i/username/",
"https://cal.com/username/",
"http://example.com:8080/path/",
"http://localhost/path/"
];
testUrls.forEach(urlStr => {
const url = new URL(urlStr);
console.log(`URL: ${urlStr}`);
console.log(` .hostname: ${url.hostname}`);
console.log(` .host: ${url.host}`);
console.log(` .protocol: ${url.protocol}`);
console.log("");
});
EOFRepository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 477
🏁 Script executed:
# Find the file and examine its context
fd "BasicsTab.tsx" --type fRepository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 143
🏁 Script executed:
# Search for any tests related to booking URL handling
fd "\.test\." --type f | head -20Repository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 1188
🏁 Script executed:
# Look for other uses of bookingUrl in the codebase
rg "bookingUrl" -A 2 -B 2Repository: qodo-benchmark/cal.com-combined-coderabbit
Length of output: 48236
Preserve ports in the displayed booking URL prefix.
Using url.hostname drops ports (e.g., http://localhost:3000/... renders as http://localhost/...), breaking consistency with the actual booking URL. Switch to url.host to preserve ports.
🛠️ Suggested fix
- return `${url.protocol}//${url.hostname}${prefix}`;
+ return `${url.protocol}//${url.host}${prefix}`;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {(() => { | |
| // Parse bookingUrl to get domain prefix (e.g., "i.cal.com/" or "cal.com/username/") | |
| if (props.bookingUrl) { | |
| try { | |
| const url = new URL(props.bookingUrl); | |
| // Get path without the last segment (slug) | |
| const pathParts = url.pathname.split("/").filter(Boolean); | |
| pathParts.pop(); // Remove slug | |
| // Compute prefix outside try/catch for React Compiler | |
| let prefix = "/"; | |
| if (pathParts.length > 0) { | |
| prefix = `/${pathParts.join("/")}/`; | |
| } | |
| return `${url.protocol}//${url.hostname}${prefix}`; | |
| } catch { | |
| // fallback | |
| } | |
| } | |
| return `cal.com/${props.username}/`; | |
| })()} | |
| {(() => { | |
| // Parse bookingUrl to get domain prefix (e.g., "i.cal.com/" or "cal.com/username/") | |
| if (props.bookingUrl) { | |
| try { | |
| const url = new URL(props.bookingUrl); | |
| // Get path without the last segment (slug) | |
| const pathParts = url.pathname.split("/").filter(Boolean); | |
| pathParts.pop(); // Remove slug | |
| // Compute prefix outside try/catch for React Compiler | |
| let prefix = "/"; | |
| if (pathParts.length > 0) { | |
| prefix = `/${pathParts.join("/")}/`; | |
| } | |
| return `${url.protocol}//${url.host}${prefix}`; | |
| } catch { | |
| // fallback | |
| } | |
| } | |
| return `cal.com/${props.username}/`; | |
| })()} |
🤖 Prompt for AI Agents
In `@companion/components/event-type-detail/tabs/BasicsTab.tsx` around lines 257 -
276, The displayed booking URL prefix in BasicsTab.tsx currently uses
url.hostname which drops ports (so http://localhost:3000 becomes
http://localhost); update the logic inside the IIFE that reads props.bookingUrl
to use url.host instead of url.hostname so ports are preserved, keeping the rest
of the logic (pathParts building, prefix construction, fallback to
`cal.com/${props.username}/`) intact and ensuring the returned string uses
`${url.protocol}//${url.host}${prefix}`.
| const bookingUrl = | ||
| `https://cal.com/${ | ||
| eventType.users?.[0]?.username || "user" | ||
| }/${eventType.slug}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use bookingUrl for copy action (currently ignored).
The copy button still constructs the URL from username/slug only, so org/custom URLs won’t be copied even though preview uses bookingUrl.
🛠️ Proposed fix
-const bookingUrl =
- `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`;
+const bookingUrl =
+ eventType.bookingUrl ||
+ `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const bookingUrl = | |
| `https://cal.com/${ | |
| eventType.users?.[0]?.username || "user" | |
| }/${eventType.slug}`; | |
| const bookingUrl = | |
| eventType.bookingUrl || | |
| `https://cal.com/${ | |
| eventType.users?.[0]?.username || "user" | |
| }/${eventType.slug}`; |
🤖 Prompt for AI Agents
In `@companion/extension/entrypoints/content.ts` around lines 1125 - 1128, The
copy button currently reconstructs the URL from eventType.users?.[0]?.username
and eventType.slug instead of reusing the already-built bookingUrl; update the
copy action (the copy button click handler / copy function in content.ts) to use
the bookingUrl variable when writing to the clipboard or setting the copied text
so org/custom URLs are preserved, rather than re-building via username/slug.
| // Helper to get username | ||
| async function getUsername(): Promise<string> { | ||
| try { | ||
| const profile = await getUserProfile(); | ||
| return profile.username; | ||
| } catch (error) { | ||
| throw new Error("Failed to get username"); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against missing username before returning.
getUsername() returns Promise<string> but can currently return undefined if the profile lacks a username. This can lead to malformed URLs or runtime surprises.
✅ Suggested fix
async function getUsername(): Promise<string> {
- try {
- const profile = await getUserProfile();
- return profile.username;
- } catch (error) {
- throw new Error("Failed to get username");
- }
+ const profile = await getUserProfile();
+ if (!profile?.username) {
+ throw new Error("Username missing in profile response");
+ }
+ return profile.username;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Helper to get username | |
| async function getUsername(): Promise<string> { | |
| try { | |
| const profile = await getUserProfile(); | |
| return profile.username; | |
| } catch (error) { | |
| throw new Error("Failed to get username"); | |
| } | |
| } | |
| async function getUsername(): Promise<string> { | |
| const profile = await getUserProfile(); | |
| if (!profile?.username) { | |
| throw new Error("Username missing in profile response"); | |
| } | |
| return profile.username; | |
| } |
🤖 Prompt for AI Agents
In `@companion/services/calcom.ts` around lines 1654 - 1662, getUsername currently
assumes profile.username exists and can return undefined; modify getUsername to
validate profile and profile.username after calling getUserProfile() and throw a
descriptive Error if username is missing (e.g., "Missing username on user
profile") instead of returning undefined. Reference the getUsername function and
the getUserProfile() call and the profile.username property when adding the
guard and error throw so callers always receive a non-empty string or a clear
failure.
Benchmark PR from qodo-benchmark#706
Summary by CodeRabbit
New Features
Style
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.