revert: Switch back to tsc for compiling.
This commit is contained in:
@@ -1,34 +1,36 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { setupGitHooks } from "./setup-git-hooks.js";
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { setupGitHooks } from './setup-git-hooks.js';
|
||||
|
||||
function detectPackageManager(ua = process.env.npm_config_user_agent ?? "") {
|
||||
function detectPackageManager(ua = process.env.npm_config_user_agent ?? '') {
|
||||
// Examples:
|
||||
// - "pnpm/10.23.0 npm/? node/v22.21.1 darwin arm64"
|
||||
// - "npm/10.9.4 node/v22.12.0 linux x64"
|
||||
// - "bun/1.2.2"
|
||||
const normalized = String(ua).trim();
|
||||
if (normalized.startsWith("pnpm/")) return "pnpm";
|
||||
if (normalized.startsWith("bun/")) return "bun";
|
||||
if (normalized.startsWith("npm/")) return "npm";
|
||||
if (normalized.startsWith("yarn/")) return "yarn";
|
||||
return "unknown";
|
||||
if (normalized.startsWith('pnpm/')) return 'pnpm';
|
||||
if (normalized.startsWith('bun/')) return 'bun';
|
||||
if (normalized.startsWith('npm/')) return 'npm';
|
||||
if (normalized.startsWith('yarn/')) return 'yarn';
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
function shouldApplyPnpmPatchedDependenciesFallback(pm = detectPackageManager()) {
|
||||
function shouldApplyPnpmPatchedDependenciesFallback(
|
||||
pm = detectPackageManager(),
|
||||
) {
|
||||
// pnpm already applies pnpm.patchedDependencies itself; re-applying would fail.
|
||||
return pm !== "pnpm";
|
||||
return pm !== 'pnpm';
|
||||
}
|
||||
|
||||
function getRepoRoot() {
|
||||
const here = path.dirname(fileURLToPath(import.meta.url));
|
||||
return path.resolve(here, "..");
|
||||
return path.resolve(here, '..');
|
||||
}
|
||||
|
||||
function ensureExecutable(targetPath) {
|
||||
if (process.platform === "win32") return;
|
||||
if (process.platform === 'win32') return;
|
||||
if (!fs.existsSync(targetPath)) return;
|
||||
try {
|
||||
const mode = fs.statSync(targetPath).mode & 0o777;
|
||||
@@ -40,29 +42,32 @@ function ensureExecutable(targetPath) {
|
||||
}
|
||||
|
||||
function hasGit(repoRoot) {
|
||||
const result = spawnSync("git", ["--version"], { cwd: repoRoot, stdio: "ignore" });
|
||||
const result = spawnSync('git', ['--version'], {
|
||||
cwd: repoRoot,
|
||||
stdio: 'ignore',
|
||||
});
|
||||
return result.status === 0;
|
||||
}
|
||||
|
||||
function extractPackageName(key) {
|
||||
if (key.startsWith("@")) {
|
||||
const idx = key.indexOf("@", 1);
|
||||
if (key.startsWith('@')) {
|
||||
const idx = key.indexOf('@', 1);
|
||||
if (idx === -1) return key;
|
||||
return key.slice(0, idx);
|
||||
}
|
||||
const idx = key.lastIndexOf("@");
|
||||
const idx = key.lastIndexOf('@');
|
||||
if (idx <= 0) return key;
|
||||
return key.slice(0, idx);
|
||||
}
|
||||
|
||||
function stripPrefix(p) {
|
||||
if (p.startsWith("a/") || p.startsWith("b/")) return p.slice(2);
|
||||
if (p.startsWith('a/') || p.startsWith('b/')) return p.slice(2);
|
||||
return p;
|
||||
}
|
||||
|
||||
function parseRange(segment) {
|
||||
// segment: "-12,5" or "+7"
|
||||
const [startRaw, countRaw] = segment.slice(1).split(",");
|
||||
const [startRaw, countRaw] = segment.slice(1).split(',');
|
||||
const start = Number.parseInt(startRaw, 10);
|
||||
const count = countRaw ? Number.parseInt(countRaw, 10) : 1;
|
||||
if (Number.isNaN(start) || Number.isNaN(count)) {
|
||||
@@ -72,12 +77,12 @@ function parseRange(segment) {
|
||||
}
|
||||
|
||||
function parsePatch(patchText) {
|
||||
const lines = patchText.split("\n");
|
||||
const lines = patchText.split('\n');
|
||||
const files = [];
|
||||
let i = 0;
|
||||
|
||||
while (i < lines.length) {
|
||||
if (!lines[i].startsWith("diff --git ")) {
|
||||
if (!lines[i].startsWith('diff --git ')) {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -86,20 +91,22 @@ function parsePatch(patchText) {
|
||||
i += 1;
|
||||
|
||||
// Skip index line(s)
|
||||
while (i < lines.length && lines[i].startsWith("index ")) i += 1;
|
||||
while (i < lines.length && lines[i].startsWith('index ')) i += 1;
|
||||
|
||||
if (i < lines.length && lines[i].startsWith("--- ")) {
|
||||
if (i < lines.length && lines[i].startsWith('--- ')) {
|
||||
file.oldPath = stripPrefix(lines[i].slice(4).trim());
|
||||
i += 1;
|
||||
}
|
||||
if (i < lines.length && lines[i].startsWith("+++ ")) {
|
||||
if (i < lines.length && lines[i].startsWith('+++ ')) {
|
||||
file.newPath = stripPrefix(lines[i].slice(4).trim());
|
||||
i += 1;
|
||||
}
|
||||
|
||||
while (i < lines.length && lines[i].startsWith("@@")) {
|
||||
while (i < lines.length && lines[i].startsWith('@@')) {
|
||||
const header = lines[i];
|
||||
const match = /^@@\s+(-\d+(?:,\d+)?)\s+(\+\d+(?:,\d+)?)\s+@@/.exec(header);
|
||||
const match = /^@@\s+(-\d+(?:,\d+)?)\s+(\+\d+(?:,\d+)?)\s+@@/.exec(
|
||||
header,
|
||||
);
|
||||
if (!match) throw new Error(`invalid hunk header: ${header}`);
|
||||
const oldRange = parseRange(match[1]);
|
||||
const newRange = parseRange(match[2]);
|
||||
@@ -108,12 +115,12 @@ function parsePatch(patchText) {
|
||||
const hunkLines = [];
|
||||
while (i < lines.length) {
|
||||
const line = lines[i];
|
||||
if (line.startsWith("@@") || line.startsWith("diff --git ")) break;
|
||||
if (line === "") {
|
||||
if (line.startsWith('@@') || line.startsWith('diff --git ')) break;
|
||||
if (line === '') {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("\\ No newline at end of file")) {
|
||||
if (line.startsWith('\\ No newline at end of file')) {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -142,16 +149,16 @@ function readFileLines(targetPath) {
|
||||
if (!fs.existsSync(targetPath)) {
|
||||
throw new Error(`target file missing: ${targetPath}`);
|
||||
}
|
||||
const raw = fs.readFileSync(targetPath, "utf-8");
|
||||
const hasTrailingNewline = raw.endsWith("\n");
|
||||
const parts = raw.split("\n");
|
||||
const raw = fs.readFileSync(targetPath, 'utf-8');
|
||||
const hasTrailingNewline = raw.endsWith('\n');
|
||||
const parts = raw.split('\n');
|
||||
if (hasTrailingNewline) parts.pop();
|
||||
return { lines: parts, hasTrailingNewline };
|
||||
}
|
||||
|
||||
function writeFileLines(targetPath, lines, hadTrailingNewline) {
|
||||
const content = lines.join("\n") + (hadTrailingNewline ? "\n" : "");
|
||||
fs.writeFileSync(targetPath, content, "utf-8");
|
||||
const content = lines.join('\n') + (hadTrailingNewline ? '\n' : '');
|
||||
fs.writeFileSync(targetPath, content, 'utf-8');
|
||||
}
|
||||
|
||||
function applyHunk(lines, hunk, offset) {
|
||||
@@ -159,7 +166,7 @@ function applyHunk(lines, hunk, offset) {
|
||||
const expected = [];
|
||||
for (const raw of hunk.lines) {
|
||||
const marker = raw[0];
|
||||
if (marker === " " || marker === "+") {
|
||||
if (marker === ' ' || marker === '+') {
|
||||
expected.push(raw.slice(1));
|
||||
}
|
||||
}
|
||||
@@ -180,21 +187,21 @@ function applyHunk(lines, hunk, offset) {
|
||||
for (const raw of hunk.lines) {
|
||||
const marker = raw[0];
|
||||
const text = raw.slice(1);
|
||||
if (marker === " ") {
|
||||
if (marker === ' ') {
|
||||
if (lines[cursor] !== text) {
|
||||
throw new Error(
|
||||
`context mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? "<eof>"}"`,
|
||||
`context mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? '<eof>'}"`,
|
||||
);
|
||||
}
|
||||
cursor += 1;
|
||||
} else if (marker === "-") {
|
||||
} else if (marker === '-') {
|
||||
if (lines[cursor] !== text) {
|
||||
throw new Error(
|
||||
`delete mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? "<eof>"}"`,
|
||||
`delete mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? '<eof>'}"`,
|
||||
);
|
||||
}
|
||||
lines.splice(cursor, 1);
|
||||
} else if (marker === "+") {
|
||||
} else if (marker === '+') {
|
||||
lines.splice(cursor, 0, text);
|
||||
cursor += 1;
|
||||
} else {
|
||||
@@ -207,11 +214,11 @@ function applyHunk(lines, hunk, offset) {
|
||||
}
|
||||
|
||||
function applyPatchToFile(targetDir, filePatch) {
|
||||
if (filePatch.newPath === "/dev/null") {
|
||||
if (filePatch.newPath === '/dev/null') {
|
||||
// deletion not needed for our patches
|
||||
return;
|
||||
}
|
||||
const relPath = stripPrefix(filePatch.newPath ?? filePatch.oldPath ?? "");
|
||||
const relPath = stripPrefix(filePatch.newPath ?? filePatch.oldPath ?? '');
|
||||
const targetPath = path.join(targetDir, relPath);
|
||||
const { lines, hasTrailingNewline } = readFileLines(targetPath);
|
||||
|
||||
@@ -225,7 +232,10 @@ function applyPatchToFile(targetDir, filePatch) {
|
||||
|
||||
function applyPatchSet({ patchText, targetDir }) {
|
||||
let resolvedTarget = path.resolve(targetDir);
|
||||
if (!fs.existsSync(resolvedTarget) || !fs.statSync(resolvedTarget).isDirectory()) {
|
||||
if (
|
||||
!fs.existsSync(resolvedTarget) ||
|
||||
!fs.statSync(resolvedTarget).isDirectory()
|
||||
) {
|
||||
console.warn(`[postinstall] skip missing target: ${resolvedTarget}`);
|
||||
return;
|
||||
}
|
||||
@@ -244,28 +254,28 @@ function applyPatchFile({ patchPath, targetDir }) {
|
||||
if (!fs.existsSync(absPatchPath)) {
|
||||
throw new Error(`missing patch: ${absPatchPath}`);
|
||||
}
|
||||
const patchText = fs.readFileSync(absPatchPath, "utf-8");
|
||||
const patchText = fs.readFileSync(absPatchPath, 'utf-8');
|
||||
applyPatchSet({ patchText, targetDir });
|
||||
}
|
||||
|
||||
function trySetupCompletion(repoRoot) {
|
||||
// Skip in CI or if explicitly disabled
|
||||
if (process.env.CI || process.env.OPENCLAW_SKIP_COMPLETION_SETUP) return;
|
||||
|
||||
const binPath = path.join(repoRoot, "openclaw.mjs");
|
||||
|
||||
const binPath = path.join(repoRoot, 'openclaw.mjs');
|
||||
if (!fs.existsSync(binPath)) return;
|
||||
|
||||
|
||||
// In development, dist might not exist yet during postinstall
|
||||
const distEntry = path.join(repoRoot, "dist", "index.js");
|
||||
const distEntry = path.join(repoRoot, 'dist', 'index.js');
|
||||
if (!fs.existsSync(distEntry)) return;
|
||||
|
||||
try {
|
||||
// Run with OPENCLAW_SKIP_POSTINSTALL to avoid any weird recursion,
|
||||
// though distinct from this script.
|
||||
spawnSync(process.execPath, [binPath, "completion", "--install", "--yes"], {
|
||||
spawnSync(process.execPath, [binPath, 'completion', '--install', '--yes'], {
|
||||
cwd: repoRoot,
|
||||
stdio: "inherit",
|
||||
env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: "1" },
|
||||
stdio: 'inherit',
|
||||
env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: '1' },
|
||||
});
|
||||
} catch (err) {
|
||||
// Ignore errors to not break install
|
||||
@@ -276,7 +286,7 @@ function main() {
|
||||
const repoRoot = getRepoRoot();
|
||||
process.chdir(repoRoot);
|
||||
|
||||
ensureExecutable(path.join(repoRoot, "dist", "entry.mjs"));
|
||||
ensureExecutable(path.join(repoRoot, 'dist', '/entry.js'));
|
||||
setupGitHooks({ repoRoot });
|
||||
trySetupCompletion(repoRoot);
|
||||
|
||||
@@ -284,18 +294,18 @@ function main() {
|
||||
return;
|
||||
}
|
||||
|
||||
const pkgPath = path.join(repoRoot, "package.json");
|
||||
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
||||
const pkgPath = path.join(repoRoot, 'package.json');
|
||||
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
||||
const patched = pkg?.pnpm?.patchedDependencies ?? {};
|
||||
|
||||
// Bun does not support pnpm.patchedDependencies. Apply these patch files to
|
||||
// node_modules packages as a best-effort compatibility layer.
|
||||
for (const [key, relPatchPath] of Object.entries(patched)) {
|
||||
if (typeof relPatchPath !== "string" || !relPatchPath.trim()) continue;
|
||||
if (typeof relPatchPath !== 'string' || !relPatchPath.trim()) continue;
|
||||
const pkgName = extractPackageName(String(key));
|
||||
if (!pkgName) continue;
|
||||
applyPatchFile({
|
||||
targetDir: path.join("node_modules", ...pkgName.split("/")),
|
||||
targetDir: path.join('node_modules', ...pkgName.split('/')),
|
||||
patchPath: relPatchPath,
|
||||
});
|
||||
}
|
||||
@@ -303,10 +313,10 @@ function main() {
|
||||
|
||||
try {
|
||||
const skip =
|
||||
process.env.OPENCLAW_SKIP_POSTINSTALL === "1" ||
|
||||
process.env.CLAWDBOT_SKIP_POSTINSTALL === "1" ||
|
||||
process.env.VITEST === "true" ||
|
||||
process.env.NODE_ENV === "test";
|
||||
process.env.OPENCLAW_SKIP_POSTINSTALL === '1' ||
|
||||
process.env.CLAWDBOT_SKIP_POSTINSTALL === '1' ||
|
||||
process.env.VITEST === 'true' ||
|
||||
process.env.NODE_ENV === 'test';
|
||||
|
||||
if (!skip) {
|
||||
main();
|
||||
|
||||
Reference in New Issue
Block a user