From 4af3ab91af950e7ada91a7d13612ac194188b7b8 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 14 Jan 2026 22:33:38 -0500 Subject: [PATCH 1/6] refactor(api): adopt `@octokit/types` Signed-off-by: Adam Setch --- package.json | 1 + pnpm-lock.yaml | 10 +++++++++ src/renderer/utils/api/client.ts | 37 ++++++++++++++++++++------------ src/renderer/utils/api/types.ts | 24 ++++++++++++++------- 4 files changed, 50 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index d48903906..ccfb68f49 100644 --- a/package.json +++ b/package.json @@ -85,6 +85,7 @@ "@graphql-codegen/cli": "6.1.0", "@graphql-codegen/schema-ast": "5.0.0", "@octokit/openapi-types": "27.0.0", + "@octokit/types": "^16.0.0", "@parcel/watcher": "2.5.1", "@primer/css": "22.1.0", "@primer/octicons-react": "19.21.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bafebed9..8c8a79d27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,6 +51,9 @@ importers: '@octokit/openapi-types': specifier: 27.0.0 version: 27.0.0 + '@octokit/types': + specifier: ^16.0.0 + version: 16.0.0 '@parcel/watcher': specifier: 2.5.1 version: 2.5.1 @@ -1620,6 +1623,9 @@ packages: '@octokit/openapi-types@27.0.0': resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==} + '@octokit/types@16.0.0': + resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==} + '@oddbird/popover-polyfill@0.5.2': resolution: {integrity: sha512-iFrvar5SOMtKFOSjYvs4z9UlLqDdJbMx0mgISLcPedv+g0ac5sgeETLGtipHCVIae6HJPclNEH5aCyD1RZaEHw==} @@ -7880,6 +7886,10 @@ snapshots: '@octokit/openapi-types@27.0.0': {} + '@octokit/types@16.0.0': + dependencies: + '@octokit/openapi-types': 27.0.0 + '@oddbird/popover-polyfill@0.5.2': {} '@parcel/watcher-android-arm64@2.5.1': diff --git a/src/renderer/utils/api/client.ts b/src/renderer/utils/api/client.ts index c77ddbc80..5015565e8 100644 --- a/src/renderer/utils/api/client.ts +++ b/src/renderer/utils/api/client.ts @@ -32,11 +32,13 @@ import { performGraphQLRequestString, } from './request'; import type { - NotificationThreadSubscription, - RawCommit, - RawCommitComment, - RawGitHubNotification, - RawRelease, + GetCommitCommentResponse, + GetCommitResponse, + GetReleaseResponse, + IgnoreNotificationThreadSubscriptionResponse, + ListNotificationsForAuthenticatedUserResponse, + MarkNotificationThreadAsDoneResponse, + MarkNotificationThreadAsReadResponse, } from './types'; import { getGitHubAPIBaseUrl, @@ -64,10 +66,11 @@ export function headNotifications( * * Endpoint documentation: https://docs.github.com/en/rest/activity/notifications#list-notifications-for-the-authenticated-user */ + export function listNotificationsForAuthenticatedUser( account: Account, settings: SettingsState, -): AxiosPromise { +): AxiosPromise { const url = getGitHubAPIBaseUrl(account.hostname); url.pathname += 'notifications'; url.searchParams.append('participating', String(settings.participating)); @@ -88,11 +91,12 @@ export function listNotificationsForAuthenticatedUser( * * Endpoint documentation: https://docs.github.com/en/rest/activity/notifications#mark-a-thread-as-read */ + export function markNotificationThreadAsRead( threadId: string, hostname: Hostname, token: Token, -): AxiosPromise { +): AxiosPromise { const url = getGitHubAPIBaseUrl(hostname); url.pathname += `notifications/threads/${threadId}`; @@ -111,7 +115,7 @@ export function markNotificationThreadAsDone( threadId: string, hostname: Hostname, token: Token, -): AxiosPromise { +): AxiosPromise { const url = getGitHubAPIBaseUrl(hostname); url.pathname += `notifications/threads/${threadId}`; @@ -127,7 +131,7 @@ export function ignoreNotificationThreadSubscription( threadId: string, hostname: Hostname, token: Token, -): AxiosPromise { +): AxiosPromise { const url = getGitHubAPIBaseUrl(hostname); url.pathname += `notifications/threads/${threadId}/subscription`; @@ -141,20 +145,22 @@ export function ignoreNotificationThreadSubscription( * * Endpoint documentation: https://docs.github.com/en/rest/commits/commits#get-a-commit */ -export function getCommit(url: Link, token: Token): AxiosPromise { +export function getCommit( + url: Link, + token: Token, +): AxiosPromise { return apiRequestAuth(url, 'GET', token); } /** * Gets a specified commit comment. - * + * * Endpoint documentation: https://docs.github.com/en/rest/commits/comments#get-a-commit-comment - */ export function getCommitComment( url: Link, token: Token, -): AxiosPromise { +): AxiosPromise { return apiRequestAuth(url, 'GET', token); } @@ -163,7 +169,10 @@ export function getCommitComment( * * Endpoint documentation: https://docs.github.com/en/rest/releases/releases#get-a-release */ -export function getRelease(url: Link, token: Token): AxiosPromise { +export function getRelease( + url: Link, + token: Token, +): AxiosPromise { return apiRequestAuth(url, 'GET', token); } diff --git a/src/renderer/utils/api/types.ts b/src/renderer/utils/api/types.ts index 2ada18d0b..f184df434 100644 --- a/src/renderer/utils/api/types.ts +++ b/src/renderer/utils/api/types.ts @@ -1,4 +1,4 @@ -import type { components } from '@octokit/openapi-types'; +import type { Endpoints } from '@octokit/types'; import type { Link } from '../../types'; @@ -7,15 +7,23 @@ export interface GitHubRESTError { documentation_url: Link; } -export type NotificationThreadSubscription = - components['schemas']['thread-subscription']; +export type ListNotificationsForAuthenticatedUserResponse = + Endpoints['GET /notifications']['response']; -export type RawCommit = components['schemas']['commit']; +export type MarkNotificationThreadAsReadResponse = + Endpoints['PATCH /notifications/threads/{thread_id}']['response']; -export type RawCommitComment = components['schemas']['commit-comment']; +export type MarkNotificationThreadAsDoneResponse = + Endpoints['DELETE /notifications/threads/{thread_id}']['response']; -export type RawGitHubNotification = components['schemas']['thread']; +export type IgnoreNotificationThreadSubscriptionResponse = + Endpoints['PUT /notifications/threads/{thread_id}/subscription']['response']; -export type RawRelease = components['schemas']['release']; +export type GetCommitResponse = + Endpoints['GET /repos/{owner}/{repo}/commits/{ref}']['response']; -export type RawUser = components['schemas']['simple-user']; +export type GetCommitCommentResponse = + Endpoints['GET /repos/{owner}/{repo}/comments/{comment_id}']['response']; + +export type GetReleaseResponse = + Endpoints['GET /repos/{owner}/{repo}/releases/{release_id}']['response']; From 5193d1e3f49628e849939003b2efd7bc75a9121b Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 20 Jan 2026 16:11:27 -0500 Subject: [PATCH 2/6] add todo for future branch Signed-off-by: Adam Setch --- src/renderer/utils/api/client.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/renderer/utils/api/client.ts b/src/renderer/utils/api/client.ts index 00eb2c4ff..ae8b61ebc 100644 --- a/src/renderer/utils/api/client.ts +++ b/src/renderer/utils/api/client.ts @@ -19,11 +19,6 @@ import type { ListNotificationsForAuthenticatedUserResponse, MarkNotificationThreadAsDoneResponse, MarkNotificationThreadAsReadResponse, - NotificationThreadSubscription, - RawCommit, - RawCommitComment, - RawGitHubNotification, - RawRelease, } from './types'; import { isAnsweredDiscussionFeatureSupported } from '../features'; @@ -185,9 +180,11 @@ export function getRelease( /** * Get the `html_url` from the GitHub response + * */ export async function getHtmlUrl(url: Link, token: Token): Promise { try { + // TODO - Add explicit type for response shape const response = (await apiRequestAuth(url, 'GET', token)).data; return response.html_url; From 00bb2de127c27823e450fcab8f1d85d8b523a075 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 20 Jan 2026 16:14:14 -0500 Subject: [PATCH 3/6] add todo for future branch Signed-off-by: Adam Setch --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b3713597f..5848d2946 100644 --- a/package.json +++ b/package.json @@ -153,4 +153,4 @@ "*": "biome check --no-errors-on-unmatched", "*.{js,ts,tsx}": "pnpm test --findRelatedTests --passWithNoTests --updateSnapshot" } -} \ No newline at end of file +} From 967ce14582d22fcbe9ef86f5fc6e028817b412d6 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 20 Jan 2026 16:27:49 -0500 Subject: [PATCH 4/6] Merge branch 'main' into refactor/octokit-types-continued Signed-off-by: Adam Setch --- src/renderer/utils/api/types.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/renderer/utils/api/types.ts b/src/renderer/utils/api/types.ts index f184df434..ef01318aa 100644 --- a/src/renderer/utils/api/types.ts +++ b/src/renderer/utils/api/types.ts @@ -8,22 +8,28 @@ export interface GitHubRESTError { } export type ListNotificationsForAuthenticatedUserResponse = - Endpoints['GET /notifications']['response']; + Endpoints['GET /notifications']['response']['data']; export type MarkNotificationThreadAsReadResponse = - Endpoints['PATCH /notifications/threads/{thread_id}']['response']; + Endpoints['PATCH /notifications/threads/{thread_id}']['response']['data']; export type MarkNotificationThreadAsDoneResponse = - Endpoints['DELETE /notifications/threads/{thread_id}']['response']; + Endpoints['DELETE /notifications/threads/{thread_id}']['response']['data']; export type IgnoreNotificationThreadSubscriptionResponse = - Endpoints['PUT /notifications/threads/{thread_id}/subscription']['response']; + Endpoints['PUT /notifications/threads/{thread_id}/subscription']['response']['data']; export type GetCommitResponse = - Endpoints['GET /repos/{owner}/{repo}/commits/{ref}']['response']; + Endpoints['GET /repos/{owner}/{repo}/commits/{ref}']['response']['data']; export type GetCommitCommentResponse = - Endpoints['GET /repos/{owner}/{repo}/comments/{comment_id}']['response']; + Endpoints['GET /repos/{owner}/{repo}/comments/{comment_id}']['response']['data']; export type GetReleaseResponse = - Endpoints['GET /repos/{owner}/{repo}/releases/{release_id}']['response']; + Endpoints['GET /repos/{owner}/{repo}/releases/{release_id}']['response']['data']; + +export type RawGitHubNotification = + Endpoints['GET /notifications']['response']['data'][number]; + +// FIXME - replace this if possible +export type RawUser = Endpoints['GET /users/{username}']['response']['data']; From 320009782259072f9760b60ca7ab43d11cfbec54 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 21 Jan 2026 07:20:10 -0500 Subject: [PATCH 5/6] refactor types Signed-off-by: Adam Setch --- src/renderer/utils/api/client.ts | 3 ++- .../utils/api/graphql/generated/graphql.ts | 1 + src/renderer/utils/api/types.ts | 24 ++++++++++++------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/renderer/utils/api/client.ts b/src/renderer/utils/api/client.ts index ae8b61ebc..4f7d392c6 100644 --- a/src/renderer/utils/api/client.ts +++ b/src/renderer/utils/api/client.ts @@ -15,6 +15,7 @@ import type { GetCommitCommentResponse, GetCommitResponse, GetReleaseResponse, + HeadNotificationsResponse, IgnoreNotificationThreadSubscriptionResponse, ListNotificationsForAuthenticatedUserResponse, MarkNotificationThreadAsDoneResponse, @@ -56,7 +57,7 @@ import { export function headNotifications( hostname: Hostname, token: Token, -): AxiosPromise { +): AxiosPromise { const url = getGitHubAPIBaseUrl(hostname); url.pathname += 'notifications'; diff --git a/src/renderer/utils/api/graphql/generated/graphql.ts b/src/renderer/utils/api/graphql/generated/graphql.ts index 24969e990..57a1d9b18 100644 --- a/src/renderer/utils/api/graphql/generated/graphql.ts +++ b/src/renderer/utils/api/graphql/generated/graphql.ts @@ -21652,6 +21652,7 @@ export type PullRequestSuggestedReviewerActorsArgs = { before?: InputMaybe; first?: InputMaybe; last?: InputMaybe; + query?: InputMaybe; }; diff --git a/src/renderer/utils/api/types.ts b/src/renderer/utils/api/types.ts index ef01318aa..2c485baa0 100644 --- a/src/renderer/utils/api/types.ts +++ b/src/renderer/utils/api/types.ts @@ -1,3 +1,4 @@ +import type { components } from '@octokit/openapi-types'; import type { Endpoints } from '@octokit/types'; import type { Link } from '../../types'; @@ -10,12 +11,6 @@ export interface GitHubRESTError { export type ListNotificationsForAuthenticatedUserResponse = Endpoints['GET /notifications']['response']['data']; -export type MarkNotificationThreadAsReadResponse = - Endpoints['PATCH /notifications/threads/{thread_id}']['response']['data']; - -export type MarkNotificationThreadAsDoneResponse = - Endpoints['DELETE /notifications/threads/{thread_id}']['response']['data']; - export type IgnoreNotificationThreadSubscriptionResponse = Endpoints['PUT /notifications/threads/{thread_id}/subscription']['response']['data']; @@ -31,5 +26,18 @@ export type GetReleaseResponse = export type RawGitHubNotification = Endpoints['GET /notifications']['response']['data'][number]; -// FIXME - replace this if possible -export type RawUser = Endpoints['GET /users/{username}']['response']['data']; +export type RawUser = components['schemas']['simple-user']; + +/** + * These API endpoints don't return a response body + */ +// HEAD request - no response body +export type HeadNotificationsResponse = NoResponseBody; + +// Endpoints['PATCH /notifications/threads/{thread_id}']['response']['data']; +export type MarkNotificationThreadAsReadResponse = NoResponseBody; + +// Endpoints['DELETE /notifications/threads/{thread_id}']['response']['data'] +export type MarkNotificationThreadAsDoneResponse = NoResponseBody; + +type NoResponseBody = void; From 3a050b5514d76e4775ae8fdd64832fa43a847818 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 21 Jan 2026 07:29:49 -0500 Subject: [PATCH 6/6] refactor types Signed-off-by: Adam Setch --- src/renderer/utils/api/types.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/renderer/utils/api/types.ts b/src/renderer/utils/api/types.ts index 2c485baa0..d09cdd5e1 100644 --- a/src/renderer/utils/api/types.ts +++ b/src/renderer/utils/api/types.ts @@ -29,15 +29,16 @@ export type RawGitHubNotification = export type RawUser = components['schemas']['simple-user']; /** - * These API endpoints don't return a response body + * These API endpoints don't return a response body: + * - HEAD /notifications + * - Endpoints['PATCH /notifications/threads/{thread_id}']['response']['data'] + * - Endpoints['DELETE /notifications/threads/{thread_id}']['response']['data'] */ -// HEAD request - no response body -export type HeadNotificationsResponse = NoResponseBody; +// biome-ignore lint/suspicious/noConfusingVoidType: This endpoint has no response body +export type HeadNotificationsResponse = void; -// Endpoints['PATCH /notifications/threads/{thread_id}']['response']['data']; -export type MarkNotificationThreadAsReadResponse = NoResponseBody; +// biome-ignore lint/suspicious/noConfusingVoidType: This endpoint has no response body +export type MarkNotificationThreadAsReadResponse = void; -// Endpoints['DELETE /notifications/threads/{thread_id}']['response']['data'] -export type MarkNotificationThreadAsDoneResponse = NoResponseBody; - -type NoResponseBody = void; +// biome-ignore lint/suspicious/noConfusingVoidType: This endpoint has no response body +export type MarkNotificationThreadAsDoneResponse = void;