Prune packaged runtime dependencies
This commit is contained in:
@@ -136,6 +136,7 @@ function ensureBundledWorkspace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function copyPackageFiles(appDir) {
|
function copyPackageFiles(appDir) {
|
||||||
|
const releaseDir = resolve(appRoot, "dist", "release");
|
||||||
cpSync(resolve(appRoot, "package.json"), resolve(appDir, "package.json"));
|
cpSync(resolve(appRoot, "package.json"), resolve(appDir, "package.json"));
|
||||||
for (const entry of packageJson.files) {
|
for (const entry of packageJson.files) {
|
||||||
const normalized = entry.endsWith("/") ? entry.slice(0, -1) : entry;
|
const normalized = entry.endsWith("/") ? entry.slice(0, -1) : entry;
|
||||||
@@ -143,7 +144,10 @@ function copyPackageFiles(appDir) {
|
|||||||
if (!existsSync(source)) continue;
|
if (!existsSync(source)) continue;
|
||||||
const destination = resolve(appDir, normalized);
|
const destination = resolve(appDir, normalized);
|
||||||
mkdirSync(dirname(destination), { recursive: true });
|
mkdirSync(dirname(destination), { recursive: true });
|
||||||
cpSync(source, destination, { recursive: true });
|
cpSync(source, destination, {
|
||||||
|
recursive: true,
|
||||||
|
filter: (path) => path !== releaseDir && !path.startsWith(`${releaseDir}/`),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cpSync(packageLockPath, resolve(appDir, "package-lock.json"));
|
cpSync(packageLockPath, resolve(appDir, "package-lock.json"));
|
||||||
@@ -160,6 +164,9 @@ function installAppDependencies(appDir, stagingRoot) {
|
|||||||
run("npm", ["ci", "--omit=dev", "--ignore-scripts", "--no-audit", "--no-fund", "--loglevel", "error"], {
|
run("npm", ["ci", "--omit=dev", "--ignore-scripts", "--no-audit", "--no-fund", "--loglevel", "error"], {
|
||||||
cwd: depsDir,
|
cwd: depsDir,
|
||||||
});
|
});
|
||||||
|
run(process.execPath, [resolve(appRoot, "scripts", "prune-runtime-deps.mjs"), depsDir], {
|
||||||
|
cwd: appRoot,
|
||||||
|
});
|
||||||
|
|
||||||
cpSync(resolve(depsDir, "node_modules"), resolve(appDir, "node_modules"), { recursive: true });
|
cpSync(resolve(depsDir, "node_modules"), resolve(appDir, "node_modules"), { recursive: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const workspaceNodeModulesDir = resolve(workspaceDir, "node_modules");
|
|||||||
const manifestPath = resolve(workspaceDir, ".runtime-manifest.json");
|
const manifestPath = resolve(workspaceDir, ".runtime-manifest.json");
|
||||||
const workspacePackageJsonPath = resolve(workspaceDir, "package.json");
|
const workspacePackageJsonPath = resolve(workspaceDir, "package.json");
|
||||||
const workspaceArchivePath = resolve(feynmanDir, "runtime-workspace.tgz");
|
const workspaceArchivePath = resolve(feynmanDir, "runtime-workspace.tgz");
|
||||||
|
const PRUNE_VERSION = 1;
|
||||||
|
|
||||||
function readPackageSpecs() {
|
function readPackageSpecs() {
|
||||||
const settings = JSON.parse(readFileSync(settingsPath, "utf8"));
|
const settings = JSON.parse(readFileSync(settingsPath, "utf8"));
|
||||||
@@ -44,7 +45,8 @@ function workspaceIsCurrent(packageSpecs) {
|
|||||||
if (
|
if (
|
||||||
manifest.nodeAbi !== process.versions.modules ||
|
manifest.nodeAbi !== process.versions.modules ||
|
||||||
manifest.platform !== process.platform ||
|
manifest.platform !== process.platform ||
|
||||||
manifest.arch !== process.arch
|
manifest.arch !== process.arch ||
|
||||||
|
manifest.pruneVersion !== PRUNE_VERSION
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -102,6 +104,7 @@ function writeManifest(packageSpecs) {
|
|||||||
nodeVersion: process.version,
|
nodeVersion: process.version,
|
||||||
platform: process.platform,
|
platform: process.platform,
|
||||||
arch: process.arch,
|
arch: process.arch,
|
||||||
|
pruneVersion: PRUNE_VERSION,
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
2,
|
2,
|
||||||
@@ -110,6 +113,15 @@ function writeManifest(packageSpecs) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pruneWorkspace() {
|
||||||
|
const result = spawnSync(process.execPath, [resolve(appRoot, "scripts", "prune-runtime-deps.mjs"), workspaceDir], {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
if (result.status !== 0) {
|
||||||
|
process.exit(result.status ?? 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function archiveIsCurrent() {
|
function archiveIsCurrent() {
|
||||||
if (!existsSync(workspaceArchivePath) || !existsSync(manifestPath)) {
|
if (!existsSync(workspaceArchivePath) || !existsSync(manifestPath)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -144,6 +156,7 @@ if (workspaceIsCurrent(packageSpecs)) {
|
|||||||
|
|
||||||
console.log("[feynman] preparing vendored runtime workspace...");
|
console.log("[feynman] preparing vendored runtime workspace...");
|
||||||
prepareWorkspace(packageSpecs);
|
prepareWorkspace(packageSpecs);
|
||||||
|
pruneWorkspace();
|
||||||
writeManifest(packageSpecs);
|
writeManifest(packageSpecs);
|
||||||
createWorkspaceArchive();
|
createWorkspaceArchive();
|
||||||
console.log("[feynman] vendored runtime workspace ready");
|
console.log("[feynman] vendored runtime workspace ready");
|
||||||
|
|||||||
140
scripts/prune-runtime-deps.mjs
Normal file
140
scripts/prune-runtime-deps.mjs
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
import { existsSync, readdirSync, rmSync, statSync } from "node:fs";
|
||||||
|
import { basename, join, resolve } from "node:path";
|
||||||
|
|
||||||
|
const root = resolve(process.argv[2] ?? ".");
|
||||||
|
const nodeModulesDir = resolve(root, "node_modules");
|
||||||
|
|
||||||
|
const STRIP_DIR_NAMES = new Set([
|
||||||
|
".github",
|
||||||
|
"__mocks__",
|
||||||
|
"__tests__",
|
||||||
|
"coverage",
|
||||||
|
"doc",
|
||||||
|
"docs",
|
||||||
|
"example",
|
||||||
|
"examples",
|
||||||
|
"test",
|
||||||
|
"tests",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const STRIP_FILE_PATTERNS = [
|
||||||
|
/\.map$/i,
|
||||||
|
/\.d\.cts$/i,
|
||||||
|
/\.d\.ts$/i,
|
||||||
|
/^README(\..+)?$/i,
|
||||||
|
/^CHANGELOG(\..+)?$/i,
|
||||||
|
];
|
||||||
|
|
||||||
|
function safeStat(path) {
|
||||||
|
try {
|
||||||
|
return statSync(path);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removePath(path) {
|
||||||
|
rmSync(path, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
function walkAndPrune(dir) {
|
||||||
|
if (!existsSync(dir)) return;
|
||||||
|
|
||||||
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
||||||
|
const path = join(dir, entry.name);
|
||||||
|
const stats = entry.isSymbolicLink() ? safeStat(path) : null;
|
||||||
|
const isDirectory = entry.isDirectory() || stats?.isDirectory();
|
||||||
|
const isFile = entry.isFile() || stats?.isFile();
|
||||||
|
|
||||||
|
if (isDirectory) {
|
||||||
|
if (STRIP_DIR_NAMES.has(entry.name)) {
|
||||||
|
removePath(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
walkAndPrune(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFile && STRIP_FILE_PATTERNS.some((pattern) => pattern.test(entry.name))) {
|
||||||
|
removePath(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function currentKoffiVariant() {
|
||||||
|
if (process.platform === "darwin" && process.arch === "arm64") return "darwin_arm64";
|
||||||
|
if (process.platform === "darwin" && process.arch === "x64") return "darwin_x64";
|
||||||
|
if (process.platform === "linux" && process.arch === "arm64") return "linux_arm64";
|
||||||
|
if (process.platform === "linux" && process.arch === "x64") return "linux_x64";
|
||||||
|
if (process.platform === "win32" && process.arch === "arm64") return "win32_arm64";
|
||||||
|
if (process.platform === "win32" && process.arch === "x64") return "win32_x64";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pruneKoffi(nodeModulesRoot) {
|
||||||
|
const koffiRoot = join(nodeModulesRoot, "koffi");
|
||||||
|
if (!existsSync(koffiRoot)) return;
|
||||||
|
|
||||||
|
for (const dirName of ["doc", "src", "vendor"]) {
|
||||||
|
removePath(join(koffiRoot, dirName));
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildRoot = join(koffiRoot, "build", "koffi");
|
||||||
|
if (!existsSync(buildRoot)) return;
|
||||||
|
|
||||||
|
const keep = currentKoffiVariant();
|
||||||
|
for (const entry of readdirSync(buildRoot, { withFileTypes: true })) {
|
||||||
|
if (entry.name === keep) continue;
|
||||||
|
removePath(join(buildRoot, entry.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pruneBetterSqlite3(nodeModulesRoot) {
|
||||||
|
const pkgRoot = join(nodeModulesRoot, "better-sqlite3");
|
||||||
|
if (!existsSync(pkgRoot)) return;
|
||||||
|
|
||||||
|
removePath(join(pkgRoot, "deps"));
|
||||||
|
removePath(join(pkgRoot, "src"));
|
||||||
|
removePath(join(pkgRoot, "binding.gyp"));
|
||||||
|
|
||||||
|
const buildRoot = join(pkgRoot, "build");
|
||||||
|
const releaseRoot = join(buildRoot, "Release");
|
||||||
|
if (existsSync(releaseRoot)) {
|
||||||
|
for (const entry of readdirSync(releaseRoot, { withFileTypes: true })) {
|
||||||
|
if (entry.name === "better_sqlite3.node") continue;
|
||||||
|
removePath(join(releaseRoot, entry.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const entry of ["Makefile", "binding.Makefile", "config.gypi", "deps", "gyp-mac-tool", "test_extension.target.mk", "better_sqlite3.target.mk"]) {
|
||||||
|
removePath(join(buildRoot, entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pruneLiteparse(nodeModulesRoot) {
|
||||||
|
const pkgRoot = join(nodeModulesRoot, "@llamaindex", "liteparse");
|
||||||
|
if (!existsSync(pkgRoot)) return;
|
||||||
|
if (existsSync(join(pkgRoot, "dist"))) {
|
||||||
|
removePath(join(pkgRoot, "src"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prunePiCodingAgent(nodeModulesRoot) {
|
||||||
|
const pkgRoot = join(nodeModulesRoot, "@mariozechner", "pi-coding-agent");
|
||||||
|
if (!existsSync(pkgRoot)) return;
|
||||||
|
removePath(join(pkgRoot, "docs"));
|
||||||
|
removePath(join(pkgRoot, "examples"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existsSync(nodeModulesDir)) {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
walkAndPrune(nodeModulesDir);
|
||||||
|
pruneKoffi(nodeModulesDir);
|
||||||
|
pruneBetterSqlite3(nodeModulesDir);
|
||||||
|
pruneLiteparse(nodeModulesDir);
|
||||||
|
prunePiCodingAgent(nodeModulesDir);
|
||||||
|
|
||||||
|
console.log(`[feynman] pruned runtime deps in ${basename(root)}`);
|
||||||
Reference in New Issue
Block a user