mirror of
https://github.com/stablyai/orca.git
synced 2026-10-01 16:02:03 +00:00
#14397 split `shared/types.ts` into 46 per-domain modules but kept the path as a re-export barrel so the import sites did not have to change. This removes the barrel: every consumer now imports from the module that actually declares the type, and `src/shared/types.ts` is deleted. Barrels hide where a type lives, make every consumer look like it depends on the whole domain, and let an unrelated edit invalidate a module that ~2,000 files transitively import. 2,323 import declarations across 2,321 files. Rewritten mechanically: each specifier was resolved to an absolute path via the TypeScript AST and recomputed, rather than string-substituted, so alias forms (`@/../../shared/ types`) and per-specifier `type` modifiers survive. Four cases the mechanical pass had to handle, each found by a gate rather than by reading the diff: - Modules inside `src/shared` import the barrel as `./types`, not `shared/types`. A pre-filter on the latter string skipped 176 of them and left imports dangling at a deleted file, which surfaced as confusing `Property 'x' is optional in type 'Repo' but required in Pick<Repo, ...>` errors rather than "module not found". - The barrel RENAMED one type on the way through (`WorkspaceSource as WorkspaceCreateTelemetrySource`), so the original name in the owning module has to be re-aliased at each consumer. - Three test files put `;(globalThis as ...)` on the line after the import. TypeScript parses that `;` as the import statement's terminator, so replacing through `statement.getEnd()` deletes it and breaks ASI. The rewrite now stops at the module specifier. - A file that already imported directly from a module got a SECOND import from it, because the barrel re-exported those same names — which trips `import/no-duplicates` under `--deny-warnings`. A post-pass merges declarations sharing a specifier and type-only-ness; the `import type` plus `import` pair from one module is left alone, since that form is allowed. Splitting one barrel import into several genuinely adds lines, which pushed `terminal-layout-pty-ownership.ts` to 301 counted lines: its 107-character import must wrap, and neither local type collapses onto one line (101 and 116 characters). Rather than contort a type declaration to fit a line budget, `collectLeafIds` and `pruneLeaves` move to `terminal-pane-layout-tree.ts` — they are pure structural operations on the layout tree and independent of PTY ownership. `visible-worktrees.ts` similarly loses its own mini-barrel re-export of `isDefaultBranchWorkspace`, with the four real consumers repointed at the declaring module. No `max-lines` bypass added. Verified: cold `tsc --noEmit` green on node, cli, and web (buildinfo deleted first — these projects are `composite: true` and reuse stale caches); the full `pnpm lint` green, not just bare oxlint — the narrower local check is what let the duplicate imports reach CI; max-lines ratchet OK at 344.
133 lines
4.1 KiB
TypeScript
133 lines
4.1 KiB
TypeScript
import { tmpdir } from 'node:os'
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
import { getDefaultSettings } from '../../shared/constants'
|
|
import type { GlobalSettings } from '../../shared/global-settings-types'
|
|
import { pluginManifestSchema } from '../../shared/plugins/plugin-manifest'
|
|
import type { Store } from '../persistence'
|
|
import { applyPluginConsent, applyPluginEnablement } from './plugin-enablement'
|
|
import type { ValidDiscoveredPlugin } from './plugin-discovery'
|
|
import type { PluginService } from './plugin-service'
|
|
|
|
const pluginKey = 'orca-samples.demo'
|
|
const manifest = pluginManifestSchema.parse({
|
|
manifestVersion: 1,
|
|
id: 'demo',
|
|
publisher: 'orca-samples',
|
|
name: 'Demo',
|
|
version: '1.0.0',
|
|
engines: { orca: '>=1.0.0' },
|
|
pluginApi: 1,
|
|
contributes: {},
|
|
capabilities: []
|
|
})
|
|
|
|
function createStore(): {
|
|
store: Store
|
|
getSettings: () => GlobalSettings
|
|
updateSettings: ReturnType<typeof vi.fn>
|
|
} {
|
|
let settings = getDefaultSettings(tmpdir())
|
|
const updateSettings = vi.fn((updates: Partial<GlobalSettings>) => {
|
|
settings = { ...settings, ...updates }
|
|
})
|
|
return {
|
|
store: { getSettings: () => settings, updateSettings } as unknown as Store,
|
|
getSettings: () => settings,
|
|
updateSettings
|
|
}
|
|
}
|
|
|
|
function createPluginService(
|
|
getFingerprint: () => string,
|
|
overrides: Partial<ValidDiscoveredPlugin> = {}
|
|
): PluginService {
|
|
return {
|
|
findValidPlugin: (requestedKey: string) =>
|
|
requestedKey === pluginKey
|
|
? {
|
|
pluginKey,
|
|
rootDir: tmpdir(),
|
|
manifest,
|
|
consentFingerprint: getFingerprint(),
|
|
consentContentHash: null,
|
|
contentHash: null,
|
|
isDev: true,
|
|
...overrides
|
|
}
|
|
: null,
|
|
reconcileActivationState: vi.fn().mockResolvedValue(undefined)
|
|
} as unknown as PluginService
|
|
}
|
|
|
|
describe('applyPluginConsent', () => {
|
|
it('stores approval only for the fingerprint the user reviewed', async () => {
|
|
const harness = createStore()
|
|
const pluginService = createPluginService(() => 'sha256-reviewed')
|
|
|
|
await applyPluginConsent({
|
|
store: harness.store,
|
|
pluginService,
|
|
pluginKey,
|
|
reviewedFingerprint: 'sha256-reviewed',
|
|
decision: 'approve'
|
|
})
|
|
|
|
expect(harness.getSettings().pluginConsents[pluginKey]).toBe('sha256-reviewed')
|
|
expect(harness.getSettings().disabledPlugins).not.toContain(pluginKey)
|
|
})
|
|
|
|
it('rejects a stale review after a same-key plugin update without writing settings', async () => {
|
|
const harness = createStore()
|
|
let currentFingerprint = 'sha256-reviewed-v1'
|
|
const pluginService = createPluginService(() => currentFingerprint)
|
|
currentFingerprint = 'sha256-current-v2'
|
|
|
|
await expect(
|
|
applyPluginConsent({
|
|
store: harness.store,
|
|
pluginService,
|
|
pluginKey,
|
|
reviewedFingerprint: 'sha256-reviewed-v1',
|
|
decision: 'approve'
|
|
})
|
|
).rejects.toThrow('changed since its permissions were reviewed')
|
|
|
|
expect(harness.updateSettings).not.toHaveBeenCalled()
|
|
expect(harness.getSettings().pluginConsents[pluginKey]).toBeUndefined()
|
|
})
|
|
|
|
it('allows a stale dialog to keep the newer plugin disabled', async () => {
|
|
const harness = createStore()
|
|
const pluginService = createPluginService(() => 'sha256-current-v2')
|
|
|
|
await applyPluginConsent({
|
|
store: harness.store,
|
|
pluginService,
|
|
pluginKey,
|
|
reviewedFingerprint: 'sha256-reviewed-v1',
|
|
decision: 'keep-disabled'
|
|
})
|
|
|
|
expect(harness.getSettings().disabledPlugins).toContain(pluginKey)
|
|
expect(pluginService.reconcileActivationState).toHaveBeenCalledOnce()
|
|
})
|
|
})
|
|
|
|
describe('applyPluginEnablement', () => {
|
|
it('does not persist unknown plugin identities', async () => {
|
|
const harness = createStore()
|
|
const pluginService = createPluginService(() => 'sha256-current')
|
|
|
|
await expect(
|
|
applyPluginEnablement({
|
|
store: harness.store,
|
|
pluginService,
|
|
pluginKey: 'orca-samples.unknown',
|
|
enabled: false
|
|
})
|
|
).rejects.toThrow('unknown plugin')
|
|
|
|
expect(harness.updateSettings).not.toHaveBeenCalled()
|
|
})
|
|
})
|