const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const { spawn } = require('node:child_process'); const axios = require(path.join(process.cwd(), 'node_modules', 'axios')); const { createManagedToolInstaller } = require(path.join(process.cwd(), 'dist', 'main', 'domain', 'managed-tools.js')); const { APPLICATION_TOOL_MANIFEST } = require(path.join(process.cwd(), 'dist', 'main', 'domain', 'tool-manifest.js')); async function downloadFile(url, destinationPath) { const response = await axios.get(url, { responseType: 'stream', timeout: 120000 }); await new Promise((resolve, reject) => { const writer = fs.createWriteStream(destinationPath); response.data.on('error', (err) => { writer.destroy(); reject(err); }); response.data.pipe(writer); writer.on('finish', () => resolve()); writer.on('error', (err) => reject(err)); }); const size = fs.statSync(destinationPath).size; console.log('downloaded', url, '->', destinationPath, size, 'bytes'); } async function extractZip(zipPath, destinationDir) { fs.mkdirSync(destinationDir, { recursive: true }); const command = `Expand-Archive -Path '${zipPath.replace(/'/g, "''")}' -DestinationPath '${destinationDir.replace(/'/g, "''")}' -Force`; await new Promise((resolve, reject) => { const proc = spawn('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', command], { windowsHide: true }); let stderr = ''; proc.stderr?.on('data', (data) => { stderr += data.toString(); }); proc.on('close', (code) => { console.log('extract close code', code, 'stderr:', stderr.trim().slice(0, 500)); if (code === 0) resolve(); else reject(new Error(`Expand-Archive exit code ${code}: ${stderr.trim()}`)); }); proc.on('error', (err) => { console.log('extract spawn error', err.message); reject(err); }); }); } (async () => { console.log('user temp:', os.tmpdir()); const root = fs.mkdtempSync(path.join(os.tmpdir(), 'tvm-diag-repair-')); console.log('sandbox:', root); for (const toolId of ['streamlink', 'ffmpeg']) { const manifest = APPLICATION_TOOL_MANIFEST[toolId]; const installationDirectory = path.join(root, 'tools', toolId); const temporaryDirectory = path.join(root, 'managed-tools-temp'); fs.mkdirSync(installationDirectory, { recursive: true }); fs.mkdirSync(temporaryDirectory, { recursive: true }); const installer = createManagedToolInstaller({ installationDirectory, temporaryDirectory, download: downloadFile, extract: extractZip, diagnostic: (message, details) => console.log('DIAG', toolId, message, JSON.stringify(details)) }); const started = Date.now(); try { const result = await installer.repair(manifest); console.log(toolId, 'repair after', Date.now() - started, 'ms:', JSON.stringify({ success: result.success, error: result.error, detail: result.detail, status: result.status, diagnostics: result.diagnostics }, null, 2)); } catch (error) { console.log(toolId, 'repair THREW after', Date.now() - started, 'ms:', String(error && error.stack || error)); } } fs.rmSync(root, { recursive: true, force: true }); })().catch((error) => { console.error('FATAL', error); process.exitCode = 1; });