File manager - Edit - /home2/zetasolve/speedfood.zetasolve.agency/wp-admin/backend.zip
Back
PK ��\� ?u p p inventory.db.backup_amount_paidnu �[��� SQLite format 3 @ . . .r� � �� 7� '��#����bb =Q+ indexsqlite_autoindex_monthly_summary_1monthly_summary�m�9tableusersusers CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'Manager', -- 'Admin' or 'Manager' permissions TEXT, -- JSON string of allowed pages/modules created_at DATETIME DEFAULT CURRENT_TIMESTAMP , status TEXT DEFAULT 'Active')��tableskusskusCREATE TABLE skus ( id INTEGER PRIMARY KEY AUTOINCREMENT, sku_code TEXT NOT NULL UNIQUE, product_id INTEGER NOT NULL, flavour TEXT NOT NULL, weight TEXT NOT NULL, current_stock INTEGER DEFAULT 0, price REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, tag TEXT DEFAULT '', FOREIGN KEY (product_id) REFERENCES products(id) )) = indexsqlite_autoindex_users_1users��wtablecustomerscustomersCREATE TABLE customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, phone TEXT, email TEXT, address TEXT, total_outstanding REAL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )1E indexsqlite_autoindex_customers_1customers �a++�ytablecredit_paymentscredit_paymentsCREATE TABLE credit_payments ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, payment_date DATE NOT NULL, amount_paid REAL NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (transaction_id) REFERENCES transactions(id) )�X �tableexpensesexpensesCREATE TABLE expenses ( id INTEGER PRIMARY KEY AUTOINCREMENT, expense_date DATE NOT NULL, description TEXT NOT NULL, category TEXT NOT NULL CHECK(category IN ('Rent', 'Advance', 'Transport', 'Utilities', 'Other')), amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )�B %%�Gtablereturn_itemsreturn_items CREATE TABLE return_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, return_id INTEGER NOT NULL, sku_id INTEGER NOT NULL, quantity INTEGER NOT NULL, FOREIGN KEY (return_id) REFERENCES returns(id) ON DELETE CASCADE, FOREIGN KEY (sku_id) REFERENCES skus(id) )�n�3tablereturnsreturns CREATE TABLE returns ( id INTEGER PRIMARY KEY AUTOINCREMENT, return_date DATE NOT NULL, original_transaction_id INTEGER, customer_name TEXT, reason TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, return_type TEXT DEFAULT 'Normal', FOREIGN KEY (original_transaction_id) REFERENCES transactions(id) )�//�gtabletransaction_itemstransaction_itemsCREATE TABLE transaction_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, sku_id INTEGER NOT NULL, quantity INTEGER NOT NULL, unit_price REAL NOT NULL, subtotal REAL NOT NULL, FOREIGN KEY (transaction_id) REFERENCES transactions(id) ON DELETE CASCADE, FOREIGN KEY (sku_id) REFERENCES skus(id) )�K%%�YtabletransactionstransactionsCREATE TABLE transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_date DATE NOT NULL, payment_type TEXT NOT NULL CHECK(payment_type IN ('Cash', 'Credit')), customer_name TEXT, total_amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )'; indexsqlite_autoindex_skus_1skusP++Ytablesqlite_sequencesqlite_sequenceCREATE TABLE sqlite_sequence(name,seq)/C indexsqlite_autoindex_products_1products�L�ktableproductsproductsCREATE TABLE products ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, description TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTA 9 ��Y9 C 3masala2026-01-10 12:22:09/ 13JuiceFresh fruit juices2025-12-21 13:03:31; M3JamFruit jams in multiple varieties2025-12-21 13:03:317 A3AcharPickles in various flavors2025-12-21 13:03:31 � ���� masalaC JuiceJam Achar �^�������:I� 1standalone_credits+monthly_summarym stand expensesCcustomer_credit_adjustments customers +credit_payments products-� monthly_summary usersreturns� usersn%return_items skus � tra/transaction_items %transactions customers t ��m< �@bA � � t > �� �3��t � � 0�t 3 DEL_DEBUGTest100g d2026-01-10 11:37:20:�s 6�s4 3 JM-PI-05Pineapple5kgl2025-12-21 13:03:311 3 AC-MX-500Mixed500g �2025-12-21 13:03:3112 3 AC-GA-10Garlic10kg �2025-12-21 13:03:31- 3JZ-MX-1LMixed1L}2025-12-21 13:03:31. 3JZ-GR-1LGrape1L �2025-12-21 13:03:31. 3JZ-OR-1LOrange1Ln2025-12-21 13:03:31. 3JZ-AP-1LApple1L �2025-12-21 13:03:31- 3JZ-MA-1LMango1Lx2025-12-21 13:03:311 3 AC-GA-20Garlic20kgP2025-12-21 13:03:31315 3JM-PI-500Pineapple500g �2025-12-21 13:03:315 #3JM-MF-05Mixed Fruit5kg:2025-12-21 13:03:317 #3JM-MF-500Mixed Fruit500g �2025-12-21 13:03:314 !3JM-ST-05Strawberry5kg�2025-12-21 13:03:316 !3JM-ST-500Strawberry500g �2025-12-21 13:03:31/ 3JM-AP-05Apple5kg2025-12-21 13:03:311 3JM-AP-500Apple500g �2025-12-21 13:03:31/ 3JM-MA-05Mango5kg@2025-12-21 13:03:311 3JM-MA-500Mango500g �2025-12-21 13:03:31� d 3AC-GA-20Garlic20kgP2025-12-21 13:03:31� 2!3cdstrawberry550g4�2025-12-22 07:03:23/ 3AC-GA-05Garlic5kgx2025-12-21 13:03:311 3AC-GA-500Garlic500g �2025-12-21 13:03:31/ 3AC-MX-20Mixed20kg02025-12-21 13:03:31/ 3AC-MX-10Mixed10kg�2025-12-21 13:03:31. 3AC-MX-05Mixed5kg�2025-12-21 13:03:31 2 3AC-MX-500Mixed500g �2025-12-21 13:03:31 � ��������an|�+8FS�������� DEL_DEBUGt DEL_TESTs m d test�JZ-MX-1LJZ-GR-1LJZ-OR-1LJZ-AP-1LJZ-MA-1LJM-PI-05 JM-PI-500JM-MF-05 JM-MF-500JM-ST-05 JM-ST-500 JM-AP-05 JM-AP-500JM-MA-05 JM-MA-500 AC-GA-20AC-GA-10AC-GA-05 AC-GA-500AC-MX-20AC-MX-10AC-MX-05 AC-MX-500 � � � � � � � �� � V 2 !32026-01-28Creditumer2026-01-28 20:00:195 !32026-01-28Creditumer �2026-01-28 14:23:36 ? !-32026-01-28CashWalk-in Customer �2026-01-28 13:37:51K!-32026-01-28CashWalk-in Customer �2026-01-28 13:06:35 K A!-32026-01-28CashWalk-in Customer �2026-01-28 13:05:05*A !-32026-01-28CreditWalk-in Customer �2026-01-28 11:08:48 A !-32026-01-28CreditWalk-in Customer �2026-01-28 11:07:51 ? !-32026-01-28CashWalk-in Customer �2026-01-28 11:04:43 �!'32026-01-28CreditTest Customer,2026-01-28 10:53:59 x!-32025-12-30CashWalk-in Customer2025-12-30 09:01:07 <!-2 !32026-01-28CreditUmer �2026-01-28 13:57:39 � x �xxxxxxx�iY � � � � �� < � �� � � � � � � � � . �, � � � �1�1� < ! %32026-01-10umerpacket break2026-01-10 10:31:54Damaged+ ! 32026-01-102026-01-10 10:08:37Normal �! 32026-01-06alliibrokn2026-01-06 19:08:01D>< 8 ! 32026-01-28umerunpacK ! E ! 932026-02-02ajdpacket seeil not work 2026-02-02 12:37:38Damaged ����� D � � 2 !32026-02-02CarTransport�2026-02-02 12:38:42 � ��V� 8 !+32026-01-28�Initial Payment2026-01-28 14:23:368 !+32026-01-28 �Initial Payment2026-01-28 13:57:397 !+3 2026-01-28�Initial Payment2026-01-28 11:08:487 !+3 2026-01-28,Initial Payment2026-01-28 11:07:516 !+3 2026-01-28dInitial Payment2026-01-28 10:53:59 � �� � �o3sy���� �O3umer$2b$10$oerj78Xgbs4J2lZglIBkWe2KAVDbf0hOV2V03y.tdQEK4fcyATmlyManager["inventory.html","billing.html"]2026-01-29 14:39:06Activem �3admin$2b$10$7tT16W.F03CB2sg3BbCje.xz6fMG5P3PCg4U2nIiNsT10HFpVVj3eAdmin["*"]2026-01-27 13:40:28Active y+�3saadbhaimerijan$2b$10$f59LhpB1YV1.uiNXfqkoFelql0ykZwnCmAuvX/GdVVHcAtdBaU.NSAdmin["*"]2026-01-10 12:24:25Active � � ��� umer admin saadb umer x��x ! 3umer2026-01-28 14:23:36 3Umer2026-01-28 13:57:39B '!- 3Test Customer1234567890test@example.com2026-01-28 10:51:3535 � ��� umerUmer' Test Customer � �� 32026-022026-02-02 12:35:48# 32026-01` 2026-01-24 18:34:49 � �� 2026-02 2026-01 � 1 ��P� '������ 0bb �/++�tablemonthly_summarymonthly_summaryCREATE TABLE monthly_summary ( id INTEGER PRIMARY KEY AUTOINCREMENT, month_year TEXT NOT NULL UNIQUE, -- Format: YYYY-MM total_sales REAL DEFAULT 0, total_transactions INTEGER DEFAULT 0, reset_date DATETIME DEFAULT CURRENT_TIMESTAMP )��Q+ indexsqlite_autoindex_monthly_summary_1monthly_summary�m�9tableusersusers CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'Manager', -- 'Admin' or 'Manager' permissions TEXT, -- JSON string of allowed pages/modules created_at DATETIME DEFAULT CURRENT_TIMESTAMP , status TEXT DEFAULT 'Active')��tableskusskusCREATE TABLE skus ( id INTEGER PRIMARY KEY AUTOINCREMENT, sku_code TEXT NOT NULL UNIQUE, product_id INTEGER NOT NULL, flavour TEXT NOT NULL, weight TEXT NOT NULL, current_stock INTEGER DEFAULT 0, price REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, tag TEXT DEFAULT '', FOREIGN KEY (product_id) REFERENCES products(id) ) 7�= indexsqlite_autoindex_users_1users��wtablecustomerscustomersCREATE TABLE customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, phone TEXT, email TEXT, address TEXT, total_outstanding REAL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )1E indexsqlite_autoindex_customers_1customers � �a++�ytablecredit_paymentscredit_paymentsCREATE TABLE credit_payments ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, payment_date DATE NOT NULL, amount_paid REAL NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FORE�%%�atabletransactionstransactionsCREATE TABLE transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_date DATE NOT NULL, payment_type TEXT NOT NULL CHECK(payment_type IN ('Cash', 'Credit')), customer_name TEXT, total_amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP , discount_percentage REAL DEFAULT 0, discount_amount REAL DEFAULT 0)�B %%�Gtablereturn_itemsreturn_items CREATE TABLE return_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, return_id INTEGER NOT NULL, sku_id INTEGER NOT NULL, quantity INTEGER NOT NULL, FOREIGN KEY (return_id) REFERENCES returns(id) ON DELETE CASCADE, FOREIGN KEY (sku_id) REFERENCES skus(id) )�n�3tablereturnsreturns CREATE TABLE returns ( id INTEGER PRIMARY KEY AUTOINCREMENT, return_date DATE NOT NULL, original_transaction_id INTEGER, customer_name TEXT, reason TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, return_type TEXT DEFAULT 'Normal', FOREIGN KEY (original_transaction_id) REFERENCES transactions(id) )�//�gtabletransaction_itemstransaction_itemsCREATE TABLE transaction_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, sku_id INTEGER NOT NULL, quantity INTEGER NOT NULL, unit_price REAL NOT NULL, subtotal REAL NOT NULL, FOREIGN KEY (transaction_id) REFERENCES transactions(id) ON DELETE CASCADE, FOREIGN KEY (sku_id) REFERENCES skus(id) ) N%%�YtabletransactionstransactionsCREATE TABLE transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_date DATE NOT NULL, payment_type TEXT NOT NULL CHECK(payment_type IN ('Cash', 'Credit')), customer_name TEXT, total_amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )'; indexsqlite_autoindex_skus_1skusP++Ytablesqlite_sequencesqlite_sequenceCREATE TABLE sqlite_sequence(name,seq)/C indexsqlite_autoindex_products_1products�L�ktableproductsproductsCREATE TABLE products ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, description TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) � � �x a .��3\� �w11�tablestandalone_creditsstandalone_creditsCREATE TABLE standalone_credits ( id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER NOT NULL, customer_name TEXT NOT NULL, total_amount REAL NOT NULL, paid_amount REAL NOT NULL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP )�TCC�/tablecustomer_credit_adjustmentscustomer_credit_adjustmentsCREATE TABLE customer_credit_adjustments ( id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER NOT NULL, adjustment_date DATE NOT NULL, amount_cleared REAL NOT NULL, notes TEXT, adjustment_type TEXT NOT NULL CHECK(adjustment_type IN ('CLEAR', 'ADJUST')), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (customer_id) REFERENCES customers(id) )�33�5tablecredit_payments_newcredit_payments_newCREATE TABLE credit_payments_new (id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER, customer_id INTEGER, payment_date DATE NOT NULL, amount_paid REAL NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (transaction_id) REFERENCES transactions(id), FOREIGN KEY (customer_id) REFERENCES customers(id))=Q+ indexsqlite_autoindex_monthly_summary_1monthly_summary�/++�tablemonthly_summarymonthly_summaryCREATE TABLE monthly_summary ( id INTEGER PRIMARY KEY AUTOINCREMENT, month_year TEXT NOT NULL UNIQUE, -- Format: YYYY-MM total_sales REAL DEFAULT 0, total_transactions INTEGER DEFAULT 0, reset_date DATETIME DEFAULT CURRENT_TIMESTAMP )1E indexsqlite_autoindex_customers_1customers��wtablecustomerscustomersCREATE TABLE customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, phone TEXT, email TEXT, address TEXT, total_outstanding REAL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )) = indexsqlite_autoindex_users_1users�m�9tableusersusers CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'Manager', -- 'Admin' or 'Manager' permissions TEXT, -- JSON string of allowed pages/modules created_at DATETIME DEFAULT CURRENT_TIMESTAMP , status TEXT DEFAULT 'Active')�++�Utablecredit_paymentscredit_paymentsCREATE TABLE credit_payments ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, payment_date DATE NOT NULL, amount_paid REAL NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, customer_id INTEGER REFERENCES customers(id), FOREIGN KEY (transaction_id) REFERENCES transactions(id) )�X �tableexpensesexpensesCREATE TABLE expenses ( id INTEGER PRIMARY KEY AUTOINCREMENT, expense_date DATE NOT NULL, description TEXT NOT NULL, category TEXT NOT NULL CHECK(category IN ('Rent', 'Advance', 'Transport', 'Utilities', 'Other')), amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) � �x3� G !A32026-01-28Credit deletion/correctionCLEAR2026-01-28 20:00:40C !932026-01-28�Full credit settlementCLEAR2026-01-28 14:23:49G !A32026-01-28 �Credit deletion/correctionCLEAR2026-01-28 14:23:08= !/32026-01-28 �Test clear creditCLEAR2026-01-28 14:20:02 � 6 33umer � �2026-02-02 12:38:032026-02-02 12:38:19PK ��\��͕� � migrate_users.jsnu �[��� const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const dbPath = path.join(__dirname, 'inventory.db'); const db = new sqlite3.Database(dbPath); db.serialize(() => { // Add status column to users table db.run("ALTER TABLE users ADD COLUMN status TEXT DEFAULT 'Active'", (err) => { if (err) { if (err.message.includes('duplicate column name')) { console.log('Column status already exists'); } else { console.error('Error adding status column:', err); } } else { console.log('Successfully added status column to users table'); } }); }); db.close(); PK ��\�4� � migrate_add_amount_paid.jsnu �[��� const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const fs = require('fs'); const dbPath = path.join(__dirname, 'inventory.db'); const backupPath = path.join(__dirname, 'inventory.db.backup_amount_paid'); // 1. Create Backup console.log('Creating backup...'); fs.copyFileSync(dbPath, backupPath); console.log(`Backup created at ${backupPath}`); const db = new sqlite3.Database(dbPath); db.serialize(() => { // 2. Add Column console.log('Adding amount_paid column...'); db.run('ALTER TABLE transactions ADD COLUMN amount_paid REAL DEFAULT 0;', (err) => { if (err) { if (err.message.includes('duplicate column name')) { console.log('Column amount_paid already exists.'); } else { console.error('Error adding column:', err); process.exit(1); } } else { console.log('Column amount_paid added successfully.'); } // 3. Verify db.all('PRAGMA table_info(transactions)', [], (err, rows) => { if (err) { console.error('Error verifying table info:', err); process.exit(1); } const hasColumn = rows.some(r => r.name === 'amount_paid'); console.log('Verification - Has amount_paid:', hasColumn); if (hasColumn) { console.log('Migration completed successfully.'); } else { console.error('Migration failed: Column not found after alter.'); process.exit(1); } }); }); }); db.close(); PK ��\Y���E E migrate_tag.jsnu �[��� const sqlite3 = require('sqlite3').verbose(); const db = new sqlite3.Database('./inventory.db'); console.log('Adding TAG column to skus table...'); db.run(`ALTER TABLE skus ADD COLUMN tag TEXT DEFAULT ''`, (err) => { if (err) { if (err.message.includes('duplicate column')) { console.log('TAG column already exists - skipping migration'); } else { console.error('Error adding TAG column:', err.message); } } else { console.log('✅ TAG column added successfully!'); } db.close(); }); PK ��\� � � server.jsnu �[��� require('dotenv').config(); const express = require('express'); const sqlite3 = require('sqlite3').verbose(); const cors = require('cors'); const bodyParser = require('body-parser'); const fs = require('fs'); const path = require('path'); const bcrypt = require('bcryptjs'); const app = express(); const PORT = process.env.PORT || 3000; const NODE_ENV = process.env.NODE_ENV || 'development'; // Middleware const corsOptions = { origin: function (origin, callback) { // Allow requests with no origin (like file:// or mobile apps) if (!origin) return callback(null, true); // Allow localhost for development if (origin.startsWith('http://localhost:') || origin.startsWith('https://localhost:')) { return callback(null, true); } // Allow production frontend - shayantraders.com if (origin === 'https://shayantraders.com' || origin === 'http://shayantraders.com' || origin === 'https://www.shayantraders.com') { return callback(null, true); } // Use environment variable for CORS if (process.env.CORS_ORIGIN && origin === process.env.CORS_ORIGIN) { return callback(null, true); } // Default: allow for development if (process.env.NODE_ENV !== 'production') { return callback(null, true); } callback(new Error('Not allowed by CORS')); }, credentials: true, optionsSuccessStatus: 200 }; app.use(cors(corsOptions)); app.use(bodyParser.json()); // API only - no static file serving // Logging middleware for production if (NODE_ENV === 'production') { app.use((req, res, next) => { console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`); next(); }); } // Initialize database const dbPath = process.env.DB_PATH || path.join(__dirname, 'inventory.db'); const db = new sqlite3.Database(dbPath, (err) => { if (err) { console.error('Error opening database:', err); } else { console.log(`Connected to SQLite database at ${dbPath}`); // Initialize schema const schema = fs.readFileSync(path.join(__dirname, 'schema.sql'), 'utf8'); db.exec(schema, (err) => { if (err) { console.error('Error initializing schema:', err); } else { console.log('Database initialized successfully'); initializeAdmin(); } }); } }); // Seed Admin User function initializeAdmin() { const adminUsername = process.env.ADMIN_USERNAME || 'admin'; const adminPassword = process.env.ADMIN_PASSWORD || 'saadislamabad'; db.get('SELECT * FROM users WHERE username = ?', [adminUsername], (err, row) => { if (err) return console.error('Error checking admin:', err); if (!row) { console.log('Creating default admin user...'); const hashedPassword = bcrypt.hashSync(adminPassword, 10); const permissions = JSON.stringify(['*']); // All permissions db.run('INSERT INTO users (username, password, role, permissions, status) VALUES (?, ?, ?, ?, ?)', [adminUsername, hashedPassword, 'Admin', permissions, 'Active'], (err) => { if (err) console.error('Error creating admin:', err); else console.log('Default admin created successfully'); } ); } }); } // ============================================ // AUTH API // ============================================ app.post('/api/login', (req, res) => { const { username, password } = req.body; db.get('SELECT * FROM users WHERE username = ?', [username], (err, user) => { if (err) return res.status(500).json({ error: err.message }); if (!user) return res.status(401).json({ error: 'Invalid credentials' }); const validPassword = bcrypt.compareSync(password, user.password); if (!validPassword) return res.status(401).json({ error: 'Invalid credentials' }); // Check if user account is disabled if (user.status === 'Disabled') { return res.status(403).json({ error: 'Account disabled. Please contact administrator.' }); } // Return user info without password const { password: _, ...userWithoutPassword } = user; res.json(userWithoutPassword); }); }); app.get('/api/users/public', (req, res) => { // Return list of users for login dropdown (id, username, role only) db.all('SELECT id, username, role FROM users ORDER BY username', [], (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); app.get('/api/users/status/:username', (req, res) => { const { username } = req.params; db.get('SELECT status FROM users WHERE username = ?', [username], (err, row) => { if (err) return res.status(500).json({ error: err.message }); if (!row) return res.status(404).json({ error: 'User not found' }); res.json({ status: row.status }); }); }); app.post('/api/users', (req, res) => { const { username, password, role, permissions } = req.body; // Define default permissions based on role if not provided let finalPermissions = permissions; if (!finalPermissions || finalPermissions.length === 0) { switch (role) { case 'Admin': finalPermissions = ['*']; break; case 'Manager': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html', 'invoices.html', 'returns.html', 'credit.html', 'expenses.html']; break; case 'Distributor': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html', 'invoices.html', 'returns.html', 'credit.html']; break; case 'Cashier': finalPermissions = ['dashboard.html', 'billing.html', 'invoices.html', 'credit.html']; break; case 'Staff': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html', 'credit.html']; break; default: finalPermissions = ['dashboard.html']; } } // Hash password const hashedPassword = bcrypt.hashSync(password, 10); const permissionsStr = JSON.stringify(finalPermissions); db.run('INSERT INTO users (username, password, role, permissions, status) VALUES (?, ?, ?, ?, ?)', [username, hashedPassword, role, permissionsStr, 'Active'], function (err) { if (err) return res.status(500).json({ error: err.message }); res.json({ id: this.lastID, success: true }); } ); }); app.get('/api/users', (req, res) => { db.all('SELECT id, username, role, permissions, status, created_at FROM users ORDER BY created_at DESC', [], (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); // Get user permissions app.get('/api/user-permissions', (req, res) => { // This endpoint can be used to get current user's permissions // For now, it's just a placeholder since permissions are stored in localStorage after login res.json({ message: 'Permissions available in user session' }); }); app.put('/api/users/:id', (req, res) => { const userId = req.params.id; const { username, password, role, permissions, status } = req.body; // Get current user data to prevent demoting self db.get('SELECT id, role FROM users WHERE id = ?', [userId], (err, currentUser) => { if (err) return res.status(500).json({ error: err.message }); db.serialize(() => { // Build update query dynamically or just handling password optionality if (password && password.trim() !== '') { const hashedPassword = bcrypt.hashSync(password, 10); // If changing role to Admin, ensure proper permissions let finalPermissions = permissions; if (role === 'Admin') { finalPermissions = ['*']; } else if (!finalPermissions || finalPermissions.length === 0) { // Use default permissions based on role if not provided switch (role) { case 'Manager': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html', 'invoices.html', 'returns.html', 'credit.html', 'expenses.html']; break; case 'Distributor': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html', 'invoices.html', 'returns.html']; break; case 'Cashier': finalPermissions = ['dashboard.html', 'billing.html', 'invoices.html']; break; case 'Staff': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html']; break; default: finalPermissions = ['dashboard.html']; } } db.run('UPDATE users SET username = ?, password = ?, role = ?, permissions = ?, status = ? WHERE id = ?', [username, hashedPassword, role, JSON.stringify(finalPermissions), status, userId], (err) => { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); } ); } else { // If changing role to Admin, ensure proper permissions let finalPermissions = permissions; if (role === 'Admin') { finalPermissions = ['*']; } else if (!finalPermissions || finalPermissions.length === 0) { // Use default permissions based on role if not provided switch (role) { case 'Manager': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html', 'invoices.html', 'returns.html', 'credit.html', 'expenses.html']; break; case 'Distributor': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html', 'invoices.html', 'returns.html']; break; case 'Cashier': finalPermissions = ['dashboard.html', 'billing.html', 'invoices.html']; break; case 'Staff': finalPermissions = ['dashboard.html', 'inventory.html', 'billing.html']; break; default: finalPermissions = ['dashboard.html']; } } db.run('UPDATE users SET username = ?, role = ?, permissions = ?, status = ? WHERE id = ?', [username, role, JSON.stringify(finalPermissions), status, userId], (err) => { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); } ); } }); }); }); app.delete('/api/users/:id', (req, res) => { const userId = req.params.id; // Prevent deleting the last admin or self (optional, but good practice) // For now, simple delete db.run('DELETE FROM users WHERE id = ?', [userId], (err) => { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); }); }); // ============================================ // PRODUCTS API // ============================================ app.get('/api/products', (req, res) => { db.all('SELECT * FROM products ORDER BY name', [], (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); app.post('/api/products', (req, res) => { const { name, description } = req.body; // Validate input if (!name || name.trim() === '') { return res.status(400).json({ error: 'Product name is required' }); } if (name.length > 50) { return res.status(400).json({ error: 'Product name must be 50 characters or less' }); } db.run('INSERT INTO products (name, description) VALUES (?, ?)', [name.trim(), description || ''], function (err) { if (err) { // Handle duplicate name error if (err.message.includes('UNIQUE constraint failed')) { return res.status(400).json({ error: 'Product name already exists' }); } return res.status(500).json({ error: err.message }); } res.json({ id: this.lastID, name: name.trim(), description: description || '' }); } ); }); // ============================================ // SKU API // ============================================ app.get('/api/skus', (req, res) => { const query = ` SELECT s.*, p.name as product_name FROM skus s JOIN products p ON s.product_id = p.id ORDER BY p.name, s.flavour, s.weight `; db.all(query, [], (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); app.get('/api/skus/:id', (req, res) => { const query = ` SELECT s.*, p.name as product_name FROM skus s JOIN products p ON s.product_id = p.id WHERE s.id = ? `; db.get(query, [req.params.id], (err, row) => { if (err) return res.status(500).json({ error: err.message }); res.json(row); }); }); app.post('/api/skus', (req, res) => { const { sku_code, product_id, flavour, weight, current_stock, price, tag } = req.body; const query = ` INSERT INTO skus (sku_code, product_id, flavour, weight, current_stock, price, tag) VALUES (?, ?, ?, ?, ?, ?, ?) `; db.run(query, [sku_code, product_id, flavour, weight, current_stock, price, tag || ''], function (err) { if (err) return res.status(500).json({ error: err.message }); res.json({ id: this.lastID, ...req.body }); }); }); app.put('/api/skus/:id', (req, res) => { const { current_stock, price, tag } = req.body; db.run('UPDATE skus SET current_stock = ?, price = ?, tag = ? WHERE id = ?', [current_stock, price, tag || '', req.params.id], (err) => { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); }); }); app.delete('/api/skus/:id', (req, res) => { // Check if used in transactions or returns first could be good, but for now simple delete // In a real app we might soft-delete or check constraints db.run('DELETE FROM skus WHERE id = ?', [req.params.id], (err) => { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); }); }); // ============================================ // TRANSACTIONS API (Billing/Sales) // ============================================ app.post('/api/transactions', (req, res) => { const { transaction_date, payment_type, customer_name, items, discount_percentage, discount_amount, amount_paid } = req.body; // Calculate total let total_amount = 0; items.forEach(item => { total_amount += item.quantity * item.unit_price; }); // Apply discount - only manual discount allowed (no automatic discount) let final_total = total_amount; let applied_discount_percentage = discount_percentage || 0; let applied_discount_amount = discount_amount || 0; // Only apply discount if it was manually entered if (applied_discount_percentage > 0 || applied_discount_amount > 0) { final_total = total_amount - applied_discount_amount; } // For cash-only flow, ensure payment type is always 'Cash' const effective_payment_type = 'Cash'; db.serialize(() => { db.run('BEGIN TRANSACTION'); // Insert transaction const transQuery = ` INSERT INTO transactions (transaction_date, payment_type, customer_name, total_amount, discount_percentage, discount_amount, amount_paid) VALUES (?, ?, ?, ?, ?, ?, ?) `; db.run(transQuery, [transaction_date, 'Cash', customer_name, total_amount, applied_discount_percentage, applied_discount_amount, amount_paid || final_total], function (err) { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } const transactionId = this.lastID; let completed = 0; items.forEach(item => { // Insert transaction item const itemQuery = ` INSERT INTO transaction_items (transaction_id, sku_id, quantity, unit_price, subtotal) VALUES (?, ?, ?, ?, ?) `; const subtotal = item.quantity * item.unit_price; db.run(itemQuery, [transactionId, item.sku_id, item.quantity, item.unit_price, subtotal], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } // Update stock db.run('UPDATE skus SET current_stock = current_stock - ? WHERE id = ?', [item.quantity, item.sku_id], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } completed++; if (completed === items.length) { // Cash payment logic - move this inside the completion check const finalizeCash = () => { db.run('COMMIT', (err) => { if (err) { return res.status(500).json({ error: 'Commit failed: ' + err.message }); } try { updateMonthlySummary(final_total); } catch (summaryErr) { console.error('Summary update failed:', summaryErr); } res.json({ id: transactionId, total_amount, final_total, discount_percentage: applied_discount_percentage, discount_amount: applied_discount_amount, amount_paid: amount_paid || final_total, success: true }); }); }; // Call finalize for cash payments finalizeCash(); } }); }); }); }); }); }); app.get('/api/transactions', (req, res) => { const { start_date, end_date } = req.query; let query = 'SELECT * FROM transactions WHERE 1=1'; const params = []; if (start_date) { query += ' AND transaction_date >= ?'; params.push(start_date); } if (end_date) { query += ' AND transaction_date <= ?'; params.push(end_date); } query += ' ORDER BY transaction_date DESC, id DESC'; db.all(query, params, (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); app.get('/api/transactions/:id', (req, res) => { db.get('SELECT * FROM transactions WHERE id = ?', [req.params.id], (err, transaction) => { if (err) return res.status(500).json({ error: err.message }); const itemsQuery = ` SELECT ti.*, s.sku_code, s.flavour, s.weight, p.name as product_name FROM transaction_items ti JOIN skus s ON ti.sku_id = s.id JOIN products p ON s.product_id = p.id WHERE ti.transaction_id = ? `; db.all(itemsQuery, [req.params.id], (err, items) => { if (err) return res.status(500).json({ error: err.message }); res.json({ ...transaction, items }); }); }); }); app.delete('/api/transactions/:id', (req, res) => { const transactionId = req.params.id; // 1. Get items to restore stock db.all('SELECT * FROM transaction_items WHERE transaction_id = ?', [transactionId], (err, items) => { if (err) return res.status(500).json({ error: err.message }); db.serialize(() => { db.run('BEGIN TRANSACTION'); // 2. Restore stock items.forEach(item => { db.run('UPDATE skus SET current_stock = current_stock + ? WHERE id = ?', [item.quantity, item.sku_id]); }); // 3. Delete items db.run('DELETE FROM transaction_items WHERE transaction_id = ?', [transactionId]); // 4. Delete transaction db.run('DELETE FROM transactions WHERE id = ?', [transactionId], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } db.run('COMMIT'); res.json({ success: true }); }); }); }); }); // ============================================ // RETURNS API // ============================================ app.get('/api/returns', (req, res) => { const { start_date, end_date } = req.query; let query = 'SELECT * FROM returns WHERE 1=1'; const params = []; if (start_date) { query += ' AND return_date >= ?'; params.push(start_date); } if (end_date) { query += ' AND return_date <= ?'; params.push(end_date); } query += ' ORDER BY return_date DESC, id DESC'; db.all(query, params, (err, rows) => { if (err) return res.status(500).json({ error: err.message }); // If no returns, return empty array if (rows.length === 0) return res.json([]); // Fetch items for these returns const returnIds = rows.map(r => r.id); const placeholders = returnIds.map(() => '?').join(','); const itemsQuery = ` SELECT ri.*, s.sku_code, s.flavour, s.weight, p.name as product_name FROM return_items ri JOIN skus s ON ri.sku_id = s.id JOIN products p ON s.product_id = p.id WHERE ri.return_id IN (${placeholders}) `; db.all(itemsQuery, returnIds, (err, items) => { if (err) return res.status(500).json({ error: err.message }); // Attach items to returns const returnsWithItems = rows.map(r => ({ ...r, items: items.filter(i => i.return_id === r.id) })); res.json(returnsWithItems); }); }); }); app.get('/api/damaged-items', (req, res) => { const query = ` SELECT r.*, ri.quantity, ri.sku_id, s.sku_code, s.flavour, s.weight, p.name as product_name FROM returns r JOIN return_items ri ON r.id = ri.return_id JOIN skus s ON ri.sku_id = s.id JOIN products p ON s.product_id = p.id WHERE r.return_type = 'Damaged' ORDER BY r.return_date DESC `; db.all(query, [], (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); app.post('/api/returns', (req, res) => { const { return_date, original_transaction_id, customer_name, reason, return_type, items } = req.body; const type = return_type || 'Normal'; // Default to Normal if not specified db.serialize(() => { db.run('BEGIN TRANSACTION'); // Insert return const returnQuery = ` INSERT INTO returns (return_date, original_transaction_id, customer_name, reason, return_type) VALUES (?, ?, ?, ?, ?) `; db.run(returnQuery, [return_date, original_transaction_id, customer_name, reason, type], function (err) { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } const returnId = this.lastID; let completed = 0; items.forEach(item => { // Insert return item db.run('INSERT INTO return_items (return_id, sku_id, quantity) VALUES (?, ?, ?)', [returnId, item.sku_id, item.quantity], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } // Update stock ONLY if it's a Normal return if (type === 'Normal') { db.run('UPDATE skus SET current_stock = current_stock + ? WHERE id = ?', [item.quantity, item.sku_id], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } completed++; if (completed === items.length) { db.run('COMMIT'); res.json({ id: returnId, success: true }); } }); } else { // For Damaged items, we don't update stock completed++; if (completed === items.length) { db.run('COMMIT'); res.json({ id: returnId, success: true }); } } }); }); }); }); }); // ============================================ // UPDATE RETURN API // ============================================ app.put('/api/returns/:id', (req, res) => { const { return_date, customer_name, reason, return_type, items } = req.body; const returnId = req.params.id; db.serialize(() => { db.run('BEGIN TRANSACTION'); // Get old return data to calculate stock adjustments db.get('SELECT return_type FROM returns WHERE id = ?', [returnId], (err, oldReturn) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } // Get old return items db.all('SELECT sku_id, quantity FROM return_items WHERE return_id = ?', [returnId], (err, oldItems) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } // Reverse old stock adjustments (if it was Normal return) if (oldReturn.return_type === 'Normal') { oldItems.forEach(item => { db.run('UPDATE skus SET current_stock = current_stock - ? WHERE id = ?', [item.quantity, item.sku_id]); }); } // Update return record db.run('UPDATE returns SET return_date = ?, customer_name = ?, reason = ?, return_type = ? WHERE id = ?', [return_date, customer_name, reason, return_type, returnId], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } // Delete old return items db.run('DELETE FROM return_items WHERE return_id = ?', [returnId], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } // Insert new return items let completed = 0; items.forEach(item => { db.run('INSERT INTO return_items (return_id, sku_id, quantity) VALUES (?, ?, ?)', [returnId, item.sku_id, item.quantity], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } // Apply new stock adjustments (if Normal return) if (return_type === 'Normal') { db.run('UPDATE skus SET current_stock = current_stock + ? WHERE id = ?', [item.quantity, item.sku_id], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } completed++; if (completed === items.length) { db.run('COMMIT'); res.json({ success: true }); } }); } else { // Damaged - no stock adjustment completed++; if (completed === items.length) { db.run('COMMIT'); res.json({ success: true }); } } }); }); }); }); }); }); }); }); app.delete('/api/returns/:id', (req, res) => { const returnId = req.params.id; db.get('SELECT * FROM returns WHERE id = ?', [returnId], (err, returnRecord) => { if (err) return res.status(500).json({ error: err.message }); if (!returnRecord) return res.status(404).json({ error: 'Return not found' }); db.all('SELECT * FROM return_items WHERE return_id = ?', [returnId], (err, items) => { if (err) return res.status(500).json({ error: err.message }); db.serialize(() => { db.run('BEGIN TRANSACTION'); // If it was a Normal return, it ADDED to stock. So we must SUBTRACT to reverse it. // If it was Damaged, it didn't affect stock (kept it away). So deleting record just removes record. if (returnRecord.return_type === 'Normal') { items.forEach(item => { db.run('UPDATE skus SET current_stock = current_stock - ? WHERE id = ?', [item.quantity, item.sku_id]); }); } db.run('DELETE FROM return_items WHERE return_id = ?', [returnId]); db.run('DELETE FROM returns WHERE id = ?', [returnId], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } db.run('COMMIT'); res.json({ success: true }); }); }); }); }); }); // ============================================ // EXPENSES API // ============================================ app.get('/api/expenses', (req, res) => { const { start_date, end_date, category } = req.query; let query = 'SELECT * FROM expenses WHERE 1=1'; const params = []; if (start_date) { query += ' AND expense_date >= ?'; params.push(start_date); } if (end_date) { query += ' AND expense_date <= ?'; params.push(end_date); } if (category) { query += ' AND category = ?'; params.push(category); } query += ' ORDER BY expense_date DESC, id DESC'; db.all(query, params, (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); app.post('/api/expenses', (req, res) => { const { expense_date, description, category, amount } = req.body; const query = ` INSERT INTO expenses (expense_date, description, category, amount) VALUES (?, ?, ?, ?) `; db.run(query, [expense_date, description, category, amount], function (err) { if (err) return res.status(500).json({ error: err.message }); res.json({ id: this.lastID, success: true }); }); }); app.delete('/api/expenses/:id', (req, res) => { const expenseId = req.params.id; db.run('DELETE FROM expenses WHERE id = ?', [expenseId], function (err) { if (err) return res.status(500).json({ error: err.message }); if (this.changes === 0) return res.status(404).json({ error: 'Expense not found' }); res.json({ success: true }); }); }); // ============================================ // CUSTOMER PAYMENTS API (for customer-level credit payments) // ============================================ app.post('/api/customer-payments', (req, res) => { const { customer_id, payment_date, amount_paid, notes } = req.body; if (!customer_id || !payment_date || !amount_paid) { return res.status(400).json({ error: 'Customer ID, payment date, and amount are required' }); } db.serialize(() => { db.run('BEGIN TRANSACTION'); // Insert credit payment record first const paymentQuery = ` INSERT INTO credit_payments (transaction_id, customer_id, payment_date, amount_paid, notes) VALUES (NULL, ?, ?, ?, ?) `; db.run(paymentQuery, [customer_id, payment_date, amount_paid, notes || 'Credit payment'], function (err) { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } const paymentId = this.lastID; // Then update customer's outstanding amount // First, get current outstanding to calculate new value db.get('SELECT total_outstanding FROM customers WHERE id = ?', [customer_id], (err, customer) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } if (!customer) { db.run('ROLLBACK'); return res.status(404).json({ error: 'Customer not found' }); } // Calculate new outstanding (ensure it doesn't go below 0) const newOutstanding = Math.max(0, customer.total_outstanding - amount_paid); // Update customer's outstanding amount db.run('UPDATE customers SET total_outstanding = ? WHERE id = ?', [newOutstanding, customer_id], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } db.run('COMMIT'); res.json({ id: paymentId, success: true }); }); }); }); }); }); // ============================================ // CREDIT PAYMENTS API (transaction-based, kept for backward compatibility) // ============================================ app.get('/api/credit-payments', (req, res) => { const { start_date, end_date, customer_name } = req.query; let query = ` SELECT cp.*, c.name as customer_name, t.total_amount, t.transaction_date, t.customer_name as transaction_customer_name FROM credit_payments cp LEFT JOIN customers c ON cp.customer_id = c.id LEFT JOIN transactions t ON cp.transaction_id = t.id WHERE 1=1 `; const params = []; if (start_date) { query += ' AND cp.payment_date >= ?'; params.push(start_date); } if (end_date) { query += ' AND cp.payment_date <= ?'; params.push(end_date); } query += ' ORDER BY cp.payment_date DESC, cp.id DESC'; db.all(query, params, (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); app.post('/api/credit-payments', (req, res) => { const { transaction_id, customer_name, payment_date, amount_paid, notes } = req.body; // Get transaction details to get customer name if not provided db.get('SELECT customer_name FROM transactions WHERE id = ?', [transaction_id], (err, transaction) => { if (err) return res.status(500).json({ error: err.message }); const actual_customer_name = customer_name || transaction.customer_name; db.serialize(() => { db.run('BEGIN TRANSACTION'); if (actual_customer_name && actual_customer_name !== 'Walk-in Customer') { // Insert credit payment record with customer_id lookup const query = ` INSERT INTO credit_payments (transaction_id, customer_id, payment_date, amount_paid, notes) VALUES (?, (SELECT id FROM customers WHERE name = ?), ?, ?, ?) `; db.run(query, [transaction_id, actual_customer_name, payment_date, amount_paid, notes], function (err) { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } const paymentId = this.lastID; // Update customer's outstanding amount db.run('UPDATE customers SET total_outstanding = total_outstanding - ? WHERE name = ?', [amount_paid, actual_customer_name], (err) => { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } db.run('COMMIT'); res.json({ id: paymentId, success: true }); }); }); } else { // For walk-in customers or when no customer name, insert payment without customer_id const query = ` INSERT INTO credit_payments (transaction_id, customer_id, payment_date, amount_paid, notes) VALUES (?, NULL, ?, ?, ?) `; db.run(query, [transaction_id, payment_date, amount_paid, notes], function (err) { if (err) { db.run('ROLLBACK'); return res.status(500).json({ error: err.message }); } const paymentId = this.lastID; // For walk-in customers, don't update customer outstanding db.run('COMMIT'); res.json({ id: paymentId, success: true }); }); } }); }); }); // Helper function to get current month-year function getCurrentMonthYear() { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); // Month is 0-indexed return `${year}-${month}`; } // Function to initialize monthly summary for current month if it doesn't exist function initializeMonthlySummary() { const monthYear = getCurrentMonthYear(); db.get('SELECT * FROM monthly_summary WHERE month_year = ?', [monthYear], (err, row) => { if (err) { console.error('Error checking monthly summary:', err); return; } if (!row) { // Initialize current month's summary db.run('INSERT OR IGNORE INTO monthly_summary (month_year, total_sales, total_transactions) VALUES (?, 0, 0)', [monthYear], (err) => { if (err) { console.error('Error initializing monthly summary:', err); } else { console.log(`Initialized monthly summary for ${monthYear}`); } }); } }); } // Function to update monthly summary when a transaction occurs function updateMonthlySummary(transactionAmount) { const monthYear = getCurrentMonthYear(); db.serialize(() => { db.run('BEGIN TRANSACTION'); // Get current summary db.get('SELECT total_sales, total_transactions FROM monthly_summary WHERE month_year = ?', [monthYear], (err, row) => { if (err) { db.run('ROLLBACK'); console.error('Error getting monthly summary:', err); return; } if (row) { // Update existing summary const newTotalSales = row.total_sales + transactionAmount; const newTotalTransactions = row.total_transactions + 1; db.run('UPDATE monthly_summary SET total_sales = ?, total_transactions = ? WHERE month_year = ?', [newTotalSales, newTotalTransactions, monthYear], (err) => { if (err) { db.run('ROLLBACK'); console.error('Error updating monthly summary:', err); } else { db.run('COMMIT'); } }); } else { // Create new summary for the month db.run('INSERT OR IGNORE INTO monthly_summary (month_year, total_sales, total_transactions) VALUES (?, ?, ?)', [monthYear, transactionAmount, 1], (err) => { if (err) { db.run('ROLLBACK'); console.error('Error creating monthly summary:', err); } else { db.run('COMMIT'); } }); } }); }); } // Initialize monthly summary on startup initializeMonthlySummary(); // Function to check and reset monthly summary at the beginning of each month function checkAndResetMonthlyIfNeeded() { const currentMonthYear = getCurrentMonthYear(); // Check if current month's summary exists db.get('SELECT * FROM monthly_summary WHERE month_year = ?', [currentMonthYear], (err, row) => { if (err) { console.error('Error checking monthly summary for reset:', err); return; } if (!row) { // Current month doesn't exist, initialize it with zeros db.run('INSERT OR IGNORE INTO monthly_summary (month_year, total_sales, total_transactions) VALUES (?, 0, 0)', [currentMonthYear], (err) => { if (err) { console.error('Error initializing current month:', err); } else { console.log(`Initialized monthly summary for ${currentMonthYear}`); } }); } }); } // Run the check on startup checkAndResetMonthlyIfNeeded(); // Schedule monthly reset for the 1st of each month at midnight const schedule = require('node-schedule'); schedule.scheduleJob('0 0 1 * *', function () { // Run on the 1st of every month at 00:00 console.log('Monthly reset check triggered automatically'); checkAndResetMonthlyIfNeeded(); }); // ============================================ // STANDALONE CREDITS API // ============================================ // Get next available customer ID for standalone credits app.get('/api/standalone-credits/next-id', (req, res) => { db.get('SELECT COALESCE(MAX(customer_id), 0) + 1 as next_id FROM standalone_credits', [], (err, row) => { if (err) return res.status(500).json({ error: err.message }); res.json({ next_id: row.next_id }); }); }); app.post('/api/standalone-credits', (req, res) => { const { customer_id, customer_name, total_amount, paid_amount } = req.body; // Validate inputs if (!customer_id || !customer_name || typeof total_amount !== 'number' || total_amount < 0) { return res.status(400).json({ error: 'Customer ID, name, and valid total amount are required' }); } if (typeof paid_amount !== 'number' || paid_amount < 0 || paid_amount > total_amount) { return res.status(400).json({ error: 'Paid amount must be a valid number between 0 and total amount' }); } db.run('INSERT INTO standalone_credits (customer_id, customer_name, total_amount, paid_amount) VALUES (?, ?, ?, ?)', [customer_id, customer_name, total_amount, paid_amount || 0], function (err) { if (err) { console.error('Error inserting standalone credit:', err); return res.status(500).json({ error: err.message }); } res.json({ id: this.lastID, success: true }); } ); }); app.get('/api/standalone-credits', (req, res) => { const { search } = req.query; let query = 'SELECT * FROM standalone_credits'; const params = []; if (search) { query += ' WHERE customer_id LIKE ? OR customer_name LIKE ?'; const searchParam = `%${search}%`; params.push(searchParam, searchParam); } query += ' ORDER BY created_at DESC'; db.all(query, params, (err, rows) => { if (err) { console.error('Error fetching standalone credits:', err); return res.status(500).json({ error: err.message }); } res.json(rows); }); }); app.put('/api/standalone-credits/:id', (req, res) => { const creditId = req.params.id; const { paid_amount } = req.body; // Validate input if (typeof paid_amount !== 'number' || paid_amount < 0) { return res.status(400).json({ error: 'Valid paid amount is required' }); } // Get current record to validate total amount db.get('SELECT total_amount FROM standalone_credits WHERE id = ?', [creditId], (err, record) => { if (err) { console.error('Error fetching credit record:', err); return res.status(500).json({ error: err.message }); } if (!record) { return res.status(404).json({ error: 'Credit record not found' }); } if (paid_amount > record.total_amount) { return res.status(400).json({ error: 'Paid amount cannot exceed total amount' }); } db.run('UPDATE standalone_credits SET paid_amount = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?', [paid_amount, creditId], (err) => { if (err) { console.error('Error updating standalone credit:', err); return res.status(500).json({ error: err.message }); } res.json({ success: true }); } ); }); }); app.delete('/api/standalone-credits/:id', (req, res) => { const creditId = req.params.id; db.run('DELETE FROM standalone_credits WHERE id = ?', [creditId], function (err) { if (err) { console.error('Error deleting standalone credit:', err); return res.status(500).json({ error: err.message }); } if (this.changes === 0) { return res.status(404).json({ error: 'Credit record not found' }); } // Re-sequence customer_ids: 1, 2, 3... based on creation order db.all('SELECT id FROM standalone_credits ORDER BY id ASC', [], (err, rows) => { if (err) { console.error('Error re-sequencing customer IDs:', err); return res.json({ success: true }); } let completed = 0; if (rows.length === 0) return res.json({ success: true }); rows.forEach((row, index) => { db.run('UPDATE standalone_credits SET customer_id = ? WHERE id = ?', [index + 1, row.id], (err) => { if (err) console.error('Error updating customer_id:', err); completed++; if (completed === rows.length) { res.json({ success: true }); } }); }); }); }); }); // ============================================ // CUSTOMERS API // ============================================ app.get('/api/customers', (req, res) => { const query = ` SELECT c.*, COALESCE(SUM(cp.amount_paid), 0) as total_paid, c.total_outstanding as current_outstanding FROM customers c LEFT JOIN credit_payments cp ON c.id = cp.customer_id GROUP BY c.id ORDER BY c.name `; db.all(query, [], (err, rows) => { if (err) return res.status(500).json({ error: err.message }); res.json(rows); }); }); // Clear customer credit (set to 0) app.put('/api/customers/:id/clear-credit', (req, res) => { const customerId = req.params.id; const { payment_date, notes } = req.body; console.log('Clearing credit for customer ID:', customerId); console.log('Request body:', req.body); db.serialize(() => { db.run('BEGIN TRANSACTION'); // Get current outstanding amount db.get('SELECT name, total_outstanding FROM customers WHERE id = ?', [customerId], (err, customer) => { if (err) { db.run('ROLLBACK'); console.error('Database error:', err); return res.status(500).json({ error: err.message }); } if (!customer) { db.run('ROLLBACK'); return res.status(404).json({ error: 'Customer not found' }); } const amountToClear = customer.total_outstanding; if (amountToClear <= 0) { db.run('ROLLBACK'); return res.status(400).json({ error: 'No outstanding balance to clear' }); } // Insert customer credit adjustment record (separate from transaction-based payments) db.run( 'INSERT INTO customer_credit_adjustments (customer_id, adjustment_date, amount_cleared, notes, adjustment_type) VALUES (?, ?, ?, ?, ?)', [customerId, payment_date, amountToClear, notes || 'Credit cleared', 'CLEAR'], function (err) { if (err) { db.run('ROLLBACK'); console.error('Insert adjustment error:', err); return res.status(500).json({ error: err.message }); } // Update customer's outstanding amount to 0 db.run('UPDATE customers SET total_outstanding = 0 WHERE id = ?', [customerId], (err) => { if (err) { db.run('ROLLBACK'); console.error('Update customer error:', err); return res.status(500).json({ error: err.message }); } db.run('COMMIT'); console.log('Credit cleared successfully for customer:', customer.name); res.json({ success: true, cleared_amount: amountToClear, customer_name: customer.name }); }); } ); }); }); }); app.post('/api/customers', (req, res) => { const { name, phone, email, address } = req.body; if (!name || name.trim() === '') { return res.status(400).json({ error: 'Customer name is required' }); } db.run('INSERT INTO customers (name, phone, email, address) VALUES (?, ?, ?, ?)', [name.trim(), phone || null, email || null, address || null], function (err) { if (err) { if (err.message.includes('UNIQUE constraint failed')) { return res.status(400).json({ error: 'Customer name already exists' }); } return res.status(500).json({ error: err.message }); } res.json({ id: this.lastID, name: name.trim(), success: true }); } ); }); app.put('/api/customers/:id', (req, res) => { const { name, phone, email, address } = req.body; const customerId = req.params.id; if (!name || name.trim() === '') { return res.status(400).json({ error: 'Customer name is required' }); } db.run('UPDATE customers SET name = ?, phone = ?, email = ?, address = ? WHERE id = ?', [name.trim(), phone || null, email || null, address || null, customerId], (err) => { if (err) { if (err.message.includes('UNIQUE constraint failed')) { return res.status(400).json({ error: 'Customer name already exists' }); } return res.status(500).json({ error: err.message }); } res.json({ success: true }); } ); }); app.delete('/api/customers/:id', (req, res) => { const customerId = req.params.id; // Check if customer has outstanding balance db.get('SELECT total_outstanding FROM customers WHERE id = ?', [customerId], (err, customer) => { if (err) return res.status(500).json({ error: err.message }); if (!customer) return res.status(404).json({ error: 'Customer not found' }); if (customer.total_outstanding > 0) { return res.status(400).json({ error: 'Cannot delete customer with outstanding balance. Please settle all dues first.' }); } db.run('DELETE FROM customers WHERE id = ?', [customerId], (err) => { if (err) return res.status(500).json({ error: err.message }); res.json({ success: true }); }); }); }); // ============================================ // DASHBOARD/SUMMARY API // ============================================ app.get('/api/dashboard', (req, res) => { const today = new Date().toISOString().split('T')[0]; const results = {}; // Get inventory value db.get('SELECT SUM(current_stock * price) as total_value FROM skus', [], (err, row) => { if (err) return res.status(500).json({ error: err.message }); results.inventory_value = row.total_value || 0; // Get today's sales db.get('SELECT COUNT(*) as count, SUM(total_amount) as total FROM transactions WHERE transaction_date = ?', [today], (err, row) => { if (err) return res.status(500).json({ error: err.message }); results.today_sales_count = row.count || 0; results.today_sales_total = row.total || 0; // Get outstanding credit (from customers table) db.get('SELECT SUM(total_outstanding) as total_outstanding FROM customers', [], (err, row) => { if (err) return res.status(500).json({ error: err.message }); results.outstanding_credit = row.total_outstanding || 0; // Get today's expenses db.get('SELECT SUM(amount) as total FROM expenses WHERE expense_date = ?', [today], (err, row) => { if (err) return res.status(500).json({ error: err.message }); results.today_expenses = row.total || 0; // Get current month's sales summary const currentMonthYear = getCurrentMonthYear(); db.get('SELECT total_sales, total_transactions FROM monthly_summary WHERE month_year = ?', [currentMonthYear], (err, row) => { if (err) { console.error('Error getting monthly summary:', err); results.monthly_sales_total = 0; results.monthly_sales_count = 0; } else { results.monthly_sales_total = row ? row.total_sales || 0 : 0; results.monthly_sales_count = row ? row.total_transactions || 0 : 0; } res.json(results); }); }); }); }); }); }); // Monthly Reports API app.get('/api/monthly-report', (req, res) => { const { month_year } = req.query; const targetMonthYear = month_year || getCurrentMonthYear(); // Get detailed monthly report const transactionsQuery = ` SELECT t.*, ti.sku_id, ti.quantity, ti.unit_price, ti.subtotal, s.sku_code, s.flavour, s.weight, p.name as product_name FROM transactions t LEFT JOIN transaction_items ti ON t.id = ti.transaction_id LEFT JOIN skus s ON ti.sku_id = s.id LEFT JOIN products p ON s.product_id = p.id WHERE strftime('%Y-%m', t.transaction_date) = ? ORDER BY t.transaction_date DESC, t.id DESC `; db.all(transactionsQuery, [targetMonthYear], (err, transactions) => { if (err) return res.status(500).json({ error: err.message }); // Group items by transaction const groupedTransactions = {}; transactions.forEach(tx => { if (!groupedTransactions[tx.id]) { groupedTransactions[tx.id] = { id: tx.id, transaction_date: tx.transaction_date, payment_type: tx.payment_type, customer_name: tx.customer_name, total_amount: tx.total_amount, discount_percentage: tx.discount_percentage, discount_amount: tx.discount_amount, items: [] }; } if (tx.sku_id) { // Only add items that exist groupedTransactions[tx.id].items.push({ sku_id: tx.sku_id, sku_code: tx.sku_code, product_name: tx.product_name, flavour: tx.flavour, weight: tx.weight, quantity: tx.quantity, unit_price: tx.unit_price, subtotal: tx.subtotal }); } }); const result = { month_year: targetMonthYear, transactions: Object.values(groupedTransactions), summary: { total_sales: Object.values(groupedTransactions).reduce((sum, tx) => sum + (tx.total_amount || 0), 0), total_transactions: Object.keys(groupedTransactions).length, total_discounts: Object.values(groupedTransactions).reduce((sum, tx) => sum + (tx.discount_amount || 0), 0) } }; res.json(result); }); }); // Endpoint to reset monthly values (admin only) app.post('/api/reset-monthly', (req, res) => { // In a real app, you'd want to verify admin privileges here const nextMonthYear = req.body.next_month_year; // Expected format: YYYY-MM if (!nextMonthYear) { return res.status(400).json({ error: 'Month year required in format YYYY-MM' }); } // Insert new month with zeros, or update if exists db.run('INSERT OR REPLACE INTO monthly_summary (month_year, total_sales, total_transactions) VALUES (?, 0, 0)', [nextMonthYear], (err) => { if (err) { return res.status(500).json({ error: err.message }); } res.json({ success: true, message: `Monthly values reset for ${nextMonthYear}` }); }); }); // Start server const server = app.listen(PORT, '0.0.0.0', () => { console.log(`Server running in ${NODE_ENV} mode on port ${PORT}`); console.log(`API only - Frontend at: ${process.env.CORS_ORIGIN || 'http://localhost:3000'}`); }); // Graceful shutdown process.on('SIGTERM', () => { console.log('SIGTERM signal received: closing HTTP server'); server.close(() => { console.log('HTTP server closed'); db.close(() => { console.log('Database connection closed'); process.exit(0); }); }); }); process.on('SIGINT', () => { console.log('SIGINT signal received: closing HTTP server'); server.close(() => { console.log('HTTP server closed'); db.close(() => { console.log('Database connection closed'); process.exit(0); }); }); }); // Handle uncaught exceptions process.on('uncaughtException', (err) => { console.error('Uncaught Exception:', err); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); });PK ��\�4��5 5 test_api.jsnu �[��� const http = require('http'); // Test creating a customer const customerData = JSON.stringify({ name: "Test Customer", phone: "1234567890", email: "test@example.com" }); const options = { hostname: 'localhost', port: 3000, path: '/api/customers', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(customerData) } }; const req = http.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { console.log('Customer creation response:', data); // Test getting customers http.get('http://localhost:3000/api/customers', (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { console.log('Customers list:', data); }); }); }); }); req.on('error', (error) => { console.error('Error:', error); }); req.write(customerData); req.end();PK ��\� s � migrate_returns.jsnu �[��� const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const dbPath = path.resolve(__dirname, 'inventory.db'); const db = new sqlite3.Database(dbPath); db.serialize(() => { console.log('Running migration: Adding return_type to returns table...'); db.run(`ALTER TABLE returns ADD COLUMN return_type TEXT DEFAULT 'Normal'`, (err) => { if (err) { if (err.message.includes('duplicate column name')) { console.log('Column return_type already exists.'); } else { console.error('Error adding column:', err.message); } } else { console.log('Successfully added return_type column.'); } }); db.run(`UPDATE returns SET return_type = 'Normal' WHERE return_type IS NULL`, (err) => { if (err) console.error('Error updating existing records:', err); else console.log('Updated existing records to Normal.'); }); // Check if we can add the check constraint (SQLite usually doesn't support adding constraints to existing tables easily without recreating, // so we'll skip the strict CHECK constraint enforcement in DB for now and handle it in code, // or we'd need a more complex migration). // For this environment, code-level validation is sufficient. }); db.close(() => { console.log('Migration complete.'); }); PK ��\0��K p p inventory.dbnu �[��� SQLite format 3 @ � � .r� � �� 7� '��#����bb =Q+ indexsqlite_autoindex_monthly_summary_1monthly_summary�m�9tableusersusers CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'Manager', -- 'Admin' or 'Manager' permissions TEXT, -- JSON string of allowed pages/modules created_at DATETIME DEFAULT CURRENT_TIMESTAMP , status TEXT DEFAULT 'Active')��tableskusskusCREATE TABLE skus ( id INTEGER PRIMARY KEY AUTOINCREMENT, sku_code TEXT NOT NULL UNIQUE, product_id INTEGER NOT NULL, flavour TEXT NOT NULL, weight TEXT NOT NULL, current_stock INTEGER DEFAULT 0, price REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, tag TEXT DEFAULT '', FOREIGN KEY (product_id) REFERENCES products(id) )) = indexsqlite_autoindex_users_1users��wtablecustomerscustomersCREATE TABLE customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, phone TEXT, email TEXT, address TEXT, total_outstanding REAL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )1E indexsqlite_autoindex_customers_1customers �a++�ytablecredit_paymentscredit_paymentsCREATE TABLE credit_payments ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, payment_date DATE NOT NULL, amount_paid REAL NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (transaction_id) REFERENCES transactions(id) )�X �tableexpensesexpensesCREATE TABLE expenses ( id INTEGER PRIMARY KEY AUTOINCREMENT, expense_date DATE NOT NULL, description TEXT NOT NULL, category TEXT NOT NULL CHECK(category IN ('Rent', 'Advance', 'Transport', 'Utilities', 'Other')), amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )�B %%�Gtablereturn_itemsreturn_items CREATE TABLE return_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, return_id INTEGER NOT NULL, sku_id INTEGER NOT NULL, quantity INTEGER NOT NULL, FOREIGN KEY (return_id) REFERENCES returns(id) ON DELETE CASCADE, FOREIGN KEY (sku_id) REFERENCES skus(id) )�n�3tablereturnsreturns CREATE TABLE returns ( id INTEGER PRIMARY KEY AUTOINCREMENT, return_date DATE NOT NULL, original_transaction_id INTEGER, customer_name TEXT, reason TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, return_type TEXT DEFAULT 'Normal', FOREIGN KEY (original_transaction_id) REFERENCES transactions(id) )�//�gtabletransaction_itemstransaction_itemsCREATE TABLE transaction_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, sku_id INTEGER NOT NULL, quantity INTEGER NOT NULL, unit_price REAL NOT NULL, subtotal REAL NOT NULL, FOREIGN KEY (transaction_id) REFERENCES transactions(id) ON DELETE CASCADE, FOREIGN KEY (sku_id) REFERENCES skus(id) )�K%%�YtabletransactionstransactionsCREATE TABLE transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_date DATE NOT NULL, payment_type TEXT NOT NULL CHECK(payment_type IN ('Cash', 'Credit')), customer_name TEXT, total_amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )'; indexsqlite_autoindex_skus_1skusP++Ytablesqlite_sequencesqlite_sequenceCREATE TABLE sqlite_sequence(name,seq)/C indexsqlite_autoindex_products_1products�L�ktableproductsproductsCREATE TABLE products ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, description TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTA ��Y9 �@ 3Masala2026-02-15 11:00:06C 3masala2026-01-10 12:22:09/ 13JuiceFresh fruit juices2025-12-21 13:03:31; M3JamFruit jams in multiple varieties2025-12-21 13:03:317 A3AcharPickles in various flavors2025-12-21 13:03:31 � ����� Masala@ masalaC JuiceJam Achar �^�������:I� 1standalone_credits+monthly_summarym stan expensesCcustomer_credit_adjustments customers +credit_payments products�� monthly_summary usersreturns� usersn%return_items skus>� tra/transaction_items%transactions customers t ��m< �@bA � � t > �� �3��t� � � 0�t 3 DEL_DEBUGTest100g d2026-01-10 11:37:20:�s 6�s4 3 JM-PI-05Pineapple5kgl2025-12-21 13:03:311 3 AC-MX-500Mixed500g �2025-12-21 13:03:3112 3 AC-GA-10Garlic10kg �2025-12-21 13:03:31- 3JZ-MX-1LMixed1L}2025-12-21 13:03:31. 3JZ-GR-1LGrape1L �2025-12-21 13:03:31. 3JZ-OR-1LOrange1Ln2025-12-21 13:03:31. 3JZ-AP-1LApple1L �2025-12-21 13:03:31- 3JZ-MA-1LMango1Lx2025-12-21 13:03:311 3 AC-GA-20Garlic20kgP2025-12-21 13:03:31315 3JM-PI-500Pineapple500g �2025-12-21 13:03:315 #3JM-MF-05Mixed Fruit5kg:2025-12-21 13:03:317 #3JM-MF-500Mixed Fruit500g �2025-12-21 13:03:314 !3JM-ST-05Strawberry5kg�2025-12-21 13:03:316 !3JM-ST-500Strawberry500g �2025-12-21 13:03:31/ 3JM-AP-05Apple5kg2025-12-21 13:03:311 3JM-AP-500Apple500g �2025-12-21 13:03:31/ 3JM-MA-05Mango5kg@2025-12-21 13:03:311 3JM-MA-500Mango500g �2025-12-21 13:03:31� ' 3AC-GA-20Garlic20kgP2025-12-:� 3AC-MX-099@biryani550g �2026-02-15 11:00:06Shan/ 3AC-GA-05Garlic5kgx2025-12-21 13:03:311 3AC-GA-500Garlic500g �2025-12-21 13:03:31/ 3AC-MX-20Mixed20kg02025-12-21 13:03:31/ 3AC-MX-10Mixed10kg�2025-12-21 13:03:31. 3AC-MX-05Mixed5kg�2025-12-21 13:03:31 2 3AC-MX-500Mixed500g �2025-12-21 13:03:31 � ���������an|�+8FS������� DEL_DEBUGt DEL_TESTs AC-MX-099 �JZ-MX-1LJZ-GR-1LJZ-OR-1LJZ-AP-1LJZ-MA-1LJM-PI-05 JM-PI-500JM-MF-05 JM-MF-500JM-ST-05 JM-ST-500 JM-AP-05 JM-AP-500JM-MA-05 JM-MA-500 AC-GA-20AC-GA-10AC-GA-05 AC-GA-500AC-MX-20AC-MX-10AC-MX-05 AC-MX-500 � ���b$ � �� � V 2 !32026-01-28Creditumer2026-01-28 20:00:195 !32026-01-28Creditumer �2026-01-28 14:23:36 ? !-32026-01-28CashWalk-in Customer �2026-01-28 13:37:51K "!-32026-01-28CashWalk-in C< !32026-05-07CashSaad �2026-05-07 16:19:38@#333333 �3 !32026-02-15CashSaad �2026-02-15 11:35:52 �5 !32026-02-15CashUmer �2026-02-15 11:01:542 �: !32026-02-02Cashhasnain �2026-02-02 13:40:22 �? !-32026-01-28CashWalk-in Customer �2026-01-28 11:04:43 �!'32026-01-28CreditTest Customer,2026-01-28 10:53:59 x!-32025-12-30CashWalk-in Customer2025-12-30 09:01:07 <!-2 !32026-01-28CreditUmer �2026-01-28 13:57:39 � x �x����xx�iY � � � � �� � � � � � � � � � � � �, � � � � _ ��J�_ @ ! -32026-05-07SaadPackage not seal2026-05-07 16:20:12Damagedm ! �32026-02-15azhanBabar ki centory 99 run say reh gai isliya packet phadd gya2026-02-15 11:38:27Damaged8 ! 32026-02-15Hunaidnothing2026-02-15 11:37:18Normal; ! %32026-02-15Saadnothing need2026-02-15 11:36:54Normal? ! 332026-02-15not sealed properly2026-02-15 11:02:42Damaged6 ! 32026-02-15Umerno need2026-02-15 11:02:18Normal � ������ � � � � � �� D !?32026-02-02Test Expense for DeletionOther�2026-02-02 138 !#32026-02-15Driver rentAdvance�2026-02-15 11:03:43 � ��V� 8 !+32026-01-28�Initial Payment2026-01-28 14:23:368 !+32026-01-28 �Initial Payment2026-01-28 13:57:397 !+3 2026-01-28�Initial Payment2026-01-28 11:08:487 !+3 2026-01-28,Initial Payment2026-01-28 11:07:516 !+3 2026-01-28dInitial Payment2026-01-28 10:53:59 � a� �4 �#�3saad$2b$10$0C/ciyLwdAx56OqE390FE.xnt3GJqkzkCPx4psPQS1xw9iPSuDRXSDistributor["inventory.html","billing.html","returns.html","damage_items.html"]2026-05-07 16:21:44Disabledm �3admin$2b$10$vPvTjr0ugQzDFOqcpvX4cOEefZKELDF8yRdG6hnBN5E3pZaG2pxfmAdmin["*"]2026-01-27 13:40:28Active y+�3saadbhaimerijan$2b$10$f59LhpB1YV1.uiNXfqkoFelql0ykZwnCmAuvX/GdVVHcAtdBaU.NSAdmin["*"]2026-01-10 12:24:25Active � ��� umer admin saad admin x��x ! 3umer2026-01-28 14:23:36 3Umer2026-01-28 13:57:39B '!- 3Test Customer1234567890test@example.com2026-01-28 10:51:3535 � ��� umerUmer' Test Customer p ���p " 32026-05 �2026-05-02 05:55:46 32026-042026-04-29 20:57:15# 32026-02@2026-02-02 12:35:48# 32026-01` 2026-01-24 18:34:49 � ���� 2026-052026-042026-02 2026-01 � 1 ��4� '������ 0bb �/++�tablemonthly_summarymonthly_summaryCREATE TABLE monthly_summary ( id INTEGER PRIMARY KEY AUTOINCREMENT, month_year TEXT NOT NULL UNIQUE, -- Format: YYYY-MM total_sales REAL DEFAULT 0, total_transactions INTEGER DEFAULT 0, reset_date DATETIME DEFAULT CURRENT_TIMESTAMP )��Q+ indexsqlite_autoindex_monthly_summary_1monthly_summary�m�9tableusersusers CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'Manager', -- 'Admin' or 'Manager' permissions TEXT, -- JSON string of allowed pages/modules created_at DATETIME DEFAULT CURRENT_TIMESTAMP , status TEXT DEFAULT 'Active')��tableskusskusCREATE TABLE skus ( id INTEGER PRIMARY KEY AUTOINCREMENT, sku_code TEXT NOT NULL UNIQUE, product_id INTEGER NOT NULL, flavour TEXT NOT NULL, weight TEXT NOT NULL, current_stock INTEGER DEFAULT 0, price REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, tag TEXT DEFAULT '', FOREIGN KEY (product_id) REFERENCES products(id) ) 7�= indexsqlite_autoindex_users_1users��wtablecustomerscustomersCREATE TABLE customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, phone TEXT, email TEXT, address TEXT, total_outstanding REAL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )1E indexsqlite_autoindex_customers_1customers � �a++�ytablecredit_paymentscredit_paymentsCREATE TABLE credit_payments ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, payment_date DATE NOT NULL, amount_paid REAL NOT NULL, notes TEXT, created_at DATETIME DEFAULT �+%%�tabletransactionstransactionsCREATE TABLE transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_date DATE NOT NULL, payment_type TEXT NOT NULL CHECK(payment_type IN ('Cash', 'Credit')), customer_name TEXT, total_amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP , discount_percentage REAL DEFAULT 0, discount_amount REAL DEFAULT 0, amount_paid REAL DEFAULT 0)�B %%�Gtablereturn_itemsreturn_items CREATE TABLE return_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, return_id INTEGER NOT NULL, sku_id INTEGER NOT NULL, quantity INTEGER NOT NULL, FOREIGN KEY (return_id) REFERENCES returns(id) ON DELETE CASCADE, FOREIGN KEY (sku_id) REFERENCES skus(id) )�n�3tablereturnsreturns CREATE TABLE returns ( id INTEGER PRIMARY KEY AUTOINCREMENT, return_date DATE NOT NULL, original_transaction_id INTEGER, customer_name TEXT, reason TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, return_type TEXT DEFAULT 'Normal', FOREIGN KEY (original_transaction_id) REFERENCES transactions(id) )�//�gtabletransaction_itemstransaction_itemsCREATE TABLE transaction_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, sku_id INTEGER NOT NULL, quantity INTEGER NOT NULL, unit_price REAL NOT NULL, subtotal REAL NOT NULL, FOREIGN KEY (transaction_id) REFERENCES transactions(id) ON DELETE CASCADE, FOREIGN KEY (sku_id) REFERENCES skus(id) ) N%%�YtabletransactionstransactionsCREATE TABLE transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_date DATE NOT NULL, payment_type TEXT NOT NULL CHECK(payment_type IN ('Cash', 'Credit')), customer_name TEXT, total_amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )'; indexsqlite_autoindex_skus_1skusP++Ytablesqlite_sequencesqlite_sequenceCREATE TABLE sqlite_sequence(name,seq)/C indexsqlite_autoindex_products_1products�L�ktableproductsproductsCREATE TABLE products ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, description TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) � � �x a .��3\� �w11�tablestandalone_creditsstandalone_creditsCREATE TABLE standalone_credits ( id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER NOT NULL, customer_name TEXT NOT NULL, total_amount REAL NOT NULL, paid_amount REAL NOT NULL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP )�TCC�/tablecustomer_credit_adjustmentscustomer_credit_adjustmentsCREATE TABLE customer_credit_adjustments ( id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER NOT NULL, adjustment_date DATE NOT NULL, amount_cleared REAL NOT NULL, notes TEXT, adjustment_type TEXT NOT NULL CHECK(adjustment_type IN ('CLEAR', 'ADJUST')), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (customer_id) REFERENCES customers(id) )�33�5tablecredit_payments_newcredit_payments_newCREATE TABLE credit_payments_new (id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER, customer_id INTEGER, payment_date DATE NOT NULL, amount_paid REAL NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (transaction_id) REFERENCES transactions(id), FOREIGN KEY (customer_id) REFERENCES customers(id))=Q+ indexsqlite_autoindex_monthly_summary_1monthly_summary�/++�tablemonthly_summarymonthly_summaryCREATE TABLE monthly_summary ( id INTEGER PRIMARY KEY AUTOINCREMENT, month_year TEXT NOT NULL UNIQUE, -- Format: YYYY-MM total_sales REAL DEFAULT 0, total_transactions INTEGER DEFAULT 0, reset_date DATETIME DEFAULT CURRENT_TIMESTAMP )1E indexsqlite_autoindex_customers_1customers��wtablecustomerscustomersCREATE TABLE customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, phone TEXT, email TEXT, address TEXT, total_outstanding REAL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )) = indexsqlite_autoindex_users_1users�m�9tableusersusers CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'Manager', -- 'Admin' or 'Manager' permissions TEXT, -- JSON string of allowed pages/modules created_at DATETIME DEFAULT CURRENT_TIMESTAMP , status TEXT DEFAULT 'Active')�++�Utablecredit_paymentscredit_paymentsCREATE TABLE credit_payments ( id INTEGER PRIMARY KEY AUTOINCREMENT, transaction_id INTEGER NOT NULL, payment_date DATE NOT NULL, amount_paid REAL NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, customer_id INTEGER REFERENCES customers(id), FOREIGN KEY (transaction_id) REFERENCES transactions(id) )�X �tableexpensesexpensesCREATE TABLE expenses ( id INTEGER PRIMARY KEY AUTOINCREMENT, expense_date DATE NOT NULL, description TEXT NOT NULL, category TEXT NOT NULL CHECK(category IN ('Rent', 'Advance', 'Transport', 'Utilities', 'Other')), amount REAL NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) � �x3� G !A32026-01-28Credit deletion/correctionCLEAR2026-01-28 20:00:40C !932026-01-28�Full credit settlementCLEAR2026-01-28 14:23:49G !A32026-01-28 �Credit deletion/correctionCLEAR2026-01-28 14:23:08= !/32026-01-28 �Test clear creditCLEAR2026-01-28 14:20:02 � �� @ +33saadbhaimerijan�2026-02-15 11:39:392026-02-15 11:39:37 33Saad��2026-05-07 16:20:362026-05-07 16:20:44? +33saadbhaimerijan�2026-02-15 11:39:392026-02-15 11:39:39PK ��\��]� � check_columns.jsnu �[��� const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const db = new sqlite3.Database(path.join(__dirname, 'inventory.db')); db.all('PRAGMA table_info(transactions)', [], (err, rows) => { if (err) { console.error(err); process.exit(1); } console.log(JSON.stringify(rows, null, 2)); const hasAmountPaid = rows.some(r => r.name === 'amount_paid'); console.log('Has amount_paid column:', hasAmountPaid); }); PK ��\#>�Ղ � db_check.jsnu �[��� const sqlite3 = require('sqlite3').verbose(); const db = new sqlite3.Database('inventory.db'); console.log('=== DATABASE STRUCTURE CHECK ==='); // Check customers table db.all('PRAGMA table_info(customers)', [], (err, rows) => { console.log('\nCustomers table columns:'); rows.forEach(row => { console.log(` ${row.name} (${row.type}) ${row.notnull ? 'NOT NULL' : ''}`); }); }); // Check credit_payments table db.all('PRAGMA table_info(credit_payments)', [], (err, rows) => { console.log('\nCredit payments table columns:'); rows.forEach(row => { console.log(` ${row.name} (${row.type}) ${row.notnull ? 'NOT NULL' : ''}`); }); }); // Check data counts db.all('SELECT COUNT(*) as count FROM customers', [], (err, rows) => { console.log(`\nCustomers count: ${rows[0].count}`); }); db.all('SELECT COUNT(*) as count FROM transactions', [], (err, rows) => { console.log(`Transactions count: ${rows[0].count}`); }); db.all('SELECT COUNT(*) as count FROM credit_payments', [], (err, rows) => { console.log(`Credit payments count: ${rows[0].count}`); db.close(); });PK ��\�M��P P test_credit_transaction.jsnu �[��� const http = require('http'); // Test creating a credit transaction const transactionData = JSON.stringify({ transaction_date: "2026-01-28", payment_type: "Credit", customer_name: "Test Customer", items: [ { sku_id: 1, quantity: 2, unit_price: 150 } ], discount_percentage: 0, discount_amount: 0, amount_paid: 100 // Partial payment }); const options = { hostname: 'localhost', port: 3000, path: '/api/transactions', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(transactionData) } }; const req = http.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { console.log('Transaction response:', data); // Check customer credit after transaction http.get('http://localhost:3000/api/customers', (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { console.log('Customers after transaction:', data); }); }); }); }); req.on('error', (error) => { console.error('Error:', error); }); req.write(transactionData); req.end();PK ��\+��b b test_expense_deletion.jsnu �[��� const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const db = new sqlite3.Database(path.join(__dirname, 'inventory.db')); const testExpense = { expense_date: new Date().toISOString().split('T')[0], category: 'Other', description: 'Test Expense for Deletion', amount: 500 }; console.log('Starting Expense Deletion Test...'); db.serialize(() => { // 1. Insert Expense db.run('INSERT INTO expenses (expense_date, category, description, amount) VALUES (?, ?, ?, ?)', [testExpense.expense_date, testExpense.category, testExpense.description, testExpense.amount], function (err) { if (err) { console.error('Error inserting expense:', err); process.exit(1); } const expenseId = this.lastID; console.log(`Expense inserted with ID: ${expenseId}`); // 2. Verify Insertion db.get('SELECT * FROM expenses WHERE id = ?', [expenseId], (err, row) => { if (err || !row) { console.error('Error verifying insertion:', err || 'Row not found'); process.exit(1); } console.log('Expense verification successful (it exists).'); // 3. Delete Expense db.run('DELETE FROM expenses WHERE id = ?', [expenseId], function (err) { if (err) { console.error('Error deleting expense:', err); process.exit(1); } if (this.changes === 0) { console.error('Deletion failed: No rows affected.'); process.exit(1); } console.log('Expense deletion command executed.'); // 4. Verify Deletion db.get('SELECT * FROM expenses WHERE id = ?', [expenseId], (err, row) => { if (err) { console.error('Error verifying deletion:', err); process.exit(1); } if (!row) { console.log('Test Passed: Expense successfully deleted.'); process.exit(0); } else { console.error('Test Failed: Expense still exists after deletion.'); process.exit(1); } }); }); }); } ); }); PK ��\�|� � test_transaction_fix.jsnu �[��� const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const db = new sqlite3.Database(path.join(__dirname, 'inventory.db')); const transaction = { transaction_date: new Date().toISOString().split('T')[0], payment_type: 'Cash', customer_name: 'Test Customer', total_amount: 100, discount_percentage: 0, discount_amount: 0, amount_paid: 100 }; // We need a valid SKU ID first db.get('SELECT id, current_stock FROM skus LIMIT 1', (err, sku) => { if (err) { console.error('Error fetching SKU:', err); process.exit(1); } if (!sku) { console.log('No SKUs found to test with. Inserting a dummy transaction without items (if allowed) or aborting.'); console.log('Aborting test as we need items for real transaction flow in server.js'); process.exit(0); } const items = [ { sku_id: sku.id, quantity: 1, unit_price: 100 } ]; console.log('Testing transaction with SKU:', sku.id); // Simulate the server.js transaction logic manually or use axios to hit the running server? // Since we don't know if the server is running, let's try to hit the API if possible, // BUT `server.js` might not be running in this environment context easily reachable via localhost if I don't start it. // I'll just run the SQL directly to see if it prepares correctly, mimicking server.js db.serialize(() => { db.run('BEGIN TRANSACTION'); const transQuery = ` INSERT INTO transactions (transaction_date, payment_type, customer_name, total_amount, discount_percentage, discount_amount, amount_paid) VALUES (?, ?, ?, ?, ?, ?, ?) `; db.run(transQuery, [ transaction.transaction_date, transaction.payment_type, transaction.customer_name, transaction.total_amount, transaction.discount_percentage, transaction.discount_amount, transaction.amount_paid ], function (err) { if (err) { console.error('Transaction INSERT failed:', err); db.run('ROLLBACK'); process.exit(1); } else { console.log('Transaction INSERT success. ID:', this.lastID); // We won't insert items or update stock to avoid messing up data too much, // just checking if the INSERT into transactions table works with the new column. db.run('ROLLBACK'); // Rollback so we don't keep test data console.log('Rolled back test transaction.'); process.exit(0); } }); }); }); PK ��\z�$#� � test_customer_payment.jsnu �[��� const http = require('http'); // Test making a customer payment to reduce outstanding balance const paymentData = JSON.stringify({ customer_id: 1, payment_date: "2026-01-28", amount_paid: 50, notes: "Test payment reduction" }); const options = { hostname: 'localhost', port: 3000, path: '/api/customer-payments', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(paymentData) } }; const req = http.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { console.log('Payment response:', data); // Check customer credit after payment http.get('http://localhost:3000/api/customers', (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { console.log('Customers after payment:', data); }); }); }); }); req.on('error', (error) => { console.error('Error:', error); }); req.write(paymentData); req.end();PK ��\��b� ! node_modules/env-paths/index.d.tsnu �[��� declare namespace envPaths { export interface Options { /** __Don't use this option unless you really have to!__ Suffix appended to the project name to avoid name conflicts with native apps. Pass an empty string to disable it. @default 'nodejs' */ readonly suffix?: string; } export interface Paths { /** Directory for data files. Example locations (with the default `nodejs` suffix): - macOS: `~/Library/Application Support/MyApp-nodejs` - Windows: `%LOCALAPPDATA%\MyApp-nodejs\Data` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Data`) - Linux: `~/.local/share/MyApp-nodejs` (or `$XDG_DATA_HOME/MyApp-nodejs`) */ readonly data: string; /** Directory for data files. Example locations (with the default `nodejs` suffix): - macOS: `~/Library/Preferences/MyApp-nodejs` - Windows: `%APPDATA%\MyApp-nodejs\Config` (for example, `C:\Users\USERNAME\AppData\Roaming\MyApp-nodejs\Config`) - Linux: `~/.config/MyApp-nodejs` (or `$XDG_CONFIG_HOME/MyApp-nodejs`) */ readonly config: string; /** Directory for non-essential data files. Example locations (with the default `nodejs` suffix): - macOS: `~/Library/Caches/MyApp-nodejs` - Windows: `%LOCALAPPDATA%\MyApp-nodejs\Cache` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Cache`) - Linux: `~/.cache/MyApp-nodejs` (or `$XDG_CACHE_HOME/MyApp-nodejs`) */ readonly cache: string; /** Directory for log files. Example locations (with the default `nodejs` suffix): - macOS: `~/Library/Logs/MyApp-nodejs` - Windows: `%LOCALAPPDATA%\MyApp-nodejs\Log` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Log`) - Linux: `~/.local/state/MyApp-nodejs` (or `$XDG_STATE_HOME/MyApp-nodejs`) */ readonly log: string; /** Directory for temporary files. Example locations (with the default `nodejs` suffix): - macOS: `/var/folders/jf/f2twvvvs5jl_m49tf034ffpw0000gn/T/MyApp-nodejs` - Windows: `%LOCALAPPDATA%\Temp\MyApp-nodejs` (for example, `C:\Users\USERNAME\AppData\Local\Temp\MyApp-nodejs`) - Linux: `/tmp/USERNAME/MyApp-nodejs` */ readonly temp: string; } } declare const envPaths: { /** Get paths for storing things like data, config, cache, etc. Note: It only generates the path strings. It doesn't create the directories for you. You could use [`make-dir`](https://github.com/sindresorhus/make-dir) to create the directories. @param name - Name of your project. Used to generate the paths. @returns The paths to use for your project on current OS. @example ``` import envPaths = require('env-paths'); const paths = envPaths('MyApp'); paths.data; //=> '/home/sindresorhus/.local/share/MyApp-nodejs' paths.config //=> '/home/sindresorhus/.config/MyApp-nodejs' ``` */ (name: string, options?: envPaths.Options): envPaths.Paths; // TODO: Remove this for the next major release, refactor the whole definition to: // declare function envPaths(name: string, options?: envPaths.Options): envPaths.Paths; // export = envPaths; default: typeof envPaths; }; export = envPaths; PK ��\s��7 7 node_modules/env-paths/readme.mdnu �[��� # env-paths > Get paths for storing things like data, config, cache, etc Uses the correct OS-specific paths. Most developers get this wrong. ## Install ``` $ npm install env-paths ``` ## Usage ```js const envPaths = require('env-paths'); const paths = envPaths('MyApp'); paths.data; //=> '/home/sindresorhus/.local/share/MyApp-nodejs' paths.config //=> '/home/sindresorhus/.config/MyApp-nodejs' ``` ## API ### paths = envPaths(name, options?) Note: It only generates the path strings. It doesn't create the directories for you. You could use [`make-dir`](https://github.com/sindresorhus/make-dir) to create the directories. #### name Type: `string` Name of your project. Used to generate the paths. #### options Type: `object` ##### suffix Type: `string`<br> Default: `'nodejs'` **Don't use this option unless you really have to!**<br> Suffix appended to the project name to avoid name conflicts with native apps. Pass an empty string to disable it. ### paths.data Directory for data files. Example locations (with the default `nodejs` [suffix](#suffix)): - macOS: `~/Library/Application Support/MyApp-nodejs` - Windows: `%LOCALAPPDATA%\MyApp-nodejs\Data` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Data`) - Linux: `~/.local/share/MyApp-nodejs` (or `$XDG_DATA_HOME/MyApp-nodejs`) ### paths.config Directory for config files. Example locations (with the default `nodejs` [suffix](#suffix)): - macOS: `~/Library/Preferences/MyApp-nodejs` - Windows: `%APPDATA%\MyApp-nodejs\Config` (for example, `C:\Users\USERNAME\AppData\Roaming\MyApp-nodejs\Config`) - Linux: `~/.config/MyApp-nodejs` (or `$XDG_CONFIG_HOME/MyApp-nodejs`) ### paths.cache Directory for non-essential data files. Example locations (with the default `nodejs` [suffix](#suffix)): - macOS: `~/Library/Caches/MyApp-nodejs` - Windows: `%LOCALAPPDATA%\MyApp-nodejs\Cache` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Cache`) - Linux: `~/.cache/MyApp-nodejs` (or `$XDG_CACHE_HOME/MyApp-nodejs`) ### paths.log Directory for log files. Example locations (with the default `nodejs` [suffix](#suffix)): - macOS: `~/Library/Logs/MyApp-nodejs` - Windows: `%LOCALAPPDATA%\MyApp-nodejs\Log` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Log`) - Linux: `~/.local/state/MyApp-nodejs` (or `$XDG_STATE_HOME/MyApp-nodejs`) ### paths.temp Directory for temporary files. Example locations (with the default `nodejs` [suffix](#suffix)): - macOS: `/var/folders/jf/f2twvvvs5jl_m49tf034ffpw0000gn/T/MyApp-nodejs` - Windows: `%LOCALAPPDATA%\Temp\MyApp-nodejs` (for example, `C:\Users\USERNAME\AppData\Local\Temp\MyApp-nodejs`) - Linux: `/tmp/USERNAME/MyApp-nodejs` --- <div align="center"> <b> <a href="https://tidelift.com/subscription/pkg/npm-env-paths?utm_source=npm-env-paths&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a> </b> <br> <sub> Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies. </sub> </div> PK ��\�E�}U U node_modules/env-paths/licensenu �[��� MIT License Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK ��\%� � # node_modules/env-paths/package.jsonnu �[��� { "name": "env-paths", "version": "2.2.1", "description": "Get paths for storing things like data, config, cache, etc", "license": "MIT", "repository": "sindresorhus/env-paths", "author": { "name": "Sindre Sorhus", "email": "sindresorhus@gmail.com", "url": "sindresorhus.com" }, "engines": { "node": ">=6" }, "scripts": { "test": "xo && ava && tsd" }, "files": [ "index.js", "index.d.ts" ], "keywords": [ "common", "user", "paths", "env", "environment", "directory", "dir", "appdir", "path", "data", "config", "cache", "logs", "temp", "linux", "unix" ], "devDependencies": { "ava": "^1.4.1", "tsd": "^0.7.1", "xo": "^0.24.0" } } PK ��\�z74k k node_modules/env-paths/index.jsnu �[��� 'use strict'; const path = require('path'); const os = require('os'); const homedir = os.homedir(); const tmpdir = os.tmpdir(); const {env} = process; const macos = name => { const library = path.join(homedir, 'Library'); return { data: path.join(library, 'Application Support', name), config: path.join(library, 'Preferences', name), cache: path.join(library, 'Caches', name), log: path.join(library, 'Logs', name), temp: path.join(tmpdir, name) }; }; const windows = name => { const appData = env.APPDATA || path.join(homedir, 'AppData', 'Roaming'); const localAppData = env.LOCALAPPDATA || path.join(homedir, 'AppData', 'Local'); return { // Data/config/cache/log are invented by me as Windows isn't opinionated about this data: path.join(localAppData, name, 'Data'), config: path.join(appData, name, 'Config'), cache: path.join(localAppData, name, 'Cache'), log: path.join(localAppData, name, 'Log'), temp: path.join(tmpdir, name) }; }; // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html const linux = name => { const username = path.basename(homedir); return { data: path.join(env.XDG_DATA_HOME || path.join(homedir, '.local', 'share'), name), config: path.join(env.XDG_CONFIG_HOME || path.join(homedir, '.config'), name), cache: path.join(env.XDG_CACHE_HOME || path.join(homedir, '.cache'), name), // https://wiki.debian.org/XDGBaseDirectorySpecification#state log: path.join(env.XDG_STATE_HOME || path.join(homedir, '.local', 'state'), name), temp: path.join(tmpdir, username, name) }; }; const envPaths = (name, options) => { if (typeof name !== 'string') { throw new TypeError(`Expected string, got ${typeof name}`); } options = Object.assign({suffix: 'nodejs'}, options); if (options.suffix) { // Add suffix to prevent possible conflict with native apps name += `-${options.suffix}`; } if (process.platform === 'darwin') { return macos(name); } if (process.platform === 'win32') { return windows(name); } return linux(name); }; module.exports = envPaths; // TODO: Remove this for the next major release module.exports.default = envPaths; PK ��\�3[�� � = node_modules/https-proxy-agent/dist/parse-proxy-response.d.tsnu �[��� /// <reference types="node" /> import { Readable } from 'stream'; export interface ProxyResponse { statusCode: number; buffered: Buffer; } export default function parseProxyResponse(socket: Readable): Promise<ProxyResponse>; PK ��\���f f . node_modules/https-proxy-agent/dist/agent.d.tsnu �[��� /// <reference types="node" /> import net from 'net'; import { Agent, ClientRequest, RequestOptions } from 'agent-base'; import { HttpsProxyAgentOptions } from '.'; /** * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. * * Outgoing HTTP requests are first tunneled through the proxy server using the * `CONNECT` HTTP request method to establish a connection to the proxy server, * and then the proxy server connects to the destination target and issues the * HTTP request from the proxy server. * * `https:` requests have their socket connection upgraded to TLS once * the connection to the proxy server has been established. * * @api public */ export default class HttpsProxyAgent extends Agent { private secureProxy; private proxy; constructor(_opts: string | HttpsProxyAgentOptions); /** * Called when the node-core HTTP client library is creating a * new HTTP request. * * @api protected */ callback(req: ClientRequest, opts: RequestOptions): Promise<net.Socket>; } PK ��\D^�p p ? node_modules/https-proxy-agent/dist/parse-proxy-response.js.mapnu �[��� {"version":3,"file":"parse-proxy-response.js","sourceRoot":"","sources":["../src/parse-proxy-response.ts"],"names":[],"mappings":";;;;;AAAA,kDAAgC;AAGhC,MAAM,KAAK,GAAG,eAAW,CAAC,wCAAwC,CAAC,CAAC;AAOpE,SAAwB,kBAAkB,CACzC,MAAgB;IAEhB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,+EAA+E;QAC/E,gFAAgF;QAChF,8EAA8E;QAC9E,8BAA8B;QAC9B,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,SAAS,IAAI;YACZ,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC;gBAAE,MAAM,CAAC,CAAC,CAAC,CAAC;;gBACZ,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,SAAS,OAAO;YACf,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACpC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACzC,CAAC;QAED,SAAS,OAAO,CAAC,GAAW;YAC3B,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,SAAS,KAAK;YACb,KAAK,CAAC,OAAO,CAAC,CAAC;QAChB,CAAC;QAED,SAAS,OAAO,CAAC,GAAU;YAC1B,OAAO,EAAE,CAAC;YACV,KAAK,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACzB,MAAM,CAAC,GAAG,CAAC,CAAC;QACb,CAAC;QAED,SAAS,MAAM,CAAC,CAAS;YACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,aAAa,IAAI,CAAC,CAAC,MAAM,CAAC;YAE1B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YACvD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAElD,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE;gBACxB,iBAAiB;gBACjB,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBACtD,IAAI,EAAE,CAAC;gBACP,OAAO;aACP;YAED,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAClC,OAAO,EACP,CAAC,EACD,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CACxB,CAAC;YACF,MAAM,UAAU,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,KAAK,CAAC,+BAA+B,EAAE,SAAS,CAAC,CAAC;YAClD,OAAO,CAAC;gBACP,UAAU;gBACV,QAAQ;aACR,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAExB,IAAI,EAAE,CAAC;IACR,CAAC,CAAC,CAAC;AACJ,CAAC;AAvED,qCAuEC"}PK ��\^|�C� � . node_modules/https-proxy-agent/dist/index.d.tsnu �[��� /// <reference types="node" /> import net from 'net'; import tls from 'tls'; import { Url } from 'url'; import { AgentOptions } from 'agent-base'; import { OutgoingHttpHeaders } from 'http'; import _HttpsProxyAgent from './agent'; declare function createHttpsProxyAgent(opts: string | createHttpsProxyAgent.HttpsProxyAgentOptions): _HttpsProxyAgent; declare namespace createHttpsProxyAgent { interface BaseHttpsProxyAgentOptions { headers?: OutgoingHttpHeaders; secureProxy?: boolean; host?: string | null; path?: string | null; port?: string | number | null; } export interface HttpsProxyAgentOptions extends AgentOptions, BaseHttpsProxyAgentOptions, Partial<Omit<Url & net.NetConnectOpts & tls.ConnectionOptions, keyof BaseHttpsProxyAgentOptions>> { } export type HttpsProxyAgent = _HttpsProxyAgent; export const HttpsProxyAgent: typeof _HttpsProxyAgent; export {}; } export = createHttpsProxyAgent; PK ��\�{�j j 0 node_modules/https-proxy-agent/dist/index.js.mapnu �[��� {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAKA,oDAAuC;AAEvC,SAAS,qBAAqB,CAC7B,IAA2D;IAE3D,OAAO,IAAI,eAAgB,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,WAAU,qBAAqB;IAoBjB,qCAAe,GAAG,eAAgB,CAAC;IAEhD,qBAAqB,CAAC,SAAS,GAAG,eAAgB,CAAC,SAAS,CAAC;AAC9D,CAAC,EAvBS,qBAAqB,KAArB,qBAAqB,QAuB9B;AAED,iBAAS,qBAAqB,CAAC"}PK ��\��}9� � ; node_modules/https-proxy-agent/dist/parse-proxy-response.jsnu �[��� "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const debug_1 = __importDefault(require("debug")); const debug = debug_1.default('https-proxy-agent:parse-proxy-response'); function parseProxyResponse(socket) { return new Promise((resolve, reject) => { // we need to buffer any HTTP traffic that happens with the proxy before we get // the CONNECT response, so that if the response is anything other than an "200" // response code, then we can re-play the "data" events on the socket once the // HTTP parser is hooked up... let buffersLength = 0; const buffers = []; function read() { const b = socket.read(); if (b) ondata(b); else socket.once('readable', read); } function cleanup() { socket.removeListener('end', onend); socket.removeListener('error', onerror); socket.removeListener('close', onclose); socket.removeListener('readable', read); } function onclose(err) { debug('onclose had error %o', err); } function onend() { debug('onend'); } function onerror(err) { cleanup(); debug('onerror %o', err); reject(err); } function ondata(b) { buffers.push(b); buffersLength += b.length; const buffered = Buffer.concat(buffers, buffersLength); const endOfHeaders = buffered.indexOf('\r\n\r\n'); if (endOfHeaders === -1) { // keep buffering debug('have not received end of HTTP headers yet...'); read(); return; } const firstLine = buffered.toString('ascii', 0, buffered.indexOf('\r\n')); const statusCode = +firstLine.split(' ')[1]; debug('got proxy server response: %o', firstLine); resolve({ statusCode, buffered }); } socket.on('error', onerror); socket.on('close', onclose); socket.on('end', onend); read(); }); } exports.default = parseProxyResponse; //# sourceMappingURL=parse-proxy-response.js.mapPK ��\��� 0 node_modules/https-proxy-agent/dist/agent.js.mapnu �[��� {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,8CAAsB;AACtB,8CAAsB;AACtB,8CAAsB;AACtB,oDAA4B;AAC5B,kDAAgC;AAEhC,2CAAkE;AAElE,kFAAwD;AAExD,MAAM,KAAK,GAAG,eAAW,CAAC,yBAAyB,CAAC,CAAC;AAErD;;;;;;;;;;;;;GAaG;AACH,MAAqB,eAAgB,SAAQ,kBAAK;IAIjD,YAAY,KAAsC;QACjD,IAAI,IAA4B,CAAC;QACjC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC9B,IAAI,GAAG,aAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SACxB;aAAM;YACN,IAAI,GAAG,KAAK,CAAC;SACb;QACD,IAAI,CAAC,IAAI,EAAE;YACV,MAAM,IAAI,KAAK,CACd,8DAA8D,CAC9D,CAAC;SACF;QACD,KAAK,CAAC,2CAA2C,EAAE,IAAI,CAAC,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,CAAC;QAEZ,MAAM,KAAK,qBAAgC,IAAI,CAAE,CAAC;QAElD,wDAAwD;QACxD,uBAAuB;QACvB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAE/D,+DAA+D;QAC/D,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC;QAC1C,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;YACnC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;SACtC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE;YAC9B,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;SACzC;QAED,sCAAsC;QACtC,sEAAsE;QACtE,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,eAAe,IAAI,KAAK,CAAC,EAAE;YACpD,KAAK,CAAC,aAAa,GAAG,CAAC,UAAU,CAAC,CAAC;SACnC;QAED,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE;YAC7B,kEAAkE;YAClE,8DAA8D;YAC9D,iEAAiE;YACjE,8BAA8B;YAC9B,OAAO,KAAK,CAAC,IAAI,CAAC;YAClB,OAAO,KAAK,CAAC,QAAQ,CAAC;SACtB;QAED,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACG,QAAQ,CACb,GAAkB,EAClB,IAAoB;;YAEpB,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;YAEpC,kDAAkD;YAClD,IAAI,MAAkB,CAAC;YACvB,IAAI,WAAW,EAAE;gBAChB,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;gBAC1C,MAAM,GAAG,aAAG,CAAC,OAAO,CAAC,KAA8B,CAAC,CAAC;aACrD;iBAAM;gBACN,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;gBAC1C,MAAM,GAAG,aAAG,CAAC,OAAO,CAAC,KAA2B,CAAC,CAAC;aAClD;YAED,MAAM,OAAO,qBAA6B,KAAK,CAAC,OAAO,CAAE,CAAC;YAC1D,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7C,IAAI,OAAO,GAAG,WAAW,QAAQ,eAAe,CAAC;YAEjD,wDAAwD;YACxD,IAAI,KAAK,CAAC,IAAI,EAAE;gBACf,OAAO,CAAC,qBAAqB,CAAC,GAAG,SAAS,MAAM,CAAC,IAAI,CACpD,KAAK,CAAC,IAAI,CACV,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;aACvB;YAED,iDAAiD;YACjD,0CAA0C;YAC1C,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;YAC1C,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE;gBACzC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;aACnB;YACD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YAEpB,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;gBACxC,OAAO,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;aAC3C;YAED,MAAM,oBAAoB,GAAG,8BAAkB,CAAC,MAAM,CAAC,CAAC;YAExD,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC;YAE/B,MAAM,EACL,UAAU,EACV,QAAQ,EACR,GAAG,MAAM,oBAAoB,CAAC;YAE/B,IAAI,UAAU,KAAK,GAAG,EAAE;gBACvB,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAE3B,IAAI,IAAI,CAAC,cAAc,EAAE;oBACxB,sDAAsD;oBACtD,8CAA8C;oBAC9C,KAAK,CAAC,oCAAoC,CAAC,CAAC;oBAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC;oBAChD,OAAO,aAAG,CAAC,OAAO,iCACd,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,KACjD,MAAM;wBACN,UAAU,IACT,CAAC;iBACH;gBAED,OAAO,MAAM,CAAC;aACd;YAED,oEAAoE;YACpE,kEAAkE;YAClE,iEAAiE;YACjE,qBAAqB;YAErB,iEAAiE;YACjE,0DAA0D;YAC1D,oEAAoE;YACpE,mBAAmB;YACnB,EAAE;YACF,4CAA4C;YAC5C,MAAM,CAAC,OAAO,EAAE,CAAC;YAEjB,MAAM,UAAU,GAAG,IAAI,aAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,UAAU,CAAC,QAAQ,GAAG,IAAI,CAAC;YAE3B,oEAAoE;YACpE,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAa,EAAE,EAAE;gBACpC,KAAK,CAAC,2CAA2C,CAAC,CAAC;gBACnD,gBAAM,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAEpC,gEAAgE;gBAChE,8DAA8D;gBAC9D,YAAY;gBACZ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACjB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,OAAO,UAAU,CAAC;QACnB,CAAC;KAAA;CACD;AA3JD,kCA2JC;AAED,SAAS,MAAM,CAAC,MAAkC;IACjD,MAAM,CAAC,MAAM,EAAE,CAAC;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,MAAe;IACnD,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,OAAO,CAAC,QAAwB;IACxC,OAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC3E,CAAC;AAED,SAAS,IAAI,CACZ,GAAM,EACN,GAAG,IAAO;IAIV,MAAM,GAAG,GAAG,EAEX,CAAC;IACF,IAAI,GAAqB,CAAC;IAC1B,KAAK,GAAG,IAAI,GAAG,EAAE;QAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YACxB,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;SACpB;KACD;IACD,OAAO,GAAG,CAAC;AACZ,CAAC"}PK ��\��C C , node_modules/https-proxy-agent/dist/index.jsnu �[��� "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; const agent_1 = __importDefault(require("./agent")); function createHttpsProxyAgent(opts) { return new agent_1.default(opts); } (function (createHttpsProxyAgent) { createHttpsProxyAgent.HttpsProxyAgent = agent_1.default; createHttpsProxyAgent.prototype = agent_1.default.prototype; })(createHttpsProxyAgent || (createHttpsProxyAgent = {})); module.exports = createHttpsProxyAgent; //# sourceMappingURL=index.js.mapPK ��\���� � , node_modules/https-proxy-agent/dist/agent.jsnu �[��� "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const net_1 = __importDefault(require("net")); const tls_1 = __importDefault(require("tls")); const url_1 = __importDefault(require("url")); const assert_1 = __importDefault(require("assert")); const debug_1 = __importDefault(require("debug")); const agent_base_1 = require("agent-base"); const parse_proxy_response_1 = __importDefault(require("./parse-proxy-response")); const debug = debug_1.default('https-proxy-agent:agent'); /** * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. * * Outgoing HTTP requests are first tunneled through the proxy server using the * `CONNECT` HTTP request method to establish a connection to the proxy server, * and then the proxy server connects to the destination target and issues the * HTTP request from the proxy server. * * `https:` requests have their socket connection upgraded to TLS once * the connection to the proxy server has been established. * * @api public */ class HttpsProxyAgent extends agent_base_1.Agent { constructor(_opts) { let opts; if (typeof _opts === 'string') { opts = url_1.default.parse(_opts); } else { opts = _opts; } if (!opts) { throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); } debug('creating new HttpsProxyAgent instance: %o', opts); super(opts); const proxy = Object.assign({}, opts); // If `true`, then connect to the proxy server over TLS. // Defaults to `false`. this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); // Prefer `hostname` over `host`, and set the `port` if needed. proxy.host = proxy.hostname || proxy.host; if (typeof proxy.port === 'string') { proxy.port = parseInt(proxy.port, 10); } if (!proxy.port && proxy.host) { proxy.port = this.secureProxy ? 443 : 80; } // ALPN is supported by Node.js >= v5. // attempt to negotiate http/1.1 for proxy servers that support http/2 if (this.secureProxy && !('ALPNProtocols' in proxy)) { proxy.ALPNProtocols = ['http 1.1']; } if (proxy.host && proxy.path) { // If both a `host` and `path` are specified then it's most likely // the result of a `url.parse()` call... we need to remove the // `path` portion so that `net.connect()` doesn't attempt to open // that as a Unix socket file. delete proxy.path; delete proxy.pathname; } this.proxy = proxy; } /** * Called when the node-core HTTP client library is creating a * new HTTP request. * * @api protected */ callback(req, opts) { return __awaiter(this, void 0, void 0, function* () { const { proxy, secureProxy } = this; // Create a socket connection to the proxy server. let socket; if (secureProxy) { debug('Creating `tls.Socket`: %o', proxy); socket = tls_1.default.connect(proxy); } else { debug('Creating `net.Socket`: %o', proxy); socket = net_1.default.connect(proxy); } const headers = Object.assign({}, proxy.headers); const hostname = `${opts.host}:${opts.port}`; let payload = `CONNECT ${hostname} HTTP/1.1\r\n`; // Inject the `Proxy-Authorization` header if necessary. if (proxy.auth) { headers['Proxy-Authorization'] = `Basic ${Buffer.from(proxy.auth).toString('base64')}`; } // The `Host` header should only include the port // number when it is not the default port. let { host, port, secureEndpoint } = opts; if (!isDefaultPort(port, secureEndpoint)) { host += `:${port}`; } headers.Host = host; headers.Connection = 'close'; for (const name of Object.keys(headers)) { payload += `${name}: ${headers[name]}\r\n`; } const proxyResponsePromise = parse_proxy_response_1.default(socket); socket.write(`${payload}\r\n`); const { statusCode, buffered } = yield proxyResponsePromise; if (statusCode === 200) { req.once('socket', resume); if (opts.secureEndpoint) { // The proxy is connecting to a TLS server, so upgrade // this socket connection to a TLS connection. debug('Upgrading socket connection to TLS'); const servername = opts.servername || opts.host; return tls_1.default.connect(Object.assign(Object.assign({}, omit(opts, 'host', 'hostname', 'path', 'port')), { socket, servername })); } return socket; } // Some other status code that's not 200... need to re-play the HTTP // header "data" events onto the socket once the HTTP machinery is // attached so that the node core `http` can parse and handle the // error status code. // Close the original socket, and a new "fake" socket is returned // instead, so that the proxy doesn't get the HTTP request // written to it (which may contain `Authorization` headers or other // sensitive data). // // See: https://hackerone.com/reports/541502 socket.destroy(); const fakeSocket = new net_1.default.Socket({ writable: false }); fakeSocket.readable = true; // Need to wait for the "socket" event to re-play the "data" events. req.once('socket', (s) => { debug('replaying proxy buffer for failed request'); assert_1.default(s.listenerCount('data') > 0); // Replay the "buffered" Buffer onto the fake `socket`, since at // this point the HTTP module machinery has been hooked up for // the user. s.push(buffered); s.push(null); }); return fakeSocket; }); } } exports.default = HttpsProxyAgent; function resume(socket) { socket.resume(); } function isDefaultPort(port, secure) { return Boolean((!secure && port === 80) || (secure && port === 443)); } function isHTTPS(protocol) { return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; } function omit(obj, ...keys) { const ret = {}; let key; for (key in obj) { if (!keys.includes(key)) { ret[key] = obj[key]; } } return ret; } //# sourceMappingURL=agent.js.mapPK ��\zGL � � ( node_modules/https-proxy-agent/README.mdnu �[��� https-proxy-agent ================ ### An HTTP(s) proxy `http.Agent` implementation for HTTPS [](https://github.com/TooTallNate/node-https-proxy-agent/actions?workflow=Node+CI) This module provides an `http.Agent` implementation that connects to a specified HTTP or HTTPS proxy server, and can be used with the built-in `https` module. Specifically, this `Agent` implementation connects to an intermediary "proxy" server and issues the [CONNECT HTTP method][CONNECT], which tells the proxy to open a direct TCP connection to the destination server. Since this agent implements the CONNECT HTTP method, it also works with other protocols that use this method when connecting over proxies (i.e. WebSockets). See the "Examples" section below for more. Installation ------------ Install with `npm`: ``` bash $ npm install https-proxy-agent ``` Examples -------- #### `https` module example ``` js var url = require('url'); var https = require('https'); var HttpsProxyAgent = require('https-proxy-agent'); // HTTP/HTTPS proxy to connect to var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; console.log('using proxy server %j', proxy); // HTTPS endpoint for the proxy to connect to var endpoint = process.argv[2] || 'https://graph.facebook.com/tootallnate'; console.log('attempting to GET %j', endpoint); var options = url.parse(endpoint); // create an instance of the `HttpsProxyAgent` class with the proxy server information var agent = new HttpsProxyAgent(proxy); options.agent = agent; https.get(options, function (res) { console.log('"response" event!', res.headers); res.pipe(process.stdout); }); ``` #### `ws` WebSocket connection example ``` js var url = require('url'); var WebSocket = require('ws'); var HttpsProxyAgent = require('https-proxy-agent'); // HTTP/HTTPS proxy to connect to var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; console.log('using proxy server %j', proxy); // WebSocket endpoint for the proxy to connect to var endpoint = process.argv[2] || 'ws://echo.websocket.org'; var parsed = url.parse(endpoint); console.log('attempting to connect to WebSocket %j', endpoint); // create an instance of the `HttpsProxyAgent` class with the proxy server information var options = url.parse(proxy); var agent = new HttpsProxyAgent(options); // finally, initiate the WebSocket connection var socket = new WebSocket(endpoint, { agent: agent }); socket.on('open', function () { console.log('"open" event!'); socket.send('hello world'); }); socket.on('message', function (data, flags) { console.log('"message" event! %j %j', data, flags); socket.close(); }); ``` API --- ### new HttpsProxyAgent(Object options) The `HttpsProxyAgent` class implements an `http.Agent` subclass that connects to the specified "HTTP(s) proxy server" in order to proxy HTTPS and/or WebSocket requests. This is achieved by using the [HTTP `CONNECT` method][CONNECT]. The `options` argument may either be a string URI of the proxy server to use, or an "options" object with more specific properties: * `host` - String - Proxy host to connect to (may use `hostname` as well). Required. * `port` - Number - Proxy port to connect to. Required. * `protocol` - String - If `https:`, then use TLS to connect to the proxy. * `headers` - Object - Additional HTTP headers to be sent on the HTTP CONNECT method. * Any other options given are passed to the `net.connect()`/`tls.connect()` functions. License ------- (The MIT License) Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [CONNECT]: http://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_Tunneling PK ��\r�ϒcV cV ; node_modules/https-proxy-agent/node_modules/debug/README.mdnu �[��� # debug [](#backers) [](#sponsors) <img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png"> A tiny JavaScript debugging utility modelled after Node.js core's debugging technique. Works in Node.js and web browsers. ## Installation ```bash $ npm install debug ``` ## Usage `debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole. Example [_app.js_](./examples/node/app.js): ```js var debug = require('debug')('http') , http = require('http') , name = 'My App'; // fake app debug('booting %o', name); http.createServer(function(req, res){ debug(req.method + ' ' + req.url); res.end('hello\n'); }).listen(3000, function(){ debug('listening'); }); // fake worker of some kind require('./worker'); ``` Example [_worker.js_](./examples/node/worker.js): ```js var a = require('debug')('worker:a') , b = require('debug')('worker:b'); function work() { a('doing lots of uninteresting work'); setTimeout(work, Math.random() * 1000); } work(); function workb() { b('doing some work'); setTimeout(workb, Math.random() * 2000); } workb(); ``` The `DEBUG` environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: <img width="647" alt="screen shot 2017-08-08 at 12 53 04 pm" src="https://user-images.githubusercontent.com/71256/29091703-a6302cdc-7c38-11e7-8304-7c0b3bc600cd.png"> <img width="647" alt="screen shot 2017-08-08 at 12 53 38 pm" src="https://user-images.githubusercontent.com/71256/29091700-a62a6888-7c38-11e7-800b-db911291ca2b.png"> <img width="647" alt="screen shot 2017-08-08 at 12 53 25 pm" src="https://user-images.githubusercontent.com/71256/29091701-a62ea114-7c38-11e7-826a-2692bedca740.png"> #### Windows command prompt notes ##### CMD On Windows the environment variable is set using the `set` command. ```cmd set DEBUG=*,-not_this ``` Example: ```cmd set DEBUG=* & node app.js ``` ##### PowerShell (VS Code default) PowerShell uses different syntax to set environment variables. ```cmd $env:DEBUG = "*,-not_this" ``` Example: ```cmd $env:DEBUG='app';node app.js ``` Then, run the program to be debugged as usual. npm script example: ```js "windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js", ``` ## Namespace Colors Every debug instance has a color generated for it based on its namespace name. This helps when visually parsing the debug output to identify which debug instance a debug line belongs to. #### Node.js In Node.js, colors are enabled when stderr is a TTY. You also _should_ install the [`supports-color`](https://npmjs.org/supports-color) module alongside debug, otherwise debug will only use a small handful of basic colors. <img width="521" src="https://user-images.githubusercontent.com/71256/29092181-47f6a9e6-7c3a-11e7-9a14-1928d8a711cd.png"> #### Web Browser Colors are also enabled on "Web Inspectors" that understand the `%c` formatting option. These are WebKit web inspectors, Firefox ([since version 31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) and the Firebug plugin for Firefox (any version). <img width="524" src="https://user-images.githubusercontent.com/71256/29092033-b65f9f2e-7c39-11e7-8e32-f6f0d8e865c1.png"> ## Millisecond diff When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. <img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png"> When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below: <img width="647" src="https://user-images.githubusercontent.com/71256/29091956-6bd78372-7c39-11e7-8c55-c948396d6edd.png"> ## Conventions If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output. ## Wildcards The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:". ## Environment Variables When running through Node.js, you can set a few environment variables that will change the behavior of the debug logging: | Name | Purpose | |-----------|-------------------------------------------------| | `DEBUG` | Enables/disables specific debugging namespaces. | | `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). | | `DEBUG_COLORS`| Whether or not to use colors in the debug output. | | `DEBUG_DEPTH` | Object inspection depth. | | `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | __Note:__ The environment variables beginning with `DEBUG_` end up being converted into an Options object that gets used with `%o`/`%O` formatters. See the Node.js documentation for [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) for the complete list. ## Formatters Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters: | Formatter | Representation | |-----------|----------------| | `%O` | Pretty-print an Object on multiple lines. | | `%o` | Pretty-print an Object all on a single line. | | `%s` | String. | | `%d` | Number (both integer and float). | | `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. | | `%%` | Single percent sign ('%'). This does not consume an argument. | ### Custom formatters You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like: ```js const createDebug = require('debug') createDebug.formatters.h = (v) => { return v.toString('hex') } // …elsewhere const debug = createDebug('foo') debug('this is hex: %h', new Buffer('hello world')) // foo this is hex: 68656c6c6f20776f726c6421 +0ms ``` ## Browser Support You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify), or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest), if you don't want to build it yourself. Debug's enable state is currently persisted by `localStorage`. Consider the situation shown below where you have `worker:a` and `worker:b`, and wish to debug both. You can enable this using `localStorage.debug`: ```js localStorage.debug = 'worker:*' ``` And then refresh the page. ```js a = debug('worker:a'); b = debug('worker:b'); setInterval(function(){ a('doing some work'); }, 1000); setInterval(function(){ b('doing some work'); }, 1200); ``` In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will—by default—only show messages logged by `debug` if the "Verbose" log level is _enabled_. <img width="647" src="https://user-images.githubusercontent.com/7143133/152083257-29034707-c42c-4959-8add-3cee850e6fcf.png"> ## Output streams By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method: Example [_stdout.js_](./examples/node/stdout.js): ```js var debug = require('debug'); var error = debug('app:error'); // by default stderr is used error('goes to stderr!'); var log = debug('app:log'); // set this namespace to log via console.log log.log = console.log.bind(console); // don't forget to bind to console! log('goes to stdout'); error('still goes to stderr!'); // set all output to go via console.info // overrides all per-namespace log settings debug.log = console.info.bind(console); error('now goes to stdout via console.info'); log('still goes to stdout, but via console.info now'); ``` ## Extend You can simply extend debugger ```js const log = require('debug')('auth'); //creates new debug instance with extended namespace const logSign = log.extend('sign'); const logLogin = log.extend('login'); log('hello'); // auth hello logSign('hello'); //auth:sign hello logLogin('hello'); //auth:login hello ``` ## Set dynamically You can also enable debug dynamically by calling the `enable()` method : ```js let debug = require('debug'); console.log(1, debug.enabled('test')); debug.enable('test'); console.log(2, debug.enabled('test')); debug.disable(); console.log(3, debug.enabled('test')); ``` print : ``` 1 false 2 true 3 false ``` Usage : `enable(namespaces)` `namespaces` can include modes separated by a colon and wildcards. Note that calling `enable()` completely overrides previously set DEBUG variable : ``` $ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))' => false ``` `disable()` Will disable all namespaces. The functions returns the namespaces currently enabled (and skipped). This can be useful if you want to disable debugging temporarily without knowing what was enabled to begin with. For example: ```js let debug = require('debug'); debug.enable('foo:*,-foo:bar'); let namespaces = debug.disable(); debug.enable(namespaces); ``` Note: There is no guarantee that the string will be identical to the initial enable string, but semantically they will be identical. ## Checking whether a debug target is enabled After you've created a debug instance, you can determine whether or not it is enabled by checking the `enabled` property: ```javascript const debug = require('debug')('http'); if (debug.enabled) { // do stuff... } ``` You can also manually toggle this property to force the debug instance to be enabled or disabled. ## Usage in child processes Due to the way `debug` detects if the output is a TTY or not, colors are not shown in child processes when `stderr` is piped. A solution is to pass the `DEBUG_COLORS=1` environment variable to the child process. For example: ```javascript worker = fork(WORKER_WRAP_PATH, [workerPath], { stdio: [ /* stdin: */ 0, /* stdout: */ 'pipe', /* stderr: */ 'pipe', 'ipc', ], env: Object.assign({}, process.env, { DEBUG_COLORS: 1 // without this settings, colors won't be shown }), }); worker.stderr.pipe(process.stderr, { end: false }); ``` ## Authors - TJ Holowaychuk - Nathan Rajlich - Andrew Rhyne - Josh Junon ## Backers Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)] <a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a> <a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a> ## Sponsors Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)] <a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a> <a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a> ## License (The MIT License) Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca> Copyright (c) 2018-2021 Josh Junon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK ��\4Jtx x = node_modules/https-proxy-agent/node_modules/debug/src/node.jsnu �[��� /** * Module dependencies. */ const tty = require('tty'); const util = require('util'); /** * This is the Node.js implementation of `debug()`. */ exports.init = init; exports.log = log; exports.formatArgs = formatArgs; exports.save = save; exports.load = load; exports.useColors = useColors; exports.destroy = util.deprecate( () => {}, 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' ); /** * Colors. */ exports.colors = [6, 2, 3, 4, 5, 1]; try { // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) // eslint-disable-next-line import/no-extraneous-dependencies const supportsColor = require('supports-color'); if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { exports.colors = [ 20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 220, 221 ]; } } catch (error) { // Swallow - we only care if `supports-color` is available; it doesn't have to be. } /** * Build up the default `inspectOpts` object from the environment variables. * * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js */ exports.inspectOpts = Object.keys(process.env).filter(key => { return /^debug_/i.test(key); }).reduce((obj, key) => { // Camel-case const prop = key .substring(6) .toLowerCase() .replace(/_([a-z])/g, (_, k) => { return k.toUpperCase(); }); // Coerce string value into JS value let val = process.env[key]; if (/^(yes|on|true|enabled)$/i.test(val)) { val = true; } else if (/^(no|off|false|disabled)$/i.test(val)) { val = false; } else if (val === 'null') { val = null; } else { val = Number(val); } obj[prop] = val; return obj; }, {}); /** * Is stdout a TTY? Colored output is enabled when `true`. */ function useColors() { return 'colors' in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd); } /** * Adds ANSI color escape codes if enabled. * * @api public */ function formatArgs(args) { const {namespace: name, useColors} = this; if (useColors) { const c = this.color; const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); const prefix = ` ${colorCode};1m${name} \u001B[0m`; args[0] = prefix + args[0].split('\n').join('\n' + prefix); args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); } else { args[0] = getDate() + name + ' ' + args[0]; } } function getDate() { if (exports.inspectOpts.hideDate) { return ''; } return new Date().toISOString() + ' '; } /** * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr. */ function log(...args) { return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n'); } /** * Save `namespaces`. * * @param {String} namespaces * @api private */ function save(namespaces) { if (namespaces) { process.env.DEBUG = namespaces; } else { // If you set a process.env field to null or undefined, it gets cast to the // string 'null' or 'undefined'. Just delete instead. delete process.env.DEBUG; } } /** * Load `namespaces`. * * @return {String} returns the previously persisted debug modes * @api private */ function load() { return process.env.DEBUG; } /** * Init logic for `debug` instances. * * Create a new `inspectOpts` object in case `useColors` is set * differently for a particular `debug` instance. */ function init(debug) { debug.inspectOpts = {}; const keys = Object.keys(exports.inspectOpts); for (let i = 0; i < keys.length; i++) { debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; } } module.exports = require('./common')(exports); const {formatters} = module.exports; /** * Map %o to `util.inspect()`, all on a single line. */ formatters.o = function (v) { this.inspectOpts.colors = this.useColors; return util.inspect(v, this.inspectOpts) .split('\n') .map(str => str.trim()) .join(' '); }; /** * Map %O to `util.inspect()`, allowing multiple lines if needed. */ formatters.O = function (v) { this.inspectOpts.colors = this.useColors; return util.inspect(v, this.inspectOpts); }; PK ��\`�*� � @ node_modules/https-proxy-agent/node_modules/debug/src/browser.jsnu �[��� /* eslint-env browser */ /** * This is the web browser implementation of `debug()`. */ exports.formatArgs = formatArgs; exports.save = save; exports.load = load; exports.useColors = useColors; exports.storage = localstorage(); exports.destroy = (() => { let warned = false; return () => { if (!warned) { warned = true; console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); } }; })(); /** * Colors. */ exports.colors = [ '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' ]; /** * Currently only WebKit-based Web Inspectors, Firefox >= v31, * and the Firebug extension (any Firefox version) are known * to support "%c" CSS customizations. * * TODO: add a `localStorage` variable to explicitly enable/disable colors */ // eslint-disable-next-line complexity function useColors() { // NB: In an Electron preload script, document will be defined but not fully // initialized. Since we know we're in Chrome, we'll just detect this case // explicitly if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { return true; } // Internet Explorer and Edge do not support colors. if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { return false; } let m; // Is webkit? http://stackoverflow.com/a/16459606/376773 // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 // eslint-disable-next-line no-return-assign return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || // Is firebug? http://stackoverflow.com/a/398120/376773 (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || // Is firefox >= v31? // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages (typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) || // Double check webkit in userAgent just in case we are in a worker (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); } /** * Colorize log arguments if enabled. * * @api public */ function formatArgs(args) { args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + '+' + module.exports.humanize(this.diff); if (!this.useColors) { return; } const c = 'color: ' + this.color; args.splice(1, 0, c, 'color: inherit'); // The final "%c" is somewhat tricky, because there could be other // arguments passed either before or after the %c, so we need to // figure out the correct index to insert the CSS into let index = 0; let lastC = 0; args[0].replace(/%[a-zA-Z%]/g, match => { if (match === '%%') { return; } index++; if (match === '%c') { // We only are interested in the *last* %c // (the user may have provided their own) lastC = index; } }); args.splice(lastC, 0, c); } /** * Invokes `console.debug()` when available. * No-op when `console.debug` is not a "function". * If `console.debug` is not available, falls back * to `console.log`. * * @api public */ exports.log = console.debug || console.log || (() => {}); /** * Save `namespaces`. * * @param {String} namespaces * @api private */ function save(namespaces) { try { if (namespaces) { exports.storage.setItem('debug', namespaces); } else { exports.storage.removeItem('debug'); } } catch (error) { // Swallow // XXX (@Qix-) should we be logging these? } } /** * Load `namespaces`. * * @return {String} returns the previously persisted debug modes * @api private */ function load() { let r; try { r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ; } catch (error) { // Swallow // XXX (@Qix-) should we be logging these? } // If debug isn't set in LS, and we're in Electron, try to load $DEBUG if (!r && typeof process !== 'undefined' && 'env' in process) { r = process.env.DEBUG; } return r; } /** * Localstorage attempts to return the localstorage. * * This is necessary because safari throws * when a user disables cookies/localstorage * and you attempt to access it. * * @return {LocalStorage} * @api private */ function localstorage() { try { // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context // The Browser also has localStorage in the global context. return localStorage; } catch (error) { // Swallow // XXX (@Qix-) should we be logging these? } } module.exports = require('./common')(exports); const {formatters} = module.exports; /** * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. */ formatters.j = function (v) { try { return JSON.stringify(v); } catch (error) { return '[UnexpectedJSONParseError]: ' + error.message; } }; PK ��\N<x{: : >