waffensachkunde
Waffensachkunde – Lernsoftware für die Sachkundeprüfung nach § 7 WaffG. Barrierefrei, offline, EUPL-1.2.
| 1 | # ===================================================================== |
| 2 | # electron-builder – Paketierung für Windows (NSIS) und macOS (DMG) |
| 3 | # --------------------------------------------------------------------- |
| 4 | # CODE-SIGNIERUNG IST BEWUSST DEAKTIVIERT. |
| 5 | # Die Anwendung wird privat weitergegeben, es gibt kein Entwicklerzertifikat. |
| 6 | # Folgen, die den Nutzenden erklärt werden müssen: |
| 7 | # - Windows SmartScreen zeigt beim ersten Start „Windows hat Ihren PC |
| 8 | # geschützt“ → „Weitere Informationen“ → „Trotzdem ausführen“. |
| 9 | # - macOS Gatekeeper blockiert die App → Rechtsklick auf die App → |
| 10 | # „Öffnen“ → im Dialog erneut „Öffnen“ (bzw. Systemeinstellungen → |
| 11 | # Datenschutz & Sicherheit → „Dennoch öffnen“). |
| 12 | # ===================================================================== |
| 13 | |
| 14 | appId: de.willerding.waffensachkunde |
| 15 | productName: Waffensachkunde Lernsoftware |
| 16 | copyright: © 2026 Olaf Willerding |
| 17 | |
| 18 | directories: |
| 19 | output: release |
| 20 | # Bewusst NICHT "build": die .gitignore im Projektwurzelverzeichnis |
| 21 | # ignoriert `build/`, dort abgelegte Icons würden also nie eingecheckt. |
| 22 | # Icons gehören nach build-resources/ (icon.ico für Windows, |
| 23 | # icon.icns bzw. icon.png >= 512x512 für macOS). |
| 24 | buildResources: build-resources |
| 25 | |
| 26 | # Nur die gebauten Bundles paketieren – die Quellen bleiben draußen. |
| 27 | files: |
| 28 | - out/**/* |
| 29 | - package.json |
| 30 | - '!**/*.map' |
| 31 | - '!**/{.eslintrc,.editorconfig,.prettierrc}' |
| 32 | - '!**/{test,tests,__tests__,e2e}/**' |
| 33 | # Die C-Quellen von better-sqlite3 – die SQLite-Amalgamation und der |
| 34 | # Aufsatz darauf. Nachgemessen 9,9 MiB (deps) plus 162 KiB (src) in jedem |
| 35 | # Paket, die nie jemand ausführt: `npmRebuild: false` weiter unten schaltet |
| 36 | # den Bau aus der Quelle ab, und `lib/binding.js` lädt ausschließlich eine |
| 37 | # fertige Datei aus `prebuilds/`. Bis Fassung 0.24.1 wurden sie mitgepackt. |
| 38 | - '!**/node_modules/better-sqlite3/{deps,src}/**' |
| 39 | - '!**/node_modules/better-sqlite3/binding.gyp' |
| 40 | |
| 41 | # Der amtliche Fragenkatalog liegt außerhalb von app/ und wird als Ressource |
| 42 | # mitgepackt. Ziel ist <app>/resources/katalog/ – genau dort sucht |
| 43 | # src/main/katalog.ts, wenn app.isPackaged true ist. Bewusst NICHT im |
| 44 | # asar-Archiv: so bleiben katalog.json und die Prüfzeichen normale Dateien, |
| 45 | # die mit fs gelesen werden können. |
| 46 | extraResources: |
| 47 | - from: ../content/katalog |
| 48 | to: katalog |
| 49 | filter: |
| 50 | - '**/*' |
| 51 | # Erklaerungen zu den Fragen. Eigener redaktioneller Inhalt, deshalb |
| 52 | # getrennt vom amtlichen Katalog; src/main/erklaerungen.ts sucht die |
| 53 | # Datei im gepackten Betrieb direkt unter <app>/resources/. |
| 54 | - from: ../content/erklaerungen.json |
| 55 | to: erklaerungen.json |
| 56 | # Glossar der Fachbegriffe (WCAG 3.1.3 und 3.1.4). |
| 57 | - from: ../content/glossar.json |
| 58 | to: glossar.json |
| 59 | # Die zitierten Normtexte. Ohne sie führte „Im Gesetz nachlesen" ins Leere: |
| 60 | # Eine vollständig offline arbeitende Software forderte zu etwas auf, das |
| 61 | # offline gerade nicht ging. Erzeugt aus content/gesetze/index.json mit |
| 62 | # data-pipeline/normtexte_bauen.py – und nur die zitierten Normen, denn der |
| 63 | # Index führt die sieben Gesetze vollständig, auch katalogfremde Normen. |
| 64 | # Gesetzestexte sind nach § 5 Abs. 1 UrhG gemeinfrei. |
| 65 | - from: ../content/normtexte.json |
| 66 | to: normtexte.json |
| 67 | # Die redaktionelle Feingliederung der Kapitel II bis IV. Der amtliche |
| 68 | # Katalog gliedert nur Kapitel I in Abschnitte; ohne diese Datei laesst sich |
| 69 | # von 230 Fragen nur das ganze Kapitel ueben. |
| 70 | - from: ../content/themen.json |
| 71 | to: themen.json |
| 72 | # Deutsche Fassung der EUPL 1.2 und die Übersicht der Fremdkomponenten. |
| 73 | # Beide zeigt der Bereich „Über diese Software“ an; MIT, BSD und Apache |
| 74 | # verlangen die Mitlieferung ihrer Texte. Ziel ist jeweils |
| 75 | # <app>/resources/ – genau dort sucht src/main/lizenzen.ts im gepackten |
| 76 | # Betrieb. |
| 77 | - from: ../LICENSE.de.txt |
| 78 | to: LICENSE.de.txt |
| 79 | - from: ../content/drittlizenzen.json |
| 80 | to: drittlizenzen.json |
| 81 | # Die Datenschutzerklärung, erzeugt aus docs/datenschutz.md über |
| 82 | # tools/datenschutz_anwendung.py. Bis 0.24.2 war sie in der Anwendung |
| 83 | # nirgends erreichbar: docs/ wird nicht mitgeliefert, und der einzige Weg |
| 84 | # nach außen führt zur Unterstützungsseite. src/main/datenschutz.ts sucht |
| 85 | # die Datei im gepackten Betrieb direkt unter <app>/resources/. |
| 86 | - from: ../content/datenschutz.json |
| 87 | to: datenschutz.json |
| 88 | |
| 89 | # better-sqlite3 ist ein natives Modul und muss außerhalb des asar-Archivs |
| 90 | # liegen, damit der Prozess die .node-Datei laden kann. |
| 91 | asar: true |
| 92 | asarUnpack: |
| 93 | - '**/node_modules/better-sqlite3/**' |
| 94 | |
| 95 | # Kein npmRebuild nötig: better-sqlite3 >= 12 liefert N-API-Prebuilds, die |
| 96 | # ABI-stabil sind und ohne Neubau unter Electron laufen. |
| 97 | npmRebuild: false |
| 98 | |
| 99 | # ── Windows ────────────────────────────────────────────────────────── |
| 100 | win: |
| 101 | # Fremde Fertigteile von better-sqlite3. `lib/binding.js` setzt den |
| 102 | # Dateinamen zur Laufzeit aus `process.platform` und `process.arch` |
| 103 | # zusammen; unter Windows kann also nur `win32-*.node` je geladen werden. |
| 104 | # Die fünf anderen wogen nachgemessen 11,0 MiB im Paket. Beide |
| 105 | # Windows-Architekturen bleiben – das Ziel unten baut zwar nur x64, aber |
| 106 | # diese Liste soll nicht stillschweigend falsch werden, wenn dort arm64 |
| 107 | # dazukommt. |
| 108 | files: |
| 109 | - '!**/node_modules/better-sqlite3/prebuilds/{darwin,linux,linuxmusl}-*.node' |
| 110 | target: |
| 111 | - target: nsis |
| 112 | arch: [x64] |
| 113 | artifactName: ${productName}-${version}-Setup-${arch}.${ext} |
| 114 | # Keine Signierung: weder Zertifikat noch Zeitstempel-Server. |
| 115 | signAndEditExecutable: true |
| 116 | signtoolOptions: null |
| 117 | |
| 118 | nsis: |
| 119 | oneClick: false |
| 120 | perMachine: false |
| 121 | allowToChangeInstallationDirectory: true |
| 122 | allowElevation: true |
| 123 | createDesktopShortcut: true |
| 124 | createStartMenuShortcut: true |
| 125 | shortcutName: Waffensachkunde |
| 126 | deleteAppDataOnUninstall: false |
| 127 | # Deutschsprachiger Installer. |
| 128 | installerLanguages: |
| 129 | - de_DE |
| 130 | language: '1031' # LCID für Deutsch (Deutschland) |
| 131 | |
| 132 | # ── Microsoft Store (AppX/MSIX) ────────────────────────────────────── |
| 133 | # |
| 134 | # WARUM DIESER WEG UND NICHT „EXE or MSI app“ |
| 135 | # Das Partner Center bietet beides an; die einfacher aussehende Option ist |
| 136 | # die teure. Microsoft verlangt für EXE/MSI ein Installationspaket, das von |
| 137 | # einer anerkannten Zertifizierungsstelle signiert ist, das der Betreiber |
| 138 | # selbst dauerhaft hostet (versionierte Adresse je Fassung) und das still |
| 139 | # installiert — der deutschsprachige NSIS-Assistent oben wäre unzulässig. |
| 140 | # Für MSIX übernimmt Microsoft Signierung und Auslieferung kostenlos. |
| 141 | # Begründung samt Belegstellen: docs/store-eintrag.md, Abschnitt 10 Punkt 1. |
| 142 | # |
| 143 | # WARUM NICHT IM `win.target` OBEN |
| 144 | # Ein zusätzliches Ziel dort verdoppelte die Bauzeit jedes gewöhnlichen |
| 145 | # `dist:win`, und `e2e/gepackt.spec.ts` misst ohnehin `release/win-unpacked/` |
| 146 | # aus dem NSIS-Bau. Das Store-Paket entsteht deshalb über einen eigenen |
| 147 | # Aufruf: `npm run dist:store`. |
| 148 | # |
| 149 | # WERKZEUGE |
| 150 | # Keine Installation nötig. `makeappx.exe` und `makepri.exe` bringt |
| 151 | # electron-builder in seinem eigenen Werkzeugpaket mit und lädt es beim |
| 152 | # ersten Lauf. |
| 153 | appx: |
| 154 | # Die drei Werte stammen wörtlich aus dem Partner Center, |
| 155 | # Produktverwaltung → Product Identity. Erfinden geht nicht: Weichen sie |
| 156 | # ab, lehnt der Upload das Paket ab, ohne zu sagen, welcher es war. |
| 157 | identityName: O-W.Waffensachkunde-Lernsoftware-OW |
| 158 | publisher: CN=54A4AD0C-C0C3-49B6-922C-7F62CBEC7197 |
| 159 | publisherDisplayName: O-W |
| 160 | |
| 161 | # ACHTUNG, hier schnappt eine Falle zu: `applicationId` fällt ohne diese |
| 162 | # Zeile auf `identityName` zurück, und electron-builder prüft ihn gegen |
| 163 | # /^([A-Za-z][A-Za-z0-9]*)(\.[A-Za-z][A-Za-z0-9]*)*$/ — **keine |
| 164 | # Bindestriche**, jedes Feld muss mit einem Buchstaben beginnen. Der |
| 165 | # Identitätsname enthält drei Bindestriche und fiele durch. Deshalb steht |
| 166 | # hier ein eigener, gültiger Wert; er ist nur programmintern und erscheint |
| 167 | # nirgends für Nutzende. |
| 168 | applicationId: WaffensachkundeLernsoftware |
| 169 | |
| 170 | displayName: Waffensachkunde Lernsoftware |
| 171 | # Kachelfarbe. `#1f2933` ist der dunkle Grundton der Anwendung; die |
| 172 | # Store-Kachel soll nicht heller strahlen als das Programm dahinter. |
| 173 | backgroundColor: '#1f2933' |
| 174 | languages: |
| 175 | - de-DE |
| 176 | |
| 177 | # Untergrenze des Betriebssystems. Ohne diese Zeile setzt electron-builder |
| 178 | # für x64 pauschal `10.0.14316.0` (AppxTarget.js) – eine Insider-Fassung |
| 179 | # von 2016. Der Store lässt die Installation dann auf Maschinen zu, auf |
| 180 | # denen die mitgelieferte Chromium-Fassung 150 gar nicht startet: Sie |
| 181 | # verlangt **Windows 10 1809 (Build 17763)**, so wie es |
| 182 | # `docs/store-eintrag.md` 8.4 auch als Systemanforderung angibt. Der |
| 183 | # Unterschied fiele nicht beim Bauen auf, sondern beim Anwender – als |
| 184 | # Programm, das sich installieren lässt und nicht startet. |
| 185 | minVersion: 10.0.17763.0 |
| 186 | # Getestet ist bislang ausschließlich unter Windows 11; die Angabe bleibt |
| 187 | # deshalb bei der Untergrenze, statt eine Erprobung zu behaupten, die es |
| 188 | # nicht gibt. Ein Durchlauf unter Windows 10 steht aus |
| 189 | # (`docs/store-eintrag.md`, Abschnitt 10 Punkt 5). |
| 190 | maxVersionTested: 10.0.17763.0 |
| 191 | |
| 192 | # Der Dateiname erbt sonst `win.artifactName` und hieße „…-Setup-x64.appx“. |
| 193 | # Ein Store-Paket ist kein Setup; wer beide Dateien nebeneinander liegen |
| 194 | # hat, soll sie am Namen unterscheiden können. |
| 195 | artifactName: ${productName}-${version}-Store-${arch}.${ext} |
| 196 | |
| 197 | # ── macOS ──────────────────────────────────────────────────────────── |
| 198 | mac: |
| 199 | # Dieselbe Rechnung wie unter Windows, gespiegelt: Unter macOS kann nur |
| 200 | # `darwin-*.node` geladen werden. Beide darwin-Fertigteile bleiben, denn |
| 201 | # das Ziel unten baut arm64 **und** x64. |
| 202 | files: |
| 203 | - '!**/node_modules/better-sqlite3/prebuilds/{win32,linux,linuxmusl}-*.node' |
| 204 | target: |
| 205 | - target: dmg |
| 206 | arch: [arm64, x64] |
| 207 | category: public.app-category.education |
| 208 | artifactName: ${productName}-${version}-${arch}.${ext} |
| 209 | # `identity: null` schaltet die Signierung explizit ab. |
| 210 | identity: null |
| 211 | # Hardened Runtime und Notarisierung setzen eine Signierung voraus und |
| 212 | # sind deshalb ebenfalls aus. |
| 213 | hardenedRuntime: false |
| 214 | gatekeeperAssess: false |
| 215 | notarize: false |
| 216 | |
| 217 | dmg: |
| 218 | artifactName: ${productName}-${version}-${arch}.${ext} |
| 219 | contents: |
| 220 | - x: 140 |
| 221 | y: 200 |
| 222 | type: file |
| 223 | - x: 400 |
| 224 | y: 200 |
| 225 | type: link |
| 226 | path: /Applications |
| 227 | |
| 228 | # Keine automatischen Updates – die App wird manuell verteilt. |
| 229 | publish: null |