97 lines
3.8 KiB
JavaScript
97 lines
3.8 KiB
JavaScript
#!/usr/bin/env node
|
|
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const REQUIRED_QUERY_COMPILERS = new Set(["query_compiler_fast_bg.postgresql.mjs", "query_compiler_fast_bg.postgresql.wasm-base64.mjs"]);
|
|
|
|
const QUERY_COMPILER_IMPORT_PATTERN = /@prisma\/client\/runtime\/(query_compiler_[^"']+)/gu;
|
|
|
|
export async function verifyGeneratedPrismaRuntimeContract(generatedClientPath) {
|
|
const source = await fs.readFile(generatedClientPath, "utf8");
|
|
const imports = new Set([...source.matchAll(QUERY_COMPILER_IMPORT_PATTERN)].map((match) => match[1]));
|
|
const missing = [...REQUIRED_QUERY_COMPILERS].filter((fileName) => !imports.has(fileName));
|
|
const unexpected = [...imports].filter((fileName) => !REQUIRED_QUERY_COMPILERS.has(fileName));
|
|
|
|
if (missing.length > 0 || unexpected.length > 0) {
|
|
throw new Error(`generated Prisma runtime contract mismatch: missing=${missing.join(",") || "none"} unexpected=${unexpected.join(",") || "none"}`);
|
|
}
|
|
|
|
return [...imports].sort();
|
|
}
|
|
|
|
export async function prunePrismaClientRuntime({ generatedClientPath, nodeModulesPath }) {
|
|
await verifyGeneratedPrismaRuntimeContract(generatedClientPath);
|
|
|
|
const virtualStorePath = path.join(nodeModulesPath, ".pnpm");
|
|
const entries = await fs.readdir(virtualStorePath, { withFileTypes: true });
|
|
const clientRoots = entries
|
|
.filter((entry) => entry.isDirectory() && entry.name.startsWith("@prisma+client@"))
|
|
.map((entry) => path.join(virtualStorePath, entry.name, "node_modules", "@prisma", "client"));
|
|
|
|
if (clientRoots.length === 0) {
|
|
throw new Error(`no @prisma/client runtime found below ${virtualStorePath}`);
|
|
}
|
|
|
|
let bytesRemoved = 0;
|
|
let filesRemoved = 0;
|
|
|
|
for (const clientRoot of clientRoots) {
|
|
const runtimePath = path.join(clientRoot, "runtime");
|
|
for (const requiredFile of REQUIRED_QUERY_COMPILERS) {
|
|
await fs.access(path.join(runtimePath, requiredFile));
|
|
}
|
|
|
|
for (const entry of await fs.readdir(runtimePath, { withFileTypes: true })) {
|
|
if (!entry.isFile() || !entry.name.startsWith("query_compiler_") || REQUIRED_QUERY_COMPILERS.has(entry.name)) continue;
|
|
const filePath = path.join(runtimePath, entry.name);
|
|
bytesRemoved += (await fs.stat(filePath)).size;
|
|
await fs.rm(filePath);
|
|
filesRemoved += 1;
|
|
}
|
|
|
|
const generatorPath = path.join(clientRoot, "generator-build");
|
|
const generatorStats = await directoryStats(generatorPath);
|
|
bytesRemoved += generatorStats.bytes;
|
|
filesRemoved += generatorStats.files;
|
|
await fs.rm(generatorPath, { force: true, recursive: true });
|
|
}
|
|
|
|
return { bytesRemoved, clientCount: clientRoots.length, filesRemoved };
|
|
}
|
|
|
|
async function directoryStats(directoryPath) {
|
|
let bytes = 0;
|
|
let files = 0;
|
|
let entries;
|
|
try {
|
|
entries = await fs.readdir(directoryPath, { withFileTypes: true });
|
|
} catch (error) {
|
|
if (error?.code === "ENOENT") return { bytes, files };
|
|
throw error;
|
|
}
|
|
for (const entry of entries) {
|
|
const entryPath = path.join(directoryPath, entry.name);
|
|
if (entry.isDirectory()) {
|
|
const nested = await directoryStats(entryPath);
|
|
bytes += nested.bytes;
|
|
files += nested.files;
|
|
} else if (entry.isFile()) {
|
|
bytes += (await fs.stat(entryPath)).size;
|
|
files += 1;
|
|
}
|
|
}
|
|
return { bytes, files };
|
|
}
|
|
|
|
async function runCli() {
|
|
const nodeModulesPath = path.resolve(process.argv[2] ?? "node_modules");
|
|
const generatedClientPath = path.resolve(process.argv[3] ?? "packages/db/generated/prisma/client/internal/class.ts");
|
|
const result = await prunePrismaClientRuntime({ generatedClientPath, nodeModulesPath });
|
|
console.log(`PRUNED prisma-clients=${result.clientCount} files=${result.filesRemoved} bytes=${result.bytesRemoved}`);
|
|
}
|
|
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
await runCli();
|
|
}
|