← back to Dw Sarah Rowland Searchfix
auto-save: 2026-07-30T09:46:44 (4 files) — list-menus.mjs read-resources-menu.mjs resources-menu.BEFORE.json update-menu.mjs
81e681684747f9840d3c23555a0bc50420ed7846 · 2026-07-30 09:46:49 -0700 · Steve Abrams
Files touched
A list-menus.mjsA read-resources-menu.mjsA resources-menu.BEFORE.jsonA update-menu.mjs
Diff
commit 81e681684747f9840d3c23555a0bc50420ed7846
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Jul 30 09:46:49 2026 -0700
auto-save: 2026-07-30T09:46:44 (4 files) — list-menus.mjs read-resources-menu.mjs resources-menu.BEFORE.json update-menu.mjs
---
list-menus.mjs | 12 ++++++++++
read-resources-menu.mjs | 11 +++++++++
resources-menu.BEFORE.json | 60 ++++++++++++++++++++++++++++++++++++++++++++++
update-menu.mjs | 18 ++++++++++++++
4 files changed, 101 insertions(+)
diff --git a/list-menus.mjs b/list-menus.mjs
new file mode 100644
index 0000000..ec899aa
--- /dev/null
+++ b/list-menus.mjs
@@ -0,0 +1,12 @@
+import fs from 'node:fs'; import os from 'node:os';
+const env=fs.readFileSync(`${os.homedir()}/Projects/secrets-manager/.env`,'utf8');
+const tok=(k)=>(env.match(new RegExp('^'+k+'=(.+)$','m'))||[])[1]?.trim();
+const T=tok('SHOPIFY_CONTENT_TOKEN')||tok('SHOPIFY_ADMIN_TOKEN');
+const S='designer-laboratory-sandbox.myshopify.com',A='2024-10';
+async function gql(q){const r=await fetch(`https://${S}/admin/api/${A}/graphql.json`,{method:'POST',headers:{'X-Shopify-Access-Token':T,'Content-Type':'application/json'},body:JSON.stringify({query:q})});return r.json();}
+const d=await gql(`{ menus(first:20){ nodes{ id handle title items{ id title url items{ id title url } } } } }`);
+if(d.errors){ console.log('ERR', JSON.stringify(d.errors).slice(0,300)); process.exit(1); }
+d.data.menus.nodes.forEach(m=>{
+ console.log(`\n== ${m.title} [${m.handle}] (${m.items.length} top items) ${m.id}`);
+ m.items.slice(0,20).forEach(i=>console.log(` - ${i.title} → ${i.url}${i.items?.length?` (${i.items.length} sub)`:''}`));
+});
diff --git a/read-resources-menu.mjs b/read-resources-menu.mjs
new file mode 100644
index 0000000..e95ff44
--- /dev/null
+++ b/read-resources-menu.mjs
@@ -0,0 +1,11 @@
+import fs from 'node:fs'; import os from 'node:os';
+const env=fs.readFileSync(`${os.homedir()}/Projects/secrets-manager/.env`,'utf8');
+const tok=(k)=>(env.match(new RegExp('^'+k+'=(.+)$','m'))||[])[1]?.trim();
+const T=tok('SHOPIFY_CONTENT_TOKEN')||tok('SHOPIFY_ADMIN_TOKEN');
+const S='designer-laboratory-sandbox.myshopify.com',A='2024-10';
+async function gql(q){const r=await fetch(`https://${S}/admin/api/${A}/graphql.json`,{method:'POST',headers:{'X-Shopify-Access-Token':T,'Content-Type':'application/json'},body:JSON.stringify({query:q})});return r.json();}
+const d=await gql(`{ menu(id:"gid://shopify/Menu/65661239361"){ handle title items{ id title type url resourceId tags items{ id title type url resourceId tags } } } }`);
+if(d.errors){console.log('ERR',JSON.stringify(d.errors));process.exit(1);}
+fs.writeFileSync(new URL('./resources-menu.BEFORE.json',import.meta.url), JSON.stringify(d.data.menu,null,2));
+console.log('handle:',d.data.menu.handle,'title:',d.data.menu.title);
+d.data.menu.items.forEach(i=>console.log(` ${i.type.padEnd(12)} ${i.title.padEnd(34)} url=${i.url||'∅'} rid=${i.resourceId||'∅'}`));
diff --git a/resources-menu.BEFORE.json b/resources-menu.BEFORE.json
new file mode 100644
index 0000000..8f90e67
--- /dev/null
+++ b/resources-menu.BEFORE.json
@@ -0,0 +1,60 @@
+{
+ "handle": "resources",
+ "title": "Resources",
+ "items": [
+ {
+ "id": "gid://shopify/MenuItem/141325664321",
+ "title": "FAQs",
+ "type": "PAGE",
+ "url": "/pages/faq",
+ "resourceId": "gid://shopify/Page/20309246064",
+ "tags": [],
+ "items": []
+ },
+ {
+ "id": "gid://shopify/MenuItem/141325697089",
+ "title": "Custom Walls",
+ "type": "PAGE",
+ "url": "/pages/custom",
+ "resourceId": "gid://shopify/Page/26648215617",
+ "tags": [],
+ "items": []
+ },
+ {
+ "id": "gid://shopify/MenuItem/141325729857",
+ "title": "Find Wallcovering Installers",
+ "type": "PAGE",
+ "url": "/pages/find-wallpaper-installers",
+ "resourceId": "gid://shopify/Page/27079770177",
+ "tags": [],
+ "items": []
+ },
+ {
+ "id": "gid://shopify/MenuItem/141325762625",
+ "title": "Wallpaper Glossary and Terms",
+ "type": "PAGE",
+ "url": "/pages/wallpaper-glossary-terms",
+ "resourceId": "gid://shopify/Page/27079737409",
+ "tags": [],
+ "items": []
+ },
+ {
+ "id": "gid://shopify/MenuItem/141325795393",
+ "title": "Wallpaper Calculator",
+ "type": "PAGE",
+ "url": "/pages/calculator",
+ "resourceId": "gid://shopify/Page/26770243649",
+ "tags": [],
+ "items": []
+ },
+ {
+ "id": "gid://shopify/MenuItem/141380747329",
+ "title": "Inspiration",
+ "type": "BLOG",
+ "url": "/blogs/news",
+ "resourceId": "gid://shopify/Blog/9243689072",
+ "tags": [],
+ "items": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/update-menu.mjs b/update-menu.mjs
new file mode 100644
index 0000000..9412a43
--- /dev/null
+++ b/update-menu.mjs
@@ -0,0 +1,18 @@
+// Add "Koroseal Designers" to the Resources menu (re-sends existing items intact).
+import fs from 'node:fs'; import os from 'node:os';
+const env=fs.readFileSync(`${os.homedir()}/Projects/secrets-manager/.env`,'utf8');
+const tok=(k)=>(env.match(new RegExp('^'+k+'=(.+)$','m'))||[])[1]?.trim();
+const T=tok('SHOPIFY_CONTENT_TOKEN')||tok('SHOPIFY_ADMIN_TOKEN');
+const S='designer-laboratory-sandbox.myshopify.com',A='2024-10';
+async function gql(q,v){const r=await fetch(`https://${S}/admin/api/${A}/graphql.json`,{method:'POST',headers:{'X-Shopify-Access-Token':T,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v})});return r.json();}
+const before=JSON.parse(fs.readFileSync(new URL('./resources-menu.BEFORE.json',import.meta.url)));
+const items=before.items.map(i=>({title:i.title, type:i.type, resourceId:i.resourceId, tags:i.tags||[]}));
+items.push({title:'Koroseal Designers', type:'PAGE', resourceId:'gid://shopify/Page/220364832819', tags:[]});
+const M=`mutation($id:ID!,$title:String!,$handle:String!,$items:[MenuItemUpdateInput!]!){
+ menuUpdate(id:$id,title:$title,handle:$handle,items:$items){ menu{ id items{ title url } } userErrors{ field message } } }`;
+const d=await gql(M,{id:'gid://shopify/Menu/65661239361', title:'Resources', handle:'resources', items});
+if(d.errors){console.log('GQL ERR',JSON.stringify(d.errors).slice(0,400));process.exit(1);}
+const ue=d.data.menuUpdate.userErrors;
+if(ue.length){console.log('userErrors',JSON.stringify(ue));process.exit(1);}
+console.log('✓ Resources menu updated. Items now:');
+d.data.menuUpdate.menu.items.forEach(i=>console.log(` - ${i.title} → ${i.url}`));
← 841c497 TK-10037: publish Meet-the-Koroseal-Designers page live (id
·
back to Dw Sarah Rowland Searchfix
·
(newest)