mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
* Split speech session lifecycle * Split terminal output scheduler pipeline * Split mobile browser pane modules * Prune resolved max-lines suppressions * Split pane tree equalization logic * Extract mobile troubleshoot screen styles * Split external automation manager * Split main window service attachments * Split hosted review creation checks * Split automation dispatch event handling * Split settings navigation metadata * Split daemon initialization lifecycle * Split GitLab item dialog * Split relay dispatcher layers * Split mobile host screen * Retarget mobile view settings source test * Split runtime file client layers * Split ports panel layers * Split runtime environments pane layers * Split local PTY provider responsibilities * Split CDP bridge responsibilities * Split relay Git handler responsibilities * Track moved relay Git fetch audit * Split Linear item drawer responsibilities * Split telemetry event schema responsibilities * Split resource usage status responsibilities * Split remote terminal multiplexer responsibilities * Split Git worktree responsibilities * Split Codex hook service responsibilities * Keep mirrored hook trust type private * Split web runtime session responsibilities * Split GitHub project view read path * Fix F3-speech for #17123 * Fix F1-cycle for #17131 * Fix F4-navtest for #17157 * Fix F2-allowlist for #17161
154 lines
4.6 KiB
TypeScript
154 lines
4.6 KiB
TypeScript
import type {
|
|
GitHubProjectFieldValue,
|
|
GitHubProjectLabel,
|
|
GitHubProjectRow,
|
|
GitHubProjectRowItemType,
|
|
GitHubProjectUser
|
|
} from '../../../shared/github/project-types'
|
|
import type { GitHubProjectViewError } from '../../../shared/github/project-result-types'
|
|
import { driftError } from './project-error-classification'
|
|
import {
|
|
normalizeFieldValue,
|
|
normalizeLabel,
|
|
normalizeUser,
|
|
type RawFieldValue,
|
|
type RawLabel,
|
|
type RawUser
|
|
} from './project-view-field-normalization'
|
|
|
|
type RawContent = {
|
|
__typename?: string
|
|
id?: string
|
|
number?: number
|
|
title?: string
|
|
body?: string
|
|
url?: string
|
|
state?: string
|
|
stateReason?: string | null
|
|
isDraft?: boolean
|
|
repository?: { nameWithOwner?: string }
|
|
assignees?: { nodes?: RawUser[] }
|
|
labels?: { nodes?: RawLabel[] }
|
|
parent?: { number?: number; title?: string; url?: string } | null
|
|
issueType?: {
|
|
id?: string
|
|
name?: string
|
|
color?: string | null
|
|
description?: string | null
|
|
} | null
|
|
}
|
|
|
|
export type RawItem = {
|
|
id?: string
|
|
type?: string
|
|
updatedAt?: string
|
|
content?: RawContent | null
|
|
fieldValues?: {
|
|
nodes?: RawFieldValue[]
|
|
pageInfo?: { hasNextPage?: boolean }
|
|
}
|
|
}
|
|
|
|
type NormalizedItemOutcome =
|
|
| { ok: true; row: GitHubProjectRow }
|
|
| { ok: false; drift: GitHubProjectViewError }
|
|
|
|
function mapItemType(raw: string | undefined, hasContent: boolean): GitHubProjectRowItemType {
|
|
if (raw === 'ISSUE') {
|
|
return 'ISSUE'
|
|
}
|
|
if (raw === 'PULL_REQUEST') {
|
|
return 'PULL_REQUEST'
|
|
}
|
|
if (raw === 'DRAFT_ISSUE') {
|
|
return 'DRAFT_ISSUE'
|
|
}
|
|
if (raw === 'REDACTED' || !hasContent) {
|
|
return 'REDACTED'
|
|
}
|
|
// Unknown item type with content — treat as redacted rather than dropping.
|
|
return 'REDACTED'
|
|
}
|
|
|
|
export function normalizeItem(raw: RawItem, position: number): NormalizedItemOutcome {
|
|
if (!raw || typeof raw.id !== 'string') {
|
|
return {
|
|
ok: false,
|
|
drift: driftError('item missing id', { path: ['items', 'nodes', position, 'id'] })
|
|
}
|
|
}
|
|
if (raw.fieldValues?.pageInfo?.hasNextPage === true) {
|
|
return {
|
|
ok: false,
|
|
drift: driftError('item field values exceeded single page', {
|
|
path: ['items', 'nodes', position, 'fieldValues', 'pageInfo', 'hasNextPage']
|
|
})
|
|
}
|
|
}
|
|
const itemType = mapItemType(raw.type, raw.content !== null && raw.content !== undefined)
|
|
const content = raw.content ?? null
|
|
const assignees = (content?.assignees?.nodes ?? [])
|
|
.map(normalizeUser)
|
|
.filter((u): u is GitHubProjectUser => u !== null)
|
|
const labels = (content?.labels?.nodes ?? [])
|
|
.map(normalizeLabel)
|
|
.filter((l): l is GitHubProjectLabel => l !== null)
|
|
const parentIssue =
|
|
content?.parent &&
|
|
typeof content.parent.number === 'number' &&
|
|
typeof content.parent.title === 'string' &&
|
|
typeof content.parent.url === 'string'
|
|
? { number: content.parent.number, title: content.parent.title, url: content.parent.url }
|
|
: null
|
|
const issueType =
|
|
content?.issueType &&
|
|
typeof content.issueType.id === 'string' &&
|
|
typeof content.issueType.name === 'string'
|
|
? {
|
|
id: content.issueType.id,
|
|
name: content.issueType.name,
|
|
color: typeof content.issueType.color === 'string' ? content.issueType.color : null,
|
|
description:
|
|
typeof content.issueType.description === 'string' ? content.issueType.description : null
|
|
}
|
|
: null
|
|
const fieldValuesByFieldId: Record<string, GitHubProjectFieldValue> = {}
|
|
for (const fv of raw.fieldValues?.nodes ?? []) {
|
|
const normalized = normalizeFieldValue(fv)
|
|
if (normalized) {
|
|
fieldValuesByFieldId[normalized.fieldId] = normalized
|
|
}
|
|
}
|
|
const title =
|
|
itemType === 'REDACTED'
|
|
? 'Restricted item'
|
|
: typeof content?.title === 'string'
|
|
? content.title
|
|
: ''
|
|
const row: GitHubProjectRow = {
|
|
id: raw.id,
|
|
itemType,
|
|
content: {
|
|
number: typeof content?.number === 'number' ? content.number : null,
|
|
title,
|
|
body: typeof content?.body === 'string' ? content.body : null,
|
|
url: typeof content?.url === 'string' ? content.url : null,
|
|
state: typeof content?.state === 'string' ? content.state : null,
|
|
stateReason: typeof content?.stateReason === 'string' ? content.stateReason : null,
|
|
isDraft: typeof content?.isDraft === 'boolean' ? content.isDraft : null,
|
|
repository:
|
|
typeof content?.repository?.nameWithOwner === 'string'
|
|
? content.repository.nameWithOwner
|
|
: null,
|
|
assignees,
|
|
labels,
|
|
parentIssue,
|
|
issueType
|
|
},
|
|
fieldValuesByFieldId,
|
|
updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt : '',
|
|
position
|
|
}
|
|
return { ok: true, row }
|
|
}
|