|
| 1 | +import SPL from 'spl.js'; |
| 2 | +import YAML from 'yaml'; |
| 3 | +import type { VizDetails, LayerConfig } from './types'; |
| 4 | +import { getTableNames, getTableSchema, getRowCount, fetchGeoJSONFeatures } from './db'; |
| 5 | + |
| 6 | +export async function initSql() { |
| 7 | + const spl = await SPL(); |
| 8 | + return spl; |
| 9 | +} |
| 10 | + |
| 11 | +export async function openDb(spl: any, arrayBuffer: ArrayBuffer) { |
| 12 | + return spl.db(arrayBuffer); |
| 13 | +} |
| 14 | + |
| 15 | +export async function parseYamlConfig(yamlText: string, subfolder: string | null): Promise<VizDetails> { |
| 16 | + const config = YAML.parse(yamlText); |
| 17 | + const dbFile = config.database || config.file; |
| 18 | + if (!dbFile) throw new Error('No database field found in YAML config'); |
| 19 | + const databasePath = dbFile.startsWith('/') ? dbFile : subfolder ? `${subfolder}/${dbFile}` : dbFile; |
| 20 | + return { |
| 21 | + title: config.title || dbFile, |
| 22 | + description: config.description || '', |
| 23 | + database: databasePath, |
| 24 | + view: config.view || '', |
| 25 | + layers: config.layers || {}, |
| 26 | + }; |
| 27 | +} |
| 28 | + |
| 29 | +export async function buildTables(db: any, layerConfigs: { [k: string]: LayerConfig }, allNames?: string[]) { |
| 30 | + const names = allNames ?? (await getTableNames(db)); |
| 31 | + const select = Object.keys(layerConfigs).length |
| 32 | + ? [...new Set(Object.values(layerConfigs).map((c) => c.table))] |
| 33 | + : ['nodes', 'links', 'zones']; |
| 34 | + |
| 35 | + const tables: Array<{ name: string; type: string; rowCount: number; columns: any[] }> = []; |
| 36 | + let hasGeometry = false; |
| 37 | + |
| 38 | + for (const name of names) { |
| 39 | + if (!select.includes(name)) continue; |
| 40 | + const schema = await getTableSchema(db, name); |
| 41 | + const rowCount = await getRowCount(db, name); |
| 42 | + const hasGeomCol = schema.some((c: any) => c.name.toLowerCase() === 'geometry'); |
| 43 | + if (hasGeomCol) hasGeometry = true; |
| 44 | + tables.push({ name, type: 'table', rowCount, columns: schema }); |
| 45 | + } |
| 46 | + return { tables, hasGeometry }; |
| 47 | +} |
| 48 | + |
| 49 | +export async function buildGeoFeatures(db: any, tables: any[], layerConfigs: { [k: string]: LayerConfig }) { |
| 50 | + const plain = JSON.parse(JSON.stringify(layerConfigs)); |
| 51 | + const layersToProcess = Object.keys(plain).length |
| 52 | + ? Object.entries(plain) |
| 53 | + : tables |
| 54 | + .filter((t) => t.columns.some((c: any) => c.name.toLowerCase() === 'geometry')) |
| 55 | + .map((t) => [t.name, { table: t.name, type: 'line' as const }]); |
| 56 | + |
| 57 | + const features: any[] = []; |
| 58 | + for (const [layerName, cfg] of layersToProcess as any) { |
| 59 | + const tableName = (cfg as LayerConfig).table || layerName; |
| 60 | + const table = tables.find((t) => t.name === tableName); |
| 61 | + if (!table) continue; |
| 62 | + if (!table.columns.some((c: any) => c.name.toLowerCase() === 'geometry')) continue; |
| 63 | + const layerFeatures = await fetchGeoJSONFeatures(db, table, layerName, cfg); |
| 64 | + features.push(...layerFeatures); |
| 65 | + } |
| 66 | + return features; |
| 67 | +} |
0 commit comments