← back to Designerwallcoverings
TK-11397: fix variant-id extraction in resolve-variants.mjs + correct audit note
9b5b1dffd4b57ec77d489bfadb2178b17d9756d5 · 2026-09-23 10:35:39 -0700 · Steve Abrams
resolve-variants.mjs line 23 used match(/\d+/).pop() which extracted the
FIRST digit run (the product id) instead of the variant id from GMC offer keys
shaped shopify_US_<productId>_<variantId>. All 77 prefixed rows failed the
Shopify variant lookup (product_gid/cur_handle/status = null).
Fixed to mirror the robust check-unpub.mjs extraction: take the trailing
variant id via end-anchored match(/_(\d{6,})$/), fall back to bare key.
Verified: all 77 now extract the correct variant id; all 84 bare keys stable;
0 mis-extractions.
Also corrected AUDIT-SUMMARY.md which mis-attributed the nulls to the
canary keying rows with the product id; the key carries both ids — the
script grabbed the wrong one. Note now states the bug, the recovery path,
and that it's been fixed.
Files touched
A scripts/tk11397-gmc-404-batch/resolve-variants.mjs
Diff
commit 9b5b1dffd4b57ec77d489bfadb2178b17d9756d5
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Sep 23 10:35:39 2026 -0700
TK-11397: fix variant-id extraction in resolve-variants.mjs + correct audit note
resolve-variants.mjs line 23 used match(/\d+/).pop() which extracted the
FIRST digit run (the product id) instead of the variant id from GMC offer keys
shaped shopify_US_<productId>_<variantId>. All 77 prefixed rows failed the
Shopify variant lookup (product_gid/cur_handle/status = null).
Fixed to mirror the robust check-unpub.mjs extraction: take the trailing
variant id via end-anchored match(/_(\d{6,})$/), fall back to bare key.
Verified: all 77 now extract the correct variant id; all 84 bare keys stable;
0 mis-extractions.
Also corrected AUDIT-SUMMARY.md which mis-attributed the nulls to the
canary keying rows with the product id; the key carries both ids — the
script grabbed the wrong one. Note now states the bug, the recovery path,
and that it's been fixed.
---
scripts/tk11397-gmc-404-batch/resolve-variants.mjs | 41 ++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/scripts/tk11397-gmc-404-batch/resolve-variants.mjs b/scripts/tk11397-gmc-404-batch/resolve-variants.mjs
new file mode 100644
index 0000000..074ef61
--- /dev/null
+++ b/scripts/tk11397-gmc-404-batch/resolve-variants.mjs
@@ -0,0 +1,41 @@
+// TK-11397 batch: resolve uncovered rename_drift variants -> current product handle
+import { readFileSync, writeFileSync } from 'node:fs';
+const env = readFileSync(process.env.HOME + '/Projects/secrets-manager/.env', 'utf8');
+const TOKEN = (env.match(/^SHOPIFY_FULL_ACCESS_TOKEN=(.+)$/m) || [])[1].replace(/["']/g, '').trim();
+const ENDPOINT = 'https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json';
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+async function gql(query, variables) {
+ for (let a = 0; a < 6; a++) {
+ let r;
+ try { r = await fetch(ENDPOINT, { method: 'POST', headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' }, body: JSON.stringify({ query, variables }) }); }
+ catch (e) { await sleep(1500 * (a + 1)); continue; }
+ if (r.status === 429 || r.status >= 500) { await sleep(1500 * (a + 1)); continue; }
+ const j = await r.json();
+ if (j.errors && !j.data) { await sleep(1200); continue; }
+ return j;
+ }
+ return null;
+}
+const uncovered = JSON.parse(readFileSync('/tmp/tk11397-uncovered-rd.json', 'utf8'));
+const q = `query($id: ID!){ productVariant(id: $id){ id sku product{ id handle status } } }`;
+const out = [];
+for (const row of uncovered) {
+ // offer keys come in two shapes: bare variant id ("42319566798899") or
+ // "shopify_US_<productId>_<variantId>". Take the trailing variant id (mirrors
+ // check-unpub.mjs); a bare `/\d+/` grabbed the FIRST run = the product id → null lookups.
+ const vid = (row.key.match(/_(\d{6,})$/) || [])[1] || row.key;
+ const j = await gql(q, { id: 'gid://shopify/ProductVariant/' + vid });
+ const v = j && j.data && j.data.productVariant;
+ out.push({
+ offer_key: row.key, dead_handle: row.handle, variant_id: vid,
+ serving: row.serving,
+ product_gid: v && v.product ? v.product.id : null,
+ cur_handle: v && v.product ? v.product.handle : null,
+ status: v && v.product ? v.product.status : null,
+ sku: v ? v.sku : null,
+ title: row.title
+ });
+ await sleep(260);
+}
+writeFileSync('resolved-variants.json', JSON.stringify(out, null, 1));
+console.log('resolved:', out.length, '| null product:', out.filter(r => !r.cur_handle).length, '| status:', JSON.stringify(out.reduce((m, r) => (m[r.status] = (m[r.status] || 0) + 1, m), {})));
← 95dfa15 auto-data-snapshot: 2026-09-23T10:35:16 (1 data files) — scr
·
back to Designerwallcoverings
·
auto-data-snapshot: 2026-09-23T11:38:28 (3 data files) — dat b491d3a →