mirror of
https://github.com/stablyai/orca.git
synced 2026-09-23 00:02:29 +00:00
refactor(integrations): split issue-tracker clients under the max-lines budget (#14704)
The GitLab, GitHub, Jira and Linear integration modules, their two IPC registrars, and the shared GitHub project types each carried a file-level `eslint-disable max-lines` and ran 351-614 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all eight suppressions and prunes their entries (341 -> 333). Pure move, no behavior change. Each client is cut along the seam it already had: per-operation modules for the issue APIs (create / update / comment / field options), and for Jira the request queue, site credential store, authenticated request, and site identity. The two IPC registrars keep their own handlers and delegate the rest to per-domain sub-registrars, so they remain real entry points rather than re-export shims. The IPC surface is proved intact rather than assumed: comparing (method, channel) multisets between HEAD and the split gives 52 registrations across 52 distinct channels on both sides. Provider-neutrality is preserved -- GitLab and GitHub keep separate, parallel module layouts rather than being merged behind a shared abstraction. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (the one remaining failure is a pre-existing load flake in an untouched file, green when re-run serially), no new runtime import cycles among 744 modules, and no lint suppression added anywhere.
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
// Why: the request half of the Project IPC contract, consumed mainly by main
|
||||
// and preload; kept apart from the ProjectV2 data model in `./project-types`
|
||||
// so renderer components importing domain shapes don't pull in arg payloads.
|
||||
import type { GitHubProjectFieldMutationValue, GitHubProjectOwnerType } from './project-types'
|
||||
import type { GitHubIssueUpdate } from '../issue-mutation-types'
|
||||
|
||||
// ─── IPC arg shapes (shared between main, preload, renderer) ──────────
|
||||
|
||||
export type GetProjectViewTableArgs = {
|
||||
owner: string
|
||||
ownerType: GitHubProjectOwnerType
|
||||
projectNumber: number
|
||||
/** GitHub host (e.g. GHES); absent means github.com. */
|
||||
host?: string
|
||||
/** View selection precedence: viewId > viewNumber > viewName > first
|
||||
* TABLE_LAYOUT view. */
|
||||
viewId?: string
|
||||
viewNumber?: number
|
||||
viewName?: string
|
||||
/** Ephemeral GitHub-search-syntax query that replaces the view's filter for
|
||||
* this fetch only. The view's stored filter on GitHub is not modified.
|
||||
* `undefined` uses the view's saved filter; `''` explicitly clears it for
|
||||
* this fetch and gets a distinct renderer cache key. */
|
||||
queryOverride?: string
|
||||
}
|
||||
|
||||
export type ProjectWorkItemDetailsBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
type: 'issue' | 'pr'
|
||||
}
|
||||
|
||||
export type UpdateProjectItemFieldArgs = {
|
||||
projectId: string
|
||||
host?: string
|
||||
itemId: string
|
||||
fieldId: string
|
||||
value: GitHubProjectFieldMutationValue
|
||||
}
|
||||
|
||||
export type ClearProjectItemFieldArgs = {
|
||||
projectId: string
|
||||
host?: string
|
||||
itemId: string
|
||||
fieldId: string
|
||||
}
|
||||
|
||||
export type UpdateIssueBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
updates: GitHubIssueUpdate & { body?: string }
|
||||
}
|
||||
|
||||
export type UpdatePullRequestBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
updates: { title?: string; body?: string; state?: 'open' | 'closed' }
|
||||
}
|
||||
|
||||
export type AddIssueCommentBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
body: string
|
||||
}
|
||||
|
||||
export type UpdateIssueCommentBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
commentId: number
|
||||
body: string
|
||||
}
|
||||
|
||||
export type DeleteIssueCommentBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
commentId: number
|
||||
}
|
||||
|
||||
export type ListLabelsBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
}
|
||||
|
||||
export type ListAssignableUsersBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
seedLogins?: string[]
|
||||
}
|
||||
|
||||
export type ListIssueTypesBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
}
|
||||
|
||||
export type UpdateIssueTypeBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
/** null clears the issue type. */
|
||||
issueTypeId: string | null
|
||||
}
|
||||
|
||||
export type ResolveProjectRefArgs = {
|
||||
input: string
|
||||
host?: string
|
||||
}
|
||||
|
||||
export type ListProjectViewsArgs = {
|
||||
owner: string
|
||||
ownerType: GitHubProjectOwnerType
|
||||
projectNumber: number
|
||||
host?: string
|
||||
}
|
||||
|
||||
export type ListAccessibleProjectsArgs = {
|
||||
/** GitHub host (e.g. GHES); absent means github.com. */
|
||||
host?: string
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// Why: the ok/error envelopes returned by Project IPC calls all share one
|
||||
// classified error, and they pull in cross-module work-item/comment/user types
|
||||
// that the ProjectV2 data model in `./project-types` never needs.
|
||||
import type { PRComment } from './comment-types'
|
||||
import type {
|
||||
GitHubIssueType,
|
||||
GitHubProjectOwnerType,
|
||||
GitHubProjectSummary,
|
||||
GitHubProjectTable,
|
||||
GitHubProjectViewSummary
|
||||
} from './project-types'
|
||||
import type { GitHubAssignableUser } from './pull-request-types'
|
||||
import type { GitHubWorkItemDetails } from './work-item-types'
|
||||
|
||||
// ─── Classified errors ─────────────────────────────────────────────────
|
||||
|
||||
export type GitHubProjectViewErrorType =
|
||||
| 'auth_required'
|
||||
| 'scope_missing'
|
||||
| 'not_found'
|
||||
| 'unsupported_layout'
|
||||
| 'too_large'
|
||||
| 'schema_drift'
|
||||
| 'validation_error'
|
||||
| 'network_error'
|
||||
| 'rate_limited'
|
||||
| 'unknown'
|
||||
|
||||
export type GitHubProjectViewError = {
|
||||
type: GitHubProjectViewErrorType
|
||||
message: string
|
||||
/** Populated when the error is classifiable from a GraphQL response. Never
|
||||
* includes tokens or full command stdout. */
|
||||
details?: { path?: (string | number)[]; code?: string }
|
||||
}
|
||||
|
||||
export type GetProjectViewTableResult =
|
||||
| { ok: true; data: GitHubProjectTable }
|
||||
| {
|
||||
ok: false
|
||||
error: GitHubProjectViewError
|
||||
/** Populated for the `too_large` case and best-effort for
|
||||
* `unsupported_layout` when a cheap count-only query succeeds. */
|
||||
totalCount?: number
|
||||
}
|
||||
|
||||
export type ListAccessibleProjectsResult =
|
||||
| {
|
||||
ok: true
|
||||
projects: GitHubProjectSummary[]
|
||||
/** Why: per-org discovery can partially fail (a single org 504s while
|
||||
* the rest succeed). The picker renders a banner listing the affected
|
||||
* org logins so the user knows their list is incomplete and can paste
|
||||
* a URL to reach missing projects. Empty when discovery was clean. */
|
||||
partialFailures?: { owner: string; message: string }[]
|
||||
}
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ResolveProjectRefResult =
|
||||
| {
|
||||
ok: true
|
||||
owner: string
|
||||
ownerType: GitHubProjectOwnerType
|
||||
number: number
|
||||
title: string
|
||||
host?: string
|
||||
// Why: when the input is a /views/{n} URL, surface the parsed view
|
||||
// number so the picker can skip the view-pick step and commit the
|
||||
// selection directly. Absent for owner/number shorthand and project
|
||||
// URLs without a /views/ segment.
|
||||
viewNumber?: number
|
||||
}
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ListProjectViewsResult =
|
||||
| { ok: true; views: GitHubProjectViewSummary[] }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ProjectWorkItemDetailsBySlugResult =
|
||||
| { ok: true; details: GitHubWorkItemDetails }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
// ─── Mutations ─────────────────────────────────────────────────────────
|
||||
|
||||
export type GitHubProjectMutationResult =
|
||||
| { ok: true }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type GitHubProjectCommentMutationResult =
|
||||
| { ok: true; comment: PRComment }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ListLabelsBySlugResult =
|
||||
| { ok: true; labels: string[] }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ListAssignableUsersBySlugResult =
|
||||
| { ok: true; users: GitHubAssignableUser[] }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ListIssueTypesBySlugResult =
|
||||
| { ok: true; types: GitHubIssueType[] }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
@@ -1,13 +1,8 @@
|
||||
/* eslint-disable max-lines -- Why: this module is the single source of truth for ProjectV2 shapes (settings, IPC payloads, view/field/value types) shared across main, preload, and renderer; splitting risks circular type imports. */
|
||||
// Why: ProjectV2 shapes are distinct enough from the issue/PR work-item types
|
||||
// that we keep them in a dedicated module. Preload and main-process callers
|
||||
// import from here directly — do not re-export through `./types.ts` just to
|
||||
// match the existing import block; routing through the issue types module
|
||||
// would obscure ownership of the Project surface.
|
||||
import type { PRComment } from './comment-types'
|
||||
import type { GitHubAssignableUser } from './pull-request-types'
|
||||
import type { GitHubWorkItemDetails } from './work-item-types'
|
||||
import type { GitHubIssueUpdate } from '../issue-mutation-types'
|
||||
|
||||
export type GitHubProjectViewLayout = 'TABLE_LAYOUT' | 'BOARD_LAYOUT' | 'ROADMAP_LAYOUT'
|
||||
export type GitHubProjectOwnerType = 'organization' | 'user'
|
||||
@@ -234,84 +229,6 @@ export type GitHubProjectSettings = {
|
||||
} | null
|
||||
}
|
||||
|
||||
// ─── Classified errors ─────────────────────────────────────────────────
|
||||
|
||||
export type GitHubProjectViewErrorType =
|
||||
| 'auth_required'
|
||||
| 'scope_missing'
|
||||
| 'not_found'
|
||||
| 'unsupported_layout'
|
||||
| 'too_large'
|
||||
| 'schema_drift'
|
||||
| 'validation_error'
|
||||
| 'network_error'
|
||||
| 'rate_limited'
|
||||
| 'unknown'
|
||||
|
||||
export type GitHubProjectViewError = {
|
||||
type: GitHubProjectViewErrorType
|
||||
message: string
|
||||
/** Populated when the error is classifiable from a GraphQL response. Never
|
||||
* includes tokens or full command stdout. */
|
||||
details?: { path?: (string | number)[]; code?: string }
|
||||
}
|
||||
|
||||
export type GetProjectViewTableResult =
|
||||
| { ok: true; data: GitHubProjectTable }
|
||||
| {
|
||||
ok: false
|
||||
error: GitHubProjectViewError
|
||||
/** Populated for the `too_large` case and best-effort for
|
||||
* `unsupported_layout` when a cheap count-only query succeeds. */
|
||||
totalCount?: number
|
||||
}
|
||||
|
||||
export type ListAccessibleProjectsResult =
|
||||
| {
|
||||
ok: true
|
||||
projects: GitHubProjectSummary[]
|
||||
/** Why: per-org discovery can partially fail (a single org 504s while
|
||||
* the rest succeed). The picker renders a banner listing the affected
|
||||
* org logins so the user knows their list is incomplete and can paste
|
||||
* a URL to reach missing projects. Empty when discovery was clean. */
|
||||
partialFailures?: { owner: string; message: string }[]
|
||||
}
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ResolveProjectRefResult =
|
||||
| {
|
||||
ok: true
|
||||
owner: string
|
||||
ownerType: GitHubProjectOwnerType
|
||||
number: number
|
||||
title: string
|
||||
host?: string
|
||||
// Why: when the input is a /views/{n} URL, surface the parsed view
|
||||
// number so the picker can skip the view-pick step and commit the
|
||||
// selection directly. Absent for owner/number shorthand and project
|
||||
// URLs without a /views/ segment.
|
||||
viewNumber?: number
|
||||
}
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ListProjectViewsResult =
|
||||
| { ok: true; views: GitHubProjectViewSummary[] }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ProjectWorkItemDetailsBySlugResult =
|
||||
| { ok: true; details: GitHubWorkItemDetails }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
// ─── Mutations ─────────────────────────────────────────────────────────
|
||||
|
||||
export type GitHubProjectMutationResult =
|
||||
| { ok: true }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type GitHubProjectCommentMutationResult =
|
||||
| { ok: true; comment: PRComment }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type GitHubProjectFieldMutationValue =
|
||||
| { kind: 'single-select'; optionId: string }
|
||||
| { kind: 'iteration'; iterationId: string }
|
||||
@@ -319,142 +236,3 @@ export type GitHubProjectFieldMutationValue =
|
||||
| { kind: 'number'; number: number }
|
||||
/** YYYY-MM-DD. */
|
||||
| { kind: 'date'; date: string }
|
||||
|
||||
export type ListLabelsBySlugResult =
|
||||
| { ok: true; labels: string[] }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ListAssignableUsersBySlugResult =
|
||||
| { ok: true; users: GitHubAssignableUser[] }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
export type ListIssueTypesBySlugResult =
|
||||
| { ok: true; types: GitHubIssueType[] }
|
||||
| { ok: false; error: GitHubProjectViewError }
|
||||
|
||||
// ─── IPC arg shapes (shared between main, preload, renderer) ──────────
|
||||
|
||||
export type GetProjectViewTableArgs = {
|
||||
owner: string
|
||||
ownerType: GitHubProjectOwnerType
|
||||
projectNumber: number
|
||||
/** GitHub host (e.g. GHES); absent means github.com. */
|
||||
host?: string
|
||||
/** View selection precedence: viewId > viewNumber > viewName > first
|
||||
* TABLE_LAYOUT view. */
|
||||
viewId?: string
|
||||
viewNumber?: number
|
||||
viewName?: string
|
||||
/** Ephemeral GitHub-search-syntax query that replaces the view's filter for
|
||||
* this fetch only. The view's stored filter on GitHub is not modified.
|
||||
* `undefined` uses the view's saved filter; `''` explicitly clears it for
|
||||
* this fetch and gets a distinct renderer cache key. */
|
||||
queryOverride?: string
|
||||
}
|
||||
|
||||
export type ProjectWorkItemDetailsBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
type: 'issue' | 'pr'
|
||||
}
|
||||
|
||||
export type UpdateProjectItemFieldArgs = {
|
||||
projectId: string
|
||||
host?: string
|
||||
itemId: string
|
||||
fieldId: string
|
||||
value: GitHubProjectFieldMutationValue
|
||||
}
|
||||
|
||||
export type ClearProjectItemFieldArgs = {
|
||||
projectId: string
|
||||
host?: string
|
||||
itemId: string
|
||||
fieldId: string
|
||||
}
|
||||
|
||||
export type UpdateIssueBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
updates: GitHubIssueUpdate & { body?: string }
|
||||
}
|
||||
|
||||
export type UpdatePullRequestBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
updates: { title?: string; body?: string; state?: 'open' | 'closed' }
|
||||
}
|
||||
|
||||
export type AddIssueCommentBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
body: string
|
||||
}
|
||||
|
||||
export type UpdateIssueCommentBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
commentId: number
|
||||
body: string
|
||||
}
|
||||
|
||||
export type DeleteIssueCommentBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
commentId: number
|
||||
}
|
||||
|
||||
export type ListLabelsBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
}
|
||||
|
||||
export type ListAssignableUsersBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
seedLogins?: string[]
|
||||
}
|
||||
|
||||
export type ListIssueTypesBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
}
|
||||
|
||||
export type UpdateIssueTypeBySlugArgs = {
|
||||
owner: string
|
||||
repo: string
|
||||
host?: string
|
||||
number: number
|
||||
/** null clears the issue type. */
|
||||
issueTypeId: string | null
|
||||
}
|
||||
|
||||
export type ResolveProjectRefArgs = {
|
||||
input: string
|
||||
host?: string
|
||||
}
|
||||
|
||||
export type ListProjectViewsArgs = {
|
||||
owner: string
|
||||
ownerType: GitHubProjectOwnerType
|
||||
projectNumber: number
|
||||
host?: string
|
||||
}
|
||||
|
||||
export type ListAccessibleProjectsArgs = {
|
||||
/** GitHub host (e.g. GHES); absent means github.com. */
|
||||
host?: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user