← back to Dw Activation Debug TK11314
scripts/verify-live-boundary.js
64 lines
#!/usr/bin/env node
'use strict';
const fs = require('node:fs');
const path = require('node:path');
const os = require('node:os');
const assert = require('node:assert/strict');
const { completeLiveProduct, canonicalProduct, widthFromLive } = require('../lib/live-product-fields');
const env = fs.readFileSync(path.join(os.homedir(), 'Projects/secrets-manager/.env'), 'utf8');
const token = (env.match(/^SHOPIFY_ADMIN_TOKEN=(.*)$/m) || [])[1]?.trim().replace(/^['"]|['"]$/g, '');
const source = fs.readFileSync(path.join(__dirname, '..', 'rotate-activate.js'), 'utf8');
const query = source.match(/const STATUS_Q = `([\s\S]+?)`;/)?.[1];
if (!query) throw new Error('Actual runtime query not found');
const snapshot = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
const validator = require(path.resolve(process.argv[3]));
const output = process.argv[4];
let requests = 0;
const costs = [];
async function read(query, variables) {
assert.match(query, /^query\(/); assert.doesNotMatch(query, /\bmutation\b/);
requests++;
const response = await fetch('https://designer-laboratory-sandbox.myshopify.com/admin/api/2026-07/graphql.json', {
method: 'POST', headers: { 'X-Shopify-Access-Token': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables }), signal: AbortSignal.timeout(30000),
});
const json = await response.json();
if (json.extensions?.cost) costs.push(json.extensions.cost.requestedQueryCost);
return { status: response.status, json };
}
async function main() {
const special = snapshot.products.filter(p => p.variants.nodes.length > 20 || p.metafields.nodes.length > 80 ||
['7867560886323','7923565461555','7896454332467','7944491794483'].some(id => p.id.endsWith('/'+id)));
const ids = [...new Set([...special, ...snapshot.products].map(p => p.id))].slice(0, 50);
const first = await read(query, { ids });
assert.equal(first.status, 200); assert.equal(first.json.errors, undefined, JSON.stringify(first.json.errors));
assert.equal(first.json.data.nodes.length, ids.length);
const products = [];
for (const initial of first.json.data.nodes) {
const complete = await completeLiveProduct(initial, read);
assert.equal(complete.variants.pageInfo.hasNextPage, false);
assert.equal(complete.metafields.pageInfo.hasNextPage, false);
const result = validator.validateBeforeActivate(canonicalProduct(complete, '', complete.vendor));
products.push({ id: complete.id, status: complete.status, vendor: complete.vendor,
variants_before: initial.variants.nodes.length, variants_after: complete.variants.nodes.length,
metafields_before: initial.metafields.nodes.length, metafields_after: complete.metafields.nodes.length,
width: widthFromLive(complete), reasons: result.reasons });
}
const designtex = products.find(p => p.id.endsWith('/7867560886323'));
assert.ok(!designtex.reasons.some(r => /legal\/disclaimer/.test(r)));
const carnegie = products.find(p => p.id.endsWith('/7923565461555'));
assert.equal(carnegie.width.source, 'dwc.width');
const fischbacher = products.find(p => p.id.endsWith('/7896454332467'));
assert.ok(fischbacher.reasons.includes('empty description'));
assert.ok(products.every(p => p.status === 'DRAFT'));
const report = { timestamp: new Date().toISOString(), verdict: 'PASS',
scope: 'Actual runtime Shopify batch query + real pagination + corrected validator; no activation or vision call',
requests, requested_query_costs: costs, graphql_mutations: 0, vision_calls: 0, products };
fs.writeFileSync(output, JSON.stringify(report, null, 2) + '\n');
console.log(JSON.stringify({ verdict: report.verdict, products: products.length, requests,
paginated_variants: products.filter(p => p.variants_after > p.variants_before).length,
paginated_metafields: products.filter(p => p.metafields_after > p.metafields_before).length,
max_query_cost: Math.max(...costs), output }));
}
main().catch(error => { console.error(error.message); process.exitCode = 1; });