Files
cannaiq/backend/src/db/seed.ts
Kelly b4a2fb7d03 feat: Add v2 architecture with multi-state support and orchestrator services
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>
2025-12-07 11:30:57 -07:00

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));
}