carthorse
Version:
A geospatial trail data processing pipeline for building 3D trail databases with elevation data
233 lines (231 loc) ⢠8.69 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const pg_1 = require("pg");
const config_loader_1 = require("../utils/config-loader");
const package_json_1 = __importDefault(require("../../package.json"));
class TrailheadManager {
constructor(config) {
this.config = config;
const dbConfig = (0, config_loader_1.getDatabasePoolConfig)();
this.pgClient = new pg_1.Pool({
host: dbConfig.host,
port: dbConfig.port,
database: dbConfig.database,
user: dbConfig.user,
password: dbConfig.password,
max: dbConfig.max,
idleTimeoutMillis: dbConfig.idleTimeoutMillis,
connectionTimeoutMillis: dbConfig.connectionTimeoutMillis
});
}
/**
* Mark a specific node as a trailhead
*/
async markTrailhead() {
if (!this.config.nodeId) {
throw new Error('Node ID is required for marking trailhead');
}
console.log(`šÆ Marking node ${this.config.nodeId} as trailhead...`);
try {
const result = await this.pgClient.query(`
SELECT public.mark_node_as_trailhead($1, $2, $3)
`, [this.config.stagingSchema, this.config.nodeId, this.config.trailheadName]);
console.log(`ā
Successfully marked node ${this.config.nodeId} as trailhead`);
}
catch (error) {
console.error(`ā Failed to mark node as trailhead: ${error}`);
throw error;
}
}
/**
* List all trailheads in the staging schema
*/
async listTrailheads() {
console.log(`š Listing trailheads in schema ${this.config.stagingSchema}...`);
try {
const result = await this.pgClient.query(`
SELECT * FROM public.list_trailheads($1)
`, [this.config.stagingSchema]);
if (result.rows.length === 0) {
console.log('š No trailheads found in this schema');
return;
}
console.log(`\nšÆ Found ${result.rows.length} trailheads:`);
console.log('ā'.repeat(80));
result.rows.forEach((trailhead, index) => {
console.log(`${index + 1}. Node ${trailhead.node_id}`);
console.log(` Location: (${trailhead.lat.toFixed(6)}, ${trailhead.lng.toFixed(6)})`);
console.log(` Elevation: ${trailhead.elevation?.toFixed(0) || 'N/A'}m`);
console.log(` Connected trails: ${trailhead.connected_trails || 'N/A'}`);
console.log('');
});
}
catch (error) {
console.error(`ā Failed to list trailheads: ${error}`);
throw error;
}
}
/**
* Clear all trailhead designations
*/
async clearAllTrailheads() {
console.log(`šļø Clearing all trailhead designations in schema ${this.config.stagingSchema}...`);
try {
const result = await this.pgClient.query(`
SELECT public.clear_all_trailheads($1)
`, [this.config.stagingSchema]);
const clearedCount = result.rows[0].clear_all_trailheads;
console.log(`ā
Cleared ${clearedCount} trailhead designations`);
}
catch (error) {
console.error(`ā Failed to clear trailheads: ${error}`);
throw error;
}
}
/**
* Validate trailhead setup
*/
async validateTrailheadSetup() {
console.log(`š Validating trailhead setup in schema ${this.config.stagingSchema}...`);
try {
const result = await this.pgClient.query(`
SELECT * FROM public.validate_trailhead_setup($1)
`, [this.config.stagingSchema]);
const validation = result.rows[0];
console.log(`š Trailhead validation results:`);
console.log(` - Valid setup: ${validation.is_valid ? 'ā
Yes' : 'ā No'}`);
console.log(` - Message: ${validation.message}`);
console.log(` - Trailhead count: ${validation.trailhead_count}`);
console.log(` - Total nodes: ${validation.total_nodes}`);
if (validation.is_valid) {
console.log(`ā
Trailhead setup is valid and ready for route generation`);
}
else {
console.log(`ā ļø No trailheads found - route generation will use default entry points`);
}
}
catch (error) {
console.error(`ā Failed to validate trailhead setup: ${error}`);
throw error;
}
}
/**
* Close database connection
*/
async close() {
await this.pgClient.end();
}
}
// CLI Command Setup
const program = new commander_1.Command();
program
.name('trailhead')
.description('Manage trailhead nodes for route generation')
.version(package_json_1.default.version)
.addHelpText('after', `
Examples:
$ carthorse trailhead mark --region boulder --schema staging_boulder_123 --node-id 42
$ carthorse trailhead mark --region boulder --schema staging_boulder_123 --node-id 42 --name "Chautauqua Trailhead"
$ carthorse trailhead list --region boulder --schema staging_boulder_123
$ carthorse trailhead clear --region boulder --schema staging_boulder_123
$ carthorse trailhead validate --region boulder --schema staging_boulder_123
Notes:
- Trailheads are nodes designated as starting points for route generation
- When trailheads are set, route generation will use only trailhead nodes
- If no trailheads are set, route generation uses default entry points
- Use --verbose for detailed output`);
// Mark trailhead command
program
.command('mark')
.description('Mark a specific node as a trailhead')
.requiredOption('-r, --region <region>', 'Region name (e.g., boulder)')
.requiredOption('-s, --schema <schema>', 'Staging schema name')
.requiredOption('-n, --node-id <id>', 'Node ID to mark as trailhead')
.option('--name <name>', 'Optional trailhead name')
.option('-v, --verbose', 'Enable verbose output')
.action(async (options) => {
const manager = new TrailheadManager({
region: options.region,
stagingSchema: options.schema,
nodeId: parseInt(options.nodeId),
trailheadName: options.name,
verbose: options.verbose
});
try {
await manager.markTrailhead();
}
finally {
await manager.close();
}
});
// List trailheads command
program
.command('list')
.description('List all trailheads in a staging schema')
.requiredOption('-r, --region <region>', 'Region name (e.g., boulder)')
.requiredOption('-s, --schema <schema>', 'Staging schema name')
.option('-v, --verbose', 'Enable verbose output')
.action(async (options) => {
const manager = new TrailheadManager({
region: options.region,
stagingSchema: options.schema,
list: true,
verbose: options.verbose
});
try {
await manager.listTrailheads();
}
finally {
await manager.close();
}
});
// Clear trailheads command
program
.command('clear')
.description('Clear all trailhead designations')
.requiredOption('-r, --region <region>', 'Region name (e.g., boulder)')
.requiredOption('-s, --schema <schema>', 'Staging schema name')
.option('-v, --verbose', 'Enable verbose output')
.action(async (options) => {
const manager = new TrailheadManager({
region: options.region,
stagingSchema: options.schema,
clearAll: true,
verbose: options.verbose
});
try {
await manager.clearAllTrailheads();
}
finally {
await manager.close();
}
});
// Validate trailhead setup command
program
.command('validate')
.description('Validate trailhead setup')
.requiredOption('-r, --region <region>', 'Region name (e.g., boulder)')
.requiredOption('-s, --schema <schema>', 'Staging schema name')
.option('-v, --verbose', 'Enable verbose output')
.action(async (options) => {
const manager = new TrailheadManager({
region: options.region,
stagingSchema: options.schema,
validate: true,
verbose: options.verbose
});
try {
await manager.validateTrailheadSetup();
}
finally {
await manager.close();
}
});
// Parse command line arguments
program.parse();
//# sourceMappingURL=trailhead.js.map