Data4Autos-Shopify-Backend/Backups/manageBrands copy.js
2026-04-13 05:23:25 +00:00

174 lines
5.9 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// routes/manageBrands.js
const express = require('express');
const axios = require('axios');
const { v4: uuid } = require('uuid');
const { getToken } = require('../tokenStore');
const { log } = require('../logger');
const router = express.Router();
// Simple in-memory process tracker
const processes = {};
async function fetchAllCollections(shop, accessToken) {
const adminUrl = `https://${shop}/admin/api/2023-10/graphql.json`;
const headers = {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
};
let allCollections = [];
let hasNextPage = true;
let endCursor = null;
const pageSize = 100;
while (hasNextPage) {
const fetchQuery = `
query GetCollections {
collections(first: ${pageSize}${endCursor ? `, after: "${endCursor}"` : ''}) {
edges {
node {
id
title
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
const fetchResp = await axios.post(adminUrl, { query: fetchQuery }, { headers });
const collections = fetchResp.data.data.collections.edges.map(e => e.node);
allCollections = allCollections.concat(collections);
hasNextPage = fetchResp.data.data.collections.pageInfo.hasNextPage;
endCursor = fetchResp.data.data.collections.pageInfo.endCursor;
}
console.log(`Fetched ${allCollections.length} collections from ${shop}`);
return allCollections;
}
router.post('/', async (req, res) => {
const { shop, selectedBrands } = req.body;
const procId = uuid();
processes[procId] = { status: 'started', detail: null };
log(shop, `🔔 [${procId}] ManageBrands initiated for ${selectedBrands.length} brands`);
//console.log(`🔔 [${procId}] ManageBrands initiated for ${selectedBrands.length} brands`);
res.json({ processId: procId, status: 'started' });
(async () => {
try {
log(shop, `🔔 [${procId}] ManageBrands started`);
processes[procId].status = 'fetching_collections';
// 1. Get token
const tokenRecord = getToken(shop);
if (!tokenRecord) throw new Error('No token for shop');
const adminUrl = `https://${shop}/admin/api/2023-10/graphql.json`;
const headers = {
'X-Shopify-Access-Token': tokenRecord.accessToken,
'Content-Type': 'application/json',
};
console.log(`🔑 [${procId}] Using access token for shop ${shop} ${adminUrl} ${tokenRecord.accessToken}`);
// 2. Fetch existing collections
// const fetchQuery = `
// { collections(first:100) { edges { node { id title } } } }
// `;
// const fetchResp = await axios.post(adminUrl, { query: fetchQuery }, { headers });
// const existing = fetchResp.data.data.collections.edges.map(e => e.node);
// log(shop, `🔍 [${procId}] Fetched ${existing.length} collections`);
const allCollections = await fetchAllCollections(shop, tokenRecord.accessToken);
log(shop, `🔍 [${procId}] Fetchedd ${allCollections.length} existing collections`);
// 3. Delete unselected
processes[procId].status = 'deleting';
// const toDelete = existing.filter(c => {
const toDelete = allCollections.filter(c => {
return !selectedBrands.find(b => b.name.toLowerCase() === c.title.toLowerCase());
});
for (let i = 0; i < toDelete.length; i++) {
const col = toDelete[i];
processes[procId].detail = `deleting ${i + 1}/${toDelete.length}`;
await axios.post(adminUrl, {
query: `
mutation { collectionDelete(input:{id:"${col.id}"}) { deletedCollectionId } }
`
}, { headers });
log(shop, `🗑️ [${procId}] Deleted collection ${col.title}`);
}
// 4. Create new
processes[procId].status = 'creating';
const existingTitles = allCollections.map(c => c.title.toLowerCase());
const toCreate = selectedBrands.filter(b => !existingTitles.includes(b.name.toLowerCase()));
for (let i = 0; i < toCreate.length; i++) {
const b = toCreate[i];
processes[procId].detail = `creating ${i + 1}/${toCreate.length}`;
const name = b.name.replace(/"/g, '\\"');
const logo = b.logo || '';
await axios.post(adminUrl, {
query: `
mutation {
collectionCreate(input:{
title:"${name}",
descriptionHtml:"Products from ${name}",
image:{altText:"${name} Logo",src:"${logo}"}
}) { collection { id } }
}
`
}, { headers });
log(shop, ` [${procId}] Created collection ${b.name}`);
}
// 5. Update metafield
processes[procId].status = 'updating_metafield';
const shopIdQuery = `{ shop { id } }`;
const shopIdResp = await axios.post(adminUrl, { query: shopIdQuery }, { headers });
const shopId = shopIdResp.data.data.shop.id;
const mfValue = JSON.stringify(selectedBrands);
await axios.post(adminUrl, {
query: `
mutation {
metafieldsSet(metafields:[{
namespace:"turn14",key:"selected_brands",type:"json",
ownerId:"${shopId}",value:${JSON.stringify(mfValue)}
}]) { metafields { id } }
}
`
}, { headers });
log(shop, `💾 [${procId}] Updated metafield with ${selectedBrands.length} entries`);
processes[procId].status = 'done';
processes[procId].detail = null;
log(shop, `✅ [${procId}] ManageBrands complete`);
} catch (err) {
processes[procId].status = 'error';
processes[procId].detail = err.message;
log(shop, `❌ [${procId}] Error: ${err.message}`);
}
})();
});
router.get('/status/:processId', (req, res) => {
const info = processes[req.params.processId];
if (!info) return res.status(404).json({ error: 'Not found' });
res.json(info);
});
module.exports = router;