This commit is contained in:
eric
2026-05-21 00:48:55 -05:00
parent e6e4f7a02e
commit c72ef5466a
2 changed files with 85 additions and 1 deletions

View File

@@ -13,7 +13,8 @@
"stage:offline-runtime": "node ./scripts/stage-offline-runtime.mjs",
"prepare:runtime": "node ./scripts/prepare-runtime.mjs",
"verify:runtime": "node ./scripts/verify-runtime.mjs",
"dist": "pnpm run prepare:runtime && pnpm run build && pnpm run gen:icons && pnpm run verify:runtime && electron-builder --win --publish never"
"verify:win-package": "node ./scripts/verify-win-package.mjs",
"dist": "pnpm run prepare:runtime && pnpm run build && pnpm run gen:icons && pnpm run verify:runtime && electron-builder --win --publish never && pnpm run verify:win-package"
},
"dependencies": {
"d3": "^7.9.0",
@@ -81,12 +82,19 @@
],
"win": {
"icon": "build/icon.ico",
"artifactName": "${productName}-Windows-x64-${version}.${ext}",
"target": [
{
"target": "portable",
"arch": [
"x64"
]
},
{
"target": "zip",
"arch": [
"x64"
]
}
]
},

View File

@@ -0,0 +1,76 @@
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const electronRoot = path.resolve(__dirname, '..')
const distRoot = path.join(electronRoot, 'dist')
const unpackedRoot = path.join(distRoot, 'win-unpacked')
const pkg = JSON.parse(fs.readFileSync(path.join(electronRoot, 'package.json'), 'utf8'))
const productName = pkg.build?.productName || pkg.productName || pkg.name
const requiredFiles = [
path.join(unpackedRoot, `${productName}.exe`),
path.join(unpackedRoot, 'ffmpeg.dll'),
path.join(unpackedRoot, 'icudtl.dat'),
path.join(unpackedRoot, 'resources', 'app.asar'),
path.join(unpackedRoot, 'resources', 'backend', 'web2.py'),
]
const pythonCandidates = [
path.join(unpackedRoot, 'resources', 'backend', 'python', 'python.exe'),
path.join(unpackedRoot, 'resources', 'backend', 'python', 'Scripts', 'python.exe'),
]
const ffmpegCandidates = [
path.join(unpackedRoot, 'resources', 'backend', 'ffmpeg', 'ffmpeg.exe'),
path.join(unpackedRoot, 'resources', 'backend', 'ffmpeg', 'bin', 'ffmpeg.exe'),
path.join(unpackedRoot, 'resources', 'backend', 'tools', 'ffmpeg', 'ffmpeg.exe'),
path.join(unpackedRoot, 'resources', 'backend', 'tools', 'ffmpeg', 'bin', 'ffmpeg.exe'),
]
const errors = []
if (!fs.existsSync(unpackedRoot)) {
errors.push(`missing unpacked app directory: ${unpackedRoot}`)
}
for (const file of requiredFiles) {
if (!fs.existsSync(file)) errors.push(`missing required file: ${file}`)
}
if (!pythonCandidates.some((p) => fs.existsSync(p))) {
errors.push(`missing bundled Python executable:\n${pythonCandidates.map((p) => `- ${p}`).join('\n')}`)
}
if (!ffmpegCandidates.some((p) => fs.existsSync(p))) {
errors.push(`missing bundled backend ffmpeg.exe:\n${ffmpegCandidates.map((p) => `- ${p}`).join('\n')}`)
}
const distEntries = fs.existsSync(distRoot) ? fs.readdirSync(distRoot, { withFileTypes: true }) : []
const rootExeArtifacts = distEntries
.filter((e) => e.isFile() && e.name.toLowerCase().endsWith('.exe'))
.map((e) => e.name)
const rootZipArtifacts = distEntries
.filter((e) => e.isFile() && e.name.toLowerCase().endsWith('.zip'))
.map((e) => e.name)
if (!rootExeArtifacts.length) {
errors.push(`missing single-file portable exe in dist root: ${distRoot}`)
}
if (!rootZipArtifacts.length) {
errors.push(`missing complete lazy-package zip in dist root: ${distRoot}`)
}
if (errors.length) {
console.error('[verify:win-package] Windows package check failed:\n')
for (const error of errors) console.error(`- ${error}\n`)
process.exit(1)
}
console.log('[verify:win-package] OK: Windows portable exe, zip package, Electron DLLs, Python, and ffmpeg are present.')
console.log(`[verify:win-package] portable exe: ${rootExeArtifacts.join(', ')}`)
console.log(`[verify:win-package] lazy zip: ${rootZipArtifacts.join(', ')}`)