feat: Add stale process monitor, users route, landing page, archive old scripts
- Add backend stale process monitoring API (/api/stale-processes) - Add users management route - Add frontend landing page and stale process monitor UI on /scraper-tools - Move old development scripts to backend/archive/ - Update frontend build with new features 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
65
backend/dist/scripts/bootstrap-stores-for-dispensaries.js
vendored
Normal file
65
backend/dist/scripts/bootstrap-stores-for-dispensaries.js
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const pg_1 = require("pg");
|
||||
const pool = new pg_1.Pool({ connectionString: process.env.DATABASE_URL });
|
||||
/**
|
||||
* Creates `stores` table records for all dispensaries that:
|
||||
* 1. Have menu_type = 'dutchie' AND platform_dispensary_id (ready for GraphQL crawl)
|
||||
* 2. Don't already have a linked stores record
|
||||
*
|
||||
* The stores table is required by the scraper engine (scrapeStore function)
|
||||
*/
|
||||
async function bootstrapStores() {
|
||||
console.log('=== Bootstrapping stores for Dutchie dispensaries ===\n');
|
||||
// Find all dutchie dispensaries without linked stores
|
||||
const result = await pool.query(`
|
||||
SELECT d.id, d.name, d.slug, d.menu_type, d.platform_dispensary_id, d.menu_url
|
||||
FROM dispensaries d
|
||||
LEFT JOIN stores s ON s.dispensary_id = d.id
|
||||
WHERE d.menu_type = 'dutchie'
|
||||
AND d.platform_dispensary_id IS NOT NULL
|
||||
AND s.id IS NULL
|
||||
ORDER BY d.id
|
||||
`);
|
||||
console.log(`Found ${result.rows.length} dispensaries needing store records\n`);
|
||||
let created = 0;
|
||||
let errors = 0;
|
||||
for (const d of result.rows) {
|
||||
try {
|
||||
// Insert store record linking to dispensary
|
||||
// Note: stores table only has basic fields: name, slug, dispensary_id, dutchie_url
|
||||
// The platform_dispensary_id for GraphQL crawling lives in the dispensaries table
|
||||
const insertResult = await pool.query(`
|
||||
INSERT INTO stores (
|
||||
name,
|
||||
slug,
|
||||
dispensary_id,
|
||||
active,
|
||||
scrape_enabled,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES ($1, $2, $3, true, true, NOW(), NOW())
|
||||
RETURNING id
|
||||
`, [
|
||||
d.name,
|
||||
d.slug || d.name.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
|
||||
d.id
|
||||
]);
|
||||
console.log(`[CREATED] Store ${insertResult.rows[0].id} for dispensary ${d.id}: ${d.name}`);
|
||||
created++;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`[ERROR] Dispensary ${d.id} (${d.name}): ${e.message}`);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
console.log('\n=== Bootstrap Summary ===');
|
||||
console.log(`Created: ${created}`);
|
||||
console.log(`Errors: ${errors}`);
|
||||
console.log(`Total needing stores: ${result.rows.length}`);
|
||||
await pool.end();
|
||||
}
|
||||
bootstrapStores().catch(e => {
|
||||
console.error('Fatal error:', e.message);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user