mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-13 23:46:06 +00:00
chore(tooling): enforce no-floating-promises and drop DOM globals from Node-side typechecking (#104422)
* chore(lint): enforce no-floating-promises repo-wide * feat(tooling): split DOM globals out of the Node-side typecheck program tsconfig.core.json now compiles src/ + packages/ with lib ES2023; new tsconfig.ui.json owns ui/ with DOM. Web-global names used by Node code alias to canonical undici/stream-web types; highlight.js loads through a validated narrow API because its d.ts force-includes lib.dom. Boundary, sparse-guard, changed-lane routing, and profile lanes cover the new ui graph. * chore(deps): declare undici-types and teach knip about the highlight.js runtime require * ci: retrigger dropped pull_request synchronize event * refactor(types): derive web-global aliases from @types/node fetch globals, drop undici-types dep * ci: retrigger after dependency guard cleared * fix(scripts): add ui lane to changed-lanes declaration union
This commit is contained in:
committed by
GitHub
parent
13817a6108
commit
ae12413ee2
2
.github/instructions/copilot.instructions.md
vendored
2
.github/instructions/copilot.instructions.md
vendored
@@ -56,7 +56,7 @@
|
||||
|
||||
- **Package manager**: pnpm (`pnpm install`)
|
||||
- **Dev**: `pnpm openclaw ...` or `pnpm dev`
|
||||
- **Type-check**: `pnpm tsgo` (core production), `pnpm tsgo:prod` (core + extension production), `pnpm check:test-types` (tests)
|
||||
- **Type-check**: `pnpm tsgo` (core production), `pnpm tsgo:prod` (core + UI + extension production), `pnpm check:test-types` (tests)
|
||||
- **Lint/format**: `pnpm check`
|
||||
- **Tests**: `pnpm test`
|
||||
- **Build**: `pnpm build`
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"typescript/no-empty-object-type": ["error", { "allowInterfaces": "with-single-extends" }],
|
||||
"typescript/no-explicit-any": "error",
|
||||
"typescript/no-extraneous-class": "error",
|
||||
"typescript/no-floating-promises": "error",
|
||||
"typescript/no-import-type-side-effects": "error",
|
||||
"typescript/no-meaningless-void-operator": "error",
|
||||
"typescript/no-misused-promises": "error",
|
||||
@@ -209,15 +210,14 @@
|
||||
"dist/",
|
||||
"dist-runtime/",
|
||||
"docs/_layouts/",
|
||||
"**/a2ui.bundle.js",
|
||||
"extensions/diffs/assets/viewer-runtime.js",
|
||||
"extensions/diffs-language-pack/assets/viewer-runtime.js",
|
||||
"extensions/canvas/src/host/a2ui/a2ui.bundle.js",
|
||||
"node_modules/",
|
||||
"patches/",
|
||||
"pnpm-lock.yaml",
|
||||
"skills/**",
|
||||
"src/auto-reply/reply/export-html/template.js",
|
||||
"src/canvas-host/a2ui/a2ui.bundle.js",
|
||||
"vendor/",
|
||||
"**/.cache/**",
|
||||
"**/.openclaw-runtime-deps-copy-*/**",
|
||||
|
||||
@@ -145,6 +145,9 @@ const config = {
|
||||
"@mistralai/mistralai",
|
||||
"cross-spawn",
|
||||
"file-type",
|
||||
// Loaded via createRequire in src/agents/utils/syntax-highlight.ts because its
|
||||
// d.ts force-includes lib.dom; knip cannot see the dynamic require.
|
||||
"highlight.js",
|
||||
"playwright-core",
|
||||
"partial-json",
|
||||
"sqlite-vec",
|
||||
|
||||
@@ -1960,7 +1960,7 @@
|
||||
"tsgo:extensions": "node scripts/run-tsgo.mjs -p tsconfig.extensions.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions.tsbuildinfo",
|
||||
"tsgo:extensions:all": "node scripts/run-tsgo.mjs -b tsconfig.extensions.projects.json",
|
||||
"tsgo:extensions:test": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo",
|
||||
"tsgo:prod": "pnpm tsgo:core && pnpm tsgo:extensions",
|
||||
"tsgo:prod": "pnpm tsgo:core && pnpm tsgo:ui && pnpm tsgo:extensions",
|
||||
"tsgo:profile": "node scripts/profile-tsgo.mjs",
|
||||
"tsgo:scripts": "node scripts/run-tsgo.mjs -p tsconfig.scripts.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/scripts.tsbuildinfo",
|
||||
"tsgo:test": "pnpm tsgo:core:test && pnpm tsgo:extensions:test && pnpm tsgo:test:root",
|
||||
@@ -1969,6 +1969,7 @@
|
||||
"tsgo:test:root": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.root.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-root.tsbuildinfo",
|
||||
"tsgo:test:src": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.src.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-src.tsbuildinfo",
|
||||
"tsgo:test:ui": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.ui.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-ui.tsbuildinfo",
|
||||
"tsgo:ui": "node scripts/run-tsgo.mjs -p tsconfig.ui.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/ui.tsbuildinfo",
|
||||
"tui": "node scripts/run-node.mjs tui",
|
||||
"tui:dev": "node scripts/run-with-env.mjs OPENCLAW_PROFILE=dev -- node scripts/run-node.mjs --dev tui",
|
||||
"tui:pty:test:watch": "node --import tsx scripts/dev/tui-pty-test-watch.ts",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export type ChangedLane =
|
||||
| "core"
|
||||
| "coreTests"
|
||||
| "ui"
|
||||
| "extensions"
|
||||
| "extensionTests"
|
||||
| "scripts"
|
||||
|
||||
@@ -12,7 +12,8 @@ const RAW_SYNC_CHANGED_LANES_ENV = "OPENCLAW_CHANGED_LANES_RAW_SYNC";
|
||||
const DOCS_PATH_RE = /^(?:docs\/|README\.md$|AGENTS\.md$|.*\.mdx?$)/u;
|
||||
const APP_PATH_RE = /^(?:apps\/|Swabble\/|appcast\.xml$)/u;
|
||||
const EXTENSION_PATH_RE = /^extensions\/[^/]+(?:\/|$)/u;
|
||||
const CORE_PATH_RE = /^(?:src\/|ui\/|packages\/)/u;
|
||||
const CORE_PATH_RE = /^(?:src\/|packages\/)/u;
|
||||
const UI_PATH_RE = /^(?:ui\/|tsconfig\.ui\.json$)/u;
|
||||
const SCRIPTS_TYPECHECK_PATH_RE =
|
||||
/^(?:scripts\/.*\.(?:[cm]?ts|[cm]?tsx)|tsconfig\.scripts\.json)$/u;
|
||||
const TEST_ROOT_TYPECHECK_PATH_RE =
|
||||
@@ -58,7 +59,7 @@ export const RELEASE_METADATA_PATHS = new Set([
|
||||
"package.json",
|
||||
]);
|
||||
|
||||
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "scripts" | "testRoot" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
|
||||
/** @typedef {"core" | "coreTests" | "ui" | "extensions" | "extensionTests" | "scripts" | "testRoot" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
@@ -87,6 +88,7 @@ export function createEmptyChangedLanes() {
|
||||
return {
|
||||
core: false,
|
||||
coreTests: false,
|
||||
ui: false,
|
||||
extensions: false,
|
||||
extensionTests: false,
|
||||
scripts: false,
|
||||
@@ -218,6 +220,18 @@ export function detectChangedLanes(changedPaths, options = {}) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (UI_PATH_RE.test(changedPath)) {
|
||||
if (isChangedLaneTestPath(changedPath)) {
|
||||
lanes.coreTests = true;
|
||||
reasons.push(`${changedPath}: UI test`);
|
||||
} else {
|
||||
lanes.ui = true;
|
||||
lanes.coreTests = true;
|
||||
reasons.push(`${changedPath}: UI production`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (APP_PATH_RE.test(changedPath)) {
|
||||
lanes.apps = true;
|
||||
reasons.push(`${changedPath}: app surface`);
|
||||
|
||||
@@ -385,6 +385,9 @@ export function createChangedCheckPlan(result, options = {}) {
|
||||
if (lanes.coreTests) {
|
||||
addTypecheck("typecheck core tests", ["tsgo:core:test"]);
|
||||
}
|
||||
if (lanes.ui) {
|
||||
addTypecheck("typecheck UI", ["tsgo:ui"]);
|
||||
}
|
||||
if (lanes.extensions) {
|
||||
addTypecheck("typecheck extensions", ["tsgo:extensions"]);
|
||||
}
|
||||
@@ -398,7 +401,7 @@ export function createChangedCheckPlan(result, options = {}) {
|
||||
addTypecheck("typecheck test root", ["tsgo:test:root"]);
|
||||
}
|
||||
|
||||
if (lanes.core || lanes.coreTests) {
|
||||
if (lanes.core || lanes.coreTests || lanes.ui) {
|
||||
const coreLintCommand = createTargetedCoreLintCommand(result.paths, baseEnv);
|
||||
if (coreLintCommand) {
|
||||
addCommand(
|
||||
|
||||
@@ -10,6 +10,7 @@ const tsgoPath = path.join(repoRoot, "node_modules", ".bin", "tsgo");
|
||||
|
||||
const coreGraphs = [
|
||||
{ name: "core", config: "tsconfig.core.json" },
|
||||
{ name: "ui", config: "tsconfig.ui.json" },
|
||||
{ name: "core-test", config: "test/tsconfig/tsconfig.core.test.json" },
|
||||
{ name: "core-test-agents", config: "test/tsconfig/tsconfig.core.test.agents.json" },
|
||||
{ name: "core-test-non-agents", config: "test/tsconfig/tsconfig.core.test.non-agents.json" },
|
||||
|
||||
@@ -12,14 +12,13 @@ const CORE_TEST_CONFIGS = new Set([
|
||||
]);
|
||||
|
||||
const CORE_PROD_CONFIGS = new Set(["tsconfig.core.json"]);
|
||||
const UI_PROD_CONFIGS = new Set(["tsconfig.ui.json"]);
|
||||
const TSGO_SPARSE_SKIP_ENV_KEY = "OPENCLAW_TSGO_SPARSE_SKIP";
|
||||
const CORE_SPARSE_ROOTS = ["packages", "ui/config", "ui/src"];
|
||||
const CORE_PROD_SPARSE_ROOTS = ["packages"];
|
||||
const UI_PROD_SPARSE_ROOTS = ["packages", "src", "ui/config", "ui/src"];
|
||||
const CORE_TEST_SPARSE_ROOTS = ["packages", "ui/config", "ui/src"];
|
||||
|
||||
const CORE_PROD_REQUIRED_PATHS = [
|
||||
{
|
||||
path: "apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/tool-display.json",
|
||||
whenPresent: "ui/src/ui/tool-display.ts",
|
||||
},
|
||||
{
|
||||
path: "scripts/lib/bundled-runtime-sidecar-paths.json",
|
||||
whenPresent: "src/plugins/runtime-sidecar-paths.ts",
|
||||
@@ -42,6 +41,13 @@ const CORE_PROD_REQUIRED_PATHS = [
|
||||
},
|
||||
];
|
||||
|
||||
const UI_PROD_REQUIRED_PATHS = [
|
||||
{
|
||||
path: "apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/tool-display.json",
|
||||
whenPresent: "ui/src/lib/chat/tool-display.ts",
|
||||
},
|
||||
];
|
||||
|
||||
const CORE_TEST_REQUIRED_PATHS = [
|
||||
"packages/plugin-package-contract/src/index.ts",
|
||||
"ui/config/control-ui-chunking.ts",
|
||||
@@ -85,7 +91,9 @@ export function getSparseTsgoGuardError(
|
||||
const projectName = projectPath ? path.basename(projectPath) : null;
|
||||
if (
|
||||
!projectName ||
|
||||
(!CORE_PROD_CONFIGS.has(projectName) && !CORE_TEST_CONFIGS.has(projectName)) ||
|
||||
(!CORE_PROD_CONFIGS.has(projectName) &&
|
||||
!UI_PROD_CONFIGS.has(projectName) &&
|
||||
!CORE_TEST_CONFIGS.has(projectName)) ||
|
||||
isMetadataOnlyCommand(args)
|
||||
) {
|
||||
return null;
|
||||
@@ -118,8 +126,14 @@ export function getSparseTsgoGuardError(
|
||||
}
|
||||
|
||||
function getRequiredSparseRootsForProject(projectName) {
|
||||
if (CORE_PROD_CONFIGS.has(projectName) || CORE_TEST_CONFIGS.has(projectName)) {
|
||||
return CORE_SPARSE_ROOTS;
|
||||
if (CORE_PROD_CONFIGS.has(projectName)) {
|
||||
return CORE_PROD_SPARSE_ROOTS;
|
||||
}
|
||||
if (UI_PROD_CONFIGS.has(projectName)) {
|
||||
return UI_PROD_SPARSE_ROOTS;
|
||||
}
|
||||
if (CORE_TEST_CONFIGS.has(projectName)) {
|
||||
return CORE_TEST_SPARSE_ROOTS;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@@ -129,6 +143,9 @@ function getRequiredPathsForProject(projectName, cwd, fileExists) {
|
||||
if (CORE_PROD_CONFIGS.has(projectName)) {
|
||||
requiredPaths.push(...conditionalRequiredPaths(CORE_PROD_REQUIRED_PATHS, cwd, fileExists));
|
||||
}
|
||||
if (UI_PROD_CONFIGS.has(projectName)) {
|
||||
requiredPaths.push(...conditionalRequiredPaths(UI_PROD_REQUIRED_PATHS, cwd, fileExists));
|
||||
}
|
||||
if (CORE_TEST_CONFIGS.has(projectName)) {
|
||||
requiredPaths.push(...CORE_TEST_REQUIRED_PATHS);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ const GRAPH_DEFINITIONS = {
|
||||
config: "tsconfig.core.json",
|
||||
description: "core production graph",
|
||||
},
|
||||
ui: {
|
||||
config: "tsconfig.ui.json",
|
||||
description: "UI production graph",
|
||||
},
|
||||
"core-test": {
|
||||
config: "test/tsconfig/tsconfig.core.test.json",
|
||||
description: "core colocated test graph",
|
||||
|
||||
@@ -807,7 +807,12 @@ export class CodeModeHeadlessTimeoutError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
function createHeadlessAbortScope(signal: AbortSignal | undefined, wallClockMs: number) {
|
||||
// Explicit return type: declaration emit cannot name the inferred AbortSignal
|
||||
// in the DOM-free core lane (@types/node keeps it in a non-exported module).
|
||||
function createHeadlessAbortScope(
|
||||
signal: AbortSignal | undefined,
|
||||
wallClockMs: number,
|
||||
): { signal: AbortSignal; cleanup: () => void } {
|
||||
const controller = new AbortController();
|
||||
const onAbort = () => controller.abort(signal?.reason);
|
||||
signal?.addEventListener("abort", onAbort, { once: true });
|
||||
|
||||
@@ -4,9 +4,40 @@
|
||||
* Highlight.js emits HTML spans; this module walks that small HTML subset and
|
||||
* maps active scopes to caller-provided text formatters.
|
||||
*/
|
||||
import hljs from "highlight.js";
|
||||
import { createRequire } from "node:module";
|
||||
import { decodeHtmlEntityAt } from "./html.js";
|
||||
|
||||
type HighlightJs = {
|
||||
getLanguage(name: string): unknown;
|
||||
highlight(
|
||||
code: string,
|
||||
options: { language: string; ignoreIllegals?: boolean },
|
||||
): { value: string };
|
||||
highlightAuto(code: string, languageSubset?: string[]): { value: string };
|
||||
};
|
||||
|
||||
function isHighlightJs(value: unknown): value is HighlightJs {
|
||||
return (
|
||||
typeof value === "object" &&
|
||||
value !== null &&
|
||||
"getLanguage" in value &&
|
||||
typeof value.getLanguage === "function" &&
|
||||
"highlight" in value &&
|
||||
typeof value.highlight === "function" &&
|
||||
"highlightAuto" in value &&
|
||||
typeof value.highlightAuto === "function"
|
||||
);
|
||||
}
|
||||
|
||||
// highlight.js ships `/// <reference lib="dom" />` in its d.ts, which would
|
||||
// silently re-inject DOM globals into the DOM-free core program. Load it
|
||||
// untyped and validate the narrow API we use instead of importing its types.
|
||||
const highlightJsModule: unknown = createRequire(import.meta.url)("highlight.js");
|
||||
if (!isHighlightJs(highlightJsModule)) {
|
||||
throw new TypeError("highlight.js did not expose the expected Node API");
|
||||
}
|
||||
const hljs = highlightJsModule;
|
||||
|
||||
/** Formatter applied to highlighted text segments. */
|
||||
export type HighlightFormatter = (text: string) => string;
|
||||
/** Mapping from highlight.js scope names to text formatters. */
|
||||
|
||||
@@ -9,7 +9,9 @@ const silentConfigIoLogger = {
|
||||
/**
|
||||
* Creates config I/O for secrets commands with config-loader logging suppressed.
|
||||
*/
|
||||
export function createSecretsConfigIO(params: { env: NodeJS.ProcessEnv }) {
|
||||
export function createSecretsConfigIO(params: {
|
||||
env: NodeJS.ProcessEnv;
|
||||
}): ReturnType<typeof createConfigIO> {
|
||||
// Secrets command output is owned by the CLI command so --json stays machine-parseable.
|
||||
return createConfigIO({
|
||||
env: params.env,
|
||||
|
||||
20
src/types/node-runtime-globals.d.ts
vendored
Normal file
20
src/types/node-runtime-globals.d.ts
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// The core lane compiles with lib ES2023 (no DOM), so these web-global names
|
||||
// no longer resolve. Derive them from the fetch globals @types/node already
|
||||
// declares (backed by undici) instead of depending on undici-types directly;
|
||||
// indexed-access derivation tracks @types/node across upgrades.
|
||||
type BodyInit = Exclude<RequestInit["body"], undefined>;
|
||||
type FormDataEntryValue = string | import("node:buffer").File;
|
||||
type HeadersInit = Exclude<RequestInit["headers"], undefined>;
|
||||
type ReadableStreamReadResult<T> =
|
||||
| import("node:stream/web").ReadableStreamReadDoneResult<T>
|
||||
| import("node:stream/web").ReadableStreamReadValueResult<T>;
|
||||
type RequestCredentials = Exclude<RequestInit["credentials"], undefined>;
|
||||
type RequestInfo = Parameters<typeof fetch>[0];
|
||||
|
||||
// Minimal surface for the one compile() caller; WebAssembly types otherwise
|
||||
// live in lib.dom, which the core lane intentionally excludes.
|
||||
declare namespace WebAssembly {
|
||||
type Module = object;
|
||||
|
||||
function compile(bytes: ArrayBuffer | ArrayBufferView): Promise<Module>;
|
||||
}
|
||||
@@ -598,6 +598,31 @@ describe("scripts/changed-lanes", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("routes UI production changes to UI prod and core test lanes", () => {
|
||||
const result = detectChangedLanes(["ui/src/app.ts"]);
|
||||
const plan = createChangedCheckPlan(result, { env: { PATH: "/usr/bin" } });
|
||||
|
||||
expectLanes(result.lanes, {
|
||||
coreTests: true,
|
||||
ui: true,
|
||||
});
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:ui");
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:core:test");
|
||||
expect(plan.commands.map((command) => command.args[0])).not.toContain("tsgo:core");
|
||||
});
|
||||
|
||||
it("routes the UI production config to UI prod and core test lanes", () => {
|
||||
const result = detectChangedLanes(["tsconfig.ui.json"]);
|
||||
const plan = createChangedCheckPlan(result, { env: { PATH: "/usr/bin" } });
|
||||
|
||||
expectLanes(result.lanes, {
|
||||
coreTests: true,
|
||||
ui: true,
|
||||
});
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:ui");
|
||||
expect(plan.commands.map((command) => command.args[0])).toContain("tsgo:core:test");
|
||||
});
|
||||
|
||||
it.each([
|
||||
"scripts/control-ui-i18n.ts",
|
||||
"scripts/lib/example.ts",
|
||||
@@ -1851,6 +1876,7 @@ describe("scripts/changed-lanes", () => {
|
||||
expect(result.lanes).toEqual({
|
||||
core: false,
|
||||
coreTests: false,
|
||||
ui: false,
|
||||
extensions: false,
|
||||
extensionTests: false,
|
||||
scripts: false,
|
||||
|
||||
@@ -140,15 +140,14 @@ describe("oxlint config", () => {
|
||||
"dist/",
|
||||
"dist-runtime/",
|
||||
"docs/_layouts/",
|
||||
"**/a2ui.bundle.js",
|
||||
"extensions/diffs/assets/viewer-runtime.js",
|
||||
"extensions/diffs-language-pack/assets/viewer-runtime.js",
|
||||
"extensions/canvas/src/host/a2ui/a2ui.bundle.js",
|
||||
"node_modules/",
|
||||
"patches/",
|
||||
"pnpm-lock.yaml",
|
||||
"skills/**",
|
||||
"src/auto-reply/reply/export-html/template.js",
|
||||
"src/canvas-host/a2ui/a2ui.bundle.js",
|
||||
"vendor/",
|
||||
"**/.cache/**",
|
||||
"**/.openclaw-runtime-deps-copy-*/**",
|
||||
|
||||
@@ -111,24 +111,41 @@ describe("run-tsgo sparse guard", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it("returns a helpful message for sparse core worktrees missing transitive project files", () => {
|
||||
it("returns a helpful message for sparse UI worktrees missing transitive project files", () => {
|
||||
const cwd = createTempDir("openclaw-run-tsgo-");
|
||||
const uiToolDisplay = path.join(cwd, "ui/src/ui/tool-display.ts");
|
||||
const uiToolDisplay = path.join(cwd, "ui/src/lib/chat/tool-display.ts");
|
||||
fs.mkdirSync(path.dirname(uiToolDisplay), { recursive: true });
|
||||
fs.writeFileSync(uiToolDisplay, "", "utf8");
|
||||
|
||||
expect(
|
||||
getSparseTsgoGuardError(["-p", "tsconfig.core.json"], {
|
||||
getSparseTsgoGuardError(["-p", "tsconfig.ui.json"], {
|
||||
cwd,
|
||||
isSparseCheckoutEnabled: () => true,
|
||||
}),
|
||||
).toMatchInlineSnapshot(`
|
||||
"tsconfig.core.json cannot be typechecked from this sparse checkout because tracked project inputs are missing or only partially included:
|
||||
"tsconfig.ui.json cannot be typechecked from this sparse checkout because tracked project inputs are missing or only partially included:
|
||||
- apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/tool-display.json
|
||||
Expand this worktree's sparse checkout to include those paths, or rerun in a full worktree."
|
||||
`);
|
||||
});
|
||||
|
||||
it("rejects sparse UI worktrees missing the transitive src root", () => {
|
||||
const cwd = createTempDir("openclaw-run-tsgo-");
|
||||
|
||||
expect(
|
||||
getSparseTsgoGuardError(["-p", "tsconfig.ui.json"], {
|
||||
cwd,
|
||||
fileExists: () => true,
|
||||
isSparseCheckoutEnabled: () => true,
|
||||
sparseCheckoutPatterns: ["/packages/", "/ui/config/", "/ui/src/"],
|
||||
}),
|
||||
).toMatchInlineSnapshot(`
|
||||
"tsconfig.ui.json cannot be typechecked from this sparse checkout because tracked project inputs are missing or only partially included:
|
||||
- src
|
||||
Expand this worktree's sparse checkout to include those paths, or rerun in a full worktree."
|
||||
`);
|
||||
});
|
||||
|
||||
it("returns a helpful message for sparse core-test worktrees missing ui and packages files", () => {
|
||||
const cwd = createTempDir("openclaw-run-tsgo-");
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
// Node-side production code must not see browser globals; ui/ owns DOM via tsconfig.ui.json.
|
||||
"lib": ["ES2023"],
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"tsBuildInfoFile": ".artifacts/tsgo-cache/core.tsbuildinfo"
|
||||
},
|
||||
"include": ["src/**/*", "ui/**/*", "packages/**/*"],
|
||||
"include": ["src/**/*", "packages/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/dist/**", "**/*.test.ts", "**/*.test.tsx", "test/**"]
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.core.json" },
|
||||
{ "path": "./tsconfig.ui.json" },
|
||||
{ "path": "./test/tsconfig/tsconfig.core.test.json" }
|
||||
]
|
||||
}
|
||||
|
||||
10
tsconfig.ui.json
Normal file
10
tsconfig.ui.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"tsBuildInfoFile": ".artifacts/tsgo-cache/ui.tsbuildinfo"
|
||||
},
|
||||
"include": ["ui/**/*", "src/**/*.d.ts", "packages/**/*.d.ts"],
|
||||
"exclude": ["node_modules", "dist", "**/dist/**", "**/*.test.ts", "**/*.test.tsx", "test/**"]
|
||||
}
|
||||
Reference in New Issue
Block a user