mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 17:53:39 +00:00
Refresh application, plugin, native, build and container dependencies through the fixed 2026-09-19T16:27:11Z cutoff. Migrate native TypeScript snapshot/printer APIs while preserving compilation and filesystem contracts; retain existing patches and compatibility holds. Document offline container-image preparation. Include the verified compiler process-census and loading-clock fixture repairs and deterministic warm-history regression. Adopt the canonical production history fixes from #159924 and #159955. Land under the maintainer's explicit approval to treat proven pre-existing CI failures as non-blocking and repair main afterward. CI36365552098 failed an unchanged Android Compose fixture's asynchronous catalog projection assertion (3518 passed,1 failed); the Android/Gradle tree matches its main parent byte-for-byte. Security and dependency reviews passed. The final rebase preserves reviewed source changes and regenerates only the intentional Node-image documentation fingerprint. See PR159401 for complete validation and the follow-up repair obligation.
98 lines
3.3 KiB
TypeScript
98 lines
3.3 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { API, type Diagnostic } from "typescript/unstable/sync";
|
|
import { createDeclarationFileSystem } from "./native-declaration-filesystem.mts";
|
|
import { formatNativeTypeScriptDiagnostics } from "./native-typescript-diagnostics.mts";
|
|
|
|
/** Read config roots/options without loading their semantic source graph. */
|
|
export function readNativeTypeScriptConfig(options: {
|
|
cwd: string;
|
|
configFileName: string;
|
|
readFile?: (file: string) => string | null;
|
|
assertInput?: (file: string) => string;
|
|
}) {
|
|
const cwd = path.resolve(options.cwd);
|
|
const configFileName = path.resolve(cwd, options.configFileName);
|
|
const contents = new Map<string, string>();
|
|
const readFile = options.readFile ?? ((file: string) => fs.readFileSync(file, "utf8"));
|
|
const view = options.assertInput
|
|
? createDeclarationFileSystem(cwd, options.assertInput, new Map())
|
|
: undefined;
|
|
let readFailure: Error | undefined;
|
|
const assertValid = () => {
|
|
view?.assertValid();
|
|
if (readFailure !== undefined) {
|
|
throw readFailure;
|
|
}
|
|
};
|
|
let parsing = true;
|
|
const api = new API({
|
|
cwd,
|
|
fs: {
|
|
...view?.filesystem,
|
|
readFile(file) {
|
|
if (view && !view.filesystem.fileExists(file)) {
|
|
return null;
|
|
}
|
|
const cached = contents.get(file);
|
|
if (cached !== undefined) {
|
|
return cached;
|
|
}
|
|
// Native config diagnostics require a project. Source bodies cannot affect
|
|
// this query; retaining real existence/discovery still preserves its roots.
|
|
if (!parsing && !file.endsWith(".json")) {
|
|
return "";
|
|
}
|
|
try {
|
|
const text = readFile(file);
|
|
if (text !== null) {
|
|
contents.set(file, text);
|
|
}
|
|
return text;
|
|
} catch (error) {
|
|
if (
|
|
error instanceof Error &&
|
|
"code" in error &&
|
|
(error.code === "ENOENT" || error.code === "ENOTDIR")
|
|
) {
|
|
return null;
|
|
}
|
|
readFailure ??= error instanceof Error ? error : new Error(String(error));
|
|
return null;
|
|
}
|
|
},
|
|
},
|
|
});
|
|
try {
|
|
const parsed = api.parseConfigFile(configFileName);
|
|
assertValid();
|
|
const syntax = api.readConfigFile(configFileName);
|
|
assertValid();
|
|
const configFiles = [...contents.keys()].toSorted();
|
|
let diagnostics: readonly Diagnostic[] = parsed.errors;
|
|
if (syntax.error) {
|
|
// Parsed options omit root JSON syntax errors; readConfigFile reports only
|
|
// the first. Open a project only for the complete malformed-config report.
|
|
parsing = false;
|
|
const snapshot = api.createSnapshot({ openProjects: [configFileName], ensurePrograms: true });
|
|
assertValid();
|
|
const project = snapshot.getConfiguredProject(configFileName);
|
|
if (!project) {
|
|
throw new Error(`Native TypeScript did not open config ${configFileName}`);
|
|
}
|
|
diagnostics = project.program.getConfigFileParsingDiagnostics();
|
|
assertValid();
|
|
}
|
|
if (diagnostics.length) {
|
|
throw new Error(
|
|
`Invalid TypeScript config ${configFileName}:\n${formatNativeTypeScriptDiagnostics(diagnostics)}`,
|
|
);
|
|
}
|
|
return { ...parsed, configFiles };
|
|
} catch (error) {
|
|
assertValid();
|
|
throw error;
|
|
} finally {
|
|
api.close();
|
|
}
|
|
}
|