#!/usr/bin/env node 'use strict'; // Run on the host. Authentication stays inside the reader container; no token // appears in command arguments, terminal output or a published daemon port. const { spawnSync } = require('node:child_process'); const path = require('node:path'); const action = process.argv[2] || 'check'; const id = process.argv[3]; if (!['check', 'state', 'pause', 'resume', 'retry'].includes(action) || (action === 'retry' && !id) || (id && !/^[a-zA-Z0-9-]{1,80}$/.test(id))) { console.error('Usage: node tools/compose-control.js check|state|pause|resume|retry '); process.exit(2); } const script = action === 'check' ? "require('./tools/check.js')" : ` const {secret}=require('./runtime/config'); (async()=>{ const action=${JSON.stringify(action)},id=${JSON.stringify(id || null)}; const response=await fetch(process.env.SCRAPER_URL+(action==='state'?'/api/state':'/api/control'),{ method:action==='state'?'GET':'POST',signal:AbortSignal.timeout(20000), headers:{authorization:'Bearer '+secret('SCRAPER_TOKEN'),'content-type':'application/json'}, ...(action==='state'?{}:{body:JSON.stringify({action,id})}) }); if(!response.ok)throw new Error('Scraper returned HTTP '+response.status); const s=await response.json(); const job=j=>j?{updated:j.updated,completed:j.completed,total:j.total,current:j.current,lastChapter:j.lastChapter}:null; console.log(JSON.stringify({version:s.version,status:s.status,paused:s.paused,settings:s.settings, sourcePaused:s.sourcePaused,publishedRevision:s.publishedRevision, active:s.active?.map(a=>({source:a.source,id:a.current?.id,title:a.current?.title,job:job(a.job)})), queue:s.queue?.map(q=>({id:q.id,title:q.title,source:q.source,status:q.status,failure:q.failure, nextAttemptAt:q.nextAttemptAt})), openIncidents:s.incidents?.filter(i=>i.state==='open').map(i=>({kind:i.kind,title:i.title,message:i.message})), runtimeHeartbeat:s.runtimeHeartbeat,nextDiscoveryAt:s.nextDiscoveryAt,libraryStatus:s.libraryStatus},null,2)); })().catch(e=>{console.error(e.message);process.exitCode=1;});`; const result = spawnSync('docker', ['compose', 'exec', '-T', 'reader', 'node', '-e', script], { cwd: path.resolve(__dirname, '..'), encoding: 'utf8', stdio: 'inherit', windowsHide: true, }); if (result.error) console.error(result.error.message); process.exit(result.status ?? 1);