exercises

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

generate_products.js (7272B)


      1 #!/usr/bin/env node
      2 
      3 /**
      4  * Generate 2000 product records for the products service
      5  * Outputs SQL INSERT statements to schemas/data/products_data.sql
      6  */
      7 
      8 const fs = require('fs');
      9 const path = require('path');
     10 
     11 // Product categories
     12 const categories = [
     13     'Electronics', 'Accessories', 'Gaming', 'Office',
     14     'Audio', 'Computers', 'Mobile', 'Wearables',
     15     'Smart Home', 'Camera', 'Networking', 'Storage'
     16 ];
     17 
     18 // Product name templates
     19 const productTypes = {
     20     Electronics: [
     21         'Monitor', 'Laptop', 'Desktop', 'Tablet', 'E-Reader',
     22         'TV', 'Projector', 'Smart Display', 'Graphics Card', 'Motherboard'
     23     ],
     24     Accessories: [
     25         'USB-C Cable', 'HDMI Cable', 'Power Adapter', 'Phone Case',
     26         'Screen Protector', 'Cable Organizer', 'Laptop Sleeve', 'USB Hub'
     27     ],
     28     Gaming: [
     29         'Gaming Mouse', 'Gaming Keyboard', 'Gaming Headset', 'Controller',
     30         'Gaming Chair', 'Mouse Pad', 'VR Headset', 'Gaming Monitor', 'Capture Card'
     31     ],
     32     Office: [
     33         'Desk Lamp', 'Office Chair', 'Standing Desk', 'Whiteboard',
     34         'Desk Organizer', 'Notebook', 'Pen Set', 'Stapler', 'Paper Shredder'
     35     ],
     36     Audio: [
     37         'Bluetooth Speaker', 'Headphones', 'Earbuds', 'Microphone',
     38         'Sound Bar', 'Subwoofer', 'Audio Interface', 'Studio Monitor'
     39     ],
     40     Computers: [
     41         'Keyboard', 'Mouse', 'Webcam', 'External Drive', 'RAM Module',
     42         'SSD', 'CPU', 'Cooling Fan', 'Power Supply', 'PC Case'
     43     ],
     44     Mobile: [
     45         'Smartphone', 'Phone Charger', 'Wireless Charger', 'Car Mount',
     46         'Selfie Stick', 'Phone Stand', 'PopSocket', 'Battery Pack'
     47     ],
     48     Wearables: [
     49         'Smart Watch', 'Fitness Tracker', 'Smart Ring', 'Smart Glasses',
     50         'Heart Rate Monitor', 'GPS Watch', 'Sleep Tracker'
     51     ],
     52     'Smart Home': [
     53         'Smart Bulb', 'Smart Plug', 'Security Camera', 'Video Doorbell',
     54         'Smart Lock', 'Smart Thermostat', 'Motion Sensor', 'Smart Switch'
     55     ],
     56     Camera: [
     57         'DSLR Camera', 'Mirrorless Camera', 'Action Camera', 'Camera Lens',
     58         'Tripod', 'Camera Bag', 'SD Card', 'Flash', 'Gimbal'
     59     ],
     60     Networking: [
     61         'Router', 'WiFi Extender', 'Network Switch', 'Modem',
     62         'Ethernet Cable', 'Powerline Adapter', 'Access Point'
     63     ],
     64     Storage: [
     65         'External SSD', 'External HDD', 'NAS Drive', 'USB Flash Drive',
     66         'SD Card Reader', 'Hard Drive Enclosure', 'Cloud Storage Device'
     67     ]
     68 };
     69 
     70 // Adjectives for product variations
     71 const adjectives = [
     72     'Pro', 'Plus', 'Max', 'Ultra', 'Premium', 'Elite', 'Advanced',
     73     'Deluxe', 'Professional', 'HD', '4K', 'Wireless', 'Portable',
     74     'Compact', 'Mini', 'XL', 'RGB', 'Ergonomic', 'Mechanical'
     75 ];
     76 
     77 // Brands
     78 const brands = [
     79     'TechPro', 'InnovateTech', 'SmartGear', 'ProElectronics', 'EliteTech',
     80     'DigitalWave', 'FutureTech', 'PrimeTech', 'CoreTech', 'NexGen',
     81     'PowerMax', 'UltraGear', 'SwiftTech', 'PrecisionTech', 'VisionTech',
     82     'SonicWave', 'FlexTech', 'SpeedTech', 'ImpactTech', 'ApexTech'
     83 ];
     84 
     85 /**
     86  * Generate a random integer between min and max (inclusive)
     87  */
     88 function randomInt(min, max) {
     89     return Math.floor(Math.random() * (max - min + 1)) + min;
     90 }
     91 
     92 /**
     93  * Pick a random element from an array
     94  */
     95 function randomChoice(array) {
     96     return array[Math.floor(Math.random() * array.length)];
     97 }
     98 
     99 /**
    100  * Generate a realistic price
    101  */
    102 function generatePrice() {
    103     const prices = [
    104         9.99, 12.99, 14.99, 19.99, 24.99, 29.99, 34.99, 39.99,
    105         49.99, 59.99, 69.99, 79.99, 89.99, 99.99, 119.99, 149.99,
    106         199.99, 249.99, 299.99, 349.99, 399.99, 449.99, 499.99,
    107         599.99, 699.99, 799.99, 899.99, 999.99, 1299.99, 1499.99,
    108         1999.99, 2499.99
    109     ];
    110     return randomChoice(prices);
    111 }
    112 
    113 /**
    114  * Generate a product description
    115  */
    116 function generateDescription(productName, category) {
    117     const templates = [
    118         `High-quality ${productName.toLowerCase()} designed for ${category.toLowerCase()} enthusiasts.`,
    119         `Premium ${productName.toLowerCase()} with advanced features and superior performance.`,
    120         `Professional-grade ${productName.toLowerCase()} perfect for work and play.`,
    121         `Innovative ${productName.toLowerCase()} combining style and functionality.`,
    122         `Top-rated ${productName.toLowerCase()} with excellent build quality and durability.`,
    123         `Feature-rich ${productName.toLowerCase()} offering exceptional value for money.`,
    124         `Cutting-edge ${productName.toLowerCase()} with the latest technology.`,
    125         `Reliable ${productName.toLowerCase()} backed by industry-leading warranty.`,
    126         `Versatile ${productName.toLowerCase()} suitable for both professionals and beginners.`,
    127         `Award-winning ${productName.toLowerCase()} with outstanding reviews.`
    128     ];
    129     return randomChoice(templates);
    130 }
    131 
    132 /**
    133  * Generate a single product
    134  */
    135 function generateProduct(index) {
    136     const category = randomChoice(categories);
    137     const productType = randomChoice(productTypes[category] || productTypes.Electronics);
    138     const adjective = Math.random() > 0.4 ? randomChoice(adjectives) + ' ' : '';
    139     const variant = randomInt(1000, 9999);
    140 
    141     const name = `${adjective}${productType} ${variant}`;
    142     const brand = randomChoice(brands);
    143     const description = generateDescription(productType, category);
    144     const price = generatePrice();
    145     const stock = randomInt(0, 500);
    146 
    147     return {
    148         name,
    149         description,
    150         price,
    151         category,
    152         stock_quantity: stock
    153     };
    154 }
    155 
    156 /**
    157  * Escape single quotes for SQL
    158  */
    159 function escapeSql(str) {
    160     if (!str) return str;
    161     return str.replace(/'/g, "''");
    162 }
    163 
    164 /**
    165  * Generate SQL INSERT statements
    166  */
    167 function generateSQL(products) {
    168     const lines = [
    169         '-- Generated products data',
    170         '-- Total products: ' + products.length,
    171         '-- Generated at: ' + new Date().toISOString(),
    172         '',
    173         'SET search_path TO products, public;',
    174         '',
    175         '-- Insert products in batches for better performance',
    176         'INSERT INTO products (name, description, price, category, stock_quantity) VALUES'
    177     ];
    178 
    179     const valueLines = products.map((product, index) => {
    180         const isLast = index === products.length - 1;
    181         const name = escapeSql(product.name);
    182         const desc = escapeSql(product.description);
    183         const category = escapeSql(product.category);
    184 
    185         return `    ('${name}', '${desc}', ${product.price}, '${category}', ${product.stock_quantity})${isLast ? ';' : ','}`;
    186     });
    187 
    188     return lines.concat(valueLines).join('\n');
    189 }
    190 
    191 /**
    192  * Main function
    193  */
    194 function main() {
    195     console.log('Generating 2000 products...');
    196 
    197     const products = [];
    198     for (let i = 0; i < 2000; i++) {
    199         products.push(generateProduct(i));
    200         if ((i + 1) % 500 === 0) {
    201             console.log(`Generated ${i + 1} products...`);
    202         }
    203     }
    204 
    205     console.log('Generating SQL...');
    206     const sql = generateSQL(products);
    207 
    208     const outputPath = path.join(__dirname, 'data', 'products_data.sql');
    209     fs.writeFileSync(outputPath, sql, 'utf8');
    210 
    211     console.log(`✓ Successfully generated ${products.length} products`);
    212     console.log(`✓ SQL file saved to: ${outputPath}`);
    213     console.log(`✓ File size: ${(sql.length / 1024).toFixed(2)} KB`);
    214 }
    215 
    216 // Run the script
    217 main();