Manifestbasierter Production-Updater 3.3, Modulnavigation, optionales Produktbild Studio, Listing-Studio-Aktionsleiste sowie plattformübergreifende Windows-/Linux-Release-Gates.
71 lines
3.3 KiB
JavaScript
71 lines
3.3 KiB
JavaScript
import { readFileSync, existsSync } from 'node:fs';
|
|
import { dirname, resolve } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
|
|
const failures = [];
|
|
const importPattern = /(?:import\s+(?:[^'";]+?\s+from\s+)?|import\s*\()\s*['"]([^'"]+)['"]/g;
|
|
|
|
function resolveImport(fromFile, specifier) {
|
|
if (!specifier.startsWith('.')) return null;
|
|
const base = resolve(dirname(fromFile), specifier);
|
|
const candidates = [base, `${base}.mjs`, `${base}.js`, resolve(base, 'index.mjs'), resolve(base, 'index.js')];
|
|
return candidates.find((candidate) => existsSync(candidate)) || null;
|
|
}
|
|
|
|
const dependencyCache = new Map();
|
|
function dependencyClosure(file, visiting = new Set()) {
|
|
if (dependencyCache.has(file)) return dependencyCache.get(file);
|
|
if (visiting.has(file)) return new Set();
|
|
visiting.add(file);
|
|
const source = readFileSync(file, 'utf8');
|
|
const result = new Set();
|
|
for (const match of source.matchAll(importPattern)) {
|
|
const dependency = resolveImport(file, match[1]);
|
|
if (!dependency) continue;
|
|
result.add(dependency);
|
|
for (const nested of dependencyClosure(dependency, new Set(visiting))) result.add(nested);
|
|
}
|
|
dependencyCache.set(file, result);
|
|
return result;
|
|
}
|
|
|
|
function collectVerifierFiles(scriptName, seen = new Set()) {
|
|
if (seen.has(scriptName)) return [];
|
|
seen.add(scriptName);
|
|
const command = pkg.scripts?.[scriptName] || '';
|
|
const files = [];
|
|
for (const match of command.matchAll(/npm run ([\w:-]+)/g)) files.push(...collectVerifierFiles(match[1], new Set(seen)));
|
|
for (const match of command.matchAll(/node(?: --no-warnings)? (tools\/[A-Za-z0-9._-]+\.mjs)/g)) files.push(resolve(root, match[1]));
|
|
return files;
|
|
}
|
|
|
|
const dbModule = resolve(root, 'lib/db.mjs');
|
|
const activeFiles = [...new Set(collectVerifierFiles('verify:all'))];
|
|
for (const file of activeFiles) {
|
|
const source = readFileSync(file, 'utf8');
|
|
const dependencies = dependencyClosure(file);
|
|
const opensVendooDatabase = dependencies.has(dbModule);
|
|
if (!opensVendooDatabase) continue;
|
|
if (!source.includes('VENDOO_DATA_DIR') || !source.includes('VENDOO_DB_PATH')) failures.push(`${file.slice(root.length + 1)} öffnet lib/db.mjs transitiv ohne isolierten Test-Datenpfad.`);
|
|
if (!source.includes('closeVendooDatabase')) failures.push(`${file.slice(root.length + 1)} öffnet lib/db.mjs transitiv, schließt die Datenbank aber nicht explizit.`);
|
|
if (!source.includes('removeTempDirectory')) failures.push(`${file.slice(root.length + 1)} verwendet nicht den Windows-tauglichen Temp-Cleanup.`);
|
|
}
|
|
|
|
for (const required of [
|
|
'tools/test-runtime-cleanup.mjs',
|
|
'tools/verify-controlled-invitations-1.42.0.mjs',
|
|
'tools/verify-initial-disabled-modules-1.41.2.mjs',
|
|
'tools/verify-windows-sqlite-cleanup-regression-1.43.0.mjs',
|
|
]) {
|
|
if (!existsSync(resolve(root, required))) failures.push(`Pflichtdatei fehlt: ${required}`);
|
|
}
|
|
|
|
if (failures.length) {
|
|
console.error(`SQLite-Cleanup-Vertragsprüfung 1.43.0 fehlgeschlagen (${failures.length}):`);
|
|
for (const failure of failures) console.error(`- ${failure}`);
|
|
process.exit(1);
|
|
}
|
|
console.log(`SQLite-Cleanup-Vertragsprüfung 1.43.0 erfolgreich: ${activeFiles.length} aktive Verifier transitiv geprüft; alle Vendoo-DB-Temp-Tests schließen ihre Handles.`);
|