chore: close quality-gate coverage gaps (#1689) (#1766)
Some checks failed
Run install, format, lint, build, and test on every push / build (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish (push) Has been cancelled
Run install, format, lint, build, and test on every push / publish-github-container-registry (push) Has been cancelled

Closes #1689. Typecheck cli/tui src, add a core/ format+lint gate, and gate core/json + core/client coverage. See PR #1766 for the full review history.
This commit is contained in:
Cliff Hall 2026-07-24 17:20:12 -04:00 • committed by GitHub
commit 373f346e5f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 2210 additions and 467 deletions

View file

@ -16,7 +16,8 @@
],
"scripts": {
"build": "tsup",
"validate": "npm run format:check && npm run lint && npm run test",
"typecheck": "tsc --noEmit -p tsconfig.json",
"validate": "npm run format:check && npm run lint && npm run typecheck && npm run test",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "npm run test-servers:build && npm run build && vitest run --coverage",

View file

@ -120,6 +120,20 @@ type MethodOutcome =
| { kind: "result"; result: McpResponse; appInfo?: CliAppInfo }
| { kind: "emitted" };
/**
* Tear down a managed list state if it was created for this method call.
*
* The `managed*State` locals below are assigned inside the `runMethod` closure,
* so TypeScript's control-flow analysis keeps them narrowed to `null` at the
* outer `finally` block (a closure "might not have run"). Routing the teardown
* through this helper — whose parameter type is the shared `destroy()` shape —
* both documents that and calls `destroy()` on whatever the closure actually
* assigned at runtime, with no `as` cast.
*/
function destroyManagedState(state: { destroy(): void } | null): void {
state?.destroy();
}
async function callMethod(
serverConfig: MCPServerConfig,
serverSettings: InspectorServerSettings | undefined,
@ -370,10 +384,10 @@ async function callMethod(
await emitResult(outcome.result, outcome.appInfo, args);
}
} finally {
managedToolsState?.destroy();
managedResourcesState?.destroy();
managedResourceTemplatesState?.destroy();
managedPromptsState?.destroy();
destroyManagedState(managedToolsState);
destroyManagedState(managedResourcesState);
destroyManagedState(managedResourceTemplatesState);
destroyManagedState(managedPromptsState);
await inspectorClient.disconnect();
}
}

View file

@ -2,10 +2,24 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"noEmit": true,
// Match clients/web/tsconfig.app.json's module/lib *resolution* options so
// the imported `core/` sources are validated the same way web's own gate
// validates them: DOM lib + bundler resolution are what core/ (browser-side
// auth, DOM types) expects, and `noUncheckedIndexedAccess` is off because
// web's app config does not extend tsconfig.base — re-enabling it here would
// flag core/ issues web never gates. This does NOT mirror web's extra
// strictness flags (noUnusedLocals, verbatimModuleSyntax, ES2023 target,
// …), so cli/tui's own src is checked slightly more loosely than web's src.
"lib": ["ES2023", "DOM", "DOM.Iterable"],
"types": ["node"],
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"module": "ESNext",
"noUncheckedIndexedAccess": false,
"paths": {
"@inspector/core/*": ["../../core/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.test.ts", "build"]
"exclude": ["node_modules", "**/*.test.ts", "**/*.test.tsx", "build"]
}