#!/usr/bin/env node
'use strict';
// Import a record now without one link whose parent record did not land (an operator choice).
//
// node skills/wix-replatform/scripts/link-waiver.js list --project-dir
[--task ]
// node skills/wix-replatform/scripts/link-waiver.js record --project-dir --task --ref [
// --record [--record ...] --parent
// (the key of the record the dependent links to: a variant's own key, not its product's)
// --decided-by --reason [--explicit-request --warning ]
//
// `list` prints the records the gate holds as dependency-parent-final, with each link's choice:
// `offer-omit` (the cutover task offers importing without the link) or `fix-only` (not offered;
// only on an explicit request, after the warning, with --explicit-request --warning). A link the
// target cannot do without is refused. `record` writes execution/link-waivers.json; the next
// --deferred-only pass of the task writes those records without the link. Nothing here writes to
// the site.
const path = require('node:path');
const fs = require('node:fs');
const waivers = require('../lib/link-waivers.js');
function parseArgs(argv) {
const args = { command: argv[0], records: [] };
for (let i = 1; i < argv.length; i += 1) {
const flag = argv[i];
if (flag === '--project-dir') args.projectDir = path.resolve(argv[++i]);
else if (flag === '--task') args.taskId = argv[++i];
else if (flag === '--ref') args.ref = argv[++i];
else if (flag === '--record') args.records.push(argv[++i]);
else if (flag === '--parent') args.parent = argv[++i];
else if (flag === '--decided-by') args.decidedBy = argv[++i];
else if (flag === '--reason') args.reason = argv[++i];
else if (flag === '--explicit-request') args.explicitRequest = true;
else if (flag === '--warning') args.warning = argv[++i];
else throw new Error(`unknown argument ${flag}`);
}
return args;
}
function diagnostic(projectDir) {
try { return JSON.parse(fs.readFileSync(path.join(projectDir, 'execution/dependency-readiness.json'), 'utf8')); }
catch (error) { if (error.code === 'ENOENT') return { tasks: {} }; throw error; }
}
function main() {
const args = parseArgs(process.argv.slice(2));
if (!args.projectDir || !['list', 'record'].includes(args.command)) throw new Error('usage: link-waiver.js list|record --project-dir ...');
const tasks = diagnostic(args.projectDir).tasks || {};
if (args.command === 'list') {
console.log(JSON.stringify(Object.values(tasks).filter(task => !args.taskId || task.taskId === args.taskId).flatMap(task => (task.finalDeferrals || []).map(row => ({ taskId: task.taskId, ...row }))), null, 2)); return;
}
const task = tasks[args.taskId];
if (!task || !args.ref || !args.parent || !args.records.length) throw new Error('record needs --task, --ref, --record and --parent');
const rows = args.records.map(sourceStableKey => ({ sourceStableKey, ref: args.ref, dependencySourceKey: args.parent }));
console.log(JSON.stringify(waivers.recordLinkWaiver({ projectDir: args.projectDir, siteId: task.siteId, taskId: args.taskId, rows, decidedBy: args.decidedBy, reason: args.reason, explicitRequest: args.explicitRequest === true, warning: args.warning || null }), null, 2));
}
try { main(); } catch (error) { console.error(error.code ? `${error.code}: ${error.message}` : error.message); process.exit(1); }
]