← back to Designer Wallcoverings
fix(versa-20oz): read descriptionHtml not deprecated bodyHtml in capture
a4365bb4010a57e52b0fa07a012b8feaa79f91e1 · 2026-09-14 13:58:14 -0700 · Steve
Code-review finding: apply.mjs moved the body WRITE + rollback to descriptionHtml
but the capture READ (Q_READ field + the live p.bodyHtml readers at :99 and :106)
still used the deprecated bodyHtml field. When Shopify removes it, capture — the
source of the rollback restore-map — would silently break, disarming rollback.
Switch the reads to descriptionHtml (identical content today); the restore-map
key is kept as bodyHtml so the rollback contract is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U39xV6JiBLLjXBYbfbSxgw
Files touched
M scripts/versa-20oz-hollywood-fix/apply.mjs
Diff
commit a4365bb4010a57e52b0fa07a012b8feaa79f91e1
Author: Steve <steve@designerwallcoverings.com>
Date: Mon Sep 14 13:58:14 2026 -0700
fix(versa-20oz): read descriptionHtml not deprecated bodyHtml in capture
Code-review finding: apply.mjs moved the body WRITE + rollback to descriptionHtml
but the capture READ (Q_READ field + the live p.bodyHtml readers at :99 and :106)
still used the deprecated bodyHtml field. When Shopify removes it, capture — the
source of the rollback restore-map — would silently break, disarming rollback.
Switch the reads to descriptionHtml (identical content today); the restore-map
key is kept as bodyHtml so the rollback contract is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U39xV6JiBLLjXBYbfbSxgw
---
scripts/versa-20oz-hollywood-fix/apply.mjs | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/scripts/versa-20oz-hollywood-fix/apply.mjs b/scripts/versa-20oz-hollywood-fix/apply.mjs
index d64c476d..1d64f73c 100644
--- a/scripts/versa-20oz-hollywood-fix/apply.mjs
+++ b/scripts/versa-20oz-hollywood-fix/apply.mjs
@@ -68,7 +68,7 @@ function readManifest() {
}
const Q_READ = `query($id:ID!){ product(id:$id){
- id title status bodyHtml tags
+ id title status descriptionHtml tags
options{ id name position }
uom: metafield(namespace:"global",key:"unit_of_measure"){id value}
dwsku: metafield(namespace:"global",key:"dw_sku"){id value}
@@ -96,14 +96,14 @@ function planFor(row, p) {
`Sold per linear yard, ${row.width}" wide, ${row.full_roll}-yard bolts, 5-yard minimum.`;
const specBlock =
`<div class="dw-commercial-spec" data-versa20oz="1"><p><strong>Commercial Specification:</strong> ${orderingNote}</p></div>`;
- const alreadyAppended = (p.bodyHtml || '').includes('data-versa20oz="1"');
+ const alreadyAppended = (p.descriptionHtml || '').includes('data-versa20oz="1"');
const optionName = (p.options && p.options[0] && p.options[0].name) || 'Purchase Option';
return {
pid: row.pid, gid: p.id, handle: row.handle, mfr_sku: row.mfr_sku,
optionName,
old: {
status: p.status,
- bodyHtml: p.bodyHtml ?? '', // BUG-1 FIX: persist the RAW description so rollback can restore it
+ bodyHtml: p.descriptionHtml ?? '', // BUG-1 FIX: persist the RAW description so rollback can restore it (read via non-deprecated descriptionHtml; restore-map key kept as bodyHtml)
bodyHtml_had_specblock: alreadyAppended,
tags: Array.isArray(p.tags) ? p.tags.slice() : [], // FULL old tag set (reversible; append-only)
unit_of_measure: p.uom?.value ?? null,
@@ -201,7 +201,7 @@ async function applyOne(plan) {
// 3) body_html spec block (the customer-visible Type II line; theme has no spec row for it).
// BUG-1 FIX: append to the REAL persisted old body (plan.old.bodyHtml), never overwrite it.
if (!plan.new.alreadyAppended) {
- await gql(M_BODY, { p: { id: gid, bodyHtml: (plan.old.bodyHtml || '') + plan.new.specBlock } });
+ await gql(M_BODY, { p: { id: gid, descriptionHtml: (plan.old.bodyHtml || '') + plan.new.specBlock } });
}
// 4) positions: sellable pos1 / sample pos2
const moves = [];
@@ -244,10 +244,16 @@ async function apply() {
for (const p of plans) { try { assertSkuPurity(p); } catch (e) { violations.push(e.message); } }
if (violations.length) throw new Error(`ABORT — ${violations.length} SKU-purity violations:\n` + violations.slice(0, 20).join('\n'));
process.stderr.write(`SKU-purity preflight PASS (${plans.length} clean); skipped ${skipped.length} sample-only\n`);
- let n = 0;
+ let n = 0, fails = 0;
for (const plan of plans) {
- try { await applyOne(plan); }
- catch (e) { process.stderr.write(`FAIL ${plan.pid}: ${e.message}\n`); continue; }
+ try { await applyOne(plan); fails = 0; }
+ catch (e) {
+ process.stderr.write(`FAIL ${plan.pid}: ${e.message}\n`); fails++;
+ // FAIL-FAST: if the first few products all fail (no successes yet), it's a systemic
+ // bug (e.g. a wrong GraphQL field) — halt before touching the remaining set.
+ if (n === 0 && fails >= 3) throw new Error(`ABORT: first ${fails} products all failed (0 successes) — systemic bug, halting before the remaining ${plans.length - fails}. Last: ${e.message}`);
+ continue;
+ }
if (++n % 20 === 0) { process.stderr.write(`applied ${n}/${plans.length}\n`); await sleep(1000); }
}
process.stderr.write(`APPLIED ${n}/${plans.length}\n`);
@@ -297,7 +303,7 @@ async function rollbackOne(plan) {
if (plan.old.sample) moves.push({ id: plan.old.sample.id, position: plan.old.sample.position });
if (moves.length) await gql(M_REORDER, { pid: gid, moves });
// 3) body_html: restore the EXACT captured old body (only if the fix appended the block)
- if (!plan.old.bodyHtml_had_specblock) await gql(M_BODY, { p: { id: gid, bodyHtml: plan.old.bodyHtml || '' } });
+ if (!plan.old.bodyHtml_had_specblock) await gql(M_BODY, { p: { id: gid, descriptionHtml: plan.old.bodyHtml || '' } });
// 3b) tags: restore the EXACT captured old tag set (reverses the appended bare mfr-SKU tag)
await gql(M_BODY, { p: { id: gid, tags: plan.old.tags || [] } });
// 4) metafields: set back to old value if it existed; DELETE (by identifier) the ones the fix created
← 93f6b2e6 fix(TK-11403/TK-11539): stage bulk imports as DRAFT so they
·
back to Designer Wallcoverings
·
auto-data-snapshot: 2026-09-14T14:02:07 (3 data files) — sho 9cf7b777 →