"use strict"; /** * Test script: End-to-end Dutchie GraphQL → DB → Dashboard flow * * This demonstrates the complete data pipeline: * 1. Fetch one product from Dutchie GraphQL via Puppeteer * 2. Normalize it to our schema * 3. Show the mapping */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const dutchie_graphql_1 = require("../scrapers/dutchie-graphql"); const fs = __importStar(require("fs")); // Load the captured sample product from schema capture const capturedData = JSON.parse(fs.readFileSync('/tmp/dutchie-schema-capture.json', 'utf-8')); const sampleProduct = capturedData.sampleProduct; console.log('='.repeat(80)); console.log('DUTCHIE GRAPHQL → DATABASE MAPPING DEMONSTRATION'); console.log('='.repeat(80)); console.log('\nšŸ“„ RAW DUTCHIE GRAPHQL PRODUCT:'); console.log('-'.repeat(80)); // Show key fields from raw product const keyRawFields = { '_id': sampleProduct._id, 'Name': sampleProduct.Name, 'cName': sampleProduct.cName, 'brandName': sampleProduct.brandName, 'brand.id': sampleProduct.brand?.id, 'type': sampleProduct.type, 'subcategory': sampleProduct.subcategory, 'strainType': sampleProduct.strainType, 'Prices': sampleProduct.Prices, 'recPrices': sampleProduct.recPrices, 'recSpecialPrices': sampleProduct.recSpecialPrices, 'special': sampleProduct.special, 'specialData.saleSpecials[0].specialName': sampleProduct.specialData?.saleSpecials?.[0]?.specialName, 'specialData.saleSpecials[0].discount': sampleProduct.specialData?.saleSpecials?.[0]?.discount, 'THCContent.range[0]': sampleProduct.THCContent?.range?.[0], 'CBDContent.range[0]': sampleProduct.CBDContent?.range?.[0], 'Status': sampleProduct.Status, 'Image': sampleProduct.Image, 'POSMetaData.canonicalSKU': sampleProduct.POSMetaData?.canonicalSKU, 'POSMetaData.children[0].quantity': sampleProduct.POSMetaData?.children?.[0]?.quantity, 'POSMetaData.children[0].quantityAvailable': sampleProduct.POSMetaData?.children?.[0]?.quantityAvailable, }; Object.entries(keyRawFields).forEach(([key, value]) => { console.log(` ${key}: ${JSON.stringify(value)}`); }); console.log('\nšŸ“¤ NORMALIZED DATABASE ROW:'); console.log('-'.repeat(80)); // Normalize the product const normalized = (0, dutchie_graphql_1.normalizeDutchieProduct)(sampleProduct); // Show the normalized result (excluding raw_data for readability) const { raw_data, cannabinoids, special_data, ...displayFields } = normalized; Object.entries(displayFields).forEach(([key, value]) => { if (value !== undefined && value !== null) { console.log(` ${key}: ${JSON.stringify(value)}`); } }); console.log('\nšŸ”— FIELD MAPPING:'); console.log('-'.repeat(80)); const fieldMappings = [ ['_id / id', 'external_id', sampleProduct._id, normalized.external_id], ['Name', 'name', sampleProduct.Name, normalized.name], ['cName', 'slug', sampleProduct.cName, normalized.slug], ['brandName', 'brand', sampleProduct.brandName, normalized.brand], ['brand.id', 'brand_external_id', sampleProduct.brand?.id, normalized.brand_external_id], ['subcategory', 'subcategory', sampleProduct.subcategory, normalized.subcategory], ['strainType', 'strain_type', sampleProduct.strainType, normalized.strain_type], ['recPrices[0]', 'rec_price', sampleProduct.recPrices?.[0], normalized.rec_price], ['recSpecialPrices[0]', 'rec_special_price', sampleProduct.recSpecialPrices?.[0], normalized.rec_special_price], ['special', 'is_on_special', sampleProduct.special, normalized.is_on_special], ['specialData...specialName', 'special_name', sampleProduct.specialData?.saleSpecials?.[0]?.specialName?.substring(0, 40) + '...', normalized.special_name?.substring(0, 40) + '...'], ['THCContent.range[0]', 'thc_percentage', sampleProduct.THCContent?.range?.[0], normalized.thc_percentage], ['CBDContent.range[0]', 'cbd_percentage', sampleProduct.CBDContent?.range?.[0], normalized.cbd_percentage], ['Status', 'status', sampleProduct.Status, normalized.status], ['Image', 'image_url', sampleProduct.Image?.substring(0, 50) + '...', normalized.image_url?.substring(0, 50) + '...'], ['POSMetaData.canonicalSKU', 'sku', sampleProduct.POSMetaData?.canonicalSKU, normalized.sku], ]; console.log(' GraphQL Field → DB Column | Value'); console.log(' ' + '-'.repeat(75)); fieldMappings.forEach(([gqlField, dbCol, gqlVal, dbVal]) => { const gqlStr = String(gqlField).padEnd(30); const dbStr = String(dbCol).padEnd(20); console.log(` ${gqlStr} → ${dbStr} | ${JSON.stringify(dbVal)}`); }); console.log('\nšŸ“Š SQL INSERT STATEMENT:'); console.log('-'.repeat(80)); // Generate example SQL const sqlExample = ` INSERT INTO products ( store_id, external_id, slug, name, brand, brand_external_id, subcategory, strain_type, rec_price, rec_special_price, is_on_special, special_name, discount_percent, thc_percentage, cbd_percentage, status, image_url, sku ) VALUES ( 1, -- store_id (Deeply Rooted) '${normalized.external_id}', -- external_id '${normalized.slug}', -- slug '${normalized.name}', -- name '${normalized.brand}', -- brand '${normalized.brand_external_id}', -- brand_external_id '${normalized.subcategory}', -- subcategory '${normalized.strain_type}', -- strain_type ${normalized.rec_price}, -- rec_price ${normalized.rec_special_price}, -- rec_special_price ${normalized.is_on_special}, -- is_on_special '${normalized.special_name?.substring(0, 50)}...', -- special_name ${normalized.discount_percent || 'NULL'}, -- discount_percent ${normalized.thc_percentage}, -- thc_percentage ${normalized.cbd_percentage}, -- cbd_percentage '${normalized.status}', -- status '${normalized.image_url}', -- image_url '${normalized.sku}' -- sku ) ON CONFLICT (store_id, slug) DO UPDATE SET ...; `; console.log(sqlExample); console.log('\nāœ… SUMMARY:'); console.log('-'.repeat(80)); console.log(` Product: ${normalized.name}`); console.log(` Brand: ${normalized.brand}`); console.log(` Category: ${normalized.subcategory}`); console.log(` Price: $${normalized.rec_price} → $${normalized.rec_special_price} (${normalized.discount_percent}% off)`); console.log(` THC: ${normalized.thc_percentage}%`); console.log(` Status: ${normalized.status}`); console.log(` On Special: ${normalized.is_on_special}`); console.log(` SKU: ${normalized.sku}`); console.log('\nšŸŽÆ DERIVED VIEWS (computed from products table):'); console.log('-'.repeat(80)); console.log(' - current_specials: Products where is_on_special = true'); console.log(' - derived_brands: Aggregated by brand name with counts/prices'); console.log(' - derived_categories: Aggregated by subcategory'); console.log('\nAll views are computed from the single products table - no separate tables needed!');