Upload via GUI (90 Dateien)

This commit is contained in:
2026-10-02 06:22:54 +00:00
parent d268e548f5
commit 906ac75443
39 changed files with 4183 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
'use strict';
/*
* build-setup.js – eigenes Setup (installer/) mit der App zusammenbauen
* ---------------------------------------------------------------------
* Läuft nach "electron-builder --win dir" (siehe "build" in package.json):
*
* 1. dist/win-unpacked (die fertige App) als ZIP packen
* 2. installer/ (WPF, .NET Framework 4.8) mit der Version aus package.json bauen
* 3. ZIP hinten an die Setup-.exe hängen:
* [Setup.exe][ZIP][8 Byte ZIP-Länge][8 Byte "AEROMCPK"]
* (das Setup liest den Anhang selbst aus, siehe installer/Payload.cs)
* 4. Zwischenstände wegräumen → übrig bleibt dist/AeroMC-Setup.exe
*
* Benötigt das .NET SDK (dotnet) – das Setup selbst läuft danach auf jedem
* Windows 10/11 ohne Zusatzinstallation.
*/
const fs = require('fs');
const path = require('path');
const { execFileSync } = require('child_process');
const ROOT = path.join(__dirname, '..');
const DIST = path.join(ROOT, 'dist');
const APP_DIR = path.join(DIST, 'win-unpacked');
const WORK = path.join(DIST, '.setup');
const ZIP = path.join(WORK, 'app.zip');
const OUT = path.join(DIST, 'AeroMC-Setup.exe');
const MAGIC = Buffer.from('AEROMCPK', 'ascii');
function schritt(text) {
console.log(`\n» ${text}`);
}
function main() {
const version = require(path.join(ROOT, 'package.json')).version;
if (!fs.existsSync(path.join(APP_DIR, 'AeroMC.exe'))) {
throw new Error(`${APP_DIR}\\AeroMC.exe fehlt – vorher "electron-builder --win dir" ausführen.`);
}
fs.rmSync(WORK, { recursive: true, force: true });
fs.mkdirSync(WORK, { recursive: true });
schritt('App wird gepackt …');
// .NET-ZIP über PowerShell: in jedem Windows enthalten, keine zusätzliche npm-Abhängigkeit
const ps = [
'Add-Type -AssemblyName System.IO.Compression.FileSystem',
`[System.IO.Compression.ZipFile]::CreateFromDirectory('${APP_DIR.replace(/'/g, "''")}', '${ZIP.replace(/'/g, "''")}', [System.IO.Compression.CompressionLevel]::Optimal, $false)`,
].join('; ');
execFileSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', ps], { stdio: 'inherit' });
schritt(`Setup ${version} wird gebaut …`);
const stubDir = path.join(WORK, 'stub');
execFileSync('dotnet', [
'build', path.join(ROOT, 'installer', 'AeroMCSetup.csproj'),
'-c', 'Release', `-p:Version=${version}`, '-p:DebugType=none',
'--nologo', '-v', 'q', '-o', stubDir,
], { stdio: 'inherit' });
const stub = path.join(stubDir, 'AeroMC-Setup.exe');
if (!fs.existsSync(stub)) throw new Error('Build des Setups fehlgeschlagen.');
schritt('App wird ans Setup angehängt …');
const zipSize = fs.statSync(ZIP).size;
const footer = Buffer.alloc(16);
footer.writeBigInt64LE(BigInt(zipSize), 0);
MAGIC.copy(footer, 8);
fs.rmSync(OUT, { force: true });
fs.copyFileSync(stub, OUT);
// ZIP in Blöcken anhängen statt komplett in den Speicher zu laden
const fd = fs.openSync(OUT, 'a');
try {
const src = fs.openSync(ZIP, 'r');
try {
const buf = Buffer.alloc(8 * 1024 * 1024);
let n;
while ((n = fs.readSync(src, buf, 0, buf.length, null)) > 0) fs.writeSync(fd, buf, 0, n);
} finally { fs.closeSync(src); }
fs.writeSync(fd, footer);
} finally { fs.closeSync(fd); }
schritt('Aufräumen …');
for (const t of [WORK, APP_DIR, path.join(DIST, 'builder-debug.yml'), path.join(DIST, 'builder-effective-config.yaml')]) {
fs.rmSync(t, { recursive: true, force: true });
}
const mb = (fs.statSync(OUT).size / 1024 / 1024).toFixed(1);
console.log(`\nFertig: ${OUT} (${mb} MB)`);
}
try {
main();
} catch (err) {
console.error(`\nFehler: ${err.message}`);
process.exit(1);
}