[object Object]

← back to Dw Sarah Rowland Searchfix

auto-save: 2026-07-30T09:16:33 (8 files) — build-titles.mjs color-map.tsv dump-skus.mjs generic-skus.txt inspect-titles.mjs

4f76e346f29fbf2d82f3f8c98bfe68652d1952e8 · 2026-07-30 09:16:38 -0700 · Steve Abrams

Files touched

Diff

commit 4f76e346f29fbf2d82f3f8c98bfe68652d1952e8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Jul 30 09:16:38 2026 -0700

    auto-save: 2026-07-30T09:16:33 (8 files) — build-titles.mjs color-map.tsv dump-skus.mjs generic-skus.txt inspect-titles.mjs
---
 build-titles.mjs          |  23 +++++
 color-map.tsv             |  35 ++++++++
 dump-skus.mjs             |  10 +++
 generic-skus.txt          |  37 ++++++++
 inspect-titles.mjs        |  21 +++++
 list-collections.mjs      |  12 +++
 title-plan.json           | 224 ++++++++++++++++++++++++++++++++++++++++++++++
 vendor-of-collections.mjs |  15 ++++
 8 files changed, 377 insertions(+)

diff --git a/build-titles.mjs b/build-titles.mjs
new file mode 100644
index 0000000..c4ee977
--- /dev/null
+++ b/build-titles.mjs
@@ -0,0 +1,23 @@
+import { gql } from './lib.mjs'; import fs from 'node:fs';
+const products=JSON.parse(fs.readFileSync(new URL('./products.json',import.meta.url)));
+const generic=products.filter(p=>p.title.trim()==='Wallcovering | Architectural Wallcoverings');
+const colorMap=Object.fromEntries(fs.readFileSync(new URL('./color-map.tsv',import.meta.url),'utf8')
+  .trim().split('\n').filter(Boolean).map(l=>l.split('\t')));
+const titleCase=(s)=>s.split(' ').map(w=>w?w[0].toUpperCase()+w.slice(1):w).join(' ');
+const plan=[];
+for(const p of generic){
+  const d=(await gql(`query($id:ID!){product(id:$id){handle variants(first:1){nodes{sku}}}}`,{id:p.id})).product;
+  const sku=d.variants.nodes[0]?.sku;
+  // handle -> pattern+colorway: strip prefix up to 'sarah-rowland-' and trailing '-srd-xxx-NN'
+  let mid=d.handle.replace(/^.*sarah-rowland-/,'').replace(/-srd-[a-z0-9]+-\d+.*$/,'').replace(/-(sample|architectural-wallcoverings).*$/,'');
+  const name=titleCase(mid.replace(/-/g,' ').trim());
+  const fam=colorMap[sku]||'';
+  const title = fam ? `${name} - ${fam} Commercial Wallcovering | Koroseal`
+                    : `${name} Commercial Wallcovering | Koroseal`;
+  plan.push({id:p.id, sku, handle:d.handle, title});
+}
+fs.writeFileSync(new URL('./title-plan.json',import.meta.url), JSON.stringify(plan,null,2));
+console.log(`Proposed titles (${plan.length}):\n`);
+plan.forEach(x=>console.log(`  ${x.sku}  ${x.title}`));
+const noFam=plan.filter(x=>!/ - /.test(x.title));
+if(noFam.length) console.log(`\n⚠ ${noFam.length} without a color family (no DB color_name): ${noFam.map(x=>x.sku).join(', ')}`);
diff --git a/color-map.tsv b/color-map.tsv
new file mode 100644
index 0000000..6f5cd76
--- /dev/null
+++ b/color-map.tsv
@@ -0,0 +1,35 @@
+DWK-302550	Off-White
+DWK-302560	Taupe
+DWK-302570	Black
+DWK-302580	Pale Green
+DWK-302600	Light Gray
+DWK-302670	Off-White
+DWK-302671	Sage Green
+DWK-302680	Off-White
+DWK-302720	Off-White
+DWK-302730	Pale Beige
+DWK-302750	White
+DWK-302760	Off-White
+DWK-302780	White
+DWK-302840	Pale Blue
+DWK-302860	Dark Slate Gray
+DWK-302880	Light Gray
+DWK-302890	Light Gray
+DWK-302900	Pale Yellow
+DWK-302910	Pale Olive
+DWK-302920	Gray
+DWK-302930	Off-White
+DWK-302940	White
+DWK-302960	Taupe
+DWK-302970	White
+DWK-302980	Khaki
+DWK-303010	Gray
+DWK-303020	Pale Beige
+DWK-303040	Steel Blue
+DWK-303050	Off-White
+DWK-303070	Light Gray
+DWK-303080	White
+DWK-303090	Beige
+DWK-303100	Light Gray
+DWK-303120	Beige
+DWK-303172	White
diff --git a/dump-skus.mjs b/dump-skus.mjs
new file mode 100644
index 0000000..6eaca8c
--- /dev/null
+++ b/dump-skus.mjs
@@ -0,0 +1,10 @@
+import { gql } from './lib.mjs'; import fs from 'node:fs';
+const products=JSON.parse(fs.readFileSync(new URL('./products.json',import.meta.url)));
+const generic=products.filter(p=>p.title.trim()==='Wallcovering | Architectural Wallcoverings');
+const out=[];
+for(const p of generic){
+  const d=(await gql(`query($id:ID!){product(id:$id){variants(first:1){nodes{sku}}}}`,{id:p.id})).product;
+  out.push(d.variants.nodes[0]?.sku);
+}
+fs.writeFileSync(new URL('./generic-skus.txt',import.meta.url), out.filter(Boolean).join('\n'));
+console.log('wrote', out.length, 'skus');
diff --git a/generic-skus.txt b/generic-skus.txt
new file mode 100644
index 0000000..352bbeb
--- /dev/null
+++ b/generic-skus.txt
@@ -0,0 +1,37 @@
+DWK-302940
+DWK-303100
+DWK-303050
+DWK-303020
+DWK-302920
+DWK-302860
+DWK-303172
+DWK-302580
+DWK-303120
+DWK-302680
+DWK-303090
+DWK-303080
+DWK-303070
+DWK-302570
+DWK-303040
+DWK-303010
+DWK-302970
+DWK-302671
+DWK-302670
+DWK-302980
+DWK-302930
+DWK-302900
+DWK-302890
+DWK-302910
+DWK-302960
+DWK-302600
+DWK-302880
+DWK-302840
+DWK-302560
+DWK-302550
+DWK-302780
+DWK-302760
+DWK-302730
+DWK-302750
+DWK-302720
+DWK-302540-Sample
+DWK-302700-Sample
\ No newline at end of file
diff --git a/inspect-titles.mjs b/inspect-titles.mjs
new file mode 100644
index 0000000..bf795cd
--- /dev/null
+++ b/inspect-titles.mjs
@@ -0,0 +1,21 @@
+import { gql } from './lib.mjs';
+import fs from 'node:fs';
+const products=JSON.parse(fs.readFileSync(new URL('./products.json',import.meta.url)));
+const generic=products.filter(p=>/^Wallcovering \| Architectural Wallcoverings\s*$/.test(p.title.trim()) || p.title.trim()==='Wallcovering | Architectural Wallcoverings');
+console.log(`Bare-title products: ${generic.length} of ${products.length}\n`);
+// what naming data exists? sample the first 6
+const Q=`query($id:ID!){ product(id:$id){ handle title
+  pat:metafield(namespace:"custom",key:"pattern_name"){value}
+  patD:metafield(namespace:"dwc",key:"pattern_name"){value}
+  col:metafield(namespace:"custom",key:"color"){value}
+  colway:metafield(namespace:"custom",key:"color_way"){value}
+  mfrpat:metafield(namespace:"custom",key:"mfr_pattern_number"){value}
+  sku:variants(first:1){nodes{sku}} } }`;
+for(const p of generic.slice(0,6)){
+  const d=(await gql(Q,{id:p.id})).product;
+  console.log(`handle: ${d.handle}`);
+  console.log(`   pattern_name(custom)=${d.pat?.value??'∅'}  pattern_name(dwc)=${d.patD?.value??'∅'}  color=${d.col?.value??'∅'}  color_way=${d.colway?.value??'∅'}  sku=${d.sku.nodes[0]?.sku??'∅'}`);
+}
+// also show 3 well-formed siblings for the naming CONVENTION
+console.log('\n— well-formed sibling titles for reference —');
+products.filter(p=>/ - .*Wallcovering/i.test(p.title)).slice(0,4).forEach(p=>console.log('  ',p.title));
diff --git a/list-collections.mjs b/list-collections.mjs
new file mode 100644
index 0000000..1baeba9
--- /dev/null
+++ b/list-collections.mjs
@@ -0,0 +1,12 @@
+import { gql } from './lib.mjs';
+const Q=`query($c:String){ collections(first:250, after:$c){ pageInfo{hasNextPage endCursor}
+  nodes{ id title handle productsCount{count} } } }`;
+let cur=null, all=[];
+do{ const d=await gql(Q,{c:cur}); all.push(...d.collections.nodes);
+  cur=d.collections.pageInfo.hasNextPage?d.collections.pageInfo.endCursor:null; }while(cur);
+console.log('total collections:', all.length);
+// heuristic: designer lines often end in "Collection" or "Wallcovering Collection"
+const cand=all.filter(c=>/collection/i.test(c.title) && c.productsCount.count>0)
+  .sort((a,b)=>a.title.localeCompare(b.title));
+console.log('\ncandidate designer/named collections:');
+cand.forEach(c=>console.log(`  ${String(c.productsCount.count).padStart(4)}  ${c.title}   [${c.handle}]`));
diff --git a/title-plan.json b/title-plan.json
new file mode 100644
index 0000000..c45c405
--- /dev/null
+++ b/title-plan.json
@@ -0,0 +1,224 @@
+[
+  {
+    "id": "gid://shopify/Product/7634022137907",
+    "sku": "DWK-302940",
+    "handle": "dwk-302940-koroseal-sarah-rowland-lilly-black-white-srd-ll3-01",
+    "title": "Lilly Black White - White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023940147",
+    "sku": "DWK-303100",
+    "handle": "dwk-303100-koroseal-sarah-rowland-ruby-bubblegum-ruby-dark-chocolate-srd-rub-01",
+    "title": "Ruby Bubblegum Ruby Dark Chocolate - Light Gray Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023383091",
+    "sku": "DWK-303050",
+    "handle": "dwk-303050-koroseal-sarah-rowland-molly-indigo-srd-mo1-01",
+    "title": "Molly Indigo - Off-White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023317555",
+    "sku": "DWK-303020",
+    "handle": "dwk-303020-koroseal-sarah-rowland-mary-margaret-taupe-srd-mma-01",
+    "title": "Mary Margaret Taupe - Pale Beige Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634022072371",
+    "sku": "DWK-302920",
+    "handle": "dwk-302920-koroseal-sarah-rowland-leo-black-gray-srd-leo-03",
+    "title": "Leo Black Gray - Gray Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634020040755",
+    "sku": "DWK-302860",
+    "handle": "dwk-302860-koroseal-sarah-rowland-harry-midnight-bark-srd-har-03",
+    "title": "Harry Midnight Bark - Dark Slate Gray Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634025480243",
+    "sku": "DWK-303172",
+    "handle": "dwk-303172-koroseal-sarah-rowland-zak-black-white-srd-zak-04",
+    "title": "Zak Black White - White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634024693811",
+    "sku": "DWK-302580",
+    "handle": "dwk-302580-koroseal-sarah-rowland-scarlett-mary-margaret-green-srd-smm-01",
+    "title": "Scarlett Mary Margaret Green - Pale Green Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634024005683",
+    "sku": "DWK-303120",
+    "handle": "dwk-303120-koroseal-sarah-rowland-sasha-2-taupe-soft-blue-srd-sa2-01",
+    "title": "Sasha 2 Taupe Soft Blue - Beige Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023907379",
+    "sku": "DWK-302680",
+    "handle": "dwk-302680-koroseal-sarah-rowland-roo-2-orange-srd-ro2-01",
+    "title": "Roo 2 Orange - Off-White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023841843",
+    "sku": "DWK-303090",
+    "handle": "dwk-303090-koroseal-sarah-rowland-roo-1-bone-srd-ro1-01",
+    "title": "Roo 1 Bone - Beige Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023710771",
+    "sku": "DWK-303080",
+    "handle": "dwk-303080-koroseal-sarah-rowland-renata-orange-blue-srd-ren-02",
+    "title": "Renata Orange Blue - White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023481395",
+    "sku": "DWK-303070",
+    "handle": "dwk-303070-koroseal-sarah-rowland-plato-spring-bone-srd-pla-03",
+    "title": "Plato Spring Bone - Light Gray Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023448627",
+    "sku": "DWK-302570",
+    "handle": "dwk-302570-koroseal-sarah-rowland-napoleon-edward-black-srd-npe-01",
+    "title": "Napoleon Edward Black - Black Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634023055411",
+    "sku": "DWK-303040",
+    "handle": "dwk-303040-koroseal-sarah-rowland-medium-chloe-storm-srd-mch-03",
+    "title": "Medium Chloe Storm - Steel Blue Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634022858803",
+    "sku": "DWK-303010",
+    "handle": "dwk-303010-koroseal-sarah-rowland-maria-gray-gold-srd-mar-05",
+    "title": "Maria Gray Gold - Gray Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634022596659",
+    "sku": "DWK-302970",
+    "handle": "dwk-302970-koroseal-sarah-rowland-littlhesta-squash-srd-lth-01",
+    "title": "Littlhesta Squash - White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634022334515",
+    "sku": "DWK-302671",
+    "handle": "dwk-302671-koroseal-sarah-rowland-linus-stripe-green-srd-lnu-02",
+    "title": "Linus Stripe Green - Sage Green Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634022268979",
+    "sku": "DWK-302670",
+    "handle": "dwk-302670-koroseal-sarah-rowland-linus-stripe-neutral-srd-lns-01",
+    "title": "Linus Stripe Neutral - Off-White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634022170675",
+    "sku": "DWK-302980",
+    "handle": "dwk-302980-koroseal-sarah-rowland-little-nora-buff-srd-lno-03",
+    "title": "Little Nora Buff - Khaki Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634022105139",
+    "sku": "DWK-302930",
+    "handle": "dwk-302930-koroseal-sarah-rowland-lilly-white-srd-ll1-01",
+    "title": "Lilly White - Off-White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634022039603",
+    "sku": "DWK-302900",
+    "handle": "dwk-302900-koroseal-sarah-rowland-leif-5-denim-srd-le5-01",
+    "title": "Leif 5 Denim - Pale Yellow Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634021941299",
+    "sku": "DWK-302890",
+    "handle": "dwk-302890-koroseal-sarah-rowland-leif-3-mud-srd-le3-01",
+    "title": "Leif 3 Mud - Light Gray Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634021842995",
+    "sku": "DWK-302910",
+    "handle": "dwk-302910-koroseal-sarah-rowland-leif-dottie-gray-bone-srd-ldo-01",
+    "title": "Leif Dottie Gray Bone - Pale Olive Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634021711923",
+    "sku": "DWK-302960",
+    "handle": "dwk-302960-koroseal-sarah-rowland-littlbeb-bone-charcoal-srd-lbe-04",
+    "title": "Littlbeb Bone Charcoal - Taupe Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634020532275",
+    "sku": "DWK-302600",
+    "handle": "dwk-302600-koroseal-sarah-rowland-haze-2-taupe-srd-hz2-01",
+    "title": "Haze 2 Taupe - Light Gray Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634020368435",
+    "sku": "DWK-302880",
+    "handle": "dwk-302880-koroseal-sarah-rowland-haz-1-taupe-srd-hz1-01",
+    "title": "Haz 1 Taupe - Light Gray Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634019778611",
+    "sku": "DWK-302840",
+    "handle": "dwk-302840-koroseal-sarah-rowland-graham-pumice-white-srd-gra-04",
+    "title": "Graham Pumice White - Pale Blue Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634019582003",
+    "sku": "DWK-302560",
+    "handle": "dwk-302560-koroseal-sarah-rowland-felix-birdicement-srd-flb-02",
+    "title": "Felix Birdicement - Taupe Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634018926643",
+    "sku": "DWK-302550",
+    "handle": "dwk-302550-koroseal-sarah-rowland-celin-linus-orange-green-srd-cln-03",
+    "title": "Celin Linus Orange Green - Off-White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634018598963",
+    "sku": "DWK-302780",
+    "handle": "dwk-302780-koroseal-sarah-rowland-chess-1-pink-yellow-srd-ch1-03",
+    "title": "Chess 1 Pink Yellow - White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634018238515",
+    "sku": "DWK-302760",
+    "handle": "dwk-302760-koroseal-sarah-rowland-celine-orange-green-srd-ce1-01",
+    "title": "Celine Orange Green - Off-White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634018205747",
+    "sku": "DWK-302730",
+    "handle": "dwk-302730-koroseal-sarah-rowland-big-nora-clay-srd-bno-01",
+    "title": "Big Nora Clay - Pale Beige Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634018140211",
+    "sku": "DWK-302750",
+    "handle": "dwk-302750-koroseal-sarah-rowland-brent-red-pink-srd-be1-01",
+    "title": "Brent Red Pink - White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634018107443",
+    "sku": "DWK-302720",
+    "handle": "dwk-302720-koroseal-sarah-rowland-big-chloe-bone-srd-bch-01",
+    "title": "Big Chloe Bone - Off-White Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634017878067",
+    "sku": "DWK-302540-Sample",
+    "handle": "aunt-jane-graham-bone-wallpaper-srd-ajg-05-sarah-rowland-sample-architectural-wallcoverings",
+    "title": "Sample Commercial Wallcovering | Koroseal"
+  },
+  {
+    "id": "gid://shopify/Product/7634017845299",
+    "sku": "DWK-302700-Sample",
+    "handle": "aunt-jane-black-wallpaper-srd-aja-01-sarah-rowland-sample-architectural-wallcoverings",
+    "title": "Sample Commercial Wallcovering | Koroseal"
+  }
+]
\ No newline at end of file
diff --git a/vendor-of-collections.mjs b/vendor-of-collections.mjs
new file mode 100644
index 0000000..70ab11a
--- /dev/null
+++ b/vendor-of-collections.mjs
@@ -0,0 +1,15 @@
+import { gql } from './lib.mjs';
+const handles=['barclay-butera-collection-1','candice-olson-collection','candice-olson-collection-1',
+ 'sarah-rowland-wallpaper-collection','kelly-wearstler-collections','the-kelly-wearstler-collection',
+ 'lorenzo-castillo-collection','emma-shipley-wallpaper-collection','paolo-moschino-collections',
+ 'papis-lovejoy','fornasetti','brand-mckenzie-wallpaper-collection','the-graduate-collection',
+ 'steve-abrams-whimsy','hollywood-sunset-collection','the-equestrian-collection','equestrian-collection'];
+const Q=`query($h:String!){ collectionByHandle(handle:$h){ title products(first:60){nodes{vendor}} } }`;
+for(const h of handles){
+  const c=(await gql(Q,{h})).collectionByHandle;
+  if(!c){ console.log(`${h}: (not found)`); continue; }
+  const hist={}; c.products.nodes.forEach(p=>hist[p.vendor||'∅']=(hist[p.vendor||'∅']||0)+1);
+  const top=Object.entries(hist).sort((a,b)=>b[1]-a[1]);
+  const koro=top.find(v=>/koroseal/i.test(v[0]));
+  console.log(`${koro?'★KOROSEAL':'         '}  ${c.title.padEnd(42)} vendors: ${top.map(([v,n])=>`${v}:${n}`).join(', ').slice(0,80)}`);
+}

← 6257f36 TK-10037: wire PDP Designer row to prefer custom.designer (l  ·  back to Dw Sarah Rowland Searchfix  ·  TK-10037: add Sarah Rowland designer photo+bio block to coll 26fabe4 →