Major additions: - Multi-state expansion: states table, StateSelector, NationalDashboard, StateHeatmap, CrossStateCompare - Orchestrator services: trace service, error taxonomy, retry manager, proxy rotator - Discovery system: dutchie discovery service, geo validation, city seeding scripts - Analytics infrastructure: analytics v2 routes, brand/pricing/stores intelligence pages - Local development: setup-local.sh starts all 5 services (postgres, backend, cannaiq, findadispo, findagram) - Migrations 037-056: crawler profiles, states, analytics indexes, worker metadata Frontend pages added: - Discovery, ChainsDashboard, IntelligenceBrands, IntelligencePricing, IntelligenceStores - StateHeatmap, CrossStateCompare, SyncInfoPanel Components added: - StateSelector, OrchestratorTraceModal, WorkflowStepper 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
78 lines
2.8 KiB
TypeScript
Executable File
78 lines
2.8 KiB
TypeScript
Executable File
import { pool } from './pool';
|
|
import bcrypt from 'bcrypt';
|
|
|
|
export async function seedDatabase() {
|
|
const client = await pool.connect();
|
|
|
|
try {
|
|
// Create admin user
|
|
const adminEmail = process.env.ADMIN_EMAIL || 'admin@example.com';
|
|
const adminPassword = process.env.ADMIN_PASSWORD || 'password';
|
|
const passwordHash = await bcrypt.hash(adminPassword, 10);
|
|
|
|
await client.query(`
|
|
INSERT INTO users (email, password_hash, role)
|
|
VALUES ($1, $2, 'superadmin')
|
|
ON CONFLICT (email) DO UPDATE
|
|
SET password_hash = $2, role = 'superadmin'
|
|
`, [adminEmail, passwordHash]);
|
|
|
|
console.log(`✅ Admin user created: ${adminEmail}`);
|
|
|
|
// Create Deeply Rooted store
|
|
const storeResult = await client.query(`
|
|
INSERT INTO stores (name, slug, dutchie_url, active, scrape_enabled)
|
|
VALUES ('Deeply Rooted', 'AZ-Deeply-Rooted', 'https://dutchie.com/embedded-menu/AZ-Deeply-Rooted', true, true)
|
|
ON CONFLICT (slug) DO UPDATE
|
|
SET name = 'Deeply Rooted', dutchie_url = 'https://dutchie.com/embedded-menu/AZ-Deeply-Rooted'
|
|
RETURNING id
|
|
`);
|
|
|
|
const storeId = storeResult.rows[0].id;
|
|
console.log(`✅ Store created: Deeply Rooted (ID: ${storeId})`);
|
|
|
|
// Create categories for the store
|
|
const categories = [
|
|
{ name: 'Shop', slug: 'shop', url: 'https://dutchie.com/embedded-menu/AZ-Deeply-Rooted' },
|
|
{ name: 'Brands', slug: 'brands', url: 'https://dutchie.com/embedded-menu/AZ-Deeply-Rooted/brands' },
|
|
{ name: 'Specials', slug: 'specials', url: 'https://dutchie.com/embedded-menu/AZ-Deeply-Rooted/specials/sale/66501e094faefa00079b1835' }
|
|
];
|
|
|
|
for (const cat of categories) {
|
|
await client.query(`
|
|
INSERT INTO categories (store_id, name, slug, dutchie_url, scrape_enabled)
|
|
VALUES ($1, $2, $3, $4, true)
|
|
ON CONFLICT (store_id, slug) DO UPDATE
|
|
SET name = $2, dutchie_url = $4
|
|
`, [storeId, cat.name, cat.slug, cat.url]);
|
|
}
|
|
|
|
console.log('✅ Categories created: Shop, Brands, Specials');
|
|
|
|
// Create a default "Featured Products" campaign
|
|
await client.query(`
|
|
INSERT INTO campaigns (name, slug, description, display_style, active)
|
|
VALUES ('Featured Products', 'featured', 'Default featured products campaign', 'grid', true)
|
|
ON CONFLICT (slug) DO NOTHING
|
|
`);
|
|
|
|
console.log('✅ Default campaign created: Featured Products');
|
|
console.log('\n🎉 Seeding completed successfully!');
|
|
console.log(`\n📧 Login: ${adminEmail}`);
|
|
console.log(`🔑 Password: ${adminPassword}`);
|
|
|
|
} catch (error) {
|
|
console.error('❌ Seeding failed:', error);
|
|
throw error;
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
// Run seed if this file is executed directly
|
|
if (require.main === module) {
|
|
seedDatabase()
|
|
.then(() => process.exit(0))
|
|
.catch(() => process.exit(1));
|
|
}
|