UNPKG

carthorse

Version:

A geospatial trail data processing pipeline for building 3D trail databases with elevation data

144 lines 6.42 kB
"use strict"; // SQL-based helper stubs for orchestrator logic // All implementations must use SQL/PostGIS, not JS/TS Object.defineProperty(exports, "__esModule", { value: true }); exports.buildMasterDatabase = buildMasterDatabase; exports.calculateAdaptiveTolerance = calculateAdaptiveTolerance; exports.estimateDatabaseSize = estimateDatabaseSize; exports.simplifyGeometryWithCounts = simplifyGeometryWithCounts; exports.calculateDistance = calculateDistance; exports.createCanonicalRoutingEdgesTable = createCanonicalRoutingEdgesTable; exports.cleanupStaging = cleanupStaging; exports.logSchemaTableState = logSchemaTableState; /** * Build the master database using SQL/PostGIS and OSM loader. * @returns {Promise<void>} */ async function buildMasterDatabase() { // TODO: Implement using SQL/PostGIS and OSM loader throw new Error('Not implemented: buildMasterDatabase (SQL/PostGIS required)'); } /** * Calculate adaptive tolerance for geometry simplification using SQL/PostGIS. * @param trails * @param targetSizeMB * @returns {Promise<number>} */ async function calculateAdaptiveTolerance(trails, targetSizeMB) { // TODO: Implement using SQL/PostGIS throw new Error('Not implemented: calculateAdaptiveTolerance (SQL/PostGIS required)'); } /** * Estimate database size using SQL/PostGIS. * @param trails * @returns {Promise<number>} */ async function estimateDatabaseSize(trails) { // TODO: Implement using SQL/PostGIS throw new Error('Not implemented: estimateDatabaseSize (SQL/PostGIS required)'); } /** * Simplify geometry and return point counts using SQL/PostGIS. * @param wkt * @param tolerance * @returns {Promise<{ simplified: string; originalPoints: number; simplifiedPoints: number }>} */ async function simplifyGeometryWithCounts(wkt, tolerance) { // TODO: Implement using SQL/PostGIS throw new Error('Not implemented: simplifyGeometryWithCounts (SQL/PostGIS required)'); } /** * Calculate distance between two coordinates using SQL/PostGIS (ST_Distance). * @param coord1 * @param coord2 * @returns {Promise<number>} */ async function calculateDistance(coord1, coord2) { // TODO: Implement using SQL/PostGIS (ST_Distance) throw new Error('Not implemented: calculateDistance (SQL/PostGIS required)'); } /** * Create the canonical routing_edges table in the given schema with all required columns and constraints. */ async function createCanonicalRoutingEdgesTable(pgClient, schemaName) { const sql = `CREATE TABLE ${schemaName}.routing_edges ( id SERIAL PRIMARY KEY, source INTEGER NOT NULL, target INTEGER NOT NULL, trail_id TEXT NOT NULL, trail_name TEXT NOT NULL, distance_km REAL NOT NULL, elevation_gain REAL CHECK(elevation_gain IS NULL OR elevation_gain >= 0), elevation_loss REAL CHECK(elevation_loss IS NULL OR elevation_loss >= 0), is_bidirectional BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT NOW(), geometry geometry(LineString, 4326), FOREIGN KEY (source) REFERENCES ${schemaName}.routing_nodes(id) ON DELETE CASCADE, FOREIGN KEY (target) REFERENCES ${schemaName}.routing_nodes(id) ON DELETE CASCADE );`; console.log('[DDL] Executing SQL for canonical routing_edges:', sql); await pgClient.query(sql); console.log('[DDL] Created canonical routing_edges table in', schemaName); } async function cleanupStaging(pgClient, stagingSchema) { try { // Check if client is still connected if (!pgClient || pgClient.connection && pgClient.connection.stream && pgClient.connection.stream.destroyed) { console.warn(`⚠️ Client connection is closed, skipping cleanup of staging schema ${stagingSchema}`); return; } await pgClient.query(`DROP SCHEMA IF EXISTS ${stagingSchema} CASCADE`); console.log(`✅ Staging schema ${stagingSchema} dropped.`); } catch (err) { console.error(`❌ Failed to drop staging schema ${stagingSchema}:`, err); } } async function logSchemaTableState(pgClient, stagingSchema, context) { try { const schemaRes = await pgClient.query(`SELECT schema_name FROM information_schema.schemata WHERE schema_name = $1`, [stagingSchema]); const tableCheck = await pgClient.query(`SELECT table_name FROM information_schema.tables WHERE table_schema = $1`, [stagingSchema]); if (schemaRes.rows.length === 0) { console.error(`[${context}] ❌ Staging schema ${stagingSchema} not found!`); } else { console.log(`[${context}] ✅ Staging schema ${stagingSchema} is present.`); } if (tableCheck.rows.length === 0) { console.error(`[${context}] ❌ No tables found in schema ${stagingSchema}!`); } else { console.log(`[${context}] Tables in ${stagingSchema}:`, tableCheck.rows.map(r => r.table_name)); } } catch (err) { console.error(`[${context}] ❌ Error checking schema/table existence:`, err); } } // Standalone test runner for createCanonicalRoutingEdgesTable if (require.main === module) { (async () => { const { Client } = require('pg'); const schemaName = process.argv[2] || 'staging_boulder_1753305242153'; const pgClient = new Client({ user: process.env.PGUSER || 'tester', host: process.env.PGHOST || 'localhost', database: process.env.PGDATABASE || 'trail_master_db_test', password: process.env.PGPASSWORD || '', port: process.env.PGPORT ? parseInt(process.env.PGPORT) : 5432, }); await pgClient.connect(); try { await pgClient.query(`CREATE SCHEMA IF NOT EXISTS ${schemaName}`); await pgClient.query(`CREATE TABLE IF NOT EXISTS ${schemaName}.routing_nodes (id SERIAL PRIMARY KEY)`); // minimal for FK await pgClient.query(`DROP TABLE IF EXISTS ${schemaName}.routing_edges CASCADE;`); await createCanonicalRoutingEdgesTable(pgClient, schemaName); const res = await pgClient.query(`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = $1 AND table_name = 'routing_edges'`, [schemaName]); console.log('[DDL-HELPER] routing_edges columns:', res.rows); } finally { await pgClient.end(); } })(); } //# sourceMappingURL=postgres-schema-helpers.js.map