← back to Flockedwallpaper
check-recent-flock.js
224 lines
require('dotenv').config();
const axios = require('axios');
const fs = require('fs');
const SHOPIFY_STORE = process.env.SHOPIFY_STORE_NAME;
const ACCESS_TOKEN = process.env.SHOPIFY_ACCESS_TOKEN;
const API_VERSION = process.env.SHOPIFY_API_VERSION || '2024-10';
// Shopify Admin API GraphQL endpoint
const GRAPHQL_ENDPOINT = `https://${SHOPIFY_STORE}.myshopify.com/admin/api/${API_VERSION}/graphql.json`;
async function fetchRecentFlockProducts() {
console.log('🔍 Fetching recently updated/created flock products from Shopify...');
const allProducts = [];
let hasNextPage = true;
let cursor = null;
// Get date 30 days ago for comparison
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
while (hasNextPage) {
const query = `
query ($cursor: String) {
products(first: 250, after: $cursor, query: "flock status:active", sortKey: UPDATED_AT, reverse: true) {
edges {
cursor
node {
id
title
handle
description
productType
vendor
tags
createdAt
updatedAt
status
variants(first: 10) {
edges {
node {
id
title
sku
price
}
}
}
featuredImage {
url
altText
}
images(first: 5) {
edges {
node {
url
altText
}
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
try {
const response = await axios.post(
GRAPHQL_ENDPOINT,
{
query: query,
variables: { cursor: cursor }
},
{
headers: {
'Content-Type': 'application/json',
'X-Shopify-Access-Token': ACCESS_TOKEN
}
}
);
if (response.data.errors) {
console.error('GraphQL Errors:', response.data.errors);
break;
}
const products = response.data.data.products.edges;
allProducts.push(...products);
hasNextPage = response.data.data.products.pageInfo.hasNextPage;
cursor = response.data.data.products.pageInfo.endCursor;
console.log(` Fetched ${allProducts.length} products so far...`);
// Rate limiting: wait 500ms between requests
await new Promise(resolve => setTimeout(resolve, 500));
} catch (error) {
console.error('❌ Error fetching products:', error.message);
if (error.response) {
console.error('Response data:', error.response.data);
}
break;
}
}
console.log(`\n✅ Total products fetched: ${allProducts.length}`);
return allProducts;
}
function findNewProducts(allProducts) {
console.log('\n🔍 Checking for new products...');
// Load existing products
let existingProducts = [];
try {
const data = fs.readFileSync('./flocked-products.json', 'utf8');
existingProducts = JSON.parse(data);
console.log(` Loaded ${existingProducts.length} existing products`);
} catch (error) {
console.log(' No existing products file found or error reading it');
}
// Create a set of existing product IDs
const existingIds = new Set(existingProducts.map(p => p.id));
// Find products that are new (not in existing list)
const newProducts = [];
const recentlyUpdated = [];
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
allProducts.forEach(product => {
const node = product.node;
const createdDate = new Date(node.createdAt);
const updatedDate = new Date(node.updatedAt);
if (!existingIds.has(node.id)) {
newProducts.push(node);
} else if (updatedDate > thirtyDaysAgo) {
recentlyUpdated.push(node);
}
});
return { newProducts, recentlyUpdated, thirtyDaysAgo };
}
function formatProduct(node) {
const variants = node.variants.edges;
const skus = variants.map(v => v.node.sku).filter(sku => sku);
return {
id: node.id,
title: node.title,
handle: node.handle,
primarySku: skus[0] || 'N/A',
image: node.featuredImage?.url || node.images.edges[0]?.node.url,
productUrl: `https://designerwallcoverings.com/products/${node.handle}`,
createdAt: node.createdAt,
updatedAt: node.updatedAt
};
}
async function main() {
try {
console.log('🚀 Checking for Recent Flock Product Updates\n');
console.log(`Store: ${SHOPIFY_STORE}`);
console.log(`API Version: ${API_VERSION}\n`);
// Fetch all products sorted by updated date
const allProducts = await fetchRecentFlockProducts();
// Find new products
const { newProducts, recentlyUpdated, thirtyDaysAgo } = findNewProducts(allProducts);
console.log('\n📊 RESULTS:');
console.log(` Total flock products in Shopify: ${allProducts.length}`);
console.log(` New products (not in existing JSON): ${newProducts.length}`);
console.log(` Recently updated (last 30 days): ${recentlyUpdated.length}`);
if (newProducts.length > 0) {
console.log('\n🆕 NEW PRODUCTS FOUND:');
console.log('=' .repeat(80));
newProducts.forEach((product, index) => {
const formatted = formatProduct(product);
console.log(`\n${index + 1}. ${formatted.title}`);
console.log(` SKU: ${formatted.primarySku}`);
console.log(` Created: ${new Date(formatted.createdAt).toLocaleDateString()}`);
console.log(` URL: ${formatted.productUrl}`);
console.log(` Image: ${formatted.image ? '✓' : '✗ Missing'}`);
});
} else {
console.log('\n✓ No new products found - all products are already in flocked-products.json');
}
if (recentlyUpdated.length > 0) {
console.log('\n\n📝 RECENTLY UPDATED PRODUCTS (Last 30 days):');
console.log('=' .repeat(80));
recentlyUpdated.slice(0, 10).forEach((product, index) => {
const formatted = formatProduct(product);
console.log(`\n${index + 1}. ${formatted.title}`);
console.log(` SKU: ${formatted.primarySku}`);
console.log(` Updated: ${new Date(formatted.updatedAt).toLocaleDateString()}`);
});
if (recentlyUpdated.length > 10) {
console.log(`\n ... and ${recentlyUpdated.length - 10} more`);
}
}
} catch (error) {
console.error('\n❌ Fatal Error:', error.message);
process.exit(1);
}
}
main();