gtfs 4.15.3 → 4.15.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/gtfs-export.ts","../../src/lib/file-utils.ts","../../src/lib/log-utils.ts","../../src/lib/import-gtfs.ts","../../src/models/models.ts","../../src/models/gtfs/agency.ts","../../src/models/gtfs/areas.ts","../../src/models/gtfs/attributions.ts","../../src/models/gtfs/booking-rules.ts","../../src/models/gtfs/calendar-dates.ts","../../src/models/gtfs/calendar.ts","../../src/models/gtfs/fare-attributes.ts","../../src/models/gtfs/fare-leg-rules.ts","../../src/models/gtfs/fare-media.ts","../../src/models/gtfs/fare-products.ts","../../src/models/gtfs/fare-rules.ts","../../src/models/gtfs/fare-transfer-rules.ts","../../src/models/gtfs/feed-info.ts","../../src/models/gtfs/frequencies.ts","../../src/models/gtfs/levels.ts","../../src/models/gtfs/location-groups.ts","../../src/models/gtfs/location-group-stops.ts","../../src/models/gtfs/locations.ts","../../src/models/gtfs/networks.ts","../../src/models/gtfs/pathways.ts","../../src/models/gtfs/route-networks.ts","../../src/models/gtfs/routes.ts","../../src/models/gtfs/shapes.ts","../../src/models/gtfs/stop-areas.ts","../../src/models/gtfs/stop-times.ts","../../src/models/gtfs/stops.ts","../../src/models/gtfs/timeframes.ts","../../src/models/gtfs/transfers.ts","../../src/models/gtfs/translations.ts","../../src/models/gtfs/trips.ts","../../src/models/non-standard/timetables.ts","../../src/models/non-standard/timetable-pages.ts","../../src/models/non-standard/timetable-stop-order.ts","../../src/models/non-standard/timetable-notes.ts","../../src/models/non-standard/timetable-notes-references.ts","../../src/models/non-standard/trips-dated-vehicle-journey.ts","../../src/models/gtfs-plus/calendar-attributes.ts","../../src/models/gtfs-plus/directions.ts","../../src/models/gtfs-plus/route-attributes.ts","../../src/models/gtfs-plus/stop-attributes.ts","../../src/models/gtfs-ride/board-alight.ts","../../src/models/gtfs-ride/rider-trip.ts","../../src/models/gtfs-ride/ridership.ts","../../src/models/gtfs-ride/trip-capacity.ts","../../src/models/gtfs-ride/ride-feed-info.ts","../../src/models/gtfs-realtime/trip-updates.ts","../../src/models/gtfs-realtime/stop-time-updates.ts","../../src/models/gtfs-realtime/vehicle-positions.ts","../../src/models/gtfs-realtime/service-alerts.ts","../../src/models/gtfs-realtime/service-alert-targets.ts","../../src/models/ods/deadhead-times.ts","../../src/models/ods/deadheads.ts","../../src/models/ods/ops-locations.ts","../../src/models/ods/run-events.ts","../../src/models/ods/runs-pieces.ts","../../src/lib/db.ts","../../src/lib/geojson-utils.ts","../../src/lib/import-gtfs-realtime.ts","../../src/lib/utils.ts","../../src/lib/export.ts","../../src/lib/advancedQuery.ts","../../src/lib/gtfs/routes.ts","../../src/lib/gtfs/shapes.ts","../../src/lib/gtfs/stops.ts","../../src/lib/gtfs/stop-times.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport PrettyError from 'pretty-error';\n\nimport { getConfig } from '../lib/file-utils.ts';\nimport { formatError } from '../lib/log-utils.ts';\nimport { exportGtfs } from '../index.ts';\n\nconst pe = new PrettyError();\n\nconst argv = yargs(hideBin(process.argv))\n .usage('Usage: $0 --configPath ./config.json')\n .help()\n .option('c', {\n alias: 'configPath',\n describe: 'Path to config file',\n type: 'string',\n })\n .option('sqlitePath', {\n describe: 'Path to SQLite database',\n type: 'string',\n })\n .parseSync();\n\nconst handleError = (error = 'Unknown Error') => {\n process.stdout.write(`\\n${formatError(error)}\\n`);\n console.error(pe.render(error));\n process.exit(1);\n};\n\nconst setupExport = async () => {\n const config = await getConfig(argv);\n await exportGtfs(config);\n process.exit();\n};\n\nsetupExport().catch(handleError);\n","import path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rm } from 'node:fs/promises';\nimport { omit, snakeCase } from 'lodash-es';\nimport sanitize from 'sanitize-filename';\nimport untildify from 'untildify';\nimport StreamZip from 'node-stream-zip';\n\n/*\n * Attempt to parse any config JSON file and read values from CLI.\n */\nexport async function getConfig(argv: {\n configPath?: string;\n gtfsPath?: string;\n gtfsUrl?: string;\n sqlitePath?: string;\n}) {\n let config;\n let data;\n\n if (argv.configPath) {\n // If a `configPath` is specified, try to read it and throw error if it doesn't exist\n try {\n data = await readFile(path.resolve(untildify(argv.configPath)), 'utf8');\n } catch (error) {\n throw new Error(\n `Cannot find configuration file at \\`${argv.configPath}\\`. Use config-sample.json as a starting point.`,\n );\n }\n\n try {\n config = Object.assign(JSON.parse(data), argv);\n } catch (error) {\n throw new Error(\n `Cannot parse configuration file at \\`${argv.configPath}\\`. Check to ensure that it is valid JSON.`,\n );\n }\n } else if (argv.gtfsPath || argv.gtfsUrl || argv.sqlitePath) {\n // Use argv values from CLI\n const agencies = [];\n if (argv.gtfsPath) {\n agencies.push({\n path: argv.gtfsPath,\n });\n }\n\n if (argv.gtfsUrl) {\n agencies.push({\n url: argv.gtfsUrl,\n });\n }\n\n config = {\n agencies,\n ...omit(argv, ['path', 'url']),\n };\n } else if (existsSync(path.resolve('./config.json'))) {\n // Else if `config.json` exists, use config values read from it\n try {\n data = await readFile(path.resolve('./config.json'), 'utf8');\n } catch (error) {\n throw new Error(\n `Cannot open configuration file at \\`${path.resolve('./config.json')}\\`. Check to ensure that it exists. Use config-sample.json as a starting point.`,\n );\n }\n\n try {\n config = Object.assign(JSON.parse(data), argv);\n console.log('Using configuration from ./config.json');\n } catch (error) {\n throw new Error(\n `Cannot parse configuration file at \\`${path.resolve('./config.json')}\\`. Check to ensure that it is valid JSON.`,\n );\n }\n } else {\n throw new Error(\n 'Cannot find configuration file. Use config-sample.json as a starting point, pass --configPath option.',\n );\n }\n\n return config;\n}\n\n/*\n * Prepare the specified directory for saving HTML timetables by deleting\n * everything.\n */\nexport async function prepDirectory(exportPath: string) {\n await rm(exportPath, { recursive: true, force: true });\n await mkdir(exportPath, { recursive: true });\n}\n\n/*\n * Unzip a zipfile into a specified directory\n */\nexport async function unzip(zipfilePath: string, exportPath: string) {\n /* eslint-disable-next-line new-cap */\n const zip = new StreamZip.async({ file: zipfilePath });\n await zip.extract(null, exportPath);\n await zip.close();\n}\n\n/*\n * Generate a folder name based on a string.\n */\nexport function generateFolderName(folderName: string) {\n return snakeCase(sanitize(folderName));\n}\n","import { clearLine, cursorTo } from 'node:readline';\nimport { noop } from 'lodash-es';\nimport * as colors from 'yoctocolors';\nimport { Config } from '../types/global_interfaces.ts';\n\n/*\n * Returns a log function based on config settings\n */\nexport function log(config: Config) {\n if (config.verbose === false) {\n return noop;\n }\n\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string, overwrite?: boolean) => {\n if (overwrite === true && process.stdout.isTTY) {\n clearLine(process.stdout, 0);\n cursorTo(process.stdout, 0);\n } else {\n process.stdout.write('\\n');\n }\n\n process.stdout.write(text);\n };\n}\n\n/*\n * Returns an warning log function based on config settings\n */\nexport function logWarning(config: Config) {\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string) => {\n process.stdout.write(`\\n${formatWarning(text)}\\n`);\n };\n}\n\n/*\n * Returns an error log function based on config settings\n */\nexport function logError(config: Config) {\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string) => {\n process.stdout.write(`\\n${formatError(text)}\\n`);\n };\n}\n\n/*\n * Format console warning text\n */\nexport function formatWarning(text: string) {\n const warningMessage = `${colors.underline('Warning')}: ${text}`;\n return colors.yellow(warningMessage);\n}\n\n/*\n * Format console error text\n */\nexport function formatError(error: any) {\n const messageText = error instanceof Error ? error.message : error;\n const errorMessage = `${colors.underline('Error')}: ${messageText.replace(\n 'Error: ',\n '',\n )}`;\n return colors.red(errorMessage);\n}\n","import path from 'node:path';\nimport { createReadStream, existsSync, lstatSync } from 'node:fs';\nimport { cp, readdir, rename, readFile, rm, writeFile } from 'node:fs/promises';\nimport { parse } from 'csv-parse';\nimport pluralize from 'pluralize';\nimport stripBomStream from 'strip-bom-stream';\nimport { temporaryDirectory } from 'tempy';\nimport Timer from 'timer-machine';\nimport untildify from 'untildify';\nimport mapSeries from 'promise-map-series';\nimport Database from 'better-sqlite3';\n\nimport * as models from '../models/models.ts';\nimport { openDb } from './db.ts';\nimport { unzip } from './file-utils.ts';\nimport { isValidJSON } from './geojson-utils.ts';\nimport { updateGtfsRealtimeData } from './import-gtfs-realtime.ts';\nimport {\n log as _log,\n logError as _logError,\n logWarning as _logWarning,\n} from './log-utils.ts';\nimport {\n calculateSecondsFromMidnight,\n setDefaultConfig,\n validateConfigForImport,\n padLeadingZeros,\n} from './utils.ts';\n\nimport { Config, ConfigAgency, Model } from '../types/global_interfaces.ts';\n\ninterface GtfsImportTask {\n exclude?: string[];\n url?: string;\n headers?: Record<string, string>;\n realtimeAlerts?: {\n url: string;\n headers?: Record<string, string>;\n };\n realtimeTripUpdates?: {\n url: string;\n headers?: Record<string, string>;\n };\n realtimeVehiclePositions?: {\n url: string;\n headers?: Record<string, string>;\n };\n downloadDir: string;\n downloadTimeout?: number;\n gtfsRealtimeExpirationSeconds: number;\n path?: string;\n csvOptions: {};\n ignoreDuplicates: boolean;\n ignoreErrors: boolean;\n sqlitePath: string;\n prefix?: string;\n currentTimestamp: number;\n log: (message: string, newLine?: boolean) => void;\n logWarning: (message: string) => void;\n logError: (message: string) => void;\n}\n\ninterface Dictionary<T> {\n [key: string]: T;\n}\ntype Tuple = [seconds: number | null, date: string | null];\n\nconst dateCache: Dictionary<Tuple> = {};\n\nconst calculateAndCacheDate = (value: string): Tuple => {\n const cached = dateCache[value];\n if (cached != null) {\n return cached;\n }\n\n const seconds = calculateSecondsFromMidnight(value);\n const date = padLeadingZeros(value);\n const computed: Tuple = [seconds, date];\n dateCache[value] = computed;\n return computed;\n};\n\nconst getTextFiles = async (folderPath: string): Promise<string[]> => {\n const files = await readdir(folderPath);\n return files.filter((filename) => filename.slice(-3) === 'txt');\n};\n\nconst TIME_COLUMN_NAMES = [\n 'start_time',\n 'end_time',\n 'arrival_time',\n 'departure_time',\n 'prior_notice_last_time',\n 'prior_notice_start_time',\n 'start_pickup_drop_off_window',\n];\n\nconst TIME_COLUMN_PAIRS = TIME_COLUMN_NAMES.map((name) => [\n name,\n name.endsWith('time') ? `${name}stamp` : `${name}_timestamp`,\n]);\n\nconst downloadGtfsFiles = async (task: GtfsImportTask): Promise<void> => {\n if (!task.url) {\n throw new Error('No `url` specified in config');\n }\n\n task.log(`Downloading GTFS from ${task.url}`);\n\n task.path = `${task.downloadDir}/gtfs.zip`;\n\n const response = await fetch(task.url, {\n method: 'GET',\n headers: task.headers || {},\n signal: task.downloadTimeout\n ? AbortSignal.timeout(task.downloadTimeout)\n : undefined,\n });\n\n if (response.status !== 200) {\n throw new Error(\n `Unable to download GTFS from ${task.url}. Got status ${response.status}.`,\n );\n }\n\n const buffer = await response.arrayBuffer();\n\n await writeFile(task.path, Buffer.from(buffer));\n task.log('Download successful');\n};\n\nconst extractGtfsFiles = async (task: GtfsImportTask): Promise<void> => {\n if (!task.path) {\n throw new Error('No `path` specified in config');\n }\n\n const gtfsPath = untildify(task.path);\n task.log(`Importing GTFS from ${task.path}\\r`);\n if (path.extname(gtfsPath) === '.zip') {\n try {\n await unzip(gtfsPath, task.downloadDir);\n const textFiles = await getTextFiles(task.downloadDir);\n\n // If no .txt files in this directory, check for subdirectories and copy them here\n if (textFiles.length === 0) {\n const files = await readdir(task.downloadDir);\n // Ignore system directories within zip file\n const folders = files\n .filter((filename) => !['__MACOSX'].includes(filename))\n .map((filename) => path.join(task.downloadDir, filename))\n .filter((source) => lstatSync(source).isDirectory());\n\n if (folders.length > 1) {\n throw new Error(\n `More than one subfolder found in zip file at \\`${task.path}\\`. Ensure that .txt files are in the top level of the zip file, or in a single subdirectory.`,\n );\n } else if (folders.length === 0) {\n throw new Error(\n `No .txt files found in \\`${task.path}\\`. Ensure that .txt files are in the top level of the zip file, or in a single subdirectory.`,\n );\n }\n\n const subfolderName = folders[0];\n const directoryTextFiles = await getTextFiles(subfolderName);\n\n if (directoryTextFiles.length === 0) {\n throw new Error(\n `No .txt files found in \\`${task.path}\\`. Ensure that .txt files are in the top level of the zip file, or in a single subdirectory.`,\n );\n }\n\n await Promise.all(\n directoryTextFiles.map(async (fileName) =>\n rename(\n path.join(subfolderName, fileName),\n path.join(task.downloadDir, fileName),\n ),\n ),\n );\n }\n } catch (error: any) {\n task.logError(error);\n throw new Error(`Unable to unzip file ${task.path}`);\n }\n } else {\n // Local file is unzipped, just copy it from there.\n try {\n await cp(gtfsPath, task.downloadDir, { recursive: true });\n } catch {\n throw new Error(\n `Unable to load files from path \\`${gtfsPath}\\` defined in configuration. Verify that path exists and contains GTFS files.`,\n );\n }\n }\n};\n\nconst createGtfsTables = (db: Database.Database): void => {\n for (const model of Object.values(models) as Model[]) {\n if (!model.schema) {\n return;\n }\n\n const columns = model.schema.map((column) => {\n let check = '';\n if (column.min !== undefined && column.max) {\n check = `CHECK( ${column.name} >= ${column.min} AND ${column.name} <= ${column.max} )`;\n } else if (column.min) {\n check = `CHECK( ${column.name} >= ${column.min} )`;\n } else if (column.max) {\n check = `CHECK( ${column.name} <= ${column.max} )`;\n }\n\n const required = column.required ? 'NOT NULL' : '';\n const columnDefault = column.default ? 'DEFAULT ' + column.default : '';\n const columnCollation = column.nocase ? 'COLLATE NOCASE' : '';\n return `${column.name} ${column.type} ${check} ${required} ${columnDefault} ${columnCollation}`;\n });\n\n // Find Primary Key fields\n const primaryColumns = model.schema.filter((column) => column.primary);\n\n if (primaryColumns.length > 0) {\n columns.push(\n `PRIMARY KEY (${primaryColumns\n .map((column) => column.name)\n .join(', ')})`,\n );\n }\n\n db.prepare(`DROP TABLE IF EXISTS ${model.filenameBase};`).run();\n\n db.prepare(\n `CREATE TABLE ${model.filenameBase} (${columns.join(', ')});`,\n ).run();\n }\n};\n\nconst createGtfsIndexes = (db: Database.Database): void => {\n for (const model of Object.values(models) as Model[]) {\n if (!model.schema) {\n return;\n }\n for (const column of model.schema.filter((column) => column.index)) {\n db.prepare(\n `CREATE INDEX idx_${model.filenameBase}_${column.name} ON ${model.filenameBase} (${column.name});`,\n ).run();\n }\n }\n};\n\nconst formatGtfsLine = (\n line: { [x: string]: any; geojson?: string },\n model: Model,\n totalLineCount: number,\n): Record<string, any> => {\n const lineNumber = totalLineCount + 1;\n const formattedLine: Record<string, any> = {};\n\n // Pre-compute these values\n const filenameBase = model.filenameBase;\n const filenameExtension = model.filenameExtension;\n\n for (const columnSchema of model.schema) {\n const { name, type, required, min, max } = columnSchema;\n let value = line[name];\n\n // Early null check\n if (value === '' || value === undefined || value === null) {\n formattedLine[name] = null;\n if (required) {\n throw new Error(\n `Missing required value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`,\n );\n }\n continue;\n }\n\n // Type conversion\n switch (type) {\n case 'date':\n value = value.replace(/-/g, '');\n if (value.length !== 8) {\n throw new Error(\n `Invalid date in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`,\n );\n }\n value = parseInt(value, 10);\n break;\n case 'integer':\n value = parseInt(value, 10);\n break;\n case 'real':\n value = parseFloat(value);\n break;\n }\n\n // Check for NaN after conversion\n if (Number.isNaN(value)) {\n formattedLine[name] = null;\n continue;\n }\n\n formattedLine[name] = value;\n\n // Validate min/max\n if (min !== undefined && value < min) {\n throw new Error(\n `Invalid value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}: below minimum value of ${min}.`,\n );\n }\n if (max !== undefined && value > max) {\n throw new Error(\n `Invalid value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}: above maximum value of ${max}.`,\n );\n }\n }\n\n // Process time columns\n for (const [timeColumnName, timestampColumnName] of TIME_COLUMN_PAIRS) {\n const value = formattedLine[timeColumnName];\n if (value) {\n const [seconds, date] = calculateAndCacheDate(value);\n formattedLine[timestampColumnName] = seconds;\n formattedLine[timeColumnName] = date;\n }\n }\n\n return formattedLine;\n};\n\nconst BATCH_SIZE = 100_000;\n\nconst importGtfsFiles = (\n db: Database.Database,\n task: GtfsImportTask,\n): Promise<void[]> =>\n mapSeries(\n Object.values(models),\n (model: Model) =>\n new Promise<void>((resolve, reject) => {\n let totalLineCount = 0;\n const filename = `${model.filenameBase}.${model.filenameExtension}`;\n\n // Filter out excluded files from config\n if (task.exclude && task.exclude.includes(model.filenameBase)) {\n task.log(`Skipping - ${filename}\\r`);\n resolve();\n return;\n }\n\n // If the model is a database/gtfs-realtime model then skip silently\n if (model.extension === 'gtfs-realtime') {\n resolve();\n return;\n }\n\n const filepath = path.join(task.downloadDir, `${filename}`);\n\n // Log missing standard GTFS files, don't log nonstandard files\n if (!existsSync(filepath)) {\n if (!model.nonstandard) {\n task.log(`Importing - ${filename} - No file found\\r`);\n }\n\n resolve();\n return;\n }\n\n task.log(`Importing - ${filename}\\r`);\n\n const columns = model.schema.filter((column) => column.name !== 'id');\n const placeholder = columns.map(({ name }) => `@${name}`).join(', ');\n const prepareStatement = `INSERT ${task.ignoreDuplicates ? 'OR IGNORE' : ''} INTO ${\n model.filenameBase\n } (${columns\n .map((column) => column.name)\n .join(', ')}) VALUES (${placeholder})`;\n\n const insert = db.prepare(prepareStatement);\n\n const insertLines = db.transaction((lines) => {\n for (const [rowNumber, line] of Object.entries(lines)) {\n try {\n if (task.prefix === undefined) {\n insert.run(line);\n } else {\n const prefixedLine = Object.fromEntries(\n Object.entries(\n line as { [x: string]: any; geojson?: string },\n ).map(([columnName, value]) => [\n columnName,\n columns.find((col) => col.name === columnName)?.prefix\n ? `${task.prefix}${value}`\n : value,\n ]),\n );\n insert.run(prefixedLine);\n }\n } catch (error: any) {\n if (error.code === 'SQLITE_CONSTRAINT_PRIMARYKEY') {\n const primaryColumns = model.schema.filter(\n (column) => column.primary,\n );\n task.logWarning(\n `Duplicate values for primary key (${primaryColumns.map((column) => column.name).join(', ')}) found in ${filename}. Set the \\`ignoreDuplicates\\` option to true in config.json to ignore this error`,\n );\n }\n\n task.logWarning(\n `Check ${filename} for invalid data on row ${rowNumber}.`,\n );\n throw error;\n }\n }\n });\n\n if (model.filenameExtension === 'txt') {\n const parser = parse({\n columns: true,\n relax_quotes: true,\n trim: true,\n skip_empty_lines: true,\n ...task.csvOptions,\n });\n\n let lines: { [x: string]: any; geojson?: string }[] = [];\n\n parser.on('readable', () => {\n let record;\n\n while ((record = parser.read())) {\n totalLineCount += 1;\n lines.push(formatGtfsLine(record, model, totalLineCount));\n\n if (lines.length >= BATCH_SIZE) {\n try {\n insertLines(lines);\n lines = [];\n } catch (error) {\n reject(error);\n }\n\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n }\n }\n });\n\n parser.on('end', () => {\n try {\n if (lines.length > 0) {\n try {\n insertLines(lines);\n } catch (error) {\n reject(error);\n }\n }\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n\n parser.on('error', reject);\n\n createReadStream(filepath).pipe(stripBomStream()).pipe(parser);\n } else if (model.filenameExtension === 'geojson') {\n readFile(filepath, 'utf8')\n .then((data) => {\n if (isValidJSON(data) === false) {\n reject(new Error(`Invalid JSON in ${filename}`));\n }\n totalLineCount += 1;\n const line = formatGtfsLine(\n { geojson: data },\n model,\n totalLineCount,\n );\n insertLines([line]);\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n resolve();\n })\n .catch(reject);\n } else {\n reject(\n new Error(`Unsupported file type: ${model.filenameExtension}`),\n );\n }\n }),\n );\n\nexport async function importGtfs(initialConfig: Config): Promise<void> {\n const timer = new Timer();\n timer.start();\n\n const config = setDefaultConfig(initialConfig);\n validateConfigForImport(config);\n const log = _log(config);\n const logError = _logError(config);\n const logWarning = _logWarning(config);\n\n try {\n const db = openDb(config);\n const agencyCount = config.agencies.length;\n\n log(\n `Starting GTFS import for ${pluralize('file', agencyCount, true)} using SQLite database at ${config.sqlitePath}`,\n );\n\n createGtfsTables(db);\n\n await mapSeries(config.agencies, async (agency: ConfigAgency) => {\n try {\n const tempPath = temporaryDirectory();\n\n const task = {\n exclude: agency.exclude,\n url: agency.url,\n headers: agency.headers,\n realtimeAlerts: agency.realtimeAlerts,\n realtimeTripUpdates: agency.realtimeTripUpdates,\n realtimeVehiclePositions: agency.realtimeVehiclePositions,\n downloadDir: tempPath,\n downloadTimeout: config.downloadTimeout,\n gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,\n path: agency.path,\n csvOptions: config.csvOptions || {},\n ignoreDuplicates: config.ignoreDuplicates,\n ignoreErrors: config.ignoreErrors,\n sqlitePath: config.sqlitePath,\n prefix: agency.prefix,\n currentTimestamp: Math.floor(Date.now() / 1000),\n log,\n logWarning,\n logError,\n };\n\n if (task.url) {\n await downloadGtfsFiles(task);\n }\n\n await extractGtfsFiles(task);\n await importGtfsFiles(db, task);\n await updateGtfsRealtimeData(task);\n\n await rm(tempPath, { recursive: true });\n } catch (error: any) {\n handleImportError(error, config, logError);\n }\n });\n\n log(`Creating DB indexes`);\n createGtfsIndexes(db);\n\n const seconds = Math.round(timer.time() / 1000);\n timer.stop();\n\n log(\n `Completed GTFS import for ${pluralize('agency', agencyCount, true)} in ${seconds} seconds\\n`,\n );\n } catch (error: any) {\n handleDatabaseError(error, config, logError);\n }\n}\n\nfunction handleImportError(\n error: any,\n config: Config,\n logError: (message: string) => void,\n): void {\n if (config.ignoreErrors) {\n logError(error.message);\n } else {\n throw error;\n }\n}\n\nfunction handleDatabaseError(\n error: any,\n config: Config,\n logError: (message: string) => void,\n): void {\n if (error?.code === 'SQLITE_CANTOPEN') {\n logError(\n `Unable to open sqlite database \"${config.sqlitePath}\" defined as \\`sqlitePath\\` config.json. Ensure the parent directory exists or remove \\`sqlitePath\\` from config.json.`,\n );\n }\n throw error;\n}\n","export { agency } from './gtfs/agency.ts';\nexport { areas } from './gtfs/areas.ts';\nexport { attributions } from './gtfs/attributions.ts';\nexport { bookingRules } from './gtfs/booking-rules.ts';\nexport { calendarDates } from './gtfs/calendar-dates.ts';\nexport { calendar } from './gtfs/calendar.ts';\nexport { fareAttributes } from './gtfs/fare-attributes.ts';\nexport { fareLegRules } from './gtfs/fare-leg-rules.ts';\nexport { fareMedia } from './gtfs/fare-media.ts';\nexport { fareProducts } from './gtfs/fare-products.ts';\nexport { fareRules } from './gtfs/fare-rules.ts';\nexport { fareTransferRules } from './gtfs/fare-transfer-rules.ts';\nexport { feedInfo } from './gtfs/feed-info.ts';\nexport { frequencies } from './gtfs/frequencies.ts';\nexport { levels } from './gtfs/levels.ts';\nexport { locationGroups } from './gtfs/location-groups.ts';\nexport { locationGroupStops } from './gtfs/location-group-stops.ts';\nexport { locations } from './gtfs/locations.ts';\nexport { networks } from './gtfs/networks.ts';\nexport { pathways } from './gtfs/pathways.ts';\nexport { routeNetworks } from './gtfs/route-networks.ts';\nexport { routes } from './gtfs/routes.ts';\nexport { shapes } from './gtfs/shapes.ts';\nexport { stopAreas } from './gtfs/stop-areas.ts';\nexport { stopTimes } from './gtfs/stop-times.ts';\nexport { stops } from './gtfs/stops.ts';\nexport { timeframes } from './gtfs/timeframes.ts';\nexport { transfers } from './gtfs/transfers.ts';\nexport { translations } from './gtfs/translations.ts';\nexport { trips } from './gtfs/trips.ts';\n\nexport { timetables } from './non-standard/timetables.ts';\nexport { timetablePages } from './non-standard/timetable-pages.ts';\nexport { timetableStopOrder } from './non-standard/timetable-stop-order.ts';\nexport { timetableNotes } from './non-standard/timetable-notes.ts';\nexport { timetableNotesReferences } from './non-standard/timetable-notes-references.ts';\nexport { tripsDatedVehicleJourney } from './non-standard/trips-dated-vehicle-journey.ts';\n\nexport { calendarAttributes } from './gtfs-plus/calendar-attributes.ts';\nexport { directions } from './gtfs-plus/directions.ts';\nexport { routeAttributes } from './gtfs-plus/route-attributes.ts';\nexport { stopAttributes } from './gtfs-plus/stop-attributes.ts';\n\nexport { boardAlight } from './gtfs-ride/board-alight.ts';\nexport { riderTrip } from './gtfs-ride/rider-trip.ts';\nexport { ridership } from './gtfs-ride/ridership.ts';\nexport { tripCapacity } from './gtfs-ride/trip-capacity.ts';\nexport { rideFeedInfo } from './gtfs-ride/ride-feed-info.ts';\n\nexport { tripUpdates } from './gtfs-realtime/trip-updates.ts';\nexport { stopTimeUpdates } from './gtfs-realtime/stop-time-updates.ts';\nexport { vehiclePositions } from './gtfs-realtime/vehicle-positions.ts';\nexport { serviceAlerts } from './gtfs-realtime/service-alerts.ts';\nexport { serviceAlertTargets } from './gtfs-realtime/service-alert-targets.ts';\n\nexport { deadheadTimes } from './ods/deadhead-times.ts';\nexport { deadheads } from './ods/deadheads.ts';\nexport { opsLocations } from './ods/ops-locations.ts';\nexport { runEvents } from './ods/run-events.ts';\nexport { runsPieces } from './ods/runs-pieces.ts';\n","export const agency = {\n filenameBase: 'agency',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'agency_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'agency_name',\n type: 'text',\n required: true,\n nocase: true,\n },\n {\n name: 'agency_url',\n type: 'text',\n required: true,\n },\n {\n name: 'agency_timezone',\n type: 'text',\n required: true,\n },\n {\n name: 'agency_lang',\n type: 'text',\n nocase: true,\n },\n {\n name: 'agency_phone',\n type: 'text',\n nocase: true,\n },\n {\n name: 'agency_fare_url',\n type: 'text',\n },\n {\n name: 'agency_email',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const areas = {\n filenameBase: 'areas',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'area_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'area_name',\n type: 'text',\n },\n ],\n};\n","export const attributions = {\n filenameBase: 'attributions',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'attribution_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'agency_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'organization_name',\n type: 'text',\n required: true,\n nocase: true,\n },\n {\n name: 'is_producer',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'is_operator',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'is_authority',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'attribution_url',\n type: 'text',\n },\n {\n name: 'attribution_email',\n type: 'text',\n nocase: true,\n },\n {\n name: 'attribution_phone',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const bookingRules = {\n filenameBase: 'booking_rules',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'booking_rule_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'booking_type',\n type: 'integer',\n required: true,\n min: 0,\n max: 2,\n },\n {\n name: 'prior_notice_duration_min',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_duration_max',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_last_day',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_last_time',\n type: 'text',\n },\n {\n name: 'prior_notice_last_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'prior_notice_start_day',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_start_time',\n type: 'text',\n },\n {\n name: 'prior_notice_start_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'prior_notice_service_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'message',\n type: 'text',\n nocase: true,\n },\n {\n name: 'pickup_message',\n type: 'text',\n nocase: true,\n },\n {\n name: 'drop_off_message',\n type: 'text',\n nocase: true,\n },\n {\n name: 'phone_number',\n type: 'text',\n nocase: true,\n },\n {\n name: 'info_url',\n type: 'text',\n },\n {\n name: 'booking_url',\n type: 'text',\n },\n ],\n};\n","export const calendarDates = {\n filenameBase: 'calendar_dates',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'service_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'date',\n type: 'date',\n required: true,\n primary: true,\n },\n {\n name: 'exception_type',\n type: 'integer',\n required: true,\n min: 1,\n max: 2,\n index: true,\n },\n {\n name: 'holiday_name',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const calendar = {\n filenameBase: 'calendar',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'service_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'monday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'tuesday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'wednesday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'thursday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'friday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'saturday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'sunday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'start_date',\n type: 'date',\n required: true,\n index: true,\n },\n {\n name: 'end_date',\n type: 'date',\n required: true,\n index: true,\n },\n ],\n};\n","export const fareAttributes = {\n filenameBase: 'fare_attributes',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'fare_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'price',\n type: 'real',\n required: true,\n },\n {\n name: 'currency_type',\n type: 'text',\n required: true,\n },\n {\n name: 'payment_method',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'transfers',\n type: 'integer',\n min: 0,\n max: 2,\n },\n {\n name: 'agency_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'transfer_duration',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const fareLegRules = {\n filenameBase: 'fare_leg_rules',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'leg_group_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'network_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'from_area_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_area_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'from_timeframe_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_timeframe_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'fare_product_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'rule_priority',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const fareMedia = {\n filenameBase: 'fare_media',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'fare_media_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'fare_media_name',\n type: 'text',\n },\n {\n name: 'fare_media_type',\n type: 'integer',\n required: true,\n min: 0,\n max: 4,\n },\n ],\n};\n","export const fareProducts = {\n filenameBase: 'fare_products',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'fare_product_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'fare_product_name',\n type: 'text',\n },\n {\n name: 'fare_media_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'amount',\n type: 'real',\n required: true,\n },\n {\n name: 'currency',\n type: 'text',\n required: true,\n },\n ],\n};\n","export const fareRules = {\n filenameBase: 'fare_rules',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'fare_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'origin_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'destination_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'contains_id',\n type: 'text',\n prefix: true,\n },\n ],\n};\n","export const fareTransferRules = {\n filenameBase: 'fare_transfer_rules',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'from_leg_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_leg_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'transfer_count',\n type: 'integer',\n min: -1,\n primary: true,\n },\n {\n name: 'duration_limit',\n type: 'integer',\n min: 0,\n primary: true,\n },\n {\n name: 'duration_limit_type',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'fare_transfer_type',\n type: 'integer',\n min: 0,\n max: 2,\n required: true,\n },\n {\n name: 'fare_product_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n ],\n};\n","export const feedInfo = {\n filenameBase: 'feed_info',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'feed_publisher_name',\n type: 'text',\n required: true,\n nocase: true,\n },\n {\n name: 'feed_publisher_url',\n type: 'text',\n required: true,\n },\n {\n name: 'feed_lang',\n type: 'text',\n required: true,\n },\n {\n name: 'default_lang',\n type: 'text',\n nocase: true,\n },\n {\n name: 'feed_start_date',\n type: 'date',\n },\n {\n name: 'feed_end_date',\n type: 'date',\n },\n {\n name: 'feed_version',\n type: 'text',\n },\n {\n name: 'feed_contact_email',\n type: 'text',\n nocase: true,\n },\n {\n name: 'feed_contact_url',\n type: 'text',\n },\n ],\n};\n","export const frequencies = {\n filenameBase: 'frequencies',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'start_time',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'start_timestamp',\n type: 'integer',\n },\n {\n name: 'end_time',\n type: 'text',\n required: true,\n },\n {\n name: 'end_timestamp',\n type: 'integer',\n },\n {\n name: 'headway_secs',\n type: 'integer',\n required: true,\n min: 0,\n },\n {\n name: 'exact_times',\n type: 'integer',\n min: 0,\n max: 1,\n },\n ],\n};\n","export const levels = {\n filenameBase: 'levels',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'level_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'level_index',\n type: 'real',\n required: true,\n },\n {\n name: 'level_name',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const locationGroups = {\n filenameBase: 'location_groups',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'location_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'location_group_name',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const locationGroupStops = {\n filenameBase: 'location_group_stops',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'location_group_id',\n type: 'text',\n prefix: true,\n index: true,\n required: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n prefix: true,\n index: true,\n },\n ],\n};\n","export const locations = {\n filenameBase: 'locations',\n filenameExtension: 'geojson',\n schema: [\n {\n name: 'geojson',\n type: 'text',\n },\n ],\n};\n","export const networks = {\n filenameBase: 'networks',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'network_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'network_name',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const pathways = {\n filenameBase: 'pathways',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'pathway_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'from_stop_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'to_stop_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'pathway_mode',\n type: 'integer',\n required: true,\n min: 1,\n max: 7,\n },\n {\n name: 'is_bidirectional',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'length',\n type: 'real',\n min: 0,\n },\n {\n name: 'traversal_time',\n type: 'integer',\n min: 0,\n },\n {\n name: 'stair_count',\n type: 'integer',\n },\n {\n name: 'max_slope',\n type: 'real',\n },\n {\n name: 'min_width',\n type: 'real',\n min: 0,\n },\n {\n name: 'signposted_as',\n type: 'text',\n nocase: true,\n },\n {\n name: 'reversed_signposted_as',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const routeNetworks = {\n filenameBase: 'route_networks',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'network_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n primary: true,\n index: true,\n prefix: true,\n },\n ],\n};\n","export const routes = {\n filenameBase: 'routes',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'route_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'agency_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'route_short_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_long_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_desc',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_type',\n type: 'integer',\n required: true,\n min: 0,\n // Support extended GTFS route types with no max value\n // https://developers.google.com/transit/gtfs/reference/extended-route-types\n },\n {\n name: 'route_url',\n type: 'text',\n },\n {\n name: 'route_color',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_text_color',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_sort_order',\n type: 'integer',\n min: 0,\n },\n {\n name: 'continuous_pickup',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'continuous_drop_off',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'network_id',\n type: 'text',\n prefix: true,\n },\n ],\n};\n","export const shapes = {\n filenameBase: 'shapes',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'shape_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'shape_pt_lat',\n type: 'real',\n required: true,\n min: -90,\n max: 90,\n },\n {\n name: 'shape_pt_lon',\n type: 'real',\n required: true,\n min: -180,\n max: 180,\n },\n {\n name: 'shape_pt_sequence',\n type: 'integer',\n required: true,\n primary: true,\n min: 0,\n },\n {\n name: 'shape_dist_traveled',\n type: 'real',\n min: 0,\n },\n ],\n};\n","export const stopAreas = {\n filenameBase: 'stop_areas',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'area_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n ],\n};\n","export const stopTimes = {\n filenameBase: 'stop_times',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'arrival_time',\n type: 'text',\n },\n {\n name: 'arrival_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'departure_time',\n type: 'text',\n },\n {\n name: 'departure_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'location_group_id',\n type: 'text',\n prefix: true,\n index: true,\n },\n {\n name: 'location_id',\n type: 'text',\n prefix: true,\n index: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n prefix: true,\n index: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n required: true,\n primary: true,\n min: 0,\n },\n {\n name: 'stop_headsign',\n type: 'text',\n nocase: true,\n },\n {\n name: 'start_pickup_drop_off_window',\n type: 'text',\n },\n {\n name: 'start_pickup_drop_off_window_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'pickup_type',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'drop_off_type',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'continuous_pickup',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'continuous_drop_off',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'shape_dist_traveled',\n type: 'real',\n min: 0,\n },\n {\n name: 'timepoint',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'pickup_booking_rule_id',\n type: 'text',\n prefix: true,\n index: true,\n },\n {\n name: 'drop_off_booking_rule_id',\n type: 'text',\n prefix: true,\n index: true,\n },\n ],\n};\n","export const stops = {\n filenameBase: 'stops',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'stop_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'stop_code',\n type: 'text',\n },\n {\n name: 'stop_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'tts_stop_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'stop_desc',\n type: 'text',\n nocase: true,\n },\n {\n name: 'stop_lat',\n type: 'real',\n min: -90,\n max: 90,\n },\n {\n name: 'stop_lon',\n type: 'real',\n min: -180,\n max: 180,\n },\n {\n name: 'zone_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'stop_url',\n type: 'text',\n },\n {\n name: 'location_type',\n type: 'integer',\n min: 0,\n max: 4,\n },\n {\n name: 'parent_station',\n type: 'text',\n index: true,\n },\n {\n name: 'stop_timezone',\n type: 'text',\n },\n {\n name: 'wheelchair_boarding',\n type: 'integer',\n min: 0,\n max: 2,\n },\n {\n name: 'level_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'platform_code',\n type: 'text',\n },\n ],\n};\n","export const timeframes = {\n filenameBase: 'timeframes',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'timeframe_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'start_time',\n type: 'text',\n },\n {\n name: 'end_time',\n type: 'text',\n },\n {\n name: 'service_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n ],\n};\n","export const transfers = {\n filenameBase: 'transfers',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'from_stop_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_stop_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'from_route_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_route_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'from_trip_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_trip_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'transfer_type',\n type: 'integer',\n min: 0,\n max: 5,\n default: 0,\n },\n {\n name: 'min_transfer_time',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const translations = {\n filenameBase: 'translations',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'table_name',\n type: 'text',\n primary: true,\n required: true,\n },\n {\n name: 'field_name',\n type: 'text',\n primary: true,\n required: true,\n },\n {\n name: 'language',\n type: 'text',\n primary: true,\n required: true,\n },\n {\n name: 'translation',\n type: 'text',\n required: true,\n },\n {\n name: 'record_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'record_sub_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'field_value',\n type: 'text',\n primary: true,\n },\n ],\n};\n","export const trips = {\n filenameBase: 'trips',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'route_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'service_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'trip_headsign',\n type: 'text',\n nocase: true,\n },\n {\n name: 'trip_short_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'block_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'shape_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'wheelchair_accessible',\n type: 'integer',\n min: 0,\n max: 2,\n },\n {\n name: 'bikes_allowed',\n type: 'integer',\n min: 0,\n max: 2,\n },\n ],\n};\n","export const timetables = {\n filenameBase: 'timetables',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'id',\n type: 'integer',\n primary: true,\n prefix: true,\n },\n {\n name: 'timetable_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'start_date',\n type: 'date',\n },\n {\n name: 'end_date',\n type: 'date',\n },\n {\n name: 'monday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'tuesday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'wednesday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'thursday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'friday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'saturday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'sunday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'start_time',\n type: 'text',\n },\n {\n name: 'start_timestamp',\n type: 'integer',\n },\n {\n name: 'end_time',\n type: 'text',\n },\n {\n name: 'end_timestamp',\n type: 'integer',\n },\n {\n name: 'timetable_label',\n type: 'text',\n nocase: true,\n },\n {\n name: 'service_notes',\n type: 'text',\n nocase: true,\n },\n {\n name: 'orientation',\n type: 'text',\n },\n {\n name: 'timetable_page_id',\n type: 'text',\n },\n {\n name: 'timetable_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n {\n name: 'direction_name',\n type: 'text',\n },\n {\n name: 'include_exceptions',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'show_trip_continuation',\n type: 'integer',\n min: 0,\n max: 1,\n },\n ],\n};\n","export const timetablePages = {\n filenameBase: 'timetable_pages',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'timetable_page_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'timetable_page_label',\n type: 'text',\n },\n {\n name: 'filename',\n type: 'text',\n },\n ],\n};\n","export const timetableStopOrder = {\n filenameBase: 'timetable_stop_order',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'id',\n type: 'integer',\n primary: true,\n prefix: true,\n },\n {\n name: 'timetable_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n ],\n};\n","export const timetableNotes = {\n filenameBase: 'timetable_notes',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'note_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'symbol',\n type: 'text',\n },\n {\n name: 'note',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const timetableNotesReferences = {\n filenameBase: 'timetable_notes_references',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'note_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'timetable_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n {\n name: 'show_on_stoptime',\n type: 'integer',\n min: 0,\n max: 1,\n },\n ],\n};\n","export const tripsDatedVehicleJourney = {\n filenameBase: 'trips_dated_vehicle_journey',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'operating_day_date',\n type: 'text',\n index: true,\n required: true,\n },\n {\n name: 'dated_vehicle_journey_gid',\n type: 'text',\n required: true,\n },\n {\n name: 'journey_number',\n type: 'integer',\n min: 0,\n max: 65535,\n index: true,\n },\n ],\n};\n","export const calendarAttributes = {\n filenameBase: 'calendar_attributes',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-plus',\n schema: [\n {\n name: 'service_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'service_description',\n type: 'text',\n required: true,\n nocase: true,\n },\n ],\n};\n","export const directions = {\n filenameBase: 'directions',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-plus',\n schema: [\n {\n name: 'route_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n primary: true,\n },\n {\n name: 'direction',\n type: 'text',\n required: true,\n },\n ],\n};\n","export const routeAttributes = {\n filenameBase: 'route_attributes',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-plus',\n schema: [\n {\n name: 'route_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'category',\n type: 'integer',\n min: 0,\n required: true,\n },\n {\n name: 'subcategory',\n type: 'integer',\n min: 101,\n required: true,\n },\n {\n name: 'running_way',\n type: 'integer',\n min: 1,\n required: true,\n },\n ],\n};\n","export const stopAttributes = {\n filenameBase: 'stop_attributes',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-plus',\n schema: [\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'accessibility_id',\n type: 'integer',\n min: 0,\n },\n {\n name: 'cardinal_direction',\n type: 'text',\n },\n {\n name: 'relative_position',\n type: 'text',\n },\n {\n name: 'stop_city',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const boardAlight = {\n filenameBase: 'board_alight',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n required: true,\n min: 0,\n index: true,\n },\n {\n name: 'record_use',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'schedule_relationship',\n type: 'integer',\n min: 0,\n max: 8,\n },\n {\n name: 'boardings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'alightings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'current_load',\n type: 'integer',\n min: 0,\n },\n {\n name: 'load_count',\n type: 'integer',\n min: 0,\n },\n {\n name: 'load_type',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'rack_down',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'bike_boardings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_alightings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'ramp_used',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'ramp_boardings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'ramp_alightings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'service_date',\n type: 'date',\n index: true,\n },\n {\n name: 'service_arrival_time',\n type: 'text',\n },\n {\n name: 'service_arrival_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'service_departure_time',\n type: 'text',\n },\n {\n name: 'service_departure_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'source',\n type: 'integer',\n min: 0,\n max: 4,\n },\n ],\n};\n","export const riderTrip = {\n filenameBase: 'rider_trip',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'rider_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'agency_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'boarding_stop_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'boarding_stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n {\n name: 'alighting_stop_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'alighting_stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n {\n name: 'service_date',\n type: 'date',\n index: true,\n },\n {\n name: 'boarding_time',\n type: 'text',\n },\n {\n name: 'boarding_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'alighting_time',\n type: 'text',\n },\n {\n name: 'alighting_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'rider_type',\n type: 'integer',\n min: 0,\n max: 13,\n },\n {\n name: 'rider_type_description',\n type: 'text',\n },\n {\n name: 'fare_paid',\n type: 'real',\n },\n {\n name: 'transaction_type',\n type: 'integer',\n min: 0,\n max: 8,\n },\n {\n name: 'fare_media',\n type: 'integer',\n min: 0,\n max: 9,\n },\n {\n name: 'accompanying_device',\n type: 'integer',\n min: 0,\n max: 6,\n },\n {\n name: 'transfer_status',\n type: 'integer',\n min: 0,\n max: 1,\n },\n ],\n};\n","export const ridership = {\n filenameBase: 'ridership',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'total_boardings',\n type: 'integer',\n min: 0,\n required: true,\n },\n {\n name: 'total_alightings',\n type: 'integer',\n min: 0,\n required: true,\n },\n {\n name: 'ridership_start_date',\n type: 'date',\n index: true,\n },\n {\n name: 'ridership_end_date',\n type: 'date',\n index: true,\n },\n {\n name: 'ridership_start_time',\n type: 'text',\n },\n {\n name: 'ridership_start_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'ridership_end_time',\n type: 'text',\n },\n {\n name: 'ridership_end_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'service_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'monday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'tuesday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'wednesday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'thursday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'friday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'saturday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'sunday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'agency_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n },\n ],\n};\n","export const tripCapacity = {\n filenameBase: 'trip_capacity',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'agency_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'service_date',\n type: 'date',\n index: true,\n },\n {\n name: 'vehicle_description',\n type: 'text',\n },\n {\n name: 'seated_capacity',\n type: 'integer',\n min: 0,\n },\n {\n name: 'standing_capacity',\n type: 'integer',\n min: 0,\n },\n {\n name: 'wheelchair_capacity',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_capacity',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const rideFeedInfo = {\n filenameBase: 'ride_feed_info',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'ride_files',\n type: 'integer',\n min: 0,\n max: 6,\n required: true,\n },\n {\n name: 'ride_start_date',\n type: 'date',\n index: true,\n },\n {\n name: 'ride_end_date',\n type: 'date',\n index: true,\n },\n {\n name: 'gtfs_feed_date',\n type: 'date',\n index: true,\n },\n {\n name: 'default_currency_type',\n type: 'text',\n },\n {\n name: 'ride_feed_version',\n type: 'text',\n },\n ],\n};\n","export const tripUpdates = {\n filenameBase: 'trip_updates',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'update_id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n },\n {\n name: 'vehicle_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.vehicle.id',\n default: null,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.trip.tripId',\n default: null,\n },\n {\n name: 'trip_start_time',\n type: 'text',\n source: 'tripUpdate.trip.startTime',\n default: null,\n },\n {\n name: 'direction_id',\n type: 'integer',\n source: 'tripUpdate.trip.directionId',\n default: null,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.trip.routeId',\n default: null,\n },\n {\n name: 'start_date',\n type: 'text',\n source: 'tripUpdate.trip.startDate',\n default: null,\n },\n {\n name: 'timestamp',\n type: 'text',\n source: 'tripUpdate.timestamp',\n default: null,\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n source: 'tripUpdate.trip.scheduleRelationship',\n default: null,\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const stopTimeUpdates = {\n filenameBase: 'stop_time_updates',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'parent.tripUpdate.trip.tripId',\n default: null,\n },\n {\n name: 'trip_start_time',\n type: 'text',\n source: 'parent.tripUpdate.trip.startTime',\n default: null,\n },\n {\n name: 'direction_id',\n type: 'integer',\n source: 'parent.tripUpdate.trip.directionId',\n default: null,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n source: 'parent.tripUpdate.trip.routeId',\n default: null,\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n source: 'stopId',\n default: null,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n source: 'stopSequence',\n default: null,\n },\n {\n name: 'arrival_delay',\n type: 'integer',\n source: 'arrival.delay',\n default: null,\n },\n {\n name: 'departure_delay',\n type: 'integer',\n source: 'departure.delay',\n default: null,\n },\n {\n name: 'departure_timestamp',\n type: 'text',\n source: 'departure.time',\n default: null,\n },\n {\n name: 'arrival_timestamp',\n type: 'text',\n source: 'arrival.time',\n default: null,\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n source: 'scheduleRelationship',\n default: null,\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const vehiclePositions = {\n filenameBase: 'vehicle_positions',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'update_id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n },\n {\n name: 'bearing',\n type: 'real',\n source: 'vehicle.position.bearing',\n default: null,\n },\n {\n name: 'latitude',\n type: 'real',\n min: -90,\n max: 90,\n source: 'vehicle.position.latitude',\n default: null,\n },\n {\n name: 'longitude',\n type: 'real',\n source: 'vehicle.position.longitude',\n min: -180,\n max: 180,\n default: null,\n },\n {\n name: 'speed',\n type: 'real',\n min: 0,\n source: 'vehicle.position.speed',\n default: null,\n },\n {\n name: 'current_stop_sequence',\n type: 'integer',\n source: 'vehicle.currentStopSequence',\n default: null,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'vehicle.trip.tripId',\n default: null,\n },\n {\n name: 'trip_start_date',\n type: 'text',\n index: true,\n source: 'vehicle.trip.startDate',\n default: null,\n },\n {\n name: 'trip_start_time',\n type: 'text',\n index: true,\n source: 'vehicle.trip.startTime',\n default: null,\n },\n {\n name: 'congestion_level',\n type: 'text',\n source: 'vehicle.congestionLevel',\n default: null,\n },\n {\n name: 'occupancy_status',\n type: 'text',\n source: 'vehicle.occupancyStatus',\n default: null,\n },\n {\n name: 'occupancy_percentage',\n type: 'integer',\n source: 'vehicle.occupancyPercentage',\n default: null,\n },\n {\n name: 'vehicle_stop_status',\n type: 'text',\n source: 'vehicle.vehicleStopStatus',\n default: null,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n index: true,\n source: 'vehicle.vehicle.id',\n default: null,\n },\n {\n name: 'vehicle_label',\n type: 'text',\n source: 'vehicle.vehicle.label',\n default: null,\n },\n {\n name: 'vehicle_license_plate',\n type: 'text',\n source: 'vehicle.vehicle.licensePlate',\n default: null,\n },\n {\n name: 'vehicle_wheelchair_accessible',\n type: 'text',\n source: 'vehicle.vehicle.wheelchairAccessible',\n default: null,\n },\n {\n name: 'timestamp',\n type: 'text',\n source: 'vehicle.timestamp',\n default: null,\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const serviceAlerts = {\n filenameBase: 'service_alerts',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n },\n {\n name: 'cause',\n type: 'integer',\n required: true,\n min: 0,\n source: 'alert.cause',\n default: 0,\n },\n {\n name: 'start_time',\n type: 'text',\n required: true,\n source: 'alert.activePeriod[0].start',\n default: '',\n },\n {\n name: 'end_time',\n type: 'text',\n required: true,\n source: 'alert.activePeriod[0].end',\n default: '',\n },\n {\n name: 'headline',\n type: 'text',\n required: true,\n source: 'alert.headerText.translation[0].text',\n default: '',\n },\n {\n name: 'description',\n type: 'text',\n required: true,\n source: 'alert.descriptionText.translation[0].text',\n default: '',\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const serviceAlertTargets = {\n filenameBase: 'service_alert_targets',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'alert_id',\n type: 'text',\n required: true,\n primary: true,\n source: 'parent.id',\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n source: 'stopId',\n default: null,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n source: 'routeId',\n default: null,\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const deadheadTimes = {\n filenameBase: 'deadhead_times',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'id',\n type: 'integer',\n primary: true,\n prefix: true,\n },\n {\n name: 'deadhead_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'arrival_time',\n type: 'text',\n required: true,\n },\n {\n name: 'arrival_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'departure_time',\n type: 'text',\n required: true,\n },\n {\n name: 'departure_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'ops_location_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'location_sequence',\n type: 'integer',\n required: true,\n min: 0,\n index: true,\n },\n {\n name: 'shape_dist_traveled',\n type: 'real',\n min: 0,\n },\n ],\n};\n","export const deadheads = {\n filenameBase: 'deadheads',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'deadhead_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'service_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'block_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'shape_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'to_trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'from_trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'to_deadhead_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'from_deadhead_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n ],\n};\n","export const opsLocations = {\n filenameBase: 'ops_locations',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'ops_location_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'ops_location_code',\n type: 'text',\n },\n {\n name: 'ops_location_name',\n type: 'text',\n required: true,\n nocase: true,\n },\n {\n name: 'ops_location_desc',\n type: 'text',\n nocase: true,\n },\n {\n name: 'ops_location_lat',\n type: 'real',\n required: true,\n min: -90,\n max: 90,\n },\n {\n name: 'ops_location_lon',\n type: 'real',\n required: true,\n min: -180,\n max: 180,\n },\n ],\n};\n","export const runEvents = {\n filenameBase: 'run_event',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'run_event_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'piece_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'event_type',\n type: 'integer',\n required: true,\n min: 0,\n index: true,\n },\n {\n name: 'event_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'event_time',\n type: 'text',\n required: true,\n },\n {\n name: 'event_duration',\n type: 'integer',\n required: true,\n min: 0,\n },\n {\n name: 'event_from_location_type',\n type: 'integer',\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'event_from_location_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'event_to_location_type',\n type: 'integer',\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'event_to_location_id',\n type: 'text',\n prefix: true,\n },\n ],\n};\n","export const runsPieces = {\n filenameBase: 'runs_pieces',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'run_id',\n type: 'text',\n required: true,\n },\n {\n name: 'piece_id',\n type: 'text',\n primary: true,\n required: true,\n },\n {\n name: 'start_type',\n type: 'integer',\n required: true,\n min: 0,\n max: 2,\n index: true,\n },\n {\n name: 'start_trip_id',\n type: 'text',\n required: true,\n index: true,\n },\n {\n name: 'start_trip_position',\n type: 'integer',\n min: 0,\n },\n {\n name: 'end_type',\n type: 'integer',\n required: true,\n min: 0,\n max: 2,\n index: true,\n },\n {\n name: 'end_trip_id',\n type: 'text',\n required: true,\n index: true,\n },\n {\n name: 'end_trip_position',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","import fs from 'fs';\n\nimport Database from 'better-sqlite3';\nimport untildify from 'untildify';\n\nconst dbs: { [key: string]: Database.Database } = {};\n\nfunction setupDb(sqlitePath: string) {\n const db = new Database(untildify(sqlitePath));\n db.pragma('journal_mode = OFF');\n db.pragma('synchronous = OFF');\n db.pragma('temp_store = MEMORY');\n dbs[sqlitePath] = db;\n\n return db;\n}\n\nexport function openDb(\n config: { db?: Database.Database; sqlitePath?: string } | null = null,\n): Database.Database {\n // If config is passed, use that to open or return db\n if (config) {\n const { sqlitePath = ':memory:', db } = config;\n\n // If db connection is passed, use it\n if (db) {\n return db;\n }\n\n // If db connection already exists, return it\n if (dbs[sqlitePath]) {\n return dbs[sqlitePath];\n }\n\n // If no db connection exists, create it\n return setupDb(sqlitePath);\n }\n\n // If no db connection exists, create a new one in memory\n if (Object.keys(dbs).length === 0) {\n return setupDb(':memory:');\n }\n\n // If only one db connection already exists, use it\n if (Object.keys(dbs).length === 1) {\n const filename = Object.keys(dbs)[0];\n return dbs[filename];\n }\n\n if (Object.keys(dbs).length > 1) {\n throw new Error(\n 'Multiple databases open, please specify which one to use.',\n );\n }\n\n throw new Error('Unable to find database connection.');\n}\n\nexport function closeDb(db: Database.Database | null = null): void {\n if (Object.keys(dbs).length === 0) {\n throw new Error(\n 'No database connection. Call `openDb(config)` before using any methods.',\n );\n }\n\n if (!db) {\n if (Object.keys(dbs).length > 1) {\n throw new Error(\n 'Multiple database connections. Pass the db you want to close as a parameter to `closeDb`.',\n );\n }\n\n db = dbs[Object.keys(dbs)[0]];\n }\n\n db.close();\n delete dbs[db.name];\n}\n\nexport function deleteDb(db: Database.Database | null = null): void {\n if (Object.keys(dbs).length === 0) {\n throw new Error(\n 'No database connection. Call `openDb(config)` before using any methods.',\n );\n }\n\n if (!db) {\n if (Object.keys(dbs).length > 1) {\n throw new Error(\n 'Multiple database connections. Pass the db you want to delete as a parameter to `deleteDb`.',\n );\n }\n\n db = dbs[Object.keys(dbs)[0]];\n }\n\n db.close();\n\n fs.unlinkSync(db.name);\n\n delete dbs[db.name];\n}\n","import {\n cloneDeep,\n compact,\n filter,\n groupBy,\n last,\n omit,\n sortBy,\n omitBy,\n} from 'lodash-es';\nimport { feature, featureCollection } from '@turf/helpers';\nimport { Shape, Stop } from '../types/global_interfaces.ts';\n\nexport function isValidJSON(string: string) {\n try {\n JSON.parse(string);\n } catch (error) {\n return false;\n }\n return true;\n}\n\ntype Position = [number, number];\n\nfunction isValidLineString(lineString?: Position[]) {\n if (!lineString) {\n return false;\n }\n\n if (lineString.length <= 1) {\n return false;\n }\n\n // Reject linestrings with two identical points\n if (\n lineString.length === 2 &&\n lineString[0][0] === lineString[1][0] &&\n lineString[0][1] === lineString[1][1]\n ) {\n return false;\n }\n\n return true;\n}\n\nfunction consolidateShapes(shapeGroups: Shape[][]) {\n const keys = new Set();\n const segmentsArray = shapeGroups.map((shapes) =>\n shapes.reduce(\n (\n memo: any[][][],\n point: { shape_pt_lon: number; shape_pt_lat: number },\n idx: number,\n ) => {\n if (idx > 0) {\n memo.push([\n [shapes[idx - 1].shape_pt_lon, shapes[idx - 1].shape_pt_lat],\n [point.shape_pt_lon, point.shape_pt_lat],\n ]);\n }\n\n return memo;\n },\n [],\n ),\n );\n\n const consolidatedLineStrings: number[][][] = [];\n\n for (const segments of segmentsArray) {\n consolidatedLineStrings.push([]);\n\n for (const segment of segments) {\n const key1 = `${segment[0][0]},${segment[0][1]},${segment[1][0]},${segment[1][1]}`;\n const key2 = `${segment[1][0]},${segment[1][1]},${segment[0][0]},${segment[0][1]}`;\n const currentLine: number[][] | undefined = last(consolidatedLineStrings);\n\n if (keys.has(key1) || keys.has(key2)) {\n consolidatedLineStrings.push([]);\n } else {\n // If its the first segment in a linestring, add both points\n if (currentLine?.length === 0) {\n currentLine.push(segment[0]);\n }\n\n currentLine?.push(segment[1]);\n keys.add(key1);\n keys.add(key2);\n }\n }\n }\n\n return filter(consolidatedLineStrings, isValidLineString);\n}\n\nfunction formatHexColor(color: null | undefined) {\n if (color === null || color === undefined) {\n return;\n }\n\n return `#${color}`;\n}\n\nfunction formatProperties(properties: Record<string, any>) {\n const formattedProperties: Record<string, any> = cloneDeep(\n omitBy(properties, (value) => value === null || value === undefined),\n );\n const formattedRouteColor = formatHexColor(properties.route_color);\n const formattedRouteTextColor = formatHexColor(properties.route_text_color);\n\n if (formattedRouteColor) {\n formattedProperties.route_color = formattedRouteColor;\n }\n\n if (formattedRouteTextColor) {\n formattedProperties.route_text_color = formattedRouteTextColor;\n }\n\n if (properties.routes) {\n formattedProperties.routes = properties.routes.map(\n (route: Record<string, any>) => formatProperties(route),\n );\n }\n\n return formattedProperties;\n}\n\nexport function shapesToGeoJSONFeature(shapes: Shape[], properties = {}) {\n const shapeGroups = Object.values(groupBy(shapes, 'shape_id')).map(\n (shapeGroup) => sortBy(shapeGroup, 'shape_pt_sequence'),\n );\n const lineStrings = consolidateShapes(shapeGroups) as Position[][];\n\n return feature(\n {\n type: 'MultiLineString',\n coordinates: lineStrings,\n },\n formatProperties(properties),\n );\n}\n\nexport function stopsToGeoJSONFeatureCollection(stops: Stop[]) {\n const features = compact(\n stops.map((stop) => {\n if (!stop.stop_lon || !stop.stop_lat) {\n return;\n }\n\n return feature(\n {\n type: 'Point',\n coordinates: [stop.stop_lon, stop.stop_lat],\n },\n formatProperties(omit(stop, ['stop_lat', 'stop_lon'])),\n );\n }),\n );\n\n return featureCollection(features);\n}\n","import pluralize from 'pluralize';\nimport GtfsRealtimeBindings from 'gtfs-realtime-bindings';\nimport sqlString from 'sqlstring-sqlite';\nimport mapSeries from 'promise-map-series';\n\nimport * as models from '../models/models.ts';\nimport { openDb } from './db.ts';\nimport {\n log as _log,\n logError as _logError,\n logWarning as _logWarning,\n} from './log-utils.ts';\nimport {\n convertLongTimeToDate,\n setDefaultConfig,\n validateConfigForImport,\n} from './utils.ts';\n\nimport {\n Config,\n ConfigAgency,\n ModelColumn,\n} from '../types/global_interfaces.ts';\n\ninterface GtfsRealtimeTask {\n realtimeAlerts?: {\n url: string;\n headers?: Record<string, string>;\n };\n realtimeTripUpdates?: {\n url: string;\n headers?: Record<string, string>;\n };\n realtimeVehiclePositions?: {\n url: string;\n headers?: Record<string, string>;\n };\n downloadTimeout?: number;\n gtfsRealtimeExpirationSeconds: number;\n ignoreErrors: boolean;\n sqlitePath: string;\n currentTimestamp: number;\n log: (message: string, newLine?: boolean) => void;\n logWarning: (message: string) => void;\n logError: (message: string) => void;\n}\n\nfunction getNestedProperty(obj: any, defaultValue: any, path?: string) {\n if (path === undefined) return defaultValue;\n const arr = path.split('.');\n while (arr.length) {\n const nextKey = arr.shift();\n if (nextKey === undefined) {\n return defaultValue;\n } else if (obj == null) {\n return defaultValue;\n } else if (nextKey?.includes('[')) {\n const arrayKey = nextKey.match(/(\\w*)\\[(\\d+)\\]/);\n if (arrayKey === null) {\n return defaultValue;\n }\n if (obj[arrayKey[1]] === undefined) {\n return defaultValue;\n }\n\n if (obj[arrayKey[1]][arrayKey[2]] === undefined) {\n return defaultValue;\n }\n\n obj = obj[arrayKey[1]][arrayKey[2]];\n } else {\n if (obj[nextKey] === undefined) {\n return defaultValue;\n }\n obj = obj[nextKey];\n }\n }\n\n if (obj.__isLong__) return convertLongTimeToDate(obj);\n\n return obj;\n}\n\nasync function fetchGtfsRealtimeData(\n urlConfig: { url: string; headers?: Record<string, string> },\n task: GtfsRealtimeTask,\n) {\n task.log(`Downloading GTFS-Realtime from ${urlConfig.url}`);\n const response = await fetch(urlConfig.url, {\n method: 'GET',\n headers: {\n ...(urlConfig.headers ?? {}),\n 'Accept-Encoding': 'gzip',\n },\n signal: task.downloadTimeout\n ? AbortSignal.timeout(task.downloadTimeout)\n : undefined,\n });\n\n if (response.status !== 200) {\n task.logWarning(\n `Unable to download GTFS-Realtime from ${urlConfig.url}. Got status ${response.status}.`,\n );\n return null;\n }\n\n const buffer = await response.arrayBuffer();\n const message = GtfsRealtimeBindings.transit_realtime.FeedMessage.decode(\n new Uint8Array(buffer),\n );\n return GtfsRealtimeBindings.transit_realtime.FeedMessage.toObject(message, {\n enums: String,\n longs: String,\n bytes: String,\n defaults: true,\n arrays: true,\n objects: true,\n oneofs: true,\n });\n}\n\nfunction removeExpiredRealtimeData(config: Config) {\n const log = _log(config);\n const db = openDb(config);\n\n log(`Removing expired GTFS-Realtime data`);\n db.prepare(\n `DELETE FROM vehicle_positions WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n db.prepare(\n `DELETE FROM trip_updates WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n db.prepare(\n `DELETE FROM stop_time_updates WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n db.prepare(\n `DELETE FROM service_alerts WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n db.prepare(\n `DELETE FROM service_alert_targets WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n log(`Removed expired GTFS-Realtime data\\r`, true);\n}\n\nfunction prepareRealtimeFieldValue(\n entity: any,\n column: ModelColumn,\n task: GtfsRealtimeTask,\n) {\n if (column.name === 'created_timestamp') {\n return task.currentTimestamp;\n }\n\n if (column.name === 'expiration_timestamp') {\n return task.currentTimestamp + task.gtfsRealtimeExpirationSeconds;\n }\n\n return sqlString.escape(\n getNestedProperty(entity, column.default, column.source),\n );\n}\n\nasync function processRealtimeAlerts(\n db: any,\n gtfsRealtimeData: any,\n task: GtfsRealtimeTask,\n) {\n task.log(`Download successful`);\n\n let totalLineCount = 0;\n\n for (const entity of gtfsRealtimeData.entity) {\n // Do base processing\n const fieldValues = models.serviceAlerts.schema.map((column: ModelColumn) =>\n prepareRealtimeFieldValue(entity, column, task),\n );\n\n try {\n db.prepare(\n `REPLACE INTO ${models.serviceAlerts.filenameBase} (${models.serviceAlerts.schema\n .map((column) => column.name)\n .join(', ')}) VALUES (${fieldValues.join(', ')})`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n const alertTargetArray = [];\n for (const informedEntity of entity.alert.informedEntity) {\n informedEntity.parent = entity;\n const subValues = models.serviceAlertTargets.schema.map((column) =>\n prepareRealtimeFieldValue(informedEntity, column, task),\n );\n alertTargetArray.push(`(${subValues.join(', ')})`);\n totalLineCount++;\n }\n\n try {\n db.prepare(\n `REPLACE INTO ${models.serviceAlertTargets.filenameBase} (${models.serviceAlertTargets.schema\n .map((column) => column.name)\n .join(', ')}) VALUES ${alertTargetArray.join(', ')}`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n task.log(`Importing - ${totalLineCount++} entries imported\\r`, true);\n }\n}\n\nasync function processRealtimeTripUpdates(\n db: any,\n gtfsRealtimeData: any,\n task: GtfsRealtimeTask,\n) {\n task.log(`Download successful`);\n\n let totalLineCount = 0;\n\n for (const entity of gtfsRealtimeData.entity) {\n // Do base processing\n const fieldValues = models.tripUpdates.schema.map((column: ModelColumn) =>\n prepareRealtimeFieldValue(entity, column, task),\n );\n\n try {\n db.prepare(\n `REPLACE INTO ${models.tripUpdates.filenameBase} (${models.tripUpdates.schema\n .map((column) => column.name)\n .join(', ')}) VALUES (${fieldValues.join(', ')})`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n const stopTimeUpdateArray = [];\n for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {\n stopTimeUpdate.parent = entity;\n const subValues = models.stopTimeUpdates.schema.map((column) =>\n prepareRealtimeFieldValue(stopTimeUpdate, column, task),\n );\n stopTimeUpdateArray.push(`(${subValues.join(', ')})`);\n totalLineCount++;\n }\n\n try {\n db.prepare(\n `REPLACE INTO ${models.stopTimeUpdates.filenameBase} (${models.stopTimeUpdates.schema\n .map((column) => column.name)\n .join(', ')}) VALUES ${stopTimeUpdateArray.join(', ')}`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n task.log(`Importing - ${totalLineCount++} entries imported\\r`, true);\n }\n}\n\nasync function processRealtimeVehiclePositions(\n db: any,\n gtfsRealtimeData: any,\n task: GtfsRealtimeTask,\n) {\n task.log(`Download successful`);\n\n let totalLineCount = 0;\n\n for (const entity of gtfsRealtimeData.entity) {\n // Do base processing\n const fieldValues = models.vehiclePositions.schema.map(\n (column: ModelColumn) => prepareRealtimeFieldValue(entity, column, task),\n );\n\n try {\n db.prepare(\n `REPLACE INTO ${models.vehiclePositions.filenameBase} (${models.vehiclePositions.schema\n .map((column) => column.name)\n .join(', ')}) VALUES (${fieldValues.join(', ')})`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n task.log(`Importing - ${totalLineCount++} entries imported\\r`, true);\n }\n}\n\nexport async function updateGtfsRealtimeData(task: GtfsRealtimeTask) {\n if (\n task.realtimeAlerts === undefined &&\n task.realtimeTripUpdates === undefined &&\n task.realtimeVehiclePositions === undefined\n ) {\n return;\n }\n\n const db = openDb({ sqlitePath: task.sqlitePath });\n\n if (task.realtimeAlerts?.url) {\n try {\n const alertsData = await fetchGtfsRealtimeData(task.realtimeAlerts, task);\n if (alertsData?.entity) {\n await processRealtimeAlerts(db, alertsData, task);\n }\n } catch (error: any) {\n if (task.ignoreErrors) {\n task.logError(error.message);\n } else {\n throw error;\n }\n }\n }\n\n if (task.realtimeTripUpdates?.url) {\n try {\n const tripUpdatesData = await fetchGtfsRealtimeData(\n task.realtimeTripUpdates,\n task,\n );\n if (tripUpdatesData?.entity) {\n await processRealtimeTripUpdates(db, tripUpdatesData, task);\n }\n } catch (error: any) {\n if (task.ignoreErrors) {\n task.logError(error.message);\n } else {\n throw error;\n }\n }\n }\n\n if (task.realtimeVehiclePositions?.url) {\n try {\n const vehiclePositionsData = await fetchGtfsRealtimeData(\n task.realtimeVehiclePositions,\n task,\n );\n if (vehiclePositionsData?.entity) {\n await processRealtimeVehiclePositions(db, vehiclePositionsData, task);\n }\n } catch (error: any) {\n if (task.ignoreErrors) {\n task.logError(error.message);\n } else {\n throw error;\n }\n }\n }\n\n task.log(`GTFS-Realtime data import complete`);\n}\n\nexport async function updateGtfsRealtime(initialConfig: Config) {\n const config = setDefaultConfig(initialConfig);\n validateConfigForImport(config);\n const log = _log(config);\n const logError = _logError(config);\n const logWarning = _logWarning(config);\n\n try {\n openDb(config);\n\n const agencyCount = config.agencies.length;\n log(\n `Starting GTFS-Realtime refresh for ${pluralize(\n 'agencies',\n agencyCount,\n true,\n )} using SQLite database at ${config.sqlitePath}`,\n );\n\n removeExpiredRealtimeData(config);\n\n await mapSeries(config.agencies, async (agency: ConfigAgency) => {\n try {\n const task = {\n realtimeAlerts: agency.realtimeAlerts,\n realtimeTripUpdates: agency.realtimeTripUpdates,\n realtimeVehiclePositions: agency.realtimeVehiclePositions,\n downloadTimeout: config.downloadTimeout,\n gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,\n ignoreErrors: config.ignoreErrors,\n sqlitePath: config.sqlitePath,\n currentTimestamp: Math.floor(Date.now() / 1000),\n log,\n logWarning,\n logError,\n };\n\n await updateGtfsRealtimeData(task);\n } catch (error: any) {\n if (config.ignoreErrors) {\n logError(error.message);\n } else {\n throw error;\n }\n }\n });\n\n log(\n `Completed GTFS-Realtime refresh for ${pluralize(\n 'agencies',\n agencyCount,\n true,\n )}\\n`,\n );\n } catch (error: any) {\n handleDatabaseError(error, config, logError);\n }\n}\n\nfunction handleDatabaseError(\n error: any,\n config: Config,\n logError: (message: string) => void,\n): void {\n if (error?.code === 'SQLITE_CANTOPEN') {\n logError(\n `Unable to open sqlite database \"${config.sqlitePath}\" defined as \\`sqlitePath\\` config.json. Ensure the parent directory exists or remove \\`sqlitePath\\` from config.json.`,\n );\n }\n throw error;\n}\n","import sqlString from 'sqlstring-sqlite';\nimport Long from 'long';\nimport {\n Config,\n JoinOptions,\n SqlWhere,\n SqlValue,\n SqlOrderBy,\n} from '../types/global_interfaces.ts';\n\n/*\n * Validate configuration.\n */\nexport function validateConfigForImport(config: Config) {\n if (!config.agencies || config.agencies.length === 0) {\n throw new Error('No `agencies` specified in config');\n }\n\n for (const [index, agency] of config.agencies.entries()) {\n if (!agency.path && !agency.url) {\n throw new Error(\n `No Agency \\`url\\` or \\`path\\` specified in config for agency index ${index}.`,\n );\n }\n }\n\n return config;\n}\n\n/*\n * Initialize configuration with defaults.\n */\nexport function setDefaultConfig(initialConfig: Config) {\n const defaults = {\n sqlitePath: ':memory:',\n ignoreDuplicates: false,\n ignoreErrors: false,\n gtfsRealtimeExpirationSeconds: 0,\n };\n\n return {\n ...defaults,\n ...initialConfig,\n };\n}\n\nexport function convertLongTimeToDate(longDate: {\n high: any;\n low: any;\n unsigned: any;\n}) {\n const { high, low, unsigned } = longDate;\n return new Date(new Long(low, high, unsigned).toInt() * 1000).toISOString();\n}\n\n/*\n * Calculate seconds from midnight for HH:mm:ss\n */\nexport function calculateSecondsFromMidnight(time: string) {\n const split = time.split(':').map((d) => Number.parseInt(d, 10));\n if (split.length !== 3) {\n return null;\n }\n\n return split[0] * 3600 + split[1] * 60 + split[2];\n}\n\n/*\n * Adds leading zeros to HH:mm:ss timestamps\n */\nexport function padLeadingZeros(time: string) {\n const split = time.split(':').map((d) => String(Number(d)).padStart(2, '0'));\n if (split.length !== 3) {\n return null;\n }\n\n return split.join(':');\n}\n\nexport function formatSelectClause(fields: string[]) {\n if (Array.isArray(fields)) {\n const selectItem =\n fields.length > 0\n ? fields.map((fieldName) => sqlString.escapeId(fieldName)).join(', ')\n : '*';\n return `SELECT ${selectItem}`;\n }\n\n const selectItem = Object.entries(fields)\n .map(\n (key) => `${sqlString.escapeId(key[0])} AS ${sqlString.escapeId(key[1])}`,\n )\n .join(', ');\n return `SELECT ${selectItem}`;\n}\n\nexport function formatJoinClause(joinObject: JoinOptions[]) {\n return joinObject\n .map(\n (data) =>\n `${data.type ? data.type + ' JOIN' : 'INNER JOIN'} ${sqlString.escapeId(\n data.table,\n )} ON ${data.on}`,\n )\n .join(' ');\n}\n\nfunction degree2radian(angle: number) {\n return (angle * Math.PI) / 180;\n}\n\nfunction radian2degree(angle: number) {\n return (angle / Math.PI) * 180;\n}\n\n/*\n * Search inside GPS coordinates boundary box\n * Distance unit: meters\n * */\nexport function formatWhereClauseBoundingBox(\n latitudeDegree: string | number,\n longitudeDegree: string | number,\n boundingBoxSideMeters: number,\n) {\n const earthRadius = 6371000;\n latitudeDegree =\n typeof latitudeDegree === 'string'\n ? parseFloat(latitudeDegree)\n : latitudeDegree;\n longitudeDegree =\n typeof longitudeDegree === 'string'\n ? parseFloat(longitudeDegree)\n : longitudeDegree;\n\n const latitudeRadian = degree2radian(latitudeDegree);\n const radiusFromLatitude = Math.cos(latitudeRadian) * earthRadius;\n\n // `boundingBoxSideMeters` is divided by 2 we are centering the coordinates in the middle of this square\n const deltaLatitude = radian2degree(boundingBoxSideMeters / 2 / earthRadius);\n const deltaLongitude = radian2degree(\n boundingBoxSideMeters / 2 / radiusFromLatitude,\n );\n\n let query = `stop_lat BETWEEN ${latitudeDegree - deltaLatitude} AND ${latitudeDegree + deltaLatitude}`;\n query += ` AND stop_lon BETWEEN ${longitudeDegree - deltaLongitude} AND ${longitudeDegree + deltaLongitude}`;\n\n return query;\n}\n\nexport function formatWhereClause(\n key: string,\n value: null | SqlValue | SqlValue[],\n) {\n if (Array.isArray(value)) {\n let whereClause = `${sqlString.escapeId(key)} IN (${value\n .filter((v) => v !== null)\n .map((v) => sqlString.escape(v))\n .join(', ')})`;\n\n if (value.includes(null)) {\n whereClause = `(${whereClause} OR ${sqlString.escapeId(key)} IS NULL)`;\n }\n\n return whereClause;\n }\n\n if (value === null) {\n return `${sqlString.escapeId(key)} IS NULL`;\n }\n\n return `${sqlString.escapeId(key)} = ${sqlString.escape(value)}`;\n}\n\nexport function formatWhereClauses(query: SqlWhere) {\n if (Object.keys(query).length === 0) {\n return '';\n }\n\n const whereClauses = Object.entries(query).map(([key, value]) =>\n formatWhereClause(key, value),\n );\n return `WHERE ${whereClauses.join(' AND ')}`;\n}\n\nexport function formatOrderByClause(orderBy: SqlOrderBy) {\n let orderByClause = '';\n\n if (orderBy.length > 0) {\n orderByClause += 'ORDER BY ';\n\n orderByClause += orderBy\n .map(([key, value]) => {\n const direction = value === 'DESC' ? 'DESC' : 'ASC';\n return `${sqlString.escapeId(key)} ${direction}`;\n })\n .join(', ');\n }\n\n return orderByClause;\n}\n\nexport function getDayOfWeekFromDate(date: number) {\n const daysOfWeek = [\n 'sunday',\n 'monday',\n 'tuesday',\n 'wednesday',\n 'thursday',\n 'friday',\n 'saturday',\n ];\n const dateString = date\n .toString()\n .replace(/(\\d{4})(\\d{2})(\\d{2})/, '$1-$2-$3');\n const [year, month, day] = dateString.split('-').map(Number);\n const dayOfWeek = new Date(year, month - 1, day).getDay();\n return daysOfWeek[dayOfWeek];\n}\n","import path from 'node:path';\nimport { writeFile } from 'node:fs/promises';\n\nimport { without, compact } from 'lodash-es';\nimport pluralize from 'pluralize';\nimport { stringify } from 'csv-stringify';\nimport sqlString from 'sqlstring-sqlite';\nimport Database from 'better-sqlite3';\nimport mapSeries from 'promise-map-series';\nimport untildify from 'untildify';\n\nimport * as models from '../models/models.ts';\nimport { openDb } from './db.ts';\nimport { prepDirectory, generateFolderName } from './file-utils.ts';\nimport { log as _log, logWarning as _logWarning } from './log-utils.ts';\nimport { setDefaultConfig } from './utils.ts';\n\nimport { Config, Model, SqlResults } from '../types/global_interfaces.ts';\n\nconst getAgencies = (db: Database.Database, config: Config) => {\n try {\n return db.prepare('SELECT agency_name FROM agency;').all() as {\n agency_name: string;\n }[];\n } catch (error) {\n if (config.sqlitePath === ':memory:') {\n throw new Error(\n 'No agencies found in SQLite. You are using an in-memory database - if running this from command line be sure to specify a value for `sqlitePath` in config.json other than \":memory:\".',\n );\n }\n\n throw new Error(\n 'No agencies found in SQLite. Be sure to first import data into SQLite using `gtfs-import` or `importGtfs(config);`',\n );\n }\n};\n\nexport const exportGtfs = async (initialConfig: Config) => {\n const config = setDefaultConfig(initialConfig);\n const log = _log(config);\n const logWarning = _logWarning(config);\n const db = openDb(config);\n\n // Get agency name for export folder from first line of agency.txt\n\n const agencies = getAgencies(db, config);\n const agencyCount = agencies.length;\n if (agencyCount === 0) {\n throw new Error(\n 'No agencies found in SQLite. Be sure to first import data into SQLite using `gtfs-import` or `importGtfs(config);`',\n );\n } else if (agencyCount > 1) {\n logWarning(\n 'More than one agency is defined in config.json. Export will merge all into one GTFS file.',\n );\n }\n\n log(\n `Starting GTFS export for ${pluralize(\n 'agency',\n agencyCount,\n true,\n )} using SQLite database at ${config.sqlitePath}`,\n );\n\n const folderName = generateFolderName(agencies[0].agency_name);\n const defaultExportPath = path.join(process.cwd(), 'gtfs-export', folderName);\n const exportPath = untildify(config.exportPath || defaultExportPath);\n\n await prepDirectory(exportPath);\n\n // Loop through each GTFS file\n const modelsToExport = Object.values(models).filter(\n (model: Model) => model.extension !== 'gtfs-realtime',\n );\n const exportedFiles = await mapSeries(\n modelsToExport,\n async (model: Model) => {\n const filePath = path.join(\n exportPath,\n `${model.filenameBase}.${model.filenameExtension}`,\n );\n const tableName = sqlString.escapeId(model.filenameBase);\n const lines = db\n .prepare(`SELECT * FROM ${tableName};`)\n .all() as SqlResults;\n\n if (!lines || lines.length === 0) {\n if (!model.nonstandard) {\n log(\n `Skipping (no data) - ${model.filenameBase}.${model.filenameExtension}\\r`,\n );\n }\n\n return;\n }\n\n if (model.filenameExtension === 'txt') {\n const excludeColumns = [\n 'id',\n 'arrival_timestamp',\n 'departure_timestamp',\n 'start_timestamp',\n 'end_timestamp',\n 'service_arrival_timestamp',\n 'service_departure_timestamp',\n 'boarding_timestamp',\n 'alighting_timestamp',\n 'ridership_start_timestamp',\n 'ridership_end_timestamp',\n ];\n\n // If no routes have values for agency_id, add it to the excludeColumns list\n if (model.filenameBase === 'routes') {\n const routesWithAgencyId = db\n .prepare(\n 'SELECT agency_id FROM routes WHERE agency_id IS NOT NULL;',\n )\n .all();\n if (!routesWithAgencyId || routesWithAgencyId.length === 0) {\n excludeColumns.push('agency_id');\n }\n }\n\n const columns = without(\n model.schema.map((column) => column.name),\n ...excludeColumns,\n );\n const fileText = await stringify(lines, { columns, header: true });\n await writeFile(filePath, fileText);\n } else if (model.filenameExtension === 'geojson') {\n const fileText = lines?.[0].geojson ?? '';\n await writeFile(filePath, fileText);\n } else {\n throw new Error(\n `Unexpected filename extension: ${model.filenameExtension}`,\n );\n }\n\n log(`Exporting - ${model.filenameBase}.${model.filenameExtension}\\r`);\n\n return `${model.filenameBase}.${model.filenameExtension}`;\n },\n );\n\n if (compact(exportedFiles).length === 0) {\n log('No GTFS data exported. Be sure to first import data into SQLite.');\n return;\n }\n\n log(`Completed GTFS export to ${exportPath}`);\n\n log(`Completed GTFS export for ${pluralize('agency', agencyCount, true)}\\n`);\n};\n","import sqlString from 'sqlstring-sqlite';\nimport Database from 'better-sqlite3';\n\nimport { openDb } from './db.ts';\n\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClauses,\n formatJoinClause,\n} from './utils.ts';\n\nimport {\n JoinOptions,\n QueryOptions,\n SqlOrderBy,\n SqlResults,\n SqlSelect,\n SqlWhere,\n} from '../types/global_interfaces.ts';\n\n/*\n * Returns an array of all agencies that match the query parameters.\n */\nexport function advancedQuery(\n table: string,\n advancedQueryOptions: {\n db?: Database.Database;\n query?: SqlWhere;\n fields?: SqlSelect;\n orderBy?: SqlOrderBy;\n join?: JoinOptions[];\n options?: QueryOptions;\n },\n): Array<Record<string, any>> {\n const defaultOptions: {\n query: SqlWhere;\n fields: SqlSelect;\n orderBy: SqlOrderBy;\n join: JoinOptions[];\n options: QueryOptions;\n } = {\n query: {},\n fields: [],\n orderBy: [],\n join: [],\n options: {},\n };\n const queryOptions = { ...defaultOptions, ...advancedQueryOptions };\n\n const db = queryOptions.options.db ?? openDb();\n const tableName = sqlString.escapeId(table);\n const selectClause = formatSelectClause(queryOptions.fields);\n const whereClause = formatWhereClauses(queryOptions.query);\n const joinClause = formatJoinClause(queryOptions.join);\n const orderByClause = formatOrderByClause(queryOptions.orderBy);\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${joinClause} ${whereClause} ${orderByClause};`,\n )\n .all() as SqlResults;\n}\n","import { omit, pick } from 'lodash-es';\n\nimport {\n QueryOptions,\n Route,\n SqlOrderBy,\n SqlSelect,\n SqlWhere,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n formatWhereClauses,\n} from '../utils.ts';\n\nfunction buildStoptimeSubquery(query: { [key: string]: string }) {\n const whereClause = formatWhereClauses(query);\n return `SELECT DISTINCT trip_id FROM stop_times ${whereClause}`;\n}\n\nfunction buildTripSubquery(query: { service_id?: string; stop_id?: string }) {\n let whereClause = '';\n const tripQuery = omit(query, ['stop_id']);\n const stoptimeQuery = pick(query, ['stop_id']);\n\n const whereClauses = Object.entries(tripQuery).map(([key, value]) =>\n formatWhereClause(key, value),\n );\n\n if (Object.values(stoptimeQuery).length > 0) {\n whereClauses.push(`trip_id IN (${buildStoptimeSubquery(stoptimeQuery)})`);\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return `SELECT DISTINCT route_id FROM trips ${whereClause}`;\n}\n\n/*\n * Returns an array of routes that match the query parameters. A `stop_id`\n * query parameter may be passed to find all routes that contain that stop.\n * A `service_id` query parameter may be passed to limit routes to specific\n * calendars.\n */\nexport function getRoutes(\n query: SqlWhere = {},\n fields: SqlSelect = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'routes';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const routeQuery = omit(query, ['stop_id', 'service_id']);\n const tripQuery: { stop_id?: any; service_id?: any } = pick(query, [\n 'stop_id',\n 'service_id',\n ]);\n\n const whereClauses = Object.entries(routeQuery).map(([key, value]) =>\n formatWhereClause(key, value),\n );\n\n if (Object.values(tripQuery).length > 0) {\n whereClauses.push(`route_id IN (${buildTripSubquery(tripQuery)})`);\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`,\n )\n .all() as Route[];\n}\n","import { compact, omit, pick } from 'lodash-es';\nimport { FeatureCollection } from 'geojson';\nimport { featureCollection } from '@turf/helpers';\n\nimport {\n QueryOptions,\n Shape,\n SqlOrderBy,\n SqlSelect,\n SqlWhere,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n formatWhereClauses,\n} from '../utils.ts';\nimport { shapesToGeoJSONFeature } from '../geojson-utils.ts';\nimport { getAgencies } from './agencies.ts';\nimport { getRoutes } from './routes.ts';\nimport { getRouteAttributes } from '../gtfs-plus/route-attributes.ts';\n\nfunction buildTripSubquery(query: { [key: string]: string }) {\n const whereClause = formatWhereClauses(query);\n return `SELECT DISTINCT shape_id FROM trips ${whereClause}`;\n}\n\n/*\n * Returns array of shapes that match the query parameters. A `route_id` query\n * parameter may be passed to find all shapes for a route. A `trip_id` query\n * parameter may be passed to find all shapes for a trip. A `direction_id`\n * query parameter may be passed to find all shapes for a direction.\n */\nexport function getShapes(\n query: SqlWhere = {},\n fields: SqlSelect = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'shapes';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const shapeQuery = omit(query, [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n ]);\n const tripQuery: {\n route_id?: any;\n trip_id?: any;\n service_id?: any;\n direction_id?: any;\n } = pick(query, ['route_id', 'trip_id', 'service_id', 'direction_id']);\n\n const whereClauses = Object.entries(shapeQuery).map(([key, value]) =>\n formatWhereClause(key, value),\n );\n\n if (Object.values(tripQuery).length > 0) {\n whereClauses.push(`shape_id IN (${buildTripSubquery(tripQuery)})`);\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`,\n )\n .all() as Shape[];\n}\n\n/*\n * Returns geoJSON of the shapes that match the query parameters. A `route_id`\n * query parameter may be passed to find all shapes for a route. A `trip_id`\n * query parameter may be passed to find all shapes for a trip. A\n * `direction_id` query parameter may be passed to find all shapes for a direction.\n */\nexport function getShapesAsGeoJSON(\n query: SqlWhere = {},\n options: QueryOptions = {},\n): FeatureCollection {\n const agencies = getAgencies({}, [], [], options);\n const routeQuery = pick(query, ['route_id']);\n const routes = getRoutes(routeQuery, [], [], options);\n const features = compact(\n routes.map((route) => {\n const shapeQuery = {\n route_id: route.route_id,\n ...omit(query, 'route_id'),\n };\n const shapes = getShapes(\n shapeQuery,\n ['shape_id', 'shape_pt_sequence', 'shape_pt_lon', 'shape_pt_lat'],\n [],\n options,\n );\n\n if (shapes.length === 0) {\n return;\n }\n\n const routeAttributes = getRouteAttributes(\n { route_id: route.route_id },\n [],\n [],\n options,\n );\n\n const agency = agencies.find(\n (agency) => agency.agency_id === route.agency_id,\n );\n\n const geojsonProperties = {\n agency_name: agency ? agency.agency_name : undefined,\n shape_id: query.shape_id,\n ...route,\n ...(routeAttributes?.[0] || []),\n };\n return shapesToGeoJSONFeature(shapes, geojsonProperties);\n }),\n );\n\n return featureCollection(features);\n}\n","import { omit, orderBy, pick } from 'lodash-es';\nimport { FeatureCollection } from 'geojson';\n\nimport {\n QueryOptions,\n SqlOrderBy,\n SqlSelect,\n SqlWhere,\n Stop,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n formatWhereClauseBoundingBox,\n formatWhereClauses,\n} from '../utils.ts';\nimport { stopsToGeoJSONFeatureCollection } from '../geojson-utils.ts';\nimport { getAgencies } from './agencies.ts';\nimport { getStopAttributes } from '../gtfs-plus/stop-attributes.ts';\n\nfunction buildTripSubquery(query: { [key: string]: string }) {\n const whereClause = formatWhereClauses(query);\n return `SELECT trip_id FROM trips ${whereClause}`;\n}\n\nfunction buildStoptimeSubquery(query: { [key: string]: string }) {\n return `SELECT DISTINCT stop_id FROM stop_times WHERE trip_id IN (${buildTripSubquery(\n query,\n )})`;\n}\n\n/*\n * Returns an array of stops that match the query parameters. A `route_id`\n * query parameter may be passed to find all shapes for a route. A `trip_id`\n * query parameter may be passed to find all shapes for a trip. A\n * `direction_id` query parameter may be passed to find all shapes for a\n * direction.\n */\nexport function getStops(\n query: SqlWhere = {},\n fields: SqlSelect = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'stops';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const stopQueryOmitKeys = [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n 'shape_id',\n ];\n\n // If bounding_box_side_m is defined, search for stops inside a bounding box so omit `stop_lat` and `stop_lon`.\n if (options.bounding_box_side_m !== undefined) {\n stopQueryOmitKeys.push('stop_lat', 'stop_lon');\n }\n\n let stopQuery = omit(query, stopQueryOmitKeys);\n\n const tripQuery: {\n route_id?: any;\n trip_id?: any;\n service_id?: any;\n direction_id?: any;\n shape_id?: any;\n } = pick(query, [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n 'shape_id',\n ]);\n\n const whereClauses = Object.entries(stopQuery).map(\n ([key, value]: [string, any]) => formatWhereClause(key, value),\n );\n\n if (\n options.bounding_box_side_m !== undefined &&\n query.stop_lat !== undefined &&\n query.stop_lon !== undefined\n ) {\n whereClauses.push(\n formatWhereClauseBoundingBox(\n query.stop_lat as number | string,\n query.stop_lon as number | string,\n options.bounding_box_side_m,\n ),\n );\n }\n\n if (Object.values(tripQuery).length > 0) {\n whereClauses.push(`stop_id IN (${buildStoptimeSubquery(tripQuery)})`);\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`,\n )\n .all() as Stop[];\n}\n\n/*\n * Returns geoJSON with stops. A `route_id` query parameter may be passed to\n * find all shapes for a route. A `trip_id` query parameter may be passed to\n * find all shapes for a trip. A `direction_id` query parameter may be passed\n * to find all shapes for a direction.\n */\nexport function getStopsAsGeoJSON(\n query: SqlWhere = {},\n options: QueryOptions = {},\n): FeatureCollection {\n const db = options.db ?? openDb();\n const stops = getStops(query, [], [], options);\n\n // Get all agencies for reference\n const agencies = getAgencies({}, [], [], options);\n\n const preparedStops = stops.map((stop) => {\n const routeSubquery =\n 'SELECT DISTINCT route_id FROM trips WHERE trip_id IN (SELECT DISTINCT trip_id FROM stop_times WHERE stop_id = ?)';\n const routes = db\n .prepare(`SELECT * FROM routes WHERE route_id IN (${routeSubquery})`)\n .all(stop.stop_id);\n\n const stopAttributes = getStopAttributes({ stop_id: stop.stop_id });\n\n return {\n ...stop,\n ...(stopAttributes?.[0] || []),\n routes: orderBy(routes, (route: { route_short_name?: string }) =>\n route?.route_short_name\n ? Number.parseInt(route.route_short_name, 10)\n : 0,\n ),\n agency_name: agencies[0].agency_name,\n };\n });\n\n // Exclude stops not part of any route\n const filteredStops = preparedStops.filter((stop) => stop.routes.length > 0);\n\n return stopsToGeoJSONFeatureCollection(filteredStops);\n}\n","import { omit } from 'lodash-es';\nimport sqlString from 'sqlstring-sqlite';\nimport {\n QueryOptions,\n SqlOrderBy,\n SqlSelect,\n SqlWhere,\n StopTime,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n calculateSecondsFromMidnight,\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n} from '../utils.ts';\nimport { getServiceIdsByDate } from './calendars.ts';\n\n/*\n * Returns an array of stoptimes that match the query parameters.\n */\nexport function getStoptimes(\n query: SqlWhere = {},\n fields: SqlSelect = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'stop_times';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const stoptimeQueryOmitKeys = ['date', 'start_time', 'end_time'];\n\n let stoptimeQuery = omit(query, stoptimeQueryOmitKeys);\n\n const whereClauses = Object.entries(stoptimeQuery).map(\n ([key, value]: [string, any]) => formatWhereClause(key, value),\n );\n\n if (query.date) {\n if (typeof query.date !== 'number') {\n throw new Error('`date` must be a number in yyyymmdd format');\n }\n\n const serviceIds = getServiceIdsByDate(query.date);\n\n const tripSubquery = `SELECT DISTINCT trip_id FROM trips WHERE service_id IN (${serviceIds.map((id) => sqlString.escape(id)).join(',')})`;\n\n whereClauses.push(`trip_id IN (${tripSubquery})`);\n }\n\n if (query.start_time) {\n if (typeof query.start_time !== 'string') {\n throw new Error('`start_time` must be a string in HH:mm:ss format');\n }\n\n whereClauses.push(\n `arrival_timestamp >= ${calculateSecondsFromMidnight(query.start_time)}`,\n );\n }\n\n if (query.end_time) {\n if (typeof query.end_time !== 'string') {\n throw new Error('`end_time` must be a string in HH:mm:ss format');\n }\n\n whereClauses.push(\n `departure_timestamp <= ${calculateSecondsFromMidnight(query.end_time)}`,\n );\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`,\n )\n .all() as StopTime[];\n}\n"],"mappings":"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","names":["argv","pluralize","untildify","mapSeries","untildify","omit","sqlString","path","compact","pluralize","sqlString","mapSeries","untildify","log","logWarning","pluralize","path","untildify","mapSeries","sqlString","compact","sqlString","omit","compact","omit","pick","featureCollection","omit","pick","omit","sqlString"]}
1
+ {"version":3,"sources":["../../src/bin/gtfs-export.ts","../../src/lib/file-utils.ts","../../src/lib/log-utils.ts","../../src/lib/import-gtfs.ts","../../src/models/models.ts","../../src/models/gtfs/agency.ts","../../src/models/gtfs/areas.ts","../../src/models/gtfs/attributions.ts","../../src/models/gtfs/booking-rules.ts","../../src/models/gtfs/calendar-dates.ts","../../src/models/gtfs/calendar.ts","../../src/models/gtfs/fare-attributes.ts","../../src/models/gtfs/fare-leg-rules.ts","../../src/models/gtfs/fare-media.ts","../../src/models/gtfs/fare-products.ts","../../src/models/gtfs/fare-rules.ts","../../src/models/gtfs/fare-transfer-rules.ts","../../src/models/gtfs/feed-info.ts","../../src/models/gtfs/frequencies.ts","../../src/models/gtfs/levels.ts","../../src/models/gtfs/location-groups.ts","../../src/models/gtfs/location-group-stops.ts","../../src/models/gtfs/locations.ts","../../src/models/gtfs/networks.ts","../../src/models/gtfs/pathways.ts","../../src/models/gtfs/route-networks.ts","../../src/models/gtfs/routes.ts","../../src/models/gtfs/shapes.ts","../../src/models/gtfs/stop-areas.ts","../../src/models/gtfs/stop-times.ts","../../src/models/gtfs/stops.ts","../../src/models/gtfs/timeframes.ts","../../src/models/gtfs/transfers.ts","../../src/models/gtfs/translations.ts","../../src/models/gtfs/trips.ts","../../src/models/non-standard/timetables.ts","../../src/models/non-standard/timetable-pages.ts","../../src/models/non-standard/timetable-stop-order.ts","../../src/models/non-standard/timetable-notes.ts","../../src/models/non-standard/timetable-notes-references.ts","../../src/models/non-standard/trips-dated-vehicle-journey.ts","../../src/models/gtfs-plus/calendar-attributes.ts","../../src/models/gtfs-plus/directions.ts","../../src/models/gtfs-plus/route-attributes.ts","../../src/models/gtfs-plus/stop-attributes.ts","../../src/models/gtfs-ride/board-alight.ts","../../src/models/gtfs-ride/rider-trip.ts","../../src/models/gtfs-ride/ridership.ts","../../src/models/gtfs-ride/trip-capacity.ts","../../src/models/gtfs-ride/ride-feed-info.ts","../../src/models/gtfs-realtime/trip-updates.ts","../../src/models/gtfs-realtime/stop-time-updates.ts","../../src/models/gtfs-realtime/vehicle-positions.ts","../../src/models/gtfs-realtime/service-alerts.ts","../../src/models/gtfs-realtime/service-alert-targets.ts","../../src/models/ods/deadhead-times.ts","../../src/models/ods/deadheads.ts","../../src/models/ods/ops-locations.ts","../../src/models/ods/run-events.ts","../../src/models/ods/runs-pieces.ts","../../src/lib/db.ts","../../src/lib/geojson-utils.ts","../../src/lib/import-gtfs-realtime.ts","../../src/lib/utils.ts","../../src/lib/export.ts","../../src/lib/advancedQuery.ts","../../src/lib/gtfs/routes.ts","../../src/lib/gtfs/shapes.ts","../../src/lib/gtfs/stops.ts","../../src/lib/gtfs/stop-times.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport PrettyError from 'pretty-error';\n\nimport { getConfig } from '../lib/file-utils.ts';\nimport { formatError } from '../lib/log-utils.ts';\nimport { exportGtfs } from '../index.ts';\n\nconst pe = new PrettyError();\n\nconst argv = yargs(hideBin(process.argv))\n .usage('Usage: $0 --configPath ./config.json')\n .help()\n .option('c', {\n alias: 'configPath',\n describe: 'Path to config file',\n type: 'string',\n })\n .option('sqlitePath', {\n describe: 'Path to SQLite database',\n type: 'string',\n })\n .parseSync();\n\nconst handleError = (error = 'Unknown Error') => {\n process.stdout.write(`\\n${formatError(error)}\\n`);\n console.error(pe.render(error));\n process.exit(1);\n};\n\nconst setupExport = async () => {\n const config = await getConfig(argv);\n await exportGtfs(config);\n process.exit();\n};\n\nsetupExport().catch(handleError);\n","import path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, rm } from 'node:fs/promises';\nimport { omit, snakeCase } from 'lodash-es';\nimport sanitize from 'sanitize-filename';\nimport untildify from 'untildify';\nimport StreamZip from 'node-stream-zip';\n\n/*\n * Attempt to parse any config JSON file and read values from CLI.\n */\nexport async function getConfig(argv: {\n configPath?: string;\n gtfsPath?: string;\n gtfsUrl?: string;\n sqlitePath?: string;\n}) {\n let config;\n let data;\n\n if (argv.configPath) {\n // If a `configPath` is specified, try to read it and throw error if it doesn't exist\n try {\n data = await readFile(path.resolve(untildify(argv.configPath)), 'utf8');\n } catch (error) {\n throw new Error(\n `Cannot find configuration file at \\`${argv.configPath}\\`. Use config-sample.json as a starting point.`,\n );\n }\n\n try {\n config = Object.assign(JSON.parse(data), argv);\n } catch (error) {\n throw new Error(\n `Cannot parse configuration file at \\`${argv.configPath}\\`. Check to ensure that it is valid JSON.`,\n );\n }\n } else if (argv.gtfsPath || argv.gtfsUrl || argv.sqlitePath) {\n // Use argv values from CLI\n const agencies = [];\n if (argv.gtfsPath) {\n agencies.push({\n path: argv.gtfsPath,\n });\n }\n\n if (argv.gtfsUrl) {\n agencies.push({\n url: argv.gtfsUrl,\n });\n }\n\n config = {\n agencies,\n ...omit(argv, ['path', 'url']),\n };\n } else if (existsSync(path.resolve('./config.json'))) {\n // Else if `config.json` exists, use config values read from it\n try {\n data = await readFile(path.resolve('./config.json'), 'utf8');\n } catch (error) {\n throw new Error(\n `Cannot open configuration file at \\`${path.resolve('./config.json')}\\`. Check to ensure that it exists. Use config-sample.json as a starting point.`,\n );\n }\n\n try {\n config = Object.assign(JSON.parse(data), argv);\n console.log('Using configuration from ./config.json');\n } catch (error) {\n throw new Error(\n `Cannot parse configuration file at \\`${path.resolve('./config.json')}\\`. Check to ensure that it is valid JSON.`,\n );\n }\n } else {\n throw new Error(\n 'Cannot find configuration file. Use config-sample.json as a starting point, pass --configPath option.',\n );\n }\n\n return config;\n}\n\n/*\n * Prepare the specified directory for saving HTML timetables by deleting\n * everything.\n */\nexport async function prepDirectory(exportPath: string) {\n await rm(exportPath, { recursive: true, force: true });\n await mkdir(exportPath, { recursive: true });\n}\n\n/*\n * Unzip a zipfile into a specified directory\n */\nexport async function unzip(zipfilePath: string, exportPath: string) {\n /* eslint-disable-next-line new-cap */\n const zip = new StreamZip.async({ file: zipfilePath });\n await zip.extract(null, exportPath);\n await zip.close();\n}\n\n/*\n * Generate a folder name based on a string.\n */\nexport function generateFolderName(folderName: string) {\n return snakeCase(sanitize(folderName));\n}\n","import { clearLine, cursorTo } from 'node:readline';\nimport { noop } from 'lodash-es';\nimport * as colors from 'yoctocolors';\nimport { Config } from '../types/global_interfaces.ts';\n\n/*\n * Returns a log function based on config settings\n */\nexport function log(config: Config) {\n if (config.verbose === false) {\n return noop;\n }\n\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string, overwrite?: boolean) => {\n if (overwrite === true && process.stdout.isTTY) {\n clearLine(process.stdout, 0);\n cursorTo(process.stdout, 0);\n } else {\n process.stdout.write('\\n');\n }\n\n process.stdout.write(text);\n };\n}\n\n/*\n * Returns an warning log function based on config settings\n */\nexport function logWarning(config: Config) {\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string) => {\n process.stdout.write(`\\n${formatWarning(text)}\\n`);\n };\n}\n\n/*\n * Returns an error log function based on config settings\n */\nexport function logError(config: Config) {\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string) => {\n process.stdout.write(`\\n${formatError(text)}\\n`);\n };\n}\n\n/*\n * Format console warning text\n */\nexport function formatWarning(text: string) {\n const warningMessage = `${colors.underline('Warning')}: ${text}`;\n return colors.yellow(warningMessage);\n}\n\n/*\n * Format console error text\n */\nexport function formatError(error: any) {\n const messageText = error instanceof Error ? error.message : error;\n const errorMessage = `${colors.underline('Error')}: ${messageText.replace(\n 'Error: ',\n '',\n )}`;\n return colors.red(errorMessage);\n}\n","import path from 'node:path';\nimport { createReadStream, existsSync, lstatSync } from 'node:fs';\nimport { cp, readdir, rename, readFile, rm, writeFile } from 'node:fs/promises';\nimport { parse } from 'csv-parse';\nimport pluralize from 'pluralize';\nimport stripBomStream from 'strip-bom-stream';\nimport { temporaryDirectory } from 'tempy';\nimport Timer from 'timer-machine';\nimport untildify from 'untildify';\nimport mapSeries from 'promise-map-series';\nimport Database from 'better-sqlite3';\n\nimport * as models from '../models/models.ts';\nimport { openDb } from './db.ts';\nimport { unzip } from './file-utils.ts';\nimport { isValidJSON } from './geojson-utils.ts';\nimport { updateGtfsRealtimeData } from './import-gtfs-realtime.ts';\nimport { log, logError, logWarning } from './log-utils.ts';\nimport {\n calculateSecondsFromMidnight,\n setDefaultConfig,\n validateConfigForImport,\n padLeadingZeros,\n} from './utils.ts';\n\nimport { Config, ConfigAgency, Model } from '../types/global_interfaces.ts';\n\ninterface GtfsImportTask {\n exclude?: string[];\n url?: string;\n headers?: Record<string, string>;\n realtimeAlerts?: {\n url: string;\n headers?: Record<string, string>;\n };\n realtimeTripUpdates?: {\n url: string;\n headers?: Record<string, string>;\n };\n realtimeVehiclePositions?: {\n url: string;\n headers?: Record<string, string>;\n };\n downloadDir: string;\n downloadTimeout?: number;\n gtfsRealtimeExpirationSeconds: number;\n path?: string;\n csvOptions: {};\n ignoreDuplicates: boolean;\n ignoreErrors: boolean;\n sqlitePath: string;\n prefix?: string;\n currentTimestamp: number;\n log: (message: string, newLine?: boolean) => void;\n logWarning: (message: string) => void;\n logError: (message: string) => void;\n}\n\ninterface Dictionary<T> {\n [key: string]: T;\n}\ntype Tuple = [seconds: number | null, date: string | null];\n\nconst dateCache: Dictionary<Tuple> = {};\n\nconst calculateAndCacheDate = (value: string): Tuple => {\n const cached = dateCache[value];\n if (cached != null) {\n return cached;\n }\n\n const seconds = calculateSecondsFromMidnight(value);\n const date = padLeadingZeros(value);\n const computed: Tuple = [seconds, date];\n dateCache[value] = computed;\n return computed;\n};\n\nconst getTextFiles = async (folderPath: string): Promise<string[]> => {\n const files = await readdir(folderPath);\n return files.filter((filename) => filename.slice(-3) === 'txt');\n};\n\nconst TIME_COLUMN_NAMES = [\n 'start_time',\n 'end_time',\n 'arrival_time',\n 'departure_time',\n 'prior_notice_last_time',\n 'prior_notice_start_time',\n 'start_pickup_drop_off_window',\n];\n\nconst TIME_COLUMN_PAIRS = TIME_COLUMN_NAMES.map((name) => [\n name,\n name.endsWith('time') ? `${name}stamp` : `${name}_timestamp`,\n]);\n\nconst downloadGtfsFiles = async (task: GtfsImportTask): Promise<void> => {\n if (!task.url) {\n throw new Error('No `url` specified in config');\n }\n\n task.log(`Downloading GTFS from ${task.url}`);\n\n task.path = `${task.downloadDir}/gtfs.zip`;\n\n const response = await fetch(task.url, {\n method: 'GET',\n headers: task.headers || {},\n signal: task.downloadTimeout\n ? AbortSignal.timeout(task.downloadTimeout)\n : undefined,\n });\n\n if (response.status !== 200) {\n throw new Error(\n `Unable to download GTFS from ${task.url}. Got status ${response.status}.`,\n );\n }\n\n const buffer = await response.arrayBuffer();\n\n await writeFile(task.path, Buffer.from(buffer));\n task.log('Download successful');\n};\n\nconst extractGtfsFiles = async (task: GtfsImportTask): Promise<void> => {\n if (!task.path) {\n throw new Error('No `path` specified in config');\n }\n\n const gtfsPath = untildify(task.path);\n task.log(`Importing GTFS from ${task.path}\\r`);\n if (path.extname(gtfsPath) === '.zip') {\n try {\n await unzip(gtfsPath, task.downloadDir);\n const textFiles = await getTextFiles(task.downloadDir);\n\n // If no .txt files in this directory, check for subdirectories and copy them here\n if (textFiles.length === 0) {\n const files = await readdir(task.downloadDir);\n // Ignore system directories within zip file\n const folders = files\n .filter((filename) => !['__MACOSX'].includes(filename))\n .map((filename) => path.join(task.downloadDir, filename))\n .filter((source) => lstatSync(source).isDirectory());\n\n if (folders.length > 1) {\n throw new Error(\n `More than one subfolder found in zip file at \\`${task.path}\\`. Ensure that .txt files are in the top level of the zip file, or in a single subdirectory.`,\n );\n } else if (folders.length === 0) {\n throw new Error(\n `No .txt files found in \\`${task.path}\\`. Ensure that .txt files are in the top level of the zip file, or in a single subdirectory.`,\n );\n }\n\n const subfolderName = folders[0];\n const directoryTextFiles = await getTextFiles(subfolderName);\n\n if (directoryTextFiles.length === 0) {\n throw new Error(\n `No .txt files found in \\`${task.path}\\`. Ensure that .txt files are in the top level of the zip file, or in a single subdirectory.`,\n );\n }\n\n await Promise.all(\n directoryTextFiles.map(async (fileName) =>\n rename(\n path.join(subfolderName, fileName),\n path.join(task.downloadDir, fileName),\n ),\n ),\n );\n }\n } catch (error: any) {\n task.logError(error);\n throw new Error(`Unable to unzip file ${task.path}`);\n }\n } else {\n // Local file is unzipped, just copy it from there.\n try {\n await cp(gtfsPath, task.downloadDir, { recursive: true });\n } catch {\n throw new Error(\n `Unable to load files from path \\`${gtfsPath}\\` defined in configuration. Verify that path exists and contains GTFS files.`,\n );\n }\n }\n};\n\nconst createGtfsTables = (db: Database.Database): void => {\n for (const model of Object.values(models) as Model[]) {\n if (!model.schema) {\n return;\n }\n\n const columns = model.schema.map((column) => {\n let check = '';\n if (column.min !== undefined && column.max) {\n check = `CHECK( ${column.name} >= ${column.min} AND ${column.name} <= ${column.max} )`;\n } else if (column.min) {\n check = `CHECK( ${column.name} >= ${column.min} )`;\n } else if (column.max) {\n check = `CHECK( ${column.name} <= ${column.max} )`;\n }\n\n const required = column.required ? 'NOT NULL' : '';\n const columnDefault = column.default ? 'DEFAULT ' + column.default : '';\n const columnCollation = column.nocase ? 'COLLATE NOCASE' : '';\n return `${column.name} ${column.type} ${check} ${required} ${columnDefault} ${columnCollation}`;\n });\n\n // Find Primary Key fields\n const primaryColumns = model.schema.filter((column) => column.primary);\n\n if (primaryColumns.length > 0) {\n columns.push(\n `PRIMARY KEY (${primaryColumns\n .map((column) => column.name)\n .join(', ')})`,\n );\n }\n\n db.prepare(`DROP TABLE IF EXISTS ${model.filenameBase};`).run();\n\n db.prepare(\n `CREATE TABLE ${model.filenameBase} (${columns.join(', ')});`,\n ).run();\n }\n};\n\nconst createGtfsIndexes = (db: Database.Database): void => {\n for (const model of Object.values(models) as Model[]) {\n if (!model.schema) {\n return;\n }\n for (const column of model.schema.filter((column) => column.index)) {\n db.prepare(\n `CREATE INDEX idx_${model.filenameBase}_${column.name} ON ${model.filenameBase} (${column.name});`,\n ).run();\n }\n }\n};\n\nconst formatGtfsLine = (\n line: { [x: string]: any; geojson?: string },\n model: Model,\n totalLineCount: number,\n): Record<string, any> => {\n const lineNumber = totalLineCount + 1;\n const formattedLine: Record<string, any> = {};\n\n // Pre-compute these values\n const filenameBase = model.filenameBase;\n const filenameExtension = model.filenameExtension;\n\n for (const columnSchema of model.schema) {\n const { name, type, required, min, max } = columnSchema;\n let value = line[name];\n\n // Early null check\n if (value === '' || value === undefined || value === null) {\n formattedLine[name] = null;\n if (required) {\n throw new Error(\n `Missing required value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`,\n );\n }\n continue;\n }\n\n // Type conversion\n switch (type) {\n case 'date':\n value = value.replace(/-/g, '');\n if (value.length !== 8) {\n throw new Error(\n `Invalid date in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`,\n );\n }\n value = parseInt(value, 10);\n break;\n case 'integer':\n value = parseInt(value, 10);\n break;\n case 'real':\n value = parseFloat(value);\n break;\n }\n\n // Check for NaN after conversion\n if (Number.isNaN(value)) {\n formattedLine[name] = null;\n continue;\n }\n\n formattedLine[name] = value;\n\n // Validate min/max\n if (min !== undefined && value < min) {\n throw new Error(\n `Invalid value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}: below minimum value of ${min}.`,\n );\n }\n if (max !== undefined && value > max) {\n throw new Error(\n `Invalid value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}: above maximum value of ${max}.`,\n );\n }\n }\n\n // Process time columns\n for (const [timeColumnName, timestampColumnName] of TIME_COLUMN_PAIRS) {\n const value = formattedLine[timeColumnName];\n if (value) {\n const [seconds, date] = calculateAndCacheDate(value);\n formattedLine[timestampColumnName] = seconds;\n formattedLine[timeColumnName] = date;\n }\n }\n\n return formattedLine;\n};\n\nconst BATCH_SIZE = 100_000;\n\nconst importGtfsFiles = (\n db: Database.Database,\n task: GtfsImportTask,\n): Promise<void[]> =>\n mapSeries(\n Object.values(models),\n (model: Model) =>\n new Promise<void>((resolve, reject) => {\n let totalLineCount = 0;\n const filename = `${model.filenameBase}.${model.filenameExtension}`;\n\n // Filter out excluded files from config\n if (task.exclude && task.exclude.includes(model.filenameBase)) {\n task.log(`Skipping - ${filename}\\r`);\n resolve();\n return;\n }\n\n // If the model is a database/gtfs-realtime model then skip silently\n if (model.extension === 'gtfs-realtime') {\n resolve();\n return;\n }\n\n const filepath = path.join(task.downloadDir, `${filename}`);\n\n // Log missing standard GTFS files, don't log nonstandard files\n if (!existsSync(filepath)) {\n if (!model.nonstandard) {\n task.log(`Importing - ${filename} - No file found\\r`);\n }\n\n resolve();\n return;\n }\n\n task.log(`Importing - ${filename}\\r`);\n\n const columns = model.schema.filter((column) => column.name !== 'id');\n const placeholder = columns.map(({ name }) => `@${name}`).join(', ');\n\n // Create a map of which columns need prefixing\n const prefixedColumns = new Set(\n columns.filter((col) => col.prefix).map((col) => col.name),\n );\n\n const prepareStatement = `INSERT ${task.ignoreDuplicates ? 'OR IGNORE' : ''} INTO ${\n model.filenameBase\n } (${columns\n .map((column) => column.name)\n .join(', ')}) VALUES (${placeholder})`;\n\n const insert = db.prepare(prepareStatement);\n\n const insertLines = db.transaction((lines) => {\n for (const [rowNumber, line] of Object.entries(lines)) {\n try {\n if (task.prefix === undefined) {\n insert.run(line);\n } else {\n const prefixedLine = Object.fromEntries(\n Object.entries(\n line as { [x: string]: any; geojson?: string },\n ).map(([columnName, value]) => [\n columnName,\n prefixedColumns.has(columnName) && value !== null\n ? `${task.prefix}${value}`\n : value,\n ]),\n );\n insert.run(prefixedLine);\n }\n } catch (error: any) {\n if (error.code === 'SQLITE_CONSTRAINT_PRIMARYKEY') {\n const primaryColumns = model.schema.filter(\n (column) => column.primary,\n );\n task.logWarning(\n `Duplicate values for primary key (${primaryColumns.map((column) => column.name).join(', ')}) found in ${filename}. Set the \\`ignoreDuplicates\\` option to true in config.json to ignore this error`,\n );\n }\n\n task.logWarning(\n `Check ${filename} for invalid data on row ${rowNumber}.`,\n );\n throw error;\n }\n }\n });\n\n if (model.filenameExtension === 'txt') {\n const parser = parse({\n columns: true,\n relax_quotes: true,\n trim: true,\n skip_empty_lines: true,\n ...task.csvOptions,\n });\n\n let lines: { [x: string]: any; geojson?: string }[] = [];\n\n parser.on('readable', () => {\n let record;\n\n while ((record = parser.read())) {\n totalLineCount += 1;\n lines.push(formatGtfsLine(record, model, totalLineCount));\n\n if (lines.length >= BATCH_SIZE) {\n try {\n insertLines(lines);\n lines = [];\n } catch (error) {\n reject(error);\n }\n\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n }\n }\n });\n\n parser.on('end', () => {\n try {\n if (lines.length > 0) {\n try {\n insertLines(lines);\n } catch (error) {\n reject(error);\n }\n }\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n resolve();\n } catch (error) {\n reject(error);\n }\n });\n\n parser.on('error', reject);\n\n createReadStream(filepath).pipe(stripBomStream()).pipe(parser);\n } else if (model.filenameExtension === 'geojson') {\n readFile(filepath, 'utf8')\n .then((data) => {\n if (isValidJSON(data) === false) {\n reject(new Error(`Invalid JSON in ${filename}`));\n }\n totalLineCount += 1;\n const line = formatGtfsLine(\n { geojson: data },\n model,\n totalLineCount,\n );\n insertLines([line]);\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n resolve();\n })\n .catch(reject);\n } else {\n reject(\n new Error(`Unsupported file type: ${model.filenameExtension}`),\n );\n }\n }),\n );\n\nexport async function importGtfs(initialConfig: Config): Promise<void> {\n const timer = new Timer();\n timer.start();\n\n const config = setDefaultConfig(initialConfig);\n validateConfigForImport(config);\n\n try {\n const db = openDb(config);\n const agencyCount = config.agencies.length;\n\n log(config)(\n `Starting GTFS import for ${pluralize('file', agencyCount, true)} using SQLite database at ${config.sqlitePath}`,\n );\n\n createGtfsTables(db);\n\n await mapSeries(config.agencies, async (agency: ConfigAgency) => {\n try {\n const tempPath = temporaryDirectory();\n\n const task = {\n exclude: agency.exclude,\n url: agency.url,\n headers: agency.headers,\n realtimeAlerts: agency.realtimeAlerts,\n realtimeTripUpdates: agency.realtimeTripUpdates,\n realtimeVehiclePositions: agency.realtimeVehiclePositions,\n downloadDir: tempPath,\n downloadTimeout: config.downloadTimeout,\n gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,\n path: agency.path,\n csvOptions: config.csvOptions || {},\n ignoreDuplicates: config.ignoreDuplicates,\n ignoreErrors: config.ignoreErrors,\n sqlitePath: config.sqlitePath,\n prefix: agency.prefix,\n currentTimestamp: Math.floor(Date.now() / 1000),\n log: log(config),\n logWarning: logWarning(config),\n logError: logError(config),\n };\n\n if (task.url) {\n await downloadGtfsFiles(task);\n }\n\n await extractGtfsFiles(task);\n await importGtfsFiles(db, task);\n await updateGtfsRealtimeData(task);\n\n await rm(tempPath, { recursive: true });\n } catch (error: any) {\n if (config.ignoreErrors) {\n logError(config)(error.message);\n } else {\n throw error;\n }\n }\n });\n\n log(config)(`Creating DB indexes`);\n createGtfsIndexes(db);\n\n const seconds = Math.round(timer.time() / 1000);\n timer.stop();\n\n log(config)(\n `Completed GTFS import for ${pluralize('agency', agencyCount, true)} in ${seconds} seconds\\n`,\n );\n } catch (error: any) {\n if (error?.code === 'SQLITE_CANTOPEN') {\n logError(config)(\n `Unable to open sqlite database \"${config.sqlitePath}\" defined as \\`sqlitePath\\` config.json. Ensure the parent directory exists or remove \\`sqlitePath\\` from config.json.`,\n );\n }\n throw error;\n }\n}\n","export { agency } from './gtfs/agency.ts';\nexport { areas } from './gtfs/areas.ts';\nexport { attributions } from './gtfs/attributions.ts';\nexport { bookingRules } from './gtfs/booking-rules.ts';\nexport { calendarDates } from './gtfs/calendar-dates.ts';\nexport { calendar } from './gtfs/calendar.ts';\nexport { fareAttributes } from './gtfs/fare-attributes.ts';\nexport { fareLegRules } from './gtfs/fare-leg-rules.ts';\nexport { fareMedia } from './gtfs/fare-media.ts';\nexport { fareProducts } from './gtfs/fare-products.ts';\nexport { fareRules } from './gtfs/fare-rules.ts';\nexport { fareTransferRules } from './gtfs/fare-transfer-rules.ts';\nexport { feedInfo } from './gtfs/feed-info.ts';\nexport { frequencies } from './gtfs/frequencies.ts';\nexport { levels } from './gtfs/levels.ts';\nexport { locationGroups } from './gtfs/location-groups.ts';\nexport { locationGroupStops } from './gtfs/location-group-stops.ts';\nexport { locations } from './gtfs/locations.ts';\nexport { networks } from './gtfs/networks.ts';\nexport { pathways } from './gtfs/pathways.ts';\nexport { routeNetworks } from './gtfs/route-networks.ts';\nexport { routes } from './gtfs/routes.ts';\nexport { shapes } from './gtfs/shapes.ts';\nexport { stopAreas } from './gtfs/stop-areas.ts';\nexport { stopTimes } from './gtfs/stop-times.ts';\nexport { stops } from './gtfs/stops.ts';\nexport { timeframes } from './gtfs/timeframes.ts';\nexport { transfers } from './gtfs/transfers.ts';\nexport { translations } from './gtfs/translations.ts';\nexport { trips } from './gtfs/trips.ts';\n\nexport { timetables } from './non-standard/timetables.ts';\nexport { timetablePages } from './non-standard/timetable-pages.ts';\nexport { timetableStopOrder } from './non-standard/timetable-stop-order.ts';\nexport { timetableNotes } from './non-standard/timetable-notes.ts';\nexport { timetableNotesReferences } from './non-standard/timetable-notes-references.ts';\nexport { tripsDatedVehicleJourney } from './non-standard/trips-dated-vehicle-journey.ts';\n\nexport { calendarAttributes } from './gtfs-plus/calendar-attributes.ts';\nexport { directions } from './gtfs-plus/directions.ts';\nexport { routeAttributes } from './gtfs-plus/route-attributes.ts';\nexport { stopAttributes } from './gtfs-plus/stop-attributes.ts';\n\nexport { boardAlight } from './gtfs-ride/board-alight.ts';\nexport { riderTrip } from './gtfs-ride/rider-trip.ts';\nexport { ridership } from './gtfs-ride/ridership.ts';\nexport { tripCapacity } from './gtfs-ride/trip-capacity.ts';\nexport { rideFeedInfo } from './gtfs-ride/ride-feed-info.ts';\n\nexport { tripUpdates } from './gtfs-realtime/trip-updates.ts';\nexport { stopTimeUpdates } from './gtfs-realtime/stop-time-updates.ts';\nexport { vehiclePositions } from './gtfs-realtime/vehicle-positions.ts';\nexport { serviceAlerts } from './gtfs-realtime/service-alerts.ts';\nexport { serviceAlertTargets } from './gtfs-realtime/service-alert-targets.ts';\n\nexport { deadheadTimes } from './ods/deadhead-times.ts';\nexport { deadheads } from './ods/deadheads.ts';\nexport { opsLocations } from './ods/ops-locations.ts';\nexport { runEvents } from './ods/run-events.ts';\nexport { runsPieces } from './ods/runs-pieces.ts';\n","export const agency = {\n filenameBase: 'agency',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'agency_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'agency_name',\n type: 'text',\n required: true,\n nocase: true,\n },\n {\n name: 'agency_url',\n type: 'text',\n required: true,\n },\n {\n name: 'agency_timezone',\n type: 'text',\n required: true,\n },\n {\n name: 'agency_lang',\n type: 'text',\n nocase: true,\n },\n {\n name: 'agency_phone',\n type: 'text',\n nocase: true,\n },\n {\n name: 'agency_fare_url',\n type: 'text',\n },\n {\n name: 'agency_email',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const areas = {\n filenameBase: 'areas',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'area_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'area_name',\n type: 'text',\n },\n ],\n};\n","export const attributions = {\n filenameBase: 'attributions',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'attribution_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'agency_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'organization_name',\n type: 'text',\n required: true,\n nocase: true,\n },\n {\n name: 'is_producer',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'is_operator',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'is_authority',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'attribution_url',\n type: 'text',\n },\n {\n name: 'attribution_email',\n type: 'text',\n nocase: true,\n },\n {\n name: 'attribution_phone',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const bookingRules = {\n filenameBase: 'booking_rules',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'booking_rule_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'booking_type',\n type: 'integer',\n required: true,\n min: 0,\n max: 2,\n },\n {\n name: 'prior_notice_duration_min',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_duration_max',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_last_day',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_last_time',\n type: 'text',\n },\n {\n name: 'prior_notice_last_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'prior_notice_start_day',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_start_time',\n type: 'text',\n },\n {\n name: 'prior_notice_start_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'prior_notice_service_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'message',\n type: 'text',\n nocase: true,\n },\n {\n name: 'pickup_message',\n type: 'text',\n nocase: true,\n },\n {\n name: 'drop_off_message',\n type: 'text',\n nocase: true,\n },\n {\n name: 'phone_number',\n type: 'text',\n nocase: true,\n },\n {\n name: 'info_url',\n type: 'text',\n },\n {\n name: 'booking_url',\n type: 'text',\n },\n ],\n};\n","export const calendarDates = {\n filenameBase: 'calendar_dates',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'service_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'date',\n type: 'date',\n required: true,\n primary: true,\n },\n {\n name: 'exception_type',\n type: 'integer',\n required: true,\n min: 1,\n max: 2,\n index: true,\n },\n {\n name: 'holiday_name',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const calendar = {\n filenameBase: 'calendar',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'service_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'monday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'tuesday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'wednesday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'thursday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'friday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'saturday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'sunday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'start_date',\n type: 'date',\n required: true,\n index: true,\n },\n {\n name: 'end_date',\n type: 'date',\n required: true,\n index: true,\n },\n ],\n};\n","export const fareAttributes = {\n filenameBase: 'fare_attributes',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'fare_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'price',\n type: 'real',\n required: true,\n },\n {\n name: 'currency_type',\n type: 'text',\n required: true,\n },\n {\n name: 'payment_method',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'transfers',\n type: 'integer',\n min: 0,\n max: 2,\n },\n {\n name: 'agency_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'transfer_duration',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const fareLegRules = {\n filenameBase: 'fare_leg_rules',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'leg_group_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'network_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'from_area_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_area_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'from_timeframe_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_timeframe_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'fare_product_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'rule_priority',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const fareMedia = {\n filenameBase: 'fare_media',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'fare_media_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'fare_media_name',\n type: 'text',\n },\n {\n name: 'fare_media_type',\n type: 'integer',\n required: true,\n min: 0,\n max: 4,\n },\n ],\n};\n","export const fareProducts = {\n filenameBase: 'fare_products',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'fare_product_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'fare_product_name',\n type: 'text',\n },\n {\n name: 'fare_media_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'amount',\n type: 'real',\n required: true,\n },\n {\n name: 'currency',\n type: 'text',\n required: true,\n },\n ],\n};\n","export const fareRules = {\n filenameBase: 'fare_rules',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'fare_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'origin_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'destination_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'contains_id',\n type: 'text',\n prefix: true,\n },\n ],\n};\n","export const fareTransferRules = {\n filenameBase: 'fare_transfer_rules',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'from_leg_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_leg_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'transfer_count',\n type: 'integer',\n min: -1,\n primary: true,\n },\n {\n name: 'duration_limit',\n type: 'integer',\n min: 0,\n primary: true,\n },\n {\n name: 'duration_limit_type',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'fare_transfer_type',\n type: 'integer',\n min: 0,\n max: 2,\n required: true,\n },\n {\n name: 'fare_product_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n ],\n};\n","export const feedInfo = {\n filenameBase: 'feed_info',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'feed_publisher_name',\n type: 'text',\n required: true,\n nocase: true,\n },\n {\n name: 'feed_publisher_url',\n type: 'text',\n required: true,\n },\n {\n name: 'feed_lang',\n type: 'text',\n required: true,\n },\n {\n name: 'default_lang',\n type: 'text',\n nocase: true,\n },\n {\n name: 'feed_start_date',\n type: 'date',\n },\n {\n name: 'feed_end_date',\n type: 'date',\n },\n {\n name: 'feed_version',\n type: 'text',\n },\n {\n name: 'feed_contact_email',\n type: 'text',\n nocase: true,\n },\n {\n name: 'feed_contact_url',\n type: 'text',\n },\n ],\n};\n","export const frequencies = {\n filenameBase: 'frequencies',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'start_time',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'start_timestamp',\n type: 'integer',\n },\n {\n name: 'end_time',\n type: 'text',\n required: true,\n },\n {\n name: 'end_timestamp',\n type: 'integer',\n },\n {\n name: 'headway_secs',\n type: 'integer',\n required: true,\n min: 0,\n },\n {\n name: 'exact_times',\n type: 'integer',\n min: 0,\n max: 1,\n },\n ],\n};\n","export const levels = {\n filenameBase: 'levels',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'level_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'level_index',\n type: 'real',\n required: true,\n },\n {\n name: 'level_name',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const locationGroups = {\n filenameBase: 'location_groups',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'location_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'location_group_name',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const locationGroupStops = {\n filenameBase: 'location_group_stops',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'location_group_id',\n type: 'text',\n prefix: true,\n index: true,\n required: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n prefix: true,\n index: true,\n },\n ],\n};\n","export const locations = {\n filenameBase: 'locations',\n filenameExtension: 'geojson',\n schema: [\n {\n name: 'geojson',\n type: 'text',\n },\n ],\n};\n","export const networks = {\n filenameBase: 'networks',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'network_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'network_name',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const pathways = {\n filenameBase: 'pathways',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'pathway_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'from_stop_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'to_stop_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'pathway_mode',\n type: 'integer',\n required: true,\n min: 1,\n max: 7,\n },\n {\n name: 'is_bidirectional',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'length',\n type: 'real',\n min: 0,\n },\n {\n name: 'traversal_time',\n type: 'integer',\n min: 0,\n },\n {\n name: 'stair_count',\n type: 'integer',\n },\n {\n name: 'max_slope',\n type: 'real',\n },\n {\n name: 'min_width',\n type: 'real',\n min: 0,\n },\n {\n name: 'signposted_as',\n type: 'text',\n nocase: true,\n },\n {\n name: 'reversed_signposted_as',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const routeNetworks = {\n filenameBase: 'route_networks',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'network_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n primary: true,\n index: true,\n prefix: true,\n },\n ],\n};\n","export const routes = {\n filenameBase: 'routes',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'route_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'agency_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'route_short_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_long_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_desc',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_type',\n type: 'integer',\n required: true,\n min: 0,\n // Support extended GTFS route types with no max value\n // https://developers.google.com/transit/gtfs/reference/extended-route-types\n },\n {\n name: 'route_url',\n type: 'text',\n },\n {\n name: 'route_color',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_text_color',\n type: 'text',\n nocase: true,\n },\n {\n name: 'route_sort_order',\n type: 'integer',\n min: 0,\n },\n {\n name: 'continuous_pickup',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'continuous_drop_off',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'network_id',\n type: 'text',\n prefix: true,\n },\n ],\n};\n","export const shapes = {\n filenameBase: 'shapes',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'shape_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'shape_pt_lat',\n type: 'real',\n required: true,\n min: -90,\n max: 90,\n },\n {\n name: 'shape_pt_lon',\n type: 'real',\n required: true,\n min: -180,\n max: 180,\n },\n {\n name: 'shape_pt_sequence',\n type: 'integer',\n required: true,\n primary: true,\n min: 0,\n },\n {\n name: 'shape_dist_traveled',\n type: 'real',\n min: 0,\n },\n ],\n};\n","export const stopAreas = {\n filenameBase: 'stop_areas',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'area_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n ],\n};\n","export const stopTimes = {\n filenameBase: 'stop_times',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'arrival_time',\n type: 'text',\n },\n {\n name: 'arrival_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'departure_time',\n type: 'text',\n },\n {\n name: 'departure_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'location_group_id',\n type: 'text',\n prefix: true,\n index: true,\n },\n {\n name: 'location_id',\n type: 'text',\n prefix: true,\n index: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n prefix: true,\n index: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n required: true,\n primary: true,\n min: 0,\n },\n {\n name: 'stop_headsign',\n type: 'text',\n nocase: true,\n },\n {\n name: 'start_pickup_drop_off_window',\n type: 'text',\n },\n {\n name: 'start_pickup_drop_off_window_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'pickup_type',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'drop_off_type',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'continuous_pickup',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'continuous_drop_off',\n type: 'integer',\n min: 0,\n max: 3,\n },\n {\n name: 'shape_dist_traveled',\n type: 'real',\n min: 0,\n },\n {\n name: 'timepoint',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'pickup_booking_rule_id',\n type: 'text',\n prefix: true,\n index: true,\n },\n {\n name: 'drop_off_booking_rule_id',\n type: 'text',\n prefix: true,\n index: true,\n },\n ],\n};\n","export const stops = {\n filenameBase: 'stops',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'stop_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'stop_code',\n type: 'text',\n },\n {\n name: 'stop_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'tts_stop_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'stop_desc',\n type: 'text',\n nocase: true,\n },\n {\n name: 'stop_lat',\n type: 'real',\n min: -90,\n max: 90,\n },\n {\n name: 'stop_lon',\n type: 'real',\n min: -180,\n max: 180,\n },\n {\n name: 'zone_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'stop_url',\n type: 'text',\n },\n {\n name: 'location_type',\n type: 'integer',\n min: 0,\n max: 4,\n },\n {\n name: 'parent_station',\n type: 'text',\n index: true,\n },\n {\n name: 'stop_timezone',\n type: 'text',\n },\n {\n name: 'wheelchair_boarding',\n type: 'integer',\n min: 0,\n max: 2,\n },\n {\n name: 'level_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'platform_code',\n type: 'text',\n },\n ],\n};\n","export const timeframes = {\n filenameBase: 'timeframes',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'timeframe_group_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'start_time',\n type: 'text',\n },\n {\n name: 'end_time',\n type: 'text',\n },\n {\n name: 'service_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n ],\n};\n","export const transfers = {\n filenameBase: 'transfers',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'from_stop_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_stop_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'from_route_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_route_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'from_trip_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'to_trip_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'transfer_type',\n type: 'integer',\n min: 0,\n max: 5,\n default: 0,\n },\n {\n name: 'min_transfer_time',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const translations = {\n filenameBase: 'translations',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'table_name',\n type: 'text',\n primary: true,\n required: true,\n },\n {\n name: 'field_name',\n type: 'text',\n primary: true,\n required: true,\n },\n {\n name: 'language',\n type: 'text',\n primary: true,\n required: true,\n },\n {\n name: 'translation',\n type: 'text',\n required: true,\n },\n {\n name: 'record_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'record_sub_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'field_value',\n type: 'text',\n primary: true,\n },\n ],\n};\n","export const trips = {\n filenameBase: 'trips',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'route_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'service_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'trip_headsign',\n type: 'text',\n nocase: true,\n },\n {\n name: 'trip_short_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'block_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'shape_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'wheelchair_accessible',\n type: 'integer',\n min: 0,\n max: 2,\n },\n {\n name: 'bikes_allowed',\n type: 'integer',\n min: 0,\n max: 2,\n },\n ],\n};\n","export const timetables = {\n filenameBase: 'timetables',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'id',\n type: 'integer',\n primary: true,\n prefix: true,\n },\n {\n name: 'timetable_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'start_date',\n type: 'date',\n },\n {\n name: 'end_date',\n type: 'date',\n },\n {\n name: 'monday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'tuesday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'wednesday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'thursday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'friday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'saturday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'sunday',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n },\n {\n name: 'start_time',\n type: 'text',\n },\n {\n name: 'start_timestamp',\n type: 'integer',\n },\n {\n name: 'end_time',\n type: 'text',\n },\n {\n name: 'end_timestamp',\n type: 'integer',\n },\n {\n name: 'timetable_label',\n type: 'text',\n nocase: true,\n },\n {\n name: 'service_notes',\n type: 'text',\n nocase: true,\n },\n {\n name: 'orientation',\n type: 'text',\n },\n {\n name: 'timetable_page_id',\n type: 'text',\n },\n {\n name: 'timetable_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n {\n name: 'direction_name',\n type: 'text',\n },\n {\n name: 'include_exceptions',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'show_trip_continuation',\n type: 'integer',\n min: 0,\n max: 1,\n },\n ],\n};\n","export const timetablePages = {\n filenameBase: 'timetable_pages',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'timetable_page_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'timetable_page_label',\n type: 'text',\n },\n {\n name: 'filename',\n type: 'text',\n },\n ],\n};\n","export const timetableStopOrder = {\n filenameBase: 'timetable_stop_order',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'id',\n type: 'integer',\n primary: true,\n prefix: true,\n },\n {\n name: 'timetable_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n ],\n};\n","export const timetableNotes = {\n filenameBase: 'timetable_notes',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'note_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'symbol',\n type: 'text',\n },\n {\n name: 'note',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const timetableNotesReferences = {\n filenameBase: 'timetable_notes_references',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'note_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'timetable_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n {\n name: 'show_on_stoptime',\n type: 'integer',\n min: 0,\n max: 1,\n },\n ],\n};\n","export const tripsDatedVehicleJourney = {\n filenameBase: 'trips_dated_vehicle_journey',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'operating_day_date',\n type: 'text',\n index: true,\n required: true,\n },\n {\n name: 'dated_vehicle_journey_gid',\n type: 'text',\n required: true,\n },\n {\n name: 'journey_number',\n type: 'integer',\n min: 0,\n max: 65535,\n index: true,\n },\n ],\n};\n","export const calendarAttributes = {\n filenameBase: 'calendar_attributes',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-plus',\n schema: [\n {\n name: 'service_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'service_description',\n type: 'text',\n required: true,\n nocase: true,\n },\n ],\n};\n","export const directions = {\n filenameBase: 'directions',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-plus',\n schema: [\n {\n name: 'route_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n primary: true,\n },\n {\n name: 'direction',\n type: 'text',\n required: true,\n },\n ],\n};\n","export const routeAttributes = {\n filenameBase: 'route_attributes',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-plus',\n schema: [\n {\n name: 'route_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'category',\n type: 'integer',\n min: 0,\n required: true,\n },\n {\n name: 'subcategory',\n type: 'integer',\n min: 101,\n required: true,\n },\n {\n name: 'running_way',\n type: 'integer',\n min: 1,\n required: true,\n },\n ],\n};\n","export const stopAttributes = {\n filenameBase: 'stop_attributes',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-plus',\n schema: [\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'accessibility_id',\n type: 'integer',\n min: 0,\n },\n {\n name: 'cardinal_direction',\n type: 'text',\n },\n {\n name: 'relative_position',\n type: 'text',\n },\n {\n name: 'stop_city',\n type: 'text',\n nocase: true,\n },\n ],\n};\n","export const boardAlight = {\n filenameBase: 'board_alight',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n required: true,\n min: 0,\n index: true,\n },\n {\n name: 'record_use',\n type: 'integer',\n required: true,\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'schedule_relationship',\n type: 'integer',\n min: 0,\n max: 8,\n },\n {\n name: 'boardings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'alightings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'current_load',\n type: 'integer',\n min: 0,\n },\n {\n name: 'load_count',\n type: 'integer',\n min: 0,\n },\n {\n name: 'load_type',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'rack_down',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'bike_boardings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_alightings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'ramp_used',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'ramp_boardings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'ramp_alightings',\n type: 'integer',\n min: 0,\n },\n {\n name: 'service_date',\n type: 'date',\n index: true,\n },\n {\n name: 'service_arrival_time',\n type: 'text',\n },\n {\n name: 'service_arrival_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'service_departure_time',\n type: 'text',\n },\n {\n name: 'service_departure_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'source',\n type: 'integer',\n min: 0,\n max: 4,\n },\n ],\n};\n","export const riderTrip = {\n filenameBase: 'rider_trip',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'rider_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'agency_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'boarding_stop_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'boarding_stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n {\n name: 'alighting_stop_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'alighting_stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n },\n {\n name: 'service_date',\n type: 'date',\n index: true,\n },\n {\n name: 'boarding_time',\n type: 'text',\n },\n {\n name: 'boarding_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'alighting_time',\n type: 'text',\n },\n {\n name: 'alighting_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'rider_type',\n type: 'integer',\n min: 0,\n max: 13,\n },\n {\n name: 'rider_type_description',\n type: 'text',\n },\n {\n name: 'fare_paid',\n type: 'real',\n },\n {\n name: 'transaction_type',\n type: 'integer',\n min: 0,\n max: 8,\n },\n {\n name: 'fare_media',\n type: 'integer',\n min: 0,\n max: 9,\n },\n {\n name: 'accompanying_device',\n type: 'integer',\n min: 0,\n max: 6,\n },\n {\n name: 'transfer_status',\n type: 'integer',\n min: 0,\n max: 1,\n },\n ],\n};\n","export const ridership = {\n filenameBase: 'ridership',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'total_boardings',\n type: 'integer',\n min: 0,\n required: true,\n },\n {\n name: 'total_alightings',\n type: 'integer',\n min: 0,\n required: true,\n },\n {\n name: 'ridership_start_date',\n type: 'date',\n index: true,\n },\n {\n name: 'ridership_end_date',\n type: 'date',\n index: true,\n },\n {\n name: 'ridership_start_time',\n type: 'text',\n },\n {\n name: 'ridership_start_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'ridership_end_time',\n type: 'text',\n },\n {\n name: 'ridership_end_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'service_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'monday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'tuesday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'wednesday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'thursday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'friday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'saturday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'sunday',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'agency_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n },\n ],\n};\n","export const tripCapacity = {\n filenameBase: 'trip_capacity',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'agency_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'service_date',\n type: 'date',\n index: true,\n },\n {\n name: 'vehicle_description',\n type: 'text',\n },\n {\n name: 'seated_capacity',\n type: 'integer',\n min: 0,\n },\n {\n name: 'standing_capacity',\n type: 'integer',\n min: 0,\n },\n {\n name: 'wheelchair_capacity',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_capacity',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const rideFeedInfo = {\n filenameBase: 'ride_feed_info',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'gtfs-ride',\n schema: [\n {\n name: 'ride_files',\n type: 'integer',\n min: 0,\n max: 6,\n required: true,\n },\n {\n name: 'ride_start_date',\n type: 'date',\n index: true,\n },\n {\n name: 'ride_end_date',\n type: 'date',\n index: true,\n },\n {\n name: 'gtfs_feed_date',\n type: 'date',\n index: true,\n },\n {\n name: 'default_currency_type',\n type: 'text',\n },\n {\n name: 'ride_feed_version',\n type: 'text',\n },\n ],\n};\n","export const tripUpdates = {\n filenameBase: 'trip_updates',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'update_id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n },\n {\n name: 'vehicle_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.vehicle.id',\n default: null,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.trip.tripId',\n default: null,\n },\n {\n name: 'trip_start_time',\n type: 'text',\n source: 'tripUpdate.trip.startTime',\n default: null,\n },\n {\n name: 'direction_id',\n type: 'integer',\n source: 'tripUpdate.trip.directionId',\n default: null,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.trip.routeId',\n default: null,\n },\n {\n name: 'start_date',\n type: 'text',\n source: 'tripUpdate.trip.startDate',\n default: null,\n },\n {\n name: 'timestamp',\n type: 'text',\n source: 'tripUpdate.timestamp',\n default: null,\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n source: 'tripUpdate.trip.scheduleRelationship',\n default: null,\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const stopTimeUpdates = {\n filenameBase: 'stop_time_updates',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'parent.tripUpdate.trip.tripId',\n default: null,\n },\n {\n name: 'trip_start_time',\n type: 'text',\n source: 'parent.tripUpdate.trip.startTime',\n default: null,\n },\n {\n name: 'direction_id',\n type: 'integer',\n source: 'parent.tripUpdate.trip.directionId',\n default: null,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n source: 'parent.tripUpdate.trip.routeId',\n default: null,\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n source: 'stopId',\n default: null,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n source: 'stopSequence',\n default: null,\n },\n {\n name: 'arrival_delay',\n type: 'integer',\n source: 'arrival.delay',\n default: null,\n },\n {\n name: 'departure_delay',\n type: 'integer',\n source: 'departure.delay',\n default: null,\n },\n {\n name: 'departure_timestamp',\n type: 'text',\n source: 'departure.time',\n default: null,\n },\n {\n name: 'arrival_timestamp',\n type: 'text',\n source: 'arrival.time',\n default: null,\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n source: 'scheduleRelationship',\n default: null,\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const vehiclePositions = {\n filenameBase: 'vehicle_positions',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'update_id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n },\n {\n name: 'bearing',\n type: 'real',\n source: 'vehicle.position.bearing',\n default: null,\n },\n {\n name: 'latitude',\n type: 'real',\n min: -90,\n max: 90,\n source: 'vehicle.position.latitude',\n default: null,\n },\n {\n name: 'longitude',\n type: 'real',\n source: 'vehicle.position.longitude',\n min: -180,\n max: 180,\n default: null,\n },\n {\n name: 'speed',\n type: 'real',\n min: 0,\n source: 'vehicle.position.speed',\n default: null,\n },\n {\n name: 'current_stop_sequence',\n type: 'integer',\n source: 'vehicle.currentStopSequence',\n default: null,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'vehicle.trip.tripId',\n default: null,\n },\n {\n name: 'trip_start_date',\n type: 'text',\n index: true,\n source: 'vehicle.trip.startDate',\n default: null,\n },\n {\n name: 'trip_start_time',\n type: 'text',\n index: true,\n source: 'vehicle.trip.startTime',\n default: null,\n },\n {\n name: 'congestion_level',\n type: 'text',\n source: 'vehicle.congestionLevel',\n default: null,\n },\n {\n name: 'occupancy_status',\n type: 'text',\n source: 'vehicle.occupancyStatus',\n default: null,\n },\n {\n name: 'occupancy_percentage',\n type: 'integer',\n source: 'vehicle.occupancyPercentage',\n default: null,\n },\n {\n name: 'vehicle_stop_status',\n type: 'text',\n source: 'vehicle.vehicleStopStatus',\n default: null,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n index: true,\n source: 'vehicle.vehicle.id',\n default: null,\n },\n {\n name: 'vehicle_label',\n type: 'text',\n source: 'vehicle.vehicle.label',\n default: null,\n },\n {\n name: 'vehicle_license_plate',\n type: 'text',\n source: 'vehicle.vehicle.licensePlate',\n default: null,\n },\n {\n name: 'vehicle_wheelchair_accessible',\n type: 'text',\n source: 'vehicle.vehicle.wheelchairAccessible',\n default: null,\n },\n {\n name: 'timestamp',\n type: 'text',\n source: 'vehicle.timestamp',\n default: null,\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const serviceAlerts = {\n filenameBase: 'service_alerts',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n },\n {\n name: 'cause',\n type: 'integer',\n required: true,\n min: 0,\n source: 'alert.cause',\n default: 0,\n },\n {\n name: 'start_time',\n type: 'text',\n required: true,\n source: 'alert.activePeriod[0].start',\n default: '',\n },\n {\n name: 'end_time',\n type: 'text',\n required: true,\n source: 'alert.activePeriod[0].end',\n default: '',\n },\n {\n name: 'headline',\n type: 'text',\n required: true,\n source: 'alert.headerText.translation[0].text',\n default: '',\n },\n {\n name: 'description',\n type: 'text',\n required: true,\n source: 'alert.descriptionText.translation[0].text',\n default: '',\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const serviceAlertTargets = {\n filenameBase: 'service_alert_targets',\n extension: 'gtfs-realtime',\n schema: [\n {\n name: 'alert_id',\n type: 'text',\n required: true,\n primary: true,\n source: 'parent.id',\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n source: 'stopId',\n default: null,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n source: 'routeId',\n default: null,\n },\n {\n name: 'created_timestamp',\n type: 'integer',\n required: true,\n },\n {\n name: 'expiration_timestamp',\n type: 'integer',\n required: true,\n },\n ],\n};\n","export const deadheadTimes = {\n filenameBase: 'deadhead_times',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'id',\n type: 'integer',\n primary: true,\n prefix: true,\n },\n {\n name: 'deadhead_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'arrival_time',\n type: 'text',\n required: true,\n },\n {\n name: 'arrival_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'departure_time',\n type: 'text',\n required: true,\n },\n {\n name: 'departure_timestamp',\n type: 'integer',\n index: true,\n },\n {\n name: 'ops_location_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'location_sequence',\n type: 'integer',\n required: true,\n min: 0,\n index: true,\n },\n {\n name: 'shape_dist_traveled',\n type: 'real',\n min: 0,\n },\n ],\n};\n","export const deadheads = {\n filenameBase: 'deadheads',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'deadhead_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'service_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'block_id',\n type: 'text',\n required: true,\n index: true,\n prefix: true,\n },\n {\n name: 'shape_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'to_trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'from_trip_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'to_deadhead_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n {\n name: 'from_deadhead_id',\n type: 'text',\n index: true,\n prefix: true,\n },\n ],\n};\n","export const opsLocations = {\n filenameBase: 'ops_locations',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'ops_location_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'ops_location_code',\n type: 'text',\n },\n {\n name: 'ops_location_name',\n type: 'text',\n required: true,\n nocase: true,\n },\n {\n name: 'ops_location_desc',\n type: 'text',\n nocase: true,\n },\n {\n name: 'ops_location_lat',\n type: 'real',\n required: true,\n min: -90,\n max: 90,\n },\n {\n name: 'ops_location_lon',\n type: 'real',\n required: true,\n min: -180,\n max: 180,\n },\n ],\n};\n","export const runEvents = {\n filenameBase: 'run_event',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'run_event_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'piece_id',\n type: 'text',\n required: true,\n prefix: true,\n },\n {\n name: 'event_type',\n type: 'integer',\n required: true,\n min: 0,\n index: true,\n },\n {\n name: 'event_name',\n type: 'text',\n nocase: true,\n },\n {\n name: 'event_time',\n type: 'text',\n required: true,\n },\n {\n name: 'event_duration',\n type: 'integer',\n required: true,\n min: 0,\n },\n {\n name: 'event_from_location_type',\n type: 'integer',\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'event_from_location_id',\n type: 'text',\n prefix: true,\n },\n {\n name: 'event_to_location_type',\n type: 'integer',\n min: 0,\n max: 1,\n index: true,\n },\n {\n name: 'event_to_location_id',\n type: 'text',\n prefix: true,\n },\n ],\n};\n","export const runsPieces = {\n filenameBase: 'runs_pieces',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'ods',\n schema: [\n {\n name: 'run_id',\n type: 'text',\n required: true,\n },\n {\n name: 'piece_id',\n type: 'text',\n primary: true,\n required: true,\n },\n {\n name: 'start_type',\n type: 'integer',\n required: true,\n min: 0,\n max: 2,\n index: true,\n },\n {\n name: 'start_trip_id',\n type: 'text',\n required: true,\n index: true,\n },\n {\n name: 'start_trip_position',\n type: 'integer',\n min: 0,\n },\n {\n name: 'end_type',\n type: 'integer',\n required: true,\n min: 0,\n max: 2,\n index: true,\n },\n {\n name: 'end_trip_id',\n type: 'text',\n required: true,\n index: true,\n },\n {\n name: 'end_trip_position',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","import fs from 'fs';\n\nimport Database from 'better-sqlite3';\nimport untildify from 'untildify';\n\nconst dbs: { [key: string]: Database.Database } = {};\n\nfunction setupDb(sqlitePath: string) {\n const db = new Database(untildify(sqlitePath));\n db.pragma('journal_mode = OFF');\n db.pragma('synchronous = OFF');\n db.pragma('temp_store = MEMORY');\n dbs[sqlitePath] = db;\n\n return db;\n}\n\nexport function openDb(\n config: { db?: Database.Database; sqlitePath?: string } | null = null,\n): Database.Database {\n // If config is passed, use that to open or return db\n if (config) {\n const { sqlitePath = ':memory:', db } = config;\n\n // If db connection is passed, use it\n if (db) {\n return db;\n }\n\n // If db connection already exists, return it\n if (dbs[sqlitePath]) {\n return dbs[sqlitePath];\n }\n\n // If no db connection exists, create it\n return setupDb(sqlitePath);\n }\n\n // If no db connection exists, create a new one in memory\n if (Object.keys(dbs).length === 0) {\n return setupDb(':memory:');\n }\n\n // If only one db connection already exists, use it\n if (Object.keys(dbs).length === 1) {\n const filename = Object.keys(dbs)[0];\n return dbs[filename];\n }\n\n if (Object.keys(dbs).length > 1) {\n throw new Error(\n 'Multiple databases open, please specify which one to use.',\n );\n }\n\n throw new Error('Unable to find database connection.');\n}\n\nexport function closeDb(db: Database.Database | null = null): void {\n if (Object.keys(dbs).length === 0) {\n throw new Error(\n 'No database connection. Call `openDb(config)` before using any methods.',\n );\n }\n\n if (!db) {\n if (Object.keys(dbs).length > 1) {\n throw new Error(\n 'Multiple database connections. Pass the db you want to close as a parameter to `closeDb`.',\n );\n }\n\n db = dbs[Object.keys(dbs)[0]];\n }\n\n db.close();\n delete dbs[db.name];\n}\n\nexport function deleteDb(db: Database.Database | null = null): void {\n if (Object.keys(dbs).length === 0) {\n throw new Error(\n 'No database connection. Call `openDb(config)` before using any methods.',\n );\n }\n\n if (!db) {\n if (Object.keys(dbs).length > 1) {\n throw new Error(\n 'Multiple database connections. Pass the db you want to delete as a parameter to `deleteDb`.',\n );\n }\n\n db = dbs[Object.keys(dbs)[0]];\n }\n\n db.close();\n\n fs.unlinkSync(db.name);\n\n delete dbs[db.name];\n}\n","import {\n cloneDeep,\n compact,\n filter,\n groupBy,\n last,\n omit,\n sortBy,\n omitBy,\n} from 'lodash-es';\nimport { feature, featureCollection } from '@turf/helpers';\nimport { Shape, Stop } from '../types/global_interfaces.ts';\n\nexport function isValidJSON(string: string) {\n try {\n JSON.parse(string);\n } catch (error) {\n return false;\n }\n return true;\n}\n\ntype Position = [number, number];\n\nfunction isValidLineString(lineString?: Position[]) {\n if (!lineString) {\n return false;\n }\n\n if (lineString.length <= 1) {\n return false;\n }\n\n // Reject linestrings with two identical points\n if (\n lineString.length === 2 &&\n lineString[0][0] === lineString[1][0] &&\n lineString[0][1] === lineString[1][1]\n ) {\n return false;\n }\n\n return true;\n}\n\nfunction consolidateShapes(shapeGroups: Shape[][]) {\n const keys = new Set();\n const segmentsArray = shapeGroups.map((shapes) =>\n shapes.reduce(\n (\n memo: any[][][],\n point: { shape_pt_lon: number; shape_pt_lat: number },\n idx: number,\n ) => {\n if (idx > 0) {\n memo.push([\n [shapes[idx - 1].shape_pt_lon, shapes[idx - 1].shape_pt_lat],\n [point.shape_pt_lon, point.shape_pt_lat],\n ]);\n }\n\n return memo;\n },\n [],\n ),\n );\n\n const consolidatedLineStrings: number[][][] = [];\n\n for (const segments of segmentsArray) {\n consolidatedLineStrings.push([]);\n\n for (const segment of segments) {\n const key1 = `${segment[0][0]},${segment[0][1]},${segment[1][0]},${segment[1][1]}`;\n const key2 = `${segment[1][0]},${segment[1][1]},${segment[0][0]},${segment[0][1]}`;\n const currentLine: number[][] | undefined = last(consolidatedLineStrings);\n\n if (keys.has(key1) || keys.has(key2)) {\n consolidatedLineStrings.push([]);\n } else {\n // If its the first segment in a linestring, add both points\n if (currentLine?.length === 0) {\n currentLine.push(segment[0]);\n }\n\n currentLine?.push(segment[1]);\n keys.add(key1);\n keys.add(key2);\n }\n }\n }\n\n return filter(consolidatedLineStrings, isValidLineString);\n}\n\nfunction formatHexColor(color: null | undefined) {\n if (color === null || color === undefined) {\n return;\n }\n\n return `#${color}`;\n}\n\nfunction formatProperties(properties: Record<string, any>) {\n const formattedProperties: Record<string, any> = cloneDeep(\n omitBy(properties, (value) => value === null || value === undefined),\n );\n const formattedRouteColor = formatHexColor(properties.route_color);\n const formattedRouteTextColor = formatHexColor(properties.route_text_color);\n\n if (formattedRouteColor) {\n formattedProperties.route_color = formattedRouteColor;\n }\n\n if (formattedRouteTextColor) {\n formattedProperties.route_text_color = formattedRouteTextColor;\n }\n\n if (properties.routes) {\n formattedProperties.routes = properties.routes.map(\n (route: Record<string, any>) => formatProperties(route),\n );\n }\n\n return formattedProperties;\n}\n\nexport function shapesToGeoJSONFeature(shapes: Shape[], properties = {}) {\n const shapeGroups = Object.values(groupBy(shapes, 'shape_id')).map(\n (shapeGroup) => sortBy(shapeGroup, 'shape_pt_sequence'),\n );\n const lineStrings = consolidateShapes(shapeGroups) as Position[][];\n\n return feature(\n {\n type: 'MultiLineString',\n coordinates: lineStrings,\n },\n formatProperties(properties),\n );\n}\n\nexport function stopsToGeoJSONFeatureCollection(stops: Stop[]) {\n const features = compact(\n stops.map((stop) => {\n if (!stop.stop_lon || !stop.stop_lat) {\n return;\n }\n\n return feature(\n {\n type: 'Point',\n coordinates: [stop.stop_lon, stop.stop_lat],\n },\n formatProperties(omit(stop, ['stop_lat', 'stop_lon'])),\n );\n }),\n );\n\n return featureCollection(features);\n}\n","import pluralize from 'pluralize';\nimport GtfsRealtimeBindings from 'gtfs-realtime-bindings';\nimport sqlString from 'sqlstring-sqlite';\nimport mapSeries from 'promise-map-series';\n\nimport * as models from '../models/models.ts';\nimport { openDb } from './db.ts';\nimport { log, logError, logWarning } from './log-utils.ts';\nimport {\n convertLongTimeToDate,\n setDefaultConfig,\n validateConfigForImport,\n} from './utils.ts';\n\nimport {\n Config,\n ConfigAgency,\n ModelColumn,\n} from '../types/global_interfaces.ts';\n\ninterface GtfsRealtimeTask {\n realtimeAlerts?: {\n url: string;\n headers?: Record<string, string>;\n };\n realtimeTripUpdates?: {\n url: string;\n headers?: Record<string, string>;\n };\n realtimeVehiclePositions?: {\n url: string;\n headers?: Record<string, string>;\n };\n downloadTimeout?: number;\n gtfsRealtimeExpirationSeconds: number;\n ignoreErrors: boolean;\n sqlitePath: string;\n currentTimestamp: number;\n log: (message: string, newLine?: boolean) => void;\n logWarning: (message: string) => void;\n logError: (message: string) => void;\n}\n\nfunction getNestedProperty(obj: any, defaultValue: any, path?: string) {\n if (path === undefined) return defaultValue;\n const arr = path.split('.');\n while (arr.length) {\n const nextKey = arr.shift();\n if (nextKey === undefined) {\n return defaultValue;\n } else if (obj == null) {\n return defaultValue;\n } else if (nextKey?.includes('[')) {\n const arrayKey = nextKey.match(/(\\w*)\\[(\\d+)\\]/);\n if (arrayKey === null) {\n return defaultValue;\n }\n if (obj[arrayKey[1]] === undefined) {\n return defaultValue;\n }\n\n if (obj[arrayKey[1]][arrayKey[2]] === undefined) {\n return defaultValue;\n }\n\n obj = obj[arrayKey[1]][arrayKey[2]];\n } else {\n if (obj[nextKey] === undefined) {\n return defaultValue;\n }\n obj = obj[nextKey];\n }\n }\n\n if (obj.__isLong__) return convertLongTimeToDate(obj);\n\n return obj;\n}\n\nasync function fetchGtfsRealtimeData(\n urlConfig: { url: string; headers?: Record<string, string> },\n task: GtfsRealtimeTask,\n) {\n task.log(`Downloading GTFS-Realtime from ${urlConfig.url}`);\n const response = await fetch(urlConfig.url, {\n method: 'GET',\n headers: {\n ...(urlConfig.headers ?? {}),\n 'Accept-Encoding': 'gzip',\n },\n signal: task.downloadTimeout\n ? AbortSignal.timeout(task.downloadTimeout)\n : undefined,\n });\n\n if (response.status !== 200) {\n task.logWarning(\n `Unable to download GTFS-Realtime from ${urlConfig.url}. Got status ${response.status}.`,\n );\n return null;\n }\n\n const buffer = await response.arrayBuffer();\n const message = GtfsRealtimeBindings.transit_realtime.FeedMessage.decode(\n new Uint8Array(buffer),\n );\n return GtfsRealtimeBindings.transit_realtime.FeedMessage.toObject(message, {\n enums: String,\n longs: String,\n bytes: String,\n defaults: true,\n arrays: true,\n objects: true,\n oneofs: true,\n });\n}\n\nfunction removeExpiredRealtimeData(config: Config) {\n const db = openDb(config);\n\n log(config)(`Removing expired GTFS-Realtime data`);\n db.prepare(\n `DELETE FROM vehicle_positions WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n db.prepare(\n `DELETE FROM trip_updates WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n db.prepare(\n `DELETE FROM stop_time_updates WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n db.prepare(\n `DELETE FROM service_alerts WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n db.prepare(\n `DELETE FROM service_alert_targets WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n log(config)(`Removed expired GTFS-Realtime data\\r`, true);\n}\n\nfunction prepareRealtimeFieldValue(\n entity: any,\n column: ModelColumn,\n task: GtfsRealtimeTask,\n) {\n if (column.name === 'created_timestamp') {\n return task.currentTimestamp;\n }\n\n if (column.name === 'expiration_timestamp') {\n return task.currentTimestamp + task.gtfsRealtimeExpirationSeconds;\n }\n\n return sqlString.escape(\n getNestedProperty(entity, column.default, column.source),\n );\n}\n\nasync function processRealtimeAlerts(\n db: any,\n gtfsRealtimeData: any,\n task: GtfsRealtimeTask,\n) {\n task.log(`Download successful`);\n\n let totalLineCount = 0;\n\n for (const entity of gtfsRealtimeData.entity) {\n // Do base processing\n const fieldValues = models.serviceAlerts.schema.map((column: ModelColumn) =>\n prepareRealtimeFieldValue(entity, column, task),\n );\n\n try {\n db.prepare(\n `REPLACE INTO ${models.serviceAlerts.filenameBase} (${models.serviceAlerts.schema\n .map((column) => column.name)\n .join(', ')}) VALUES (${fieldValues.join(', ')})`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n const alertTargetArray = [];\n for (const informedEntity of entity.alert.informedEntity) {\n informedEntity.parent = entity;\n const subValues = models.serviceAlertTargets.schema.map((column) =>\n prepareRealtimeFieldValue(informedEntity, column, task),\n );\n alertTargetArray.push(`(${subValues.join(', ')})`);\n totalLineCount++;\n }\n\n try {\n db.prepare(\n `REPLACE INTO ${models.serviceAlertTargets.filenameBase} (${models.serviceAlertTargets.schema\n .map((column) => column.name)\n .join(', ')}) VALUES ${alertTargetArray.join(', ')}`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n task.log(`Importing - ${totalLineCount++} entries imported\\r`, true);\n }\n}\n\nasync function processRealtimeTripUpdates(\n db: any,\n gtfsRealtimeData: any,\n task: GtfsRealtimeTask,\n) {\n task.log(`Download successful`);\n\n let totalLineCount = 0;\n\n for (const entity of gtfsRealtimeData.entity) {\n // Do base processing\n const fieldValues = models.tripUpdates.schema.map((column: ModelColumn) =>\n prepareRealtimeFieldValue(entity, column, task),\n );\n\n try {\n db.prepare(\n `REPLACE INTO ${models.tripUpdates.filenameBase} (${models.tripUpdates.schema\n .map((column) => column.name)\n .join(', ')}) VALUES (${fieldValues.join(', ')})`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n const stopTimeUpdateArray = [];\n for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {\n stopTimeUpdate.parent = entity;\n const subValues = models.stopTimeUpdates.schema.map((column) =>\n prepareRealtimeFieldValue(stopTimeUpdate, column, task),\n );\n stopTimeUpdateArray.push(`(${subValues.join(', ')})`);\n totalLineCount++;\n }\n\n try {\n db.prepare(\n `REPLACE INTO ${models.stopTimeUpdates.filenameBase} (${models.stopTimeUpdates.schema\n .map((column) => column.name)\n .join(', ')}) VALUES ${stopTimeUpdateArray.join(', ')}`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n task.log(`Importing - ${totalLineCount++} entries imported\\r`, true);\n }\n}\n\nasync function processRealtimeVehiclePositions(\n db: any,\n gtfsRealtimeData: any,\n task: GtfsRealtimeTask,\n) {\n task.log(`Download successful`);\n\n let totalLineCount = 0;\n\n for (const entity of gtfsRealtimeData.entity) {\n // Do base processing\n const fieldValues = models.vehiclePositions.schema.map(\n (column: ModelColumn) => prepareRealtimeFieldValue(entity, column, task),\n );\n\n try {\n db.prepare(\n `REPLACE INTO ${models.vehiclePositions.filenameBase} (${models.vehiclePositions.schema\n .map((column) => column.name)\n .join(', ')}) VALUES (${fieldValues.join(', ')})`,\n ).run();\n } catch (error: any) {\n task.logWarning('Import error: ' + error.message);\n }\n\n task.log(`Importing - ${totalLineCount++} entries imported\\r`, true);\n }\n}\n\nexport async function updateGtfsRealtimeData(task: GtfsRealtimeTask) {\n if (\n task.realtimeAlerts === undefined &&\n task.realtimeTripUpdates === undefined &&\n task.realtimeVehiclePositions === undefined\n ) {\n return;\n }\n\n const db = openDb({ sqlitePath: task.sqlitePath });\n\n if (task.realtimeAlerts?.url) {\n try {\n const alertsData = await fetchGtfsRealtimeData(task.realtimeAlerts, task);\n if (alertsData?.entity) {\n await processRealtimeAlerts(db, alertsData, task);\n }\n } catch (error: any) {\n if (task.ignoreErrors) {\n task.logError(error.message);\n } else {\n throw error;\n }\n }\n }\n\n if (task.realtimeTripUpdates?.url) {\n try {\n const tripUpdatesData = await fetchGtfsRealtimeData(\n task.realtimeTripUpdates,\n task,\n );\n if (tripUpdatesData?.entity) {\n await processRealtimeTripUpdates(db, tripUpdatesData, task);\n }\n } catch (error: any) {\n if (task.ignoreErrors) {\n task.logError(error.message);\n } else {\n throw error;\n }\n }\n }\n\n if (task.realtimeVehiclePositions?.url) {\n try {\n const vehiclePositionsData = await fetchGtfsRealtimeData(\n task.realtimeVehiclePositions,\n task,\n );\n if (vehiclePositionsData?.entity) {\n await processRealtimeVehiclePositions(db, vehiclePositionsData, task);\n }\n } catch (error: any) {\n if (task.ignoreErrors) {\n task.logError(error.message);\n } else {\n throw error;\n }\n }\n }\n\n task.log(`GTFS-Realtime data import complete`);\n}\n\nexport async function updateGtfsRealtime(initialConfig: Config) {\n const config = setDefaultConfig(initialConfig);\n validateConfigForImport(config);\n\n try {\n openDb(config);\n\n const agencyCount = config.agencies.length;\n log(config)(\n `Starting GTFS-Realtime refresh for ${pluralize(\n 'agencies',\n agencyCount,\n true,\n )} using SQLite database at ${config.sqlitePath}`,\n );\n\n removeExpiredRealtimeData(config);\n\n await mapSeries(config.agencies, async (agency: ConfigAgency) => {\n try {\n const task = {\n realtimeAlerts: agency.realtimeAlerts,\n realtimeTripUpdates: agency.realtimeTripUpdates,\n realtimeVehiclePositions: agency.realtimeVehiclePositions,\n downloadTimeout: config.downloadTimeout,\n gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,\n ignoreErrors: config.ignoreErrors,\n sqlitePath: config.sqlitePath,\n currentTimestamp: Math.floor(Date.now() / 1000),\n log: log(config),\n logWarning: logWarning(config),\n logError: logError(config),\n };\n\n await updateGtfsRealtimeData(task);\n } catch (error: any) {\n if (config.ignoreErrors) {\n logError(config)(error.message);\n } else {\n throw error;\n }\n }\n });\n\n log(config)(\n `Completed GTFS-Realtime refresh for ${pluralize(\n 'agencies',\n agencyCount,\n true,\n )}\\n`,\n );\n } catch (error: any) {\n if (error?.code === 'SQLITE_CANTOPEN') {\n logError(config)(\n `Unable to open sqlite database \"${config.sqlitePath}\" defined as \\`sqlitePath\\` config.json. Ensure the parent directory exists or remove \\`sqlitePath\\` from config.json.`,\n );\n }\n throw error;\n }\n}\n","import sqlString from 'sqlstring-sqlite';\nimport Long from 'long';\nimport {\n Config,\n JoinOptions,\n SqlWhere,\n SqlValue,\n SqlOrderBy,\n} from '../types/global_interfaces.ts';\n\n/*\n * Validate configuration.\n */\nexport function validateConfigForImport(config: Config) {\n if (!config.agencies || config.agencies.length === 0) {\n throw new Error('No `agencies` specified in config');\n }\n\n for (const [index, agency] of config.agencies.entries()) {\n if (!agency.path && !agency.url) {\n throw new Error(\n `No Agency \\`url\\` or \\`path\\` specified in config for agency index ${index}.`,\n );\n }\n }\n\n return config;\n}\n\n/*\n * Initialize configuration with defaults.\n */\nexport function setDefaultConfig(initialConfig: Config) {\n const defaults = {\n sqlitePath: ':memory:',\n ignoreDuplicates: false,\n ignoreErrors: false,\n gtfsRealtimeExpirationSeconds: 0,\n };\n\n return {\n ...defaults,\n ...initialConfig,\n };\n}\n\nexport function convertLongTimeToDate(longDate: {\n high: any;\n low: any;\n unsigned: any;\n}) {\n const { high, low, unsigned } = longDate;\n return new Date(new Long(low, high, unsigned).toInt() * 1000).toISOString();\n}\n\n/*\n * Calculate seconds from midnight for HH:mm:ss\n */\nexport function calculateSecondsFromMidnight(time: string) {\n const split = time.split(':').map((d) => Number.parseInt(d, 10));\n if (split.length !== 3) {\n return null;\n }\n\n return split[0] * 3600 + split[1] * 60 + split[2];\n}\n\n/*\n * Adds leading zeros to HH:mm:ss timestamps\n */\nexport function padLeadingZeros(time: string) {\n const split = time.split(':').map((d) => String(Number(d)).padStart(2, '0'));\n if (split.length !== 3) {\n return null;\n }\n\n return split.join(':');\n}\n\nexport function formatSelectClause(fields: string[]) {\n if (Array.isArray(fields)) {\n const selectItem =\n fields.length > 0\n ? fields.map((fieldName) => sqlString.escapeId(fieldName)).join(', ')\n : '*';\n return `SELECT ${selectItem}`;\n }\n\n const selectItem = Object.entries(fields)\n .map(\n (key) => `${sqlString.escapeId(key[0])} AS ${sqlString.escapeId(key[1])}`,\n )\n .join(', ');\n return `SELECT ${selectItem}`;\n}\n\nexport function formatJoinClause(joinObject: JoinOptions[]) {\n return joinObject\n .map(\n (data) =>\n `${data.type ? data.type + ' JOIN' : 'INNER JOIN'} ${sqlString.escapeId(\n data.table,\n )} ON ${data.on}`,\n )\n .join(' ');\n}\n\nfunction degree2radian(angle: number) {\n return (angle * Math.PI) / 180;\n}\n\nfunction radian2degree(angle: number) {\n return (angle / Math.PI) * 180;\n}\n\n/*\n * Search inside GPS coordinates boundary box\n * Distance unit: meters\n * */\nexport function formatWhereClauseBoundingBox(\n latitudeDegree: string | number,\n longitudeDegree: string | number,\n boundingBoxSideMeters: number,\n) {\n const earthRadius = 6371000;\n latitudeDegree =\n typeof latitudeDegree === 'string'\n ? parseFloat(latitudeDegree)\n : latitudeDegree;\n longitudeDegree =\n typeof longitudeDegree === 'string'\n ? parseFloat(longitudeDegree)\n : longitudeDegree;\n\n const latitudeRadian = degree2radian(latitudeDegree);\n const radiusFromLatitude = Math.cos(latitudeRadian) * earthRadius;\n\n // `boundingBoxSideMeters` is divided by 2 we are centering the coordinates in the middle of this square\n const deltaLatitude = radian2degree(boundingBoxSideMeters / 2 / earthRadius);\n const deltaLongitude = radian2degree(\n boundingBoxSideMeters / 2 / radiusFromLatitude,\n );\n\n let query = `stop_lat BETWEEN ${latitudeDegree - deltaLatitude} AND ${latitudeDegree + deltaLatitude}`;\n query += ` AND stop_lon BETWEEN ${longitudeDegree - deltaLongitude} AND ${longitudeDegree + deltaLongitude}`;\n\n return query;\n}\n\nexport function formatWhereClause(\n key: string,\n value: null | SqlValue | SqlValue[],\n) {\n if (Array.isArray(value)) {\n let whereClause = `${sqlString.escapeId(key)} IN (${value\n .filter((v) => v !== null)\n .map((v) => sqlString.escape(v))\n .join(', ')})`;\n\n if (value.includes(null)) {\n whereClause = `(${whereClause} OR ${sqlString.escapeId(key)} IS NULL)`;\n }\n\n return whereClause;\n }\n\n if (value === null) {\n return `${sqlString.escapeId(key)} IS NULL`;\n }\n\n return `${sqlString.escapeId(key)} = ${sqlString.escape(value)}`;\n}\n\nexport function formatWhereClauses(query: SqlWhere) {\n if (Object.keys(query).length === 0) {\n return '';\n }\n\n const whereClauses = Object.entries(query).map(([key, value]) =>\n formatWhereClause(key, value),\n );\n return `WHERE ${whereClauses.join(' AND ')}`;\n}\n\nexport function formatOrderByClause(orderBy: SqlOrderBy) {\n let orderByClause = '';\n\n if (orderBy.length > 0) {\n orderByClause += 'ORDER BY ';\n\n orderByClause += orderBy\n .map(([key, value]) => {\n const direction = value === 'DESC' ? 'DESC' : 'ASC';\n return `${sqlString.escapeId(key)} ${direction}`;\n })\n .join(', ');\n }\n\n return orderByClause;\n}\n\nexport function getDayOfWeekFromDate(date: number) {\n const daysOfWeek = [\n 'sunday',\n 'monday',\n 'tuesday',\n 'wednesday',\n 'thursday',\n 'friday',\n 'saturday',\n ];\n const dateString = date\n .toString()\n .replace(/(\\d{4})(\\d{2})(\\d{2})/, '$1-$2-$3');\n const [year, month, day] = dateString.split('-').map(Number);\n const dayOfWeek = new Date(year, month - 1, day).getDay();\n return daysOfWeek[dayOfWeek];\n}\n","import path from 'node:path';\nimport { writeFile } from 'node:fs/promises';\n\nimport { without, compact } from 'lodash-es';\nimport pluralize from 'pluralize';\nimport { stringify } from 'csv-stringify';\nimport sqlString from 'sqlstring-sqlite';\nimport Database from 'better-sqlite3';\nimport mapSeries from 'promise-map-series';\nimport untildify from 'untildify';\n\nimport * as models from '../models/models.ts';\nimport { openDb } from './db.ts';\nimport { prepDirectory, generateFolderName } from './file-utils.ts';\nimport { log, logWarning } from './log-utils.ts';\nimport { setDefaultConfig } from './utils.ts';\n\nimport { Config, Model, SqlResults } from '../types/global_interfaces.ts';\n\nconst getAgencies = (db: Database.Database, config: Config) => {\n try {\n return db.prepare('SELECT agency_name FROM agency;').all() as {\n agency_name: string;\n }[];\n } catch (error) {\n if (config.sqlitePath === ':memory:') {\n throw new Error(\n 'No agencies found in SQLite. You are using an in-memory database - if running this from command line be sure to specify a value for `sqlitePath` in config.json other than \":memory:\".',\n );\n }\n\n throw new Error(\n 'No agencies found in SQLite. Be sure to first import data into SQLite using `gtfs-import` or `importGtfs(config);`',\n );\n }\n};\n\nexport const exportGtfs = async (initialConfig: Config) => {\n const config = setDefaultConfig(initialConfig);\n const db = openDb(config);\n\n // Get agency name for export folder from first line of agency.txt\n\n const agencies = getAgencies(db, config);\n const agencyCount = agencies.length;\n if (agencyCount === 0) {\n throw new Error(\n 'No agencies found in SQLite. Be sure to first import data into SQLite using `gtfs-import` or `importGtfs(config);`',\n );\n } else if (agencyCount > 1) {\n logWarning(config)(\n 'More than one agency is defined in config.json. Export will merge all into one GTFS file.',\n );\n }\n\n log(config)(\n `Starting GTFS export for ${pluralize(\n 'agency',\n agencyCount,\n true,\n )} using SQLite database at ${config.sqlitePath}`,\n );\n\n const folderName = generateFolderName(agencies[0].agency_name);\n const defaultExportPath = path.join(process.cwd(), 'gtfs-export', folderName);\n const exportPath = untildify(config.exportPath || defaultExportPath);\n\n await prepDirectory(exportPath);\n\n // Loop through each GTFS file\n const modelsToExport = Object.values(models).filter(\n (model: Model) => model.extension !== 'gtfs-realtime',\n );\n const exportedFiles = await mapSeries(\n modelsToExport,\n async (model: Model) => {\n const filePath = path.join(\n exportPath,\n `${model.filenameBase}.${model.filenameExtension}`,\n );\n const tableName = sqlString.escapeId(model.filenameBase);\n const lines = db\n .prepare(`SELECT * FROM ${tableName};`)\n .all() as SqlResults;\n\n if (!lines || lines.length === 0) {\n if (!model.nonstandard) {\n log(config)(\n `Skipping (no data) - ${model.filenameBase}.${model.filenameExtension}\\r`,\n );\n }\n\n return;\n }\n\n if (model.filenameExtension === 'txt') {\n const excludeColumns = [\n 'id',\n 'arrival_timestamp',\n 'departure_timestamp',\n 'start_timestamp',\n 'end_timestamp',\n 'service_arrival_timestamp',\n 'service_departure_timestamp',\n 'boarding_timestamp',\n 'alighting_timestamp',\n 'ridership_start_timestamp',\n 'ridership_end_timestamp',\n ];\n\n // If no routes have values for agency_id, add it to the excludeColumns list\n if (model.filenameBase === 'routes') {\n const routesWithAgencyId = db\n .prepare(\n 'SELECT agency_id FROM routes WHERE agency_id IS NOT NULL;',\n )\n .all();\n if (!routesWithAgencyId || routesWithAgencyId.length === 0) {\n excludeColumns.push('agency_id');\n }\n }\n\n const columns = without(\n model.schema.map((column) => column.name),\n ...excludeColumns,\n );\n const fileText = await stringify(lines, { columns, header: true });\n await writeFile(filePath, fileText);\n } else if (model.filenameExtension === 'geojson') {\n const fileText = lines?.[0].geojson ?? '';\n await writeFile(filePath, fileText);\n } else {\n throw new Error(\n `Unexpected filename extension: ${model.filenameExtension}`,\n );\n }\n\n log(config)(\n `Exporting - ${model.filenameBase}.${model.filenameExtension}\\r`,\n );\n\n return `${model.filenameBase}.${model.filenameExtension}`;\n },\n );\n\n if (compact(exportedFiles).length === 0) {\n log(config)(\n 'No GTFS data exported. Be sure to first import data into SQLite.',\n );\n return;\n }\n\n log(config)(`Completed GTFS export to ${exportPath}`);\n\n log(config)(\n `Completed GTFS export for ${pluralize('agency', agencyCount, true)}\\n`,\n );\n};\n","import sqlString from 'sqlstring-sqlite';\nimport Database from 'better-sqlite3';\n\nimport { openDb } from './db.ts';\n\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClauses,\n formatJoinClause,\n} from './utils.ts';\n\nimport {\n JoinOptions,\n QueryOptions,\n SqlOrderBy,\n SqlResults,\n SqlSelect,\n SqlWhere,\n} from '../types/global_interfaces.ts';\n\n/*\n * Returns an array of all agencies that match the query parameters.\n */\nexport function advancedQuery(\n table: string,\n advancedQueryOptions: {\n db?: Database.Database;\n query?: SqlWhere;\n fields?: SqlSelect;\n orderBy?: SqlOrderBy;\n join?: JoinOptions[];\n options?: QueryOptions;\n },\n): Array<Record<string, any>> {\n const defaultOptions: {\n query: SqlWhere;\n fields: SqlSelect;\n orderBy: SqlOrderBy;\n join: JoinOptions[];\n options: QueryOptions;\n } = {\n query: {},\n fields: [],\n orderBy: [],\n join: [],\n options: {},\n };\n const queryOptions = { ...defaultOptions, ...advancedQueryOptions };\n\n const db = queryOptions.options.db ?? openDb();\n const tableName = sqlString.escapeId(table);\n const selectClause = formatSelectClause(queryOptions.fields);\n const whereClause = formatWhereClauses(queryOptions.query);\n const joinClause = formatJoinClause(queryOptions.join);\n const orderByClause = formatOrderByClause(queryOptions.orderBy);\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${joinClause} ${whereClause} ${orderByClause};`,\n )\n .all() as SqlResults;\n}\n","import { omit, pick } from 'lodash-es';\n\nimport {\n QueryOptions,\n Route,\n SqlOrderBy,\n SqlSelect,\n SqlWhere,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n formatWhereClauses,\n} from '../utils.ts';\n\nfunction buildStoptimeSubquery(query: { [key: string]: string }) {\n const whereClause = formatWhereClauses(query);\n return `SELECT DISTINCT trip_id FROM stop_times ${whereClause}`;\n}\n\nfunction buildTripSubquery(query: { service_id?: string; stop_id?: string }) {\n let whereClause = '';\n const tripQuery = omit(query, ['stop_id']);\n const stoptimeQuery = pick(query, ['stop_id']);\n\n const whereClauses = Object.entries(tripQuery).map(([key, value]) =>\n formatWhereClause(key, value),\n );\n\n if (Object.values(stoptimeQuery).length > 0) {\n whereClauses.push(`trip_id IN (${buildStoptimeSubquery(stoptimeQuery)})`);\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return `SELECT DISTINCT route_id FROM trips ${whereClause}`;\n}\n\n/*\n * Returns an array of routes that match the query parameters. A `stop_id`\n * query parameter may be passed to find all routes that contain that stop.\n * A `service_id` query parameter may be passed to limit routes to specific\n * calendars.\n */\nexport function getRoutes(\n query: SqlWhere = {},\n fields: SqlSelect = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'routes';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const routeQuery = omit(query, ['stop_id', 'service_id']);\n const tripQuery: { stop_id?: any; service_id?: any } = pick(query, [\n 'stop_id',\n 'service_id',\n ]);\n\n const whereClauses = Object.entries(routeQuery).map(([key, value]) =>\n formatWhereClause(key, value),\n );\n\n if (Object.values(tripQuery).length > 0) {\n whereClauses.push(`route_id IN (${buildTripSubquery(tripQuery)})`);\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`,\n )\n .all() as Route[];\n}\n","import { compact, omit, pick } from 'lodash-es';\nimport { FeatureCollection } from 'geojson';\nimport { featureCollection } from '@turf/helpers';\n\nimport {\n QueryOptions,\n Shape,\n SqlOrderBy,\n SqlSelect,\n SqlWhere,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n formatWhereClauses,\n} from '../utils.ts';\nimport { shapesToGeoJSONFeature } from '../geojson-utils.ts';\nimport { getAgencies } from './agencies.ts';\nimport { getRoutes } from './routes.ts';\nimport { getRouteAttributes } from '../gtfs-plus/route-attributes.ts';\n\nfunction buildTripSubquery(query: { [key: string]: string }) {\n const whereClause = formatWhereClauses(query);\n return `SELECT DISTINCT shape_id FROM trips ${whereClause}`;\n}\n\n/*\n * Returns array of shapes that match the query parameters. A `route_id` query\n * parameter may be passed to find all shapes for a route. A `trip_id` query\n * parameter may be passed to find all shapes for a trip. A `direction_id`\n * query parameter may be passed to find all shapes for a direction.\n */\nexport function getShapes(\n query: SqlWhere = {},\n fields: SqlSelect = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'shapes';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const shapeQuery = omit(query, [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n ]);\n const tripQuery: {\n route_id?: any;\n trip_id?: any;\n service_id?: any;\n direction_id?: any;\n } = pick(query, ['route_id', 'trip_id', 'service_id', 'direction_id']);\n\n const whereClauses = Object.entries(shapeQuery).map(([key, value]) =>\n formatWhereClause(key, value),\n );\n\n if (Object.values(tripQuery).length > 0) {\n whereClauses.push(`shape_id IN (${buildTripSubquery(tripQuery)})`);\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`,\n )\n .all() as Shape[];\n}\n\n/*\n * Returns geoJSON of the shapes that match the query parameters. A `route_id`\n * query parameter may be passed to find all shapes for a route. A `trip_id`\n * query parameter may be passed to find all shapes for a trip. A\n * `direction_id` query parameter may be passed to find all shapes for a direction.\n */\nexport function getShapesAsGeoJSON(\n query: SqlWhere = {},\n options: QueryOptions = {},\n): FeatureCollection {\n const agencies = getAgencies({}, [], [], options);\n const routeQuery = pick(query, ['route_id']);\n const routes = getRoutes(routeQuery, [], [], options);\n const features = compact(\n routes.map((route) => {\n const shapeQuery = {\n route_id: route.route_id,\n ...omit(query, 'route_id'),\n };\n const shapes = getShapes(\n shapeQuery,\n ['shape_id', 'shape_pt_sequence', 'shape_pt_lon', 'shape_pt_lat'],\n [],\n options,\n );\n\n if (shapes.length === 0) {\n return;\n }\n\n const routeAttributes = getRouteAttributes(\n { route_id: route.route_id },\n [],\n [],\n options,\n );\n\n const agency = agencies.find(\n (agency) => agency.agency_id === route.agency_id,\n );\n\n const geojsonProperties = {\n agency_name: agency ? agency.agency_name : undefined,\n shape_id: query.shape_id,\n ...route,\n ...(routeAttributes?.[0] || []),\n };\n return shapesToGeoJSONFeature(shapes, geojsonProperties);\n }),\n );\n\n return featureCollection(features);\n}\n","import { omit, orderBy, pick } from 'lodash-es';\nimport { FeatureCollection } from 'geojson';\n\nimport {\n QueryOptions,\n SqlOrderBy,\n SqlSelect,\n SqlWhere,\n Stop,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n formatWhereClauseBoundingBox,\n formatWhereClauses,\n} from '../utils.ts';\nimport { stopsToGeoJSONFeatureCollection } from '../geojson-utils.ts';\nimport { getAgencies } from './agencies.ts';\nimport { getStopAttributes } from '../gtfs-plus/stop-attributes.ts';\n\nfunction buildTripSubquery(query: { [key: string]: string }) {\n const whereClause = formatWhereClauses(query);\n return `SELECT trip_id FROM trips ${whereClause}`;\n}\n\nfunction buildStoptimeSubquery(query: { [key: string]: string }) {\n return `SELECT DISTINCT stop_id FROM stop_times WHERE trip_id IN (${buildTripSubquery(\n query,\n )})`;\n}\n\n/*\n * Returns an array of stops that match the query parameters. A `route_id`\n * query parameter may be passed to find all shapes for a route. A `trip_id`\n * query parameter may be passed to find all shapes for a trip. A\n * `direction_id` query parameter may be passed to find all shapes for a\n * direction.\n */\nexport function getStops(\n query: SqlWhere = {},\n fields: SqlSelect = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'stops';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const stopQueryOmitKeys = [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n 'shape_id',\n ];\n\n // If bounding_box_side_m is defined, search for stops inside a bounding box so omit `stop_lat` and `stop_lon`.\n if (options.bounding_box_side_m !== undefined) {\n stopQueryOmitKeys.push('stop_lat', 'stop_lon');\n }\n\n let stopQuery = omit(query, stopQueryOmitKeys);\n\n const tripQuery: {\n route_id?: any;\n trip_id?: any;\n service_id?: any;\n direction_id?: any;\n shape_id?: any;\n } = pick(query, [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n 'shape_id',\n ]);\n\n const whereClauses = Object.entries(stopQuery).map(\n ([key, value]: [string, any]) => formatWhereClause(key, value),\n );\n\n if (\n options.bounding_box_side_m !== undefined &&\n query.stop_lat !== undefined &&\n query.stop_lon !== undefined\n ) {\n whereClauses.push(\n formatWhereClauseBoundingBox(\n query.stop_lat as number | string,\n query.stop_lon as number | string,\n options.bounding_box_side_m,\n ),\n );\n }\n\n if (Object.values(tripQuery).length > 0) {\n whereClauses.push(`stop_id IN (${buildStoptimeSubquery(tripQuery)})`);\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`,\n )\n .all() as Stop[];\n}\n\n/*\n * Returns geoJSON with stops. A `route_id` query parameter may be passed to\n * find all shapes for a route. A `trip_id` query parameter may be passed to\n * find all shapes for a trip. A `direction_id` query parameter may be passed\n * to find all shapes for a direction.\n */\nexport function getStopsAsGeoJSON(\n query: SqlWhere = {},\n options: QueryOptions = {},\n): FeatureCollection {\n const db = options.db ?? openDb();\n const stops = getStops(query, [], [], options);\n\n // Get all agencies for reference\n const agencies = getAgencies({}, [], [], options);\n\n const preparedStops = stops.map((stop) => {\n const routeSubquery =\n 'SELECT DISTINCT route_id FROM trips WHERE trip_id IN (SELECT DISTINCT trip_id FROM stop_times WHERE stop_id = ?)';\n const routes = db\n .prepare(`SELECT * FROM routes WHERE route_id IN (${routeSubquery})`)\n .all(stop.stop_id);\n\n const stopAttributes = getStopAttributes({ stop_id: stop.stop_id });\n\n return {\n ...stop,\n ...(stopAttributes?.[0] || []),\n routes: orderBy(routes, (route: { route_short_name?: string }) =>\n route?.route_short_name\n ? Number.parseInt(route.route_short_name, 10)\n : 0,\n ),\n agency_name: agencies[0].agency_name,\n };\n });\n\n // Exclude stops not part of any route\n const filteredStops = preparedStops.filter((stop) => stop.routes.length > 0);\n\n return stopsToGeoJSONFeatureCollection(filteredStops);\n}\n","import { omit } from 'lodash-es';\nimport sqlString from 'sqlstring-sqlite';\nimport {\n QueryOptions,\n SqlOrderBy,\n SqlSelect,\n SqlWhere,\n StopTime,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n calculateSecondsFromMidnight,\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n} from '../utils.ts';\nimport { getServiceIdsByDate } from './calendars.ts';\n\n/*\n * Returns an array of stoptimes that match the query parameters.\n */\nexport function getStoptimes(\n query: SqlWhere = {},\n fields: SqlSelect = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'stop_times';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const stoptimeQueryOmitKeys = ['date', 'start_time', 'end_time'];\n\n let stoptimeQuery = omit(query, stoptimeQueryOmitKeys);\n\n const whereClauses = Object.entries(stoptimeQuery).map(\n ([key, value]: [string, any]) => formatWhereClause(key, value),\n );\n\n if (query.date) {\n if (typeof query.date !== 'number') {\n throw new Error('`date` must be a number in yyyymmdd format');\n }\n\n const serviceIds = getServiceIdsByDate(query.date);\n\n const tripSubquery = `SELECT DISTINCT trip_id FROM trips WHERE service_id IN (${serviceIds.map((id) => sqlString.escape(id)).join(',')})`;\n\n whereClauses.push(`trip_id IN (${tripSubquery})`);\n }\n\n if (query.start_time) {\n if (typeof query.start_time !== 'string') {\n throw new Error('`start_time` must be a string in HH:mm:ss format');\n }\n\n whereClauses.push(\n `arrival_timestamp >= ${calculateSecondsFromMidnight(query.start_time)}`,\n );\n }\n\n if (query.end_time) {\n if (typeof query.end_time !== 'string') {\n throw new Error('`end_time` must be a string in HH:mm:ss format');\n }\n\n whereClauses.push(\n `departure_timestamp <= ${calculateSecondsFromMidnight(query.end_time)}`,\n );\n }\n\n if (whereClauses.length > 0) {\n whereClause = `WHERE ${whereClauses.join(' AND ')}`;\n }\n\n return db\n .prepare(\n `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`,\n )\n .all() as StopTime[];\n}\n"],"mappings":"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","names":["argv","pluralize","untildify","mapSeries","untildify","omit","sqlString","path","compact","pluralize","sqlString","mapSeries","untildify","pluralize","path","untildify","mapSeries","sqlString","compact","sqlString","omit","compact","omit","pick","featureCollection","omit","pick","omit","sqlString"]}