← back to Tk 10965 Zero Price Analysis

cli-args.mjs

30 lines

export const USAGE = `Usage: node apply-fix.mjs <mode> [options]
  --help                 Show usage without initialization
  --plan | --enumerate   Validate frozen manifest and print plan; no adapter or journal
  --canary | --all       Execute frozen canary membership or complete manifest OFFLINE
  --rollback             Restore only confirmed journal successes OFFLINE
Required: --manifest FILE --expected-sha256 HASH --expected-store-id SHOP_GID
Execution: --offline-state FILE --journal FILE
Existing journal: --journal-sha256 HASH (external checkpoint required)
Live execution is disabled. Legacy scans, numeric canaries and restore maps are refused.`;
export function parseArgs(args) {
  const [mode, ...rest] = args;
  if (!['--help','--plan','--enumerate','--canary','--all','--rollback'].includes(mode)) throw new Error('A recognized mode is required.');
  if (mode === '--help') { if (rest.length) throw new Error('Unexpected arguments.'); return {mode}; }
  const cli = {mode};
  const options = new Set(['--manifest','--expected-sha256','--expected-store-id','--offline-state','--journal','--journal-sha256']);
  for (let i=0;i<rest.length;i+=2) {
    const [k,v] = rest.slice(i,i+2);
    if (!options.has(k) || Object.hasOwn(cli,k) || !v?.trim() || v.startsWith('-')) throw new Error('Invalid, duplicate or missing option: ' + k);
    cli[k] = v;
  }
  for (const k of ['--manifest','--expected-sha256','--expected-store-id']) if (!cli[k]) throw new Error('Required: ' + k);
  for (const k of ['--expected-sha256','--journal-sha256']) if (cli[k] && !/^[a-f0-9]{64}$/.test(cli[k])) throw new Error('Invalid SHA256: '+k);
  if (!/^gid:\/\/shopify\/Shop\/[1-9][0-9]*$/.test(cli['--expected-store-id'])) throw new Error('Invalid expected store ID.');
  const plan = ['--plan','--enumerate'].includes(mode);
  if (plan && ['--offline-state','--journal','--journal-sha256'].some(k=>cli[k])) throw new Error('Plan cannot initialize adapter or journal.');
  if (!plan && (!cli['--offline-state'] || !cli['--journal'])) throw new Error('Live execution disabled; offline-state and journal required.');
  if (mode==='--rollback' && !cli['--journal-sha256']) throw new Error('Rollback requires pinned journal SHA256.');
  return cli;
}