107 lines
3.5 KiB
JavaScript
Executable File
107 lines
3.5 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/**
|
|
* latest.json 무결성 보장 — 빈 파일·깨진 JSON 방지 (Tauri updater JSON parse 오류 예방)
|
|
*/
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { spawnSync } from 'node:child_process';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
function arg(name, fallback) {
|
|
const i = process.argv.indexOf(name);
|
|
return i >= 0 && process.argv[i + 1] ? process.argv[i + 1] : fallback;
|
|
}
|
|
|
|
const dir = path.resolve(arg('--dir', 'frontend/public/desktop/updates'));
|
|
const version = arg('--version', '0.1.0');
|
|
const rawBaseUrl = arg('--base-url', 'https://stock.exdev.co.kr/desktop/updates');
|
|
const baseUrl = rawBaseUrl.replace(/\/$/, '').replace(/^http:\/\//i, 'https://');
|
|
const notes = arg('--notes', `GoldenChart Desktop ${version}`);
|
|
const latestPath = path.join(dir, 'latest.json');
|
|
const generator = path.join(__dirname, 'generate-desktop-latest-json.mjs');
|
|
|
|
function isValidManifest(obj) {
|
|
return obj
|
|
&& typeof obj === 'object'
|
|
&& typeof obj.version === 'string'
|
|
&& obj.version.trim().length > 0
|
|
&& typeof obj.pub_date === 'string'
|
|
&& obj.platforms
|
|
&& typeof obj.platforms === 'object'
|
|
&& !Array.isArray(obj.platforms);
|
|
}
|
|
|
|
function readManifest() {
|
|
if (!fs.existsSync(latestPath)) return null;
|
|
if (fs.statSync(latestPath).size < 8) return null;
|
|
try {
|
|
const obj = JSON.parse(fs.readFileSync(latestPath, 'utf8'));
|
|
return isValidManifest(obj) ? obj : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function writeManifest(manifest) {
|
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
const tmp = `${latestPath}.tmp`;
|
|
const body = `${JSON.stringify(manifest, null, 2)}\n`;
|
|
if (body.length < 8) throw new Error('refusing to write empty latest.json');
|
|
fs.writeFileSync(tmp, body, 'utf8');
|
|
fs.renameSync(tmp, latestPath);
|
|
}
|
|
|
|
function runGenerate() {
|
|
const r = spawnSync(
|
|
process.execPath,
|
|
[generator, '--version', version, '--dir', dir, '--base-url', baseUrl, '--notes', notes],
|
|
{ encoding: 'utf8' },
|
|
);
|
|
if (r.status === 0) return readManifest();
|
|
return null;
|
|
}
|
|
|
|
function fallbackManifest(existing) {
|
|
return {
|
|
version: existing?.version?.trim() || version,
|
|
notes: existing?.notes?.trim() || notes,
|
|
pub_date: new Date().toISOString(),
|
|
platforms: existing?.platforms && typeof existing.platforms === 'object' ? existing.platforms : {},
|
|
};
|
|
}
|
|
|
|
if (!fs.existsSync(dir)) {
|
|
console.error('[ensure-latest] directory not found:', dir);
|
|
process.exit(1);
|
|
}
|
|
|
|
let manifest = readManifest();
|
|
const platformKeys = manifest ? Object.keys(manifest.platforms) : [];
|
|
|
|
const hasLegacyExdevUrl = manifest && platformKeys.some((k) => {
|
|
const u = manifest.platforms[k]?.url ?? '';
|
|
return /exdev\.co\.kr/i.test(u);
|
|
});
|
|
|
|
if (manifest && platformKeys.length > 0 && !hasLegacyExdevUrl) {
|
|
console.log('[ensure-latest] OK v' + manifest.version + ' platforms=' + platformKeys.join(','));
|
|
process.exit(0);
|
|
}
|
|
|
|
if (hasLegacyExdevUrl) {
|
|
console.warn('[ensure-latest] legacy exdev.co.kr URL in platforms — regenerate');
|
|
}
|
|
|
|
const generated = runGenerate();
|
|
if (generated && Object.keys(generated.platforms).length > 0) {
|
|
console.log('[ensure-latest] regenerated v' + generated.version + ' platforms=' + Object.keys(generated.platforms).join(','));
|
|
process.exit(0);
|
|
}
|
|
|
|
manifest = fallbackManifest(manifest);
|
|
writeManifest(manifest);
|
|
console.warn('[ensure-latest] fallback v' + manifest.version + ' (platforms empty — Jenkins desktop publish 필요)');
|
|
process.exit(2);
|