← back to Dw Daily Catchup 20260909

scripts/repair-missing-storefront.js

66 lines

'use strict';
const fs = require('node:fs');
const path = require('node:path');
const os = require('node:os');
const vm = require('node:vm');
const assert = require('node:assert/strict');
assert.deepEqual(process.argv.slice(2), ['--commit', '7876575002675']);
const production = path.join(os.homedir(), 'Projects/dw-rotation-activator');
const evidence = path.resolve('verification/tk11326');
const id = 'gid://shopify/Product/7876575002675';
const pub = 'gid://shopify/Publication/22208643184';
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, '');
async function gqlRetry(query, variables) {
  const response = await fetch('https://designer-laboratory-sandbox.myshopify.com/admin/api/2026-07/graphql.json', {
    method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Shopify-Access-Token': token },
    body: JSON.stringify({ query, variables }), signal: AbortSignal.timeout(30000),
  });
  return { status: response.status, json: await response.json() };
}
const query = `query($id:ID!){product(id:$id){id title status handle
 onStore:publishedOnPublication(publicationId:"${pub}")
 onGoogle:publishedOnPublication(publicationId:"gid://shopify/Publication/29646651457")
 images(first:1){nodes{url}} variants(first:100){nodes{id sku title price} pageInfo{hasNextPage}}}}`;
async function read() {
  const r = await gqlRetry(query, { id });
  assert.equal(r.status, 200); assert.equal(r.json.errors, undefined);
  assert.equal(r.json.data.product.id, id);
  return r.json.data.product;
}
async function main() {
  assert.equal(JSON.parse(fs.readFileSync(path.join(production, '.drain.lock/TK-11326-owner.json'))).ticket, 'TK-11326');
  const baseline = JSON.parse(fs.readFileSync(path.join(evidence, 'live-before.json')));
  assert.ok(baseline.predicted.includes(id)); assert.ok(!baseline.controls.includes(id));
  const before = await read();
  assert.equal(before.status, 'ACTIVE'); assert.equal(before.onGoogle, false);
  const ledger = fs.readFileSync(path.join(production, 'out/activation-ledger-2026-09-09.json'), 'utf8');
  fs.writeFileSync(path.join(evidence, 'publication-repair-before.json'), JSON.stringify(before, null, 2) + '\n');
  const source = fs.readFileSync(path.join(production, 'rotate-activate.js'), 'utf8');
  const fn = source.slice(source.indexOf('async function publishToChannels(pid) {'), source.indexOf('// ── load the canonical ordered DRAFT queue'));
  assert.ok(fn.includes('confirmedOnlineStore'));
  const checks = require(path.join(production, 'lib/publication-result.js'));
  const publish = vm.runInNewContext(`(${fn.trim()})`, {
    loadPubs: async () => [{ id: pub, name: 'Online Store' }], gqlRetry, ...checks,
  });
  if (!before.onStore) {
    const result = await publish(id);
    assert.equal(result.published, true, JSON.stringify(result));
  }
  const after = await read();
  assert.equal(after.status, 'ACTIVE'); assert.equal(after.onStore, true); assert.equal(after.onGoogle, false);
  for (const key of ['variants', 'images', 'title', 'handle']) assert.deepEqual(after[key], before[key]);
  assert.equal(fs.readFileSync(path.join(production, 'out/activation-ledger-2026-09-09.json'), 'utf8'), ledger);
  const url = `https://www.designerwallcoverings.com/products/${after.handle}`;
  const response = await fetch(url, { signal: AbortSignal.timeout(30000) });
  assert.equal(response.status, 200); assert.ok((await response.text()).includes(id.split('/').pop()));
  const report = { timestamp: new Date().toISOString(), verdict: 'PASS', product: id,
    mutation: before.onStore ? 'none; already repaired' : 'Publish exact product to Online Store only', before, after,
    ledger_unchanged: true, storefront: { url, status: 200, product_id_found: true },
    runtime_function: 'Actual installed publishToChannels function, exact Online Store-only input',
    rollback: 'Exact prestate saved; reverse would unpublish only this Online Store assignment' };
  fs.writeFileSync(path.join(evidence, 'publication-repair-verified.json'), JSON.stringify(report, null, 2) + '\n');
  console.log(JSON.stringify({ verdict: 'PASS', product: id, storefront: report.storefront, ledger_unchanged: true }));
}
main().catch(e => { console.error(e.stack); process.exitCode = 1; });