mirror of
https://github.com/stablyai/orca.git
synced 2026-11-03 02:27:43 +00:00
`src/shared` is a flat directory of ~1,150 entries. The worktree, github, and
linear domains accounted for 71 of them, so finding the module you wanted meant
scanning a wall of same-prefixed filenames.
Move each domain into its own folder and drop the now-redundant prefix:
src/shared/github-pr-types.ts -> src/shared/github/pull-request-types.ts
src/shared/worktree-id.ts -> src/shared/worktree/id.ts
src/shared/linear-links.ts -> src/shared/linear/links.ts
This follows the existing `network/` and `new-workspace/` convention in the
same directory, which also drop the prefix inside the folder.
Whole clusters move, including tests. Foldering only part of a domain would be
worse than flat: a reader would have to check both `github/` and the flat
directory, and `github-auth-types.ts` / `github-project-types.ts` are type
modules that belong with the rest. No files with these prefixes remain flat.
Import specifiers were rewritten by resolving each one to an absolute path and
recomputing it, not by string substitution, so the `@/../../shared/...` alias
forms are handled correctly. 501 specifiers across 298 files.
Two things `tsc` cannot catch, handled explicitly:
- `github-project-types.ts` carries its own `max-lines` bypass, so its baseline
entry is REPOINTED to the new path rather than pruned. Pruning would drop the
bypass and then flag the new path as a fresh violation. Ratchet stays at 345.
- `mobile/` is outside `pnpm typecheck` and cannot be typechecked here
(`mobile/node_modules` is empty). Instead every relative specifier in the repo
was resolved against the filesystem: 174 unresolved before this change and 174
after — identical, so nothing broke in mobile either.
The pinned `tests/e2e/.cross-version-checkouts` fixtures are deliberately NOT
rewritten; they are a snapshot of an older release and still reference the old
paths.
Verified: cold `tsc --noEmit` green on node, cli, and web (buildinfo deleted
first — these projects are `composite: true` and reuse stale caches).
68 lines
2.9 KiB
TypeScript
68 lines
2.9 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { classifyGitHubUnavailable, isGitHubUnavailableError } from './api-availability'
|
|
|
|
describe('classifyGitHubUnavailable', () => {
|
|
it('classifies HTTP 5xx outages as server_error', () => {
|
|
expect(classifyGitHubUnavailable('HTTP 503: Service Unavailable')).toBe('server_error')
|
|
expect(classifyGitHubUnavailable('gh: Command failed: HTTP 502 Bad Gateway')).toBe(
|
|
'server_error'
|
|
)
|
|
expect(classifyGitHubUnavailable('GitHub API error: 500 Internal Server Error')).toBe(
|
|
'server_error'
|
|
)
|
|
expect(classifyGitHubUnavailable('The service is temporarily unavailable')).toBe('server_error')
|
|
})
|
|
|
|
it('classifies transport failures as network', () => {
|
|
for (const message of [
|
|
'request to https://api.github.com failed, reason: getaddrinfo ENOTFOUND api.github.com',
|
|
'error connecting to api.github.com\ncheck your internet connection or GitHub status',
|
|
'dial tcp: lookup api.github.com: no such host',
|
|
'connect ETIMEDOUT 140.82.112.5:443',
|
|
'TimeoutError: request aborted',
|
|
'NetworkError when attempting to fetch resource',
|
|
'network unavailable',
|
|
'fetch failed',
|
|
'socket hang up',
|
|
'could not resolve host: api.github.com',
|
|
'connection refused'
|
|
]) {
|
|
expect(classifyGitHubUnavailable(message)).toBe('network')
|
|
}
|
|
})
|
|
|
|
it('classifies rate limiting as rate_limited (even when it carries HTTP 403)', () => {
|
|
expect(classifyGitHubUnavailable('HTTP 403: API rate limit exceeded')).toBe('rate_limited')
|
|
expect(classifyGitHubUnavailable('You have exceeded a secondary rate limit')).toBe(
|
|
'rate_limited'
|
|
)
|
|
expect(classifyGitHubUnavailable('HTTP 429 Too Many Requests')).toBe('rate_limited')
|
|
})
|
|
|
|
it('returns null for non-reachability failures', () => {
|
|
expect(classifyGitHubUnavailable('HTTP 403: Resource not accessible by integration')).toBeNull()
|
|
expect(classifyGitHubUnavailable('HTTP 404: Not Found')).toBeNull()
|
|
expect(classifyGitHubUnavailable('could not resolve to a Repository with the name')).toBeNull()
|
|
expect(
|
|
classifyGitHubUnavailable(
|
|
"GraphQL: Could not resolve to a Repository with the name 'network'."
|
|
)
|
|
).toBeNull()
|
|
expect(classifyGitHubUnavailable('gh auth login required')).toBeNull()
|
|
expect(classifyGitHubUnavailable('')).toBeNull()
|
|
})
|
|
|
|
it('does not misread unrelated 3-digit numbers as a server outage', () => {
|
|
expect(classifyGitHubUnavailable('found 512 pull requests')).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('isGitHubUnavailableError', () => {
|
|
it('detects reachability failures from Error objects and strings', () => {
|
|
expect(isGitHubUnavailableError(new Error('HTTP 503: Service Unavailable'))).toBe(true)
|
|
expect(isGitHubUnavailableError('fetch failed')).toBe(true)
|
|
expect(isGitHubUnavailableError(new Error('HTTP 404: Not Found'))).toBe(false)
|
|
expect(isGitHubUnavailableError(null)).toBe(false)
|
|
})
|
|
})
|