← back to Designer Wallcoverings
Archive all 154 live Nicolette Mayer Wallpaper products (Steve: do not show on Shopify)
408f0bb9e70abeb2e4a9255c7c85601848a00465 · 2026-06-12 08:02:39 -0700 · SteveStudio2
Files touched
A shopify/scripts/archive-nicolette-mayer.js
Diff
commit 408f0bb9e70abeb2e4a9255c7c85601848a00465
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Fri Jun 12 08:02:39 2026 -0700
Archive all 154 live Nicolette Mayer Wallpaper products (Steve: do not show on Shopify)
---
shopify/scripts/archive-nicolette-mayer.js | 62 ++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/shopify/scripts/archive-nicolette-mayer.js b/shopify/scripts/archive-nicolette-mayer.js
new file mode 100644
index 00000000..3287a50c
--- /dev/null
+++ b/shopify/scripts/archive-nicolette-mayer.js
@@ -0,0 +1,62 @@
+#!/usr/bin/env node
+/**
+ * archive-nicolette-mayer.js — hide Nicolette Mayer from the DW storefront.
+ *
+ * Steve 2026-06-12: "Do not show nicolette meyer on shopify." 154 ACTIVE
+ * "Nicolette Mayer Wallpaper" products are live (Fabrics already all archived).
+ * This sets status=ARCHIVED on each via Shopify Admin GraphQL — reversible
+ * (flip back to ACTIVE any time). Mirrors the change into local shopify_products.
+ *
+ * Scoped: vendor ILIKE '%nicolette%' AND status='ACTIVE' only. Dry-run unless --go.
+ */
+const https = require('https');
+const fs = require('fs');
+const os = require('os');
+const { execFileSync } = require('child_process');
+
+const GO = process.argv.includes('--go');
+const env = fs.readFileSync(os.homedir() + '/Projects/secrets-manager/.env', 'utf8');
+const TOKEN = (env.match(/^SHOPIFY_ADMIN_TOKEN=(.*)$/m) || [])[1].replace(/['"]/g, '').trim();
+const STORE = 'designer-laboratory-sandbox.myshopify.com', API = '2024-10';
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+const psql = sql => execFileSync('psql', ['-d', 'dw_unified', '-At', '-F', '\t', '-c', sql], { encoding: 'utf8', maxBuffer: 1 << 28 }).trim();
+
+function gql(query, variables) {
+ const d = JSON.stringify({ query, variables });
+ return new Promise(res => {
+ const r = https.request({ host: STORE, path: `/admin/api/${API}/graphql.json`, method: 'POST',
+ headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(d) } },
+ x => { let b = ''; x.on('data', c => b += c); x.on('end', () => { try { res(JSON.parse(b)); } catch { res({}); } }); });
+ r.on('error', () => res({})); r.write(d); r.end();
+ });
+}
+
+const MUT = `mutation($id:ID!){ productUpdate(input:{id:$id, status:ARCHIVED}){ product{id status} userErrors{field message} } }`;
+
+(async () => {
+ const rows = psql(`SELECT DISTINCT shopify_id FROM shopify_products
+ WHERE vendor ILIKE '%nicolette%' AND status='ACTIVE' AND shopify_id IS NOT NULL`);
+ const ids = rows ? rows.split('\n').filter(Boolean) : [];
+ console.log(`Nicolette Mayer ACTIVE products to archive: ${ids.length}`);
+ if (!ids.length) { console.log('nothing to archive'); return; }
+ if (!GO) { console.log('DRY RUN — re-run with --go to archive. Sample:', ids.slice(0, 3).join(', ')); return; }
+
+ let ok = 0, fail = 0;
+ for (const id of ids) {
+ const gid = id.startsWith('gid://') ? id : `gid://shopify/Product/${id}`;
+ const r = await gql(MUT, { id: gid });
+ const ue = r?.data?.productUpdate?.userErrors;
+ if (r?.data?.productUpdate?.product?.status === 'ARCHIVED') {
+ ok++;
+ psql(`UPDATE shopify_products SET status='ARCHIVED' WHERE shopify_id='${id.replace(/'/g, "''")}'`);
+ if (ok % 25 === 0) process.stdout.write(`\r archived ${ok}…`);
+ } else {
+ fail++;
+ console.log(`\n ✗ ${gid} ${JSON.stringify(ue || r).slice(0, 160)}`);
+ }
+ await sleep(250);
+ }
+ console.log(`\n✓ archived ${ok} / ${ids.length} (failed ${fail})`);
+ const remain = psql(`SELECT count(DISTINCT shopify_id) FROM shopify_products WHERE vendor ILIKE '%nicolette%' AND status='ACTIVE'`);
+ console.log(`Nicolette ACTIVE remaining in mirror: ${remain}`);
+})().catch(e => { console.error('ERR', e.message); process.exit(1); });
← f3aead0e vendors: wire Brewster & York (costExpr=cost) — price list a
·
back to Designer Wallcoverings
·
Add dedup-kravet-active.js: dry-run-default tool to archive 6f53fddf →