Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/scripts/prune-prisma-client-runtime.mjs
T

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();
}