gtfs 4.18.6 → 4.18.7
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.
- package/dist/bin/gtfs-export.js +8 -0
- package/dist/bin/gtfs-export.js.map +1 -1
- package/dist/bin/gtfs-import.js +8 -0
- package/dist/bin/gtfs-import.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/models/models.d.ts +10 -0
- package/dist/models/models.js +8 -0
- package/dist/models/models.js.map +1 -1
- package/package.json +3 -3
|
@@ -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/rider-categories.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-informed_entities.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/models/tides/devices.ts","../../src/models/tides/fare-transactions.ts","../../src/models/tides/operators.ts","../../src/models/tides/passenger-events.ts","../../src/models/tides/station-activities.ts","../../src/models/tides/stop-visits.ts","../../src/models/tides/train-cars.ts","../../src/models/tides/trips-performed.ts","../../src/models/tides/vehicle-train-cars.ts","../../src/models/tides/vehicle-locations.ts","../../src/models/tides/vehicles.ts","../../src/lib/db.ts","../../src/lib/errors.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","../../src/lib/gtfs/trips.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';\nimport type { Config } from '../types/global_interfaces.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 as Config);\n process.exit();\n};\n\nsetupExport().catch(handleError);\n","import path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { mkdir, readFile, rm } from 'node:fs/promises';\nimport { omit, snakeCase } from 'lodash-es';\nimport sanitize from 'sanitize-filename';\nimport StreamZip from 'node-stream-zip';\nimport type { Config } from '../types/global_interfaces.ts';\n\nimport { log } from './log-utils.ts';\n\nconst homeDirectory = homedir();\n\n/** Configuration command line arguments interface */\ninterface ConfigArgs {\n configPath?: string;\n gtfsPath?: string;\n gtfsUrl?: string;\n sqlitePath?: string;\n}\n\n/**\n * Attempts to parse and load configuration from various sources\n * Priority: 1. CLI config path 2. CLI direct args 3. ./config.json\n * @param {ConfigArgs} argv - Command line arguments\n * @throws {Error} If configuration cannot be found or parsed\n * @returns {Promise<Record<string, any>>} Parsed configuration object\n * @example\n * const config = await getConfig({ configPath: './my-config.json' });\n */\nexport async function getConfig(argv: ConfigArgs): Promise<Config> {\n let config;\n let data;\n\n try {\n if (argv.configPath) {\n const configPath = path.resolve(untildify(argv.configPath));\n data = await readFile(configPath, 'utf8');\n config = Object.assign(JSON.parse(data), argv);\n } else if (argv.gtfsPath || argv.gtfsUrl || argv.sqlitePath) {\n const agencies = [\n ...(argv.gtfsPath ? [{ path: argv.gtfsPath }] : []),\n ...(argv.gtfsUrl ? [{ url: argv.gtfsUrl }] : []),\n ];\n\n config = {\n agencies,\n ...omit(argv, ['path', 'url']),\n };\n } else if (existsSync(path.resolve('./config.json'))) {\n data = await readFile(path.resolve('./config.json'), 'utf8');\n config = Object.assign(JSON.parse(data), argv);\n log(config)('Using configuration from ./config.json');\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 } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(\n `Cannot parse configuration file. Check to ensure that it is valid JSON. Error: ${error.message}`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\n/**\n * Prepares a directory for saving files by clearing its contents\n * @param {string} exportPath - Path to the directory to prepare\n * @returns {Promise<void>}\n * @example\n * await prepDirectory('./output');\n */\nexport async function prepDirectory(exportPath: string): Promise<void> {\n await rm(exportPath, { recursive: true, force: true });\n await mkdir(exportPath, { recursive: true });\n}\n\n/**\n * Extracts contents of a zip file to specified directory\n * @param {string} zipfilePath - Path to the zip file\n * @param {string} exportPath - Directory to extract contents to\n * @returns {Promise<void>}\n * @throws {Error} If zip file cannot be opened or extracted\n * @example\n * await unzip('./data.zip', './extracted');\n */\nexport async function unzip(\n zipfilePath: string,\n exportPath: string,\n): Promise<void> {\n try {\n const zip = new StreamZip.async({ file: zipfilePath });\n await zip.extract(null, exportPath);\n await zip.close();\n } catch (error) {\n throw new Error(\n `Failed to extract zip file: ${error instanceof Error ? error.message : 'Unknown error'}`,\n { cause: error },\n );\n }\n}\n\n/**\n * Generates a safe folder name from input string\n * Converts to snake_case and removes unsafe characters\n * @param {string} folderName - Input string to convert to folder name\n * @returns {string} Sanitized folder name\n * @example\n * generateFolderName('My Folder!') // returns 'my_folder'\n */\nexport function generateFolderName(folderName: string): string {\n if (!folderName || typeof folderName !== 'string') {\n throw new Error('Folder name must be a non-empty string');\n }\n return snakeCase(sanitize(folderName));\n}\n\n/**\n * Converts a tilde path to a full path\n * @param pathWithTilde The path to convert\n * @returns The full path\n */\nexport function untildify(pathWithTilde: string): string {\n return homeDirectory\n ? pathWithTilde.replace(/^~(?=$|\\/|\\\\)/, homeDirectory)\n : pathWithTilde;\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/** Function type for logging with optional line overwrite */\ntype LogFunction = (text: string, overwrite?: boolean) => void;\n\n/**\n * Creates a logging function based on configuration settings\n * @param {Config} config - Configuration object containing logging preferences\n * @returns {LogFunction} Logging function that writes to stdout, or noop if verbose is false\n * @example\n * const logger = log({ verbose: true });\n * logger('Processing...', true); // Overwrites current line\n * logger('Done!'); // Writes on new line\n */\nexport function log(config: Config): LogFunction {\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 = false): void => {\n if (overwrite && 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 * Creates a warning logging function\n * @param {Config} config - Configuration object containing logging preferences\n * @returns {(text: string) => void} Function that logs formatted warning messages\n * @example\n * const warnLogger = logWarning(config);\n * warnLogger('Resource not found'); // Outputs yellow warning message\n */\nexport function logWarning(config: Config): (text: string) => void {\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string): void => {\n process.stdout.write(`\\n${formatWarning(text)}\\n`);\n };\n}\n\n/**\n * Creates an error logging function\n * @param {Config} config - Configuration object containing logging preferences\n * @returns {(text: string) => void} Function that logs formatted error messages\n * @example\n * const errorLogger = logError(config);\n * errorLogger('Failed to connect'); // Outputs red error message\n */\nexport function logError(config: Config): (text: string) => void {\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string): void => {\n process.stdout.write(`\\n${formatError(text)}\\n`);\n };\n}\n\n/**\n * Formats warning text with yellow color and underline\n * @param {string} text - The warning message to format\n * @returns {string} Formatted warning message in yellow with underlined \"Warning\" prefix\n * @example\n * const formattedWarning = formatWarning('Resource not found');\n * console.log(formattedWarning); // Yellow \"Warning: Resource not found\"\n */\nexport function formatWarning(text: string): string {\n return colors.yellow(`${colors.underline('Warning')}: ${text}`);\n}\n\n/**\n * Formats error text with red color and underline\n * @param {Error | string} error - The error object or message to format\n * @returns {string} Formatted error message in red with underlined \"Error\" prefix\n * @example\n * const formattedError = formatError(new Error('Connection failed'));\n * console.log(formattedError); // Red \"Error: Connection failed\"\n */\nexport function formatError(error: Error | string): string {\n const messageText = error instanceof Error ? error.message : error;\n const cleanMessage = messageText.replace(/^Error:\\s*/i, '');\n\n return colors.red(`${colors.underline('Error')}: ${cleanMessage}`);\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 stripBomStream from 'strip-bom-stream';\nimport { temporaryDirectory } from 'tempy';\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 { untildify, 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 getTimestampColumnName,\n padLeadingZeros,\n applyPrefixToValue,\n pluralize,\n setDefaultConfig,\n validateConfigForImport,\n} from './utils.ts';\nimport {\n addImportError,\n addImportWarning,\n createImportReport,\n formatGtfsError,\n GtfsError,\n GtfsErrorCategory,\n GtfsErrorCode,\n GtfsWarningCode,\n ImportReport,\n toGtfsError,\n} from './errors.ts';\n\nimport {\n Config,\n ConfigAgency,\n Model,\n SqlValue,\n TableNames,\n} from '../types/global_interfaces.ts';\n\ninterface GtfsImportTask {\n exclude?: TableNames[];\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: object;\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 report?: ImportReport;\n}\n\nfunction reportTaskError(task: GtfsImportTask, error: GtfsError): void {\n if (task.report) {\n addImportError(task.report, error);\n }\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 downloadGtfsFiles = async (task: GtfsImportTask): Promise<void> => {\n if (!task.url) {\n throw new GtfsError('No `url` specified in config', {\n code: GtfsErrorCode.GTFS_CONFIG_INVALID,\n category: GtfsErrorCategory.CONFIG,\n });\n }\n\n task.log(`Downloading GTFS from ${task.url}`);\n\n task.path = `${task.downloadDir}/gtfs.zip`;\n\n try {\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 GtfsError(\n `Unable to download GTFS from ${task.url}. Got status ${response.status}.`,\n {\n code: GtfsErrorCode.GTFS_DOWNLOAD_HTTP,\n category: GtfsErrorCategory.DOWNLOAD,\n statusCode: response.status,\n details: {\n url: task.url,\n status: response.status,\n statusText: response.statusText,\n },\n },\n );\n }\n\n const buffer = await response.arrayBuffer();\n await writeFile(task.path, Buffer.from(buffer));\n task.log('Download successful');\n } catch (error: unknown) {\n throw toGtfsError(error, {\n message: `Unable to download GTFS from ${task.url}.`,\n code: GtfsErrorCode.GTFS_DOWNLOAD_FAILED,\n category: GtfsErrorCategory.DOWNLOAD,\n details: { url: task.url },\n });\n }\n};\n\nconst extractGtfsFiles = async (task: GtfsImportTask): Promise<void> => {\n if (!task.path) {\n throw new GtfsError('No `path` specified in config', {\n code: GtfsErrorCode.GTFS_CONFIG_INVALID,\n category: GtfsErrorCategory.CONFIG,\n details: { field: 'path' },\n });\n }\n\n const gtfsPath = untildify(task.path);\n task.log(`Importing static 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 GtfsError(\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 code: GtfsErrorCode.GTFS_ZIP_INVALID,\n category: GtfsErrorCategory.ZIP,\n details: { path: task.path, folderCount: folders.length },\n },\n );\n } else if (folders.length === 0) {\n throw new GtfsError(\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 code: GtfsErrorCode.GTFS_ZIP_INVALID,\n category: GtfsErrorCategory.ZIP,\n details: { path: task.path },\n },\n );\n }\n\n const subfolderName = folders[0];\n const directoryTextFiles = await getTextFiles(subfolderName);\n\n if (directoryTextFiles.length === 0) {\n throw new GtfsError(\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 code: GtfsErrorCode.GTFS_ZIP_INVALID,\n category: GtfsErrorCategory.ZIP,\n details: { path: task.path, subfolderName },\n },\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: unknown) {\n const wrappedError = toGtfsError(error, {\n message: `Unable to unzip file ${task.path}`,\n code: GtfsErrorCode.GTFS_ZIP_INVALID,\n category: GtfsErrorCategory.ZIP,\n details: { path: task.path },\n });\n task.logError(formatGtfsError(wrappedError));\n throw wrappedError;\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 (error: unknown) {\n throw new GtfsError(\n `Unable to load files from path \\`${gtfsPath}\\` defined in configuration. Verify that path exists and contains GTFS files.`,\n {\n code: GtfsErrorCode.GTFS_DOWNLOAD_FAILED,\n category: GtfsErrorCategory.DOWNLOAD,\n details: { path: gtfsPath },\n cause: error,\n },\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 sqlColumnCreateStatements = [];\n\n for (const column of model.schema) {\n const checks = [];\n if (column.min !== undefined && column.max) {\n checks.push(\n `${column.name} >= ${column.min} AND ${column.name} <= ${column.max}`,\n );\n } else if (column.min) {\n checks.push(`${column.name} >= ${column.min}`);\n } else if (column.max) {\n checks.push(`${column.name} <= ${column.max}`);\n }\n\n if (column.type === 'integer') {\n checks.push(\n `(TYPEOF(${column.name}) = 'integer' OR ${column.name} IS NULL)`,\n );\n } else if (column.type === 'real') {\n checks.push(\n `(TYPEOF(${column.name}) = 'real' OR ${column.name} IS NULL)`,\n );\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 const checkClause =\n checks.length > 0 ? `CHECK(${checks.join(' AND ')})` : '';\n\n sqlColumnCreateStatements.push(\n `${column.name} ${column.type} ${checkClause} ${required} ${columnDefault} ${columnCollation}`,\n );\n\n // Add an additional timestamp column for time columns\n if (column.type === 'time') {\n sqlColumnCreateStatements.push(\n `${getTimestampColumnName(column.name)} INTEGER GENERATED ALWAYS AS (\n CASE\n WHEN ${column.name} IS NULL OR ${column.name} = '' THEN NULL\n ELSE CAST(\n substr(${column.name}, 1, instr(${column.name}, ':') - 1) * 3600 +\n substr(${column.name}, instr(${column.name}, ':') + 1, 2) * 60 +\n substr(${column.name}, -2) AS INTEGER\n )\n END\n ) STORED`,\n );\n }\n }\n\n // Find Primary Key fields\n const primaryColumns = model.schema.filter((column) => column.primary);\n\n if (primaryColumns.length > 0) {\n sqlColumnCreateStatements.push(\n `PRIMARY KEY (${primaryColumns.map(({ name }) => name).join(', ')})`,\n );\n }\n\n db.prepare(`DROP TABLE IF EXISTS ${model.filenameBase};`).run();\n\n db.prepare(\n `CREATE TABLE ${model.filenameBase} (${sqlColumnCreateStatements.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) {\n if (column.index) {\n db.prepare(\n `CREATE INDEX idx_${model.filenameBase}_${column.name} ON ${model.filenameBase} (${column.name});`,\n ).run();\n }\n\n if (column.type === 'time') {\n // Index all timestamp columns\n const timestampColumnName = getTimestampColumnName(column.name);\n db.prepare(\n `CREATE INDEX idx_${model.filenameBase}_${timestampColumnName} ON ${model.filenameBase} (${timestampColumnName});`,\n ).run();\n }\n }\n }\n};\n\nconst formatGtfsLine = (\n line: { [x: string]: string | null },\n model: Model,\n totalLineCount: number,\n): Record<string, string | null> => {\n const lineNumber = totalLineCount + 1;\n const formattedLine: Record<string, string | null> = {};\n const filenameBase = model.filenameBase;\n const filenameExtension = model.filenameExtension;\n\n for (const { name, type, required } of model.schema) {\n let value: string | null = line[name];\n\n // Early null check\n if (value === '' || value === undefined || value === null) {\n formattedLine[name] = null;\n\n if (required) {\n throw new GtfsError(\n `Missing required value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`,\n {\n code: GtfsErrorCode.GTFS_REQUIRED_FIELD_MISSING,\n category: GtfsErrorCategory.VALIDATION,\n details: {\n file: `${filenameBase}.${filenameExtension}`,\n line: lineNumber,\n column: name,\n },\n },\n );\n }\n continue;\n }\n\n if (type === 'date') {\n // Handle YYYY-MM-DD format\n value = value?.toString().replace(/-/g, '');\n if (value.length !== 8) {\n throw new GtfsError(\n `Invalid date in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`,\n {\n code: GtfsErrorCode.GTFS_INVALID_DATE,\n category: GtfsErrorCategory.VALIDATION,\n details: {\n file: `${filenameBase}.${filenameExtension}`,\n line: lineNumber,\n column: name,\n value,\n },\n },\n );\n }\n } else if (type === 'time') {\n value = padLeadingZeros(value);\n }\n\n if (type === 'json') {\n value = JSON.stringify(value);\n }\n\n formattedLine[name] = value;\n }\n\n return formattedLine;\n};\n\nconst BATCH_SIZE = 100_000;\n\nconst importGtfsFiles = async (\n db: Database.Database,\n task: GtfsImportTask,\n): Promise<void> => {\n await 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 // Skip any models that are excluded by config\n if (task.exclude && task.exclude.includes(model.filenameBase)) {\n task.log(`Skipping - ${filename}\\r`);\n resolve();\n return;\n }\n\n // Skip gtfs-realtime models not present in static GTFS\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 // Create a list of all columns\n const columns = model.schema;\n\n // Create a map of which columns need prefixing\n const prefixedColumns = new Set(\n columns\n .filter((column) => column.prefix)\n .map((column) => column.name),\n );\n\n const prepareStatement = `INSERT ${task.ignoreDuplicates ? 'OR IGNORE' : ''} INTO ${\n model.filenameBase\n } (${columns.map(({ name }) => name).join(', ')}) VALUES (${columns\n .map(({ name }) => `@${name}`)\n .join(', ')})`;\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]: unknown; geojson?: string },\n ).map(([columnName, value]) => [\n columnName,\n applyPrefixToValue(\n value as string,\n prefixedColumns.has(columnName),\n task.prefix,\n ),\n ]),\n );\n insert.run(prefixedLine);\n }\n } catch (error: unknown) {\n if (\n (error as Error & { code?: string }).code ===\n 'SQLITE_CONSTRAINT_PRIMARYKEY'\n ) {\n const primaryColumns = columns.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 if (task.report) {\n addImportWarning(task.report, {\n code: GtfsWarningCode.GTFS_DUPLICATE_PRIMARY_KEY,\n message: `Duplicate values for primary key found in ${filename}.`,\n details: {\n file: filename,\n line: Number(rowNumber) + 1,\n columns: primaryColumns.map((column) => column.name),\n },\n });\n }\n }\n\n task.logWarning(\n `Check ${filename} for invalid data on line ${rowNumber + 1}.`,\n );\n throw toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: {\n file: filename,\n line: Number(rowNumber) + 1,\n sqlitePath: task.sqlitePath,\n dbCode: (error as { code?: unknown }).code,\n },\n });\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]: SqlValue; geojson?: string }[] = [];\n\n parser.on('readable', () => {\n try {\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 insertLines(lines);\n lines = [];\n\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n }\n }\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n });\n if (task.ignoreErrors) {\n reportTaskError(task, gtfsError);\n task.logError(\n `Error processing ${filename}: ${gtfsError.message}`,\n );\n resolve();\n } else {\n reject(gtfsError);\n }\n }\n });\n\n parser.on('end', () => {\n try {\n if (lines.length > 0) {\n try {\n insertLines(lines);\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message:\n error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { file: filename, sqlitePath: task.sqlitePath },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Error inserting data for ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n return;\n } else {\n reject(gtfsError);\n return;\n }\n }\n }\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n resolve();\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { file: filename, sqlitePath: task.sqlitePath },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Error finalizing ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n } else {\n reject(gtfsError);\n }\n }\n });\n\n parser.on('error', (error: unknown) => {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Parser error for ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n } else {\n reject(gtfsError);\n }\n });\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 if (task.ignoreErrors) {\n task.logError(`Invalid JSON in ${filename}`);\n reportTaskError(\n task,\n new GtfsError(`Invalid JSON in ${filename}`, {\n code: GtfsErrorCode.GTFS_JSON_INVALID,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n }),\n );\n resolve();\n return;\n } else {\n reject(\n new GtfsError(`Invalid JSON in ${filename}`, {\n code: GtfsErrorCode.GTFS_JSON_INVALID,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n }),\n );\n return;\n }\n }\n totalLineCount += 1;\n const line = formatGtfsLine(\n { geojson: data },\n model,\n totalLineCount,\n );\n try {\n insertLines([line]);\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n resolve();\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message:\n error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { file: filename, sqlitePath: task.sqlitePath },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Error inserting data for ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n } else {\n reject(gtfsError);\n }\n }\n })\n .catch((error: unknown) => {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Error reading ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n } else {\n reject(gtfsError);\n }\n });\n } else {\n if (task.ignoreErrors) {\n task.logError(\n `Unsupported file type: ${model.filenameExtension} for ${filename}`,\n );\n resolve();\n } else {\n reject(\n new GtfsError(\n `Unsupported file type: ${model.filenameExtension}`,\n {\n code: GtfsErrorCode.GTFS_UNSUPPORTED_FILE_TYPE,\n category: GtfsErrorCategory.PARSE,\n details: {\n file: filename,\n extension: model.filenameExtension,\n },\n },\n ),\n );\n }\n }\n }),\n );\n task.log(`Static GTFS import complete`);\n};\n\n/**\n * Function to import GTFS files into the database\n *\n * @param initialConfig\n */\nexport async function importGtfs(initialConfig: Config): Promise<ImportReport>;\nexport async function importGtfs(initialConfig: Config): Promise<void>;\nexport async function importGtfs(\n initialConfig: Config,\n): Promise<void | ImportReport> {\n // Start timer\n const startTime = process.hrtime.bigint();\n\n const config = setDefaultConfig(initialConfig);\n validateConfigForImport(config);\n const report = config.includeImportReport ? createImportReport() : undefined;\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', 'files', agencyCount)} 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 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 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 report,\n };\n\n if ('url' in agency) {\n Object.assign(task, { url: agency.url });\n\n await downloadGtfsFiles(task);\n } else {\n Object.assign(task, {\n path: agency.path,\n });\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: unknown) {\n const wrappedError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n });\n if (config.ignoreErrors) {\n logError(config)(formatGtfsError(wrappedError));\n if (report) {\n addImportError(report, wrappedError);\n }\n } else {\n throw wrappedError;\n }\n }\n });\n\n log(config)(`Creating DB indexes`);\n createGtfsIndexes(db);\n\n const endTime = process.hrtime.bigint();\n const elapsedSeconds = Number(endTime - startTime) / 1_000_000_000;\n\n log(config)(\n `Completed GTFS import in ${elapsedSeconds.toFixed(1)} seconds\\n`,\n );\n } catch (error: unknown) {\n if ((error as Error & { code?: string }).code === 'SQLITE_CANTOPEN') {\n const dbOpenError = new GtfsError(\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 code: GtfsErrorCode.DB_OPEN_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: {\n sqlitePath: config.sqlitePath,\n dbCode: (error as Error & { code?: string }).code,\n },\n cause: error,\n },\n );\n logError(config)(dbOpenError.message);\n throw dbOpenError;\n }\n throw toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n });\n }\n\n if (report) {\n return report;\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 { riderCategories } from './gtfs/rider-categories.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 { serviceAlertInformedEntities } from './gtfs-realtime/service-alert-informed_entities.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\nexport { devices } from './tides/devices.ts';\nexport { fareTransactions } from './tides/fare-transactions.ts';\nexport { operators } from './tides/operators.ts';\nexport { passengerEvents } from './tides/passenger-events.ts';\nexport { stationActivities } from './tides/station-activities.ts';\nexport { stopVisits } from './tides/stop-visits.ts';\nexport { trainCars } from './tides/train-cars.ts';\nexport { tripsPerformed } from './tides/trips-performed.ts';\nexport { vehicleTrainCars } from './tides/vehicle-train-cars.ts';\nexport { vehicleLocations } from './tides/vehicle-locations.ts';\nexport { vehicles } from './tides/vehicles.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 name: 'cemv_support',\n type: 'integer',\n min: 0,\n max: 2,\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 primary: 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: 'time',\n },\n {\n name: 'prior_notice_start_day',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_start_time',\n type: 'time',\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: 'rider_category_id',\n type: 'text',\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 primary: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'origin_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'destination_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'contains_id',\n type: 'text',\n primary: true,\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: 'time',\n required: true,\n primary: true,\n },\n {\n name: 'end_time',\n type: 'time',\n required: true,\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 primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n prefix: true,\n index: true,\n primary: 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 riderCategories = {\n filenameBase: 'rider_categories',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'rider_category_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'rider_category_name',\n type: 'text',\n required: true,\n },\n {\n name: 'is_default_fare_category',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'eligibility_url',\n type: 'text',\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 name: 'cemv_support',\n type: 'integer',\n min: 0,\n max: 2,\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 primary: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n primary: 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: 'time',\n },\n {\n name: 'departure_time',\n type: 'time',\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: 'time',\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 prefix: 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 name: 'stop_access',\n type: 'integer',\n min: 0,\n max: 1,\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: 'time',\n primary: true,\n },\n {\n name: 'end_time',\n type: 'time',\n primary: true,\n },\n {\n name: 'service_id',\n type: 'text',\n required: true,\n primary: 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 name: 'cars_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: 'timetable_id',\n type: 'text',\n prefix: true,\n required: true,\n primary: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n required: true,\n primary: 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: 'time',\n },\n {\n name: 'end_time',\n type: 'time',\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 required: 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: 'timetable_id',\n type: 'text',\n index: true,\n prefix: true,\n required: true,\n primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n required: true,\n primary: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n required: true,\n primary: 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 required: true,\n },\n {\n name: 'symbol',\n type: 'text',\n },\n {\n name: 'note',\n type: 'text',\n nocase: true,\n required: 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 required: true,\n primary: true,\n },\n {\n name: 'timetable_id',\n type: 'text',\n prefix: true,\n primary: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n primary: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n prefix: true,\n primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n primary: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n min: 0,\n primary: 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: 'time',\n },\n {\n name: 'service_departure_time',\n type: 'time',\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: 'time',\n },\n {\n name: 'alighting_time',\n type: 'time',\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: 'time',\n },\n {\n name: 'ridership_end_time',\n type: 'time',\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: 'id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n prefix: true,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.vehicle.id',\n default: null,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.trip.tripId',\n default: null,\n prefix: true,\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 prefix: true,\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 prefix: true,\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 prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n source: 'stopId',\n default: null,\n prefix: true,\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: 'id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n prefix: true,\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 prefix: true,\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 prefix: true,\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 prefix: true,\n },\n {\n name: 'active_period',\n type: 'json',\n source: 'alert.activePeriod',\n },\n {\n name: 'cause',\n type: 'text',\n source: 'alert.cause',\n },\n {\n name: 'effect',\n type: 'text',\n source: 'alert.effect',\n },\n {\n name: 'url',\n type: 'text',\n source: 'alert.url.translation[0].text',\n default: '',\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: 'header_text',\n type: 'text',\n required: true,\n source: 'alert.headerText.translation[0].text',\n default: '',\n },\n {\n name: 'description_text',\n type: 'text',\n required: true,\n source: 'alert.descriptionText.translation[0].text',\n default: '',\n },\n {\n name: 'tts_header_text',\n type: 'text',\n source: 'alert.ttsHeaderText.translation[0].text',\n },\n {\n name: 'tts_description_text',\n type: 'text',\n source: 'alert.ttsDescriptionText.translation[0].text',\n },\n {\n name: 'severity_level',\n type: 'text',\n source: 'alert.severityLevel',\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 serviceAlertInformedEntities = {\n filenameBase: 'service_alert_informed_entities',\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 prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n source: 'stopId',\n default: null,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n source: 'routeId',\n default: null,\n prefix: true,\n },\n {\n name: 'route_type',\n type: 'integer',\n index: true,\n source: 'routeType',\n default: null,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'trip.tripId',\n default: null,\n prefix: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n index: true,\n source: 'directionId',\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: 'deadhead_id',\n type: 'text',\n required: true,\n index: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'arrival_time',\n type: 'time',\n required: true,\n },\n {\n name: 'departure_time',\n type: 'time',\n required: 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 primary: 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","export const devices = {\n filenameBase: 'devices',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'device_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'vehicle_id',\n type: 'text',\n },\n {\n name: 'train_car_id',\n type: 'text',\n },\n {\n name: 'device_type',\n type: 'text',\n },\n {\n name: 'device_vendor',\n type: 'text',\n },\n {\n name: 'device_model',\n type: 'text',\n },\n {\n name: 'device_location',\n type: 'text',\n },\n ],\n};\n","export const fareTransactions = {\n filenameBase: 'fare_transactions',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'transaction_id',\n type: 'text',\n required: true,\n index: true,\n },\n {\n name: 'service_date',\n type: 'date',\n required: true,\n },\n {\n name: 'event_timestamp',\n type: 'text',\n required: true,\n },\n {\n name: 'location_ping_id',\n type: 'text',\n },\n {\n name: 'amount',\n type: 'real',\n required: true,\n },\n {\n name: 'currency_type',\n type: 'text',\n },\n {\n name: 'fare_action',\n type: 'text',\n required: true,\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n },\n {\n name: 'trip_id_scheduled',\n type: 'text',\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'trip_stop_sequence',\n type: 'integer',\n min: 1,\n },\n {\n name: 'scheduled_stop_sequence',\n type: 'integer',\n min: 0,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n },\n {\n name: 'device_id',\n type: 'text',\n },\n {\n name: 'fare_id',\n type: 'text',\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'num_riders',\n type: 'integer',\n min: 0,\n },\n {\n name: 'fare_media_id',\n type: 'text',\n },\n {\n name: 'rider_category',\n type: 'text',\n },\n {\n name: 'fare_product',\n type: 'text',\n },\n {\n name: 'fare_period',\n type: 'text',\n },\n {\n name: 'fare_capped',\n type: 'text',\n required: true,\n },\n {\n name: 'token_id',\n type: 'text',\n },\n {\n name: 'balance',\n type: 'real',\n },\n ],\n};\n","export const operators = {\n filenameBase: 'operators',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'operator_id',\n type: 'text',\n required: true,\n primary: true,\n },\n ],\n};\n","export const passengerEvents = {\n filenameBase: 'passenger_events',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'passenger_event_id',\n type: 'text',\n required: true,\n index: true,\n },\n {\n name: 'service_date',\n type: 'date',\n required: true,\n },\n {\n name: 'event_timestamp',\n type: 'text',\n required: true,\n },\n {\n name: 'location_ping_id',\n type: 'text',\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n },\n {\n name: 'trip_id_scheduled',\n type: 'text',\n },\n {\n name: 'trip_stop_sequence',\n type: 'integer',\n min: 1,\n },\n {\n name: 'scheduled_stop_sequence',\n type: 'integer',\n min: 0,\n },\n {\n name: 'event_type',\n type: 'text',\n required: true,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n },\n {\n name: 'device_id',\n type: 'text',\n },\n {\n name: 'train_car_id',\n type: 'text',\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'event_count',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const stationActivities = {\n filenameBase: 'station_activities',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'service_date',\n type: 'date',\n required: true,\n primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'time_period_start',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'time_period_end',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'time_period_category',\n type: 'text',\n },\n {\n name: 'total_entries',\n type: 'integer',\n min: 0,\n },\n {\n name: 'total_exits',\n type: 'integer',\n min: 0,\n },\n {\n name: 'number_of_transactions',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_entries',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_exits',\n type: 'integer',\n min: 0,\n },\n {\n name: 'ramp_entries',\n type: 'integer',\n min: 0,\n },\n {\n name: 'ramp_exits',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const stopVisits = {\n filenameBase: 'stop_visits',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'service_date',\n type: 'date',\n required: true,\n primary: true,\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'trip_stop_sequence',\n type: 'integer',\n min: 1,\n required: true,\n primary: true,\n },\n {\n name: 'scheduled_stop_sequence',\n type: 'integer',\n min: 0,\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'vehicle_id',\n type: 'text',\n },\n {\n name: 'dwell',\n type: 'integer',\n min: 0,\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'timepoint',\n type: 'text',\n },\n {\n name: 'schedule_arrival_time',\n type: 'text',\n },\n {\n name: 'schedule_departure_time',\n type: 'text',\n },\n {\n name: 'actual_arrival_time',\n type: 'text',\n },\n {\n name: 'actual_departure_time',\n type: 'text',\n },\n {\n name: 'distance',\n type: 'integer',\n min: 0,\n },\n {\n name: 'boarding_1',\n type: 'integer',\n min: 0,\n },\n {\n name: 'alighting_1',\n type: 'integer',\n min: 0,\n },\n {\n name: 'boarding_2',\n type: 'integer',\n min: 0,\n },\n {\n name: 'alighting_2',\n type: 'integer',\n min: 0,\n },\n {\n name: 'departure_load',\n type: 'integer',\n min: 0,\n },\n {\n name: 'door_open',\n type: 'text',\n },\n {\n name: 'door_close',\n type: 'text',\n },\n {\n name: 'door_status',\n type: 'text',\n },\n {\n name: 'ramp_deployed_time',\n type: 'text',\n },\n {\n name: 'ramp_failure',\n type: 'text',\n },\n {\n name: 'kneel_deployed_time',\n type: 'integer',\n min: 0,\n },\n {\n name: 'lift_deployed_time',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_rack_deployed',\n type: 'text',\n },\n {\n name: 'bike_load',\n type: 'integer',\n min: 0,\n },\n {\n name: 'revenue',\n type: 'real',\n },\n {\n name: 'number_of_transactions',\n type: 'integer',\n min: 0,\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n },\n ],\n};\n","export const trainCars = {\n filenameBase: 'train_cars',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'train_car_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'model_name',\n type: 'text',\n },\n {\n name: 'facility_name',\n type: 'text',\n },\n {\n name: 'capacity_seated',\n type: 'integer',\n min: 0,\n },\n {\n name: 'capacity_wheelchair',\n type: 'integer',\n min: 0,\n },\n {\n name: 'capacity_bike',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_rack',\n type: 'text',\n },\n {\n name: 'capacity_standing',\n type: 'integer',\n min: 0,\n },\n {\n name: 'train_car_type',\n type: 'text',\n },\n ],\n};\n","export const tripsPerformed = {\n filenameBase: 'trips_performed',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'service_date',\n type: 'date',\n required: true,\n primary: true,\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n },\n {\n name: 'trip_id_scheduled',\n type: 'text',\n },\n {\n name: 'route_id',\n type: 'text',\n },\n {\n name: 'route_type',\n type: 'text',\n },\n {\n name: 'ntd_mode',\n type: 'text',\n },\n {\n name: 'route_type_agency',\n type: 'text',\n },\n {\n name: 'shape_id',\n type: 'text',\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'operator_id',\n type: 'text',\n },\n {\n name: 'block_id',\n type: 'text',\n },\n {\n name: 'trip_start_stop_id',\n type: 'text',\n },\n {\n name: 'trip_end_stop_id',\n type: 'text',\n },\n {\n name: 'schedule_trip_start',\n type: 'text',\n },\n {\n name: 'schedule_trip_end',\n type: 'text',\n },\n {\n name: 'actual_trip_start',\n type: 'text',\n },\n {\n name: 'actual_trip_end',\n type: 'text',\n },\n {\n name: 'trip_type',\n type: 'text',\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n },\n ],\n};\n","export const vehicleTrainCars = {\n filenameBase: 'vehicle_train_cars',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'train_car_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'train_car_order',\n type: 'integer',\n min: 0,\n },\n {\n name: 'operator_id',\n type: 'text',\n },\n ],\n};\n","export const vehicleLocations = {\n filenameBase: 'vehicle_locations',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'location_ping_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'service_date',\n type: 'date',\n },\n {\n name: 'event_timestamp',\n type: 'text',\n required: true,\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n },\n {\n name: 'trip_id_scheduled',\n type: 'text',\n },\n {\n name: 'trip_stop_sequence',\n type: 'integer',\n min: 1,\n },\n {\n name: 'scheduled_stop_sequence',\n type: 'integer',\n min: 0,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n },\n {\n name: 'device_id',\n type: 'text',\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'current_status',\n type: 'text',\n },\n {\n name: 'latitude',\n type: 'real',\n min: -90,\n max: 90,\n },\n {\n name: 'longitude',\n type: 'real',\n min: -180,\n max: 180,\n },\n {\n name: 'gps_quality',\n type: 'text',\n },\n {\n name: 'heading',\n type: 'real',\n min: 0,\n max: 360,\n },\n {\n name: 'speed',\n type: 'real',\n min: 0,\n },\n {\n name: 'odometer',\n type: 'real',\n min: 0,\n },\n {\n name: 'schedule_deviation',\n type: 'integer',\n },\n {\n name: 'headway_deviation',\n type: 'integer',\n },\n {\n name: 'trip_type',\n type: 'text',\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n },\n ],\n};\n","export const vehicles = {\n filenameBase: 'vehicles',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'vehicle_start',\n type: 'text',\n },\n {\n name: 'vehicle_end',\n type: 'text',\n },\n {\n name: 'model_name',\n type: 'text',\n },\n {\n name: 'facility_name',\n type: 'text',\n },\n {\n name: 'capacity_seated',\n type: 'integer',\n min: 0,\n },\n {\n name: 'capacity_wheelchair',\n type: 'integer',\n min: 0,\n },\n {\n name: 'capacity_bike',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_rack',\n type: 'text',\n },\n {\n name: 'capacity_standing',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","import fs from 'fs';\n\nimport Database from 'better-sqlite3';\n\nimport { untildify } from './file-utils.ts';\nimport { GtfsError, GtfsErrorCategory, GtfsErrorCode } from './errors.ts';\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 GtfsError(\n 'Multiple databases open, please specify which one to use.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { openDatabaseCount: Object.keys(dbs).length },\n },\n );\n }\n\n throw new GtfsError('Unable to find database connection.', {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n });\n}\n\nexport function closeDb(db: Database.Database | null = null): void {\n if (Object.keys(dbs).length === 0) {\n throw new GtfsError(\n 'No database connection. Call `openDb(config)` before using any methods.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n },\n );\n }\n\n if (!db) {\n if (Object.keys(dbs).length > 1) {\n throw new GtfsError(\n 'Multiple database connections. Pass the db you want to close as a parameter to `closeDb`.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { openDatabaseCount: Object.keys(dbs).length },\n },\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 GtfsError(\n 'No database connection. Call `openDb(config)` before using any methods.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n },\n );\n }\n\n if (!db) {\n if (Object.keys(dbs).length > 1) {\n throw new GtfsError(\n 'Multiple database connections. Pass the db you want to delete as a parameter to `deleteDb`.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { openDatabaseCount: Object.keys(dbs).length },\n },\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","export enum GtfsErrorCategory {\n CONFIG = 'config',\n DOWNLOAD = 'download',\n ZIP = 'zip',\n VALIDATION = 'validation',\n DATABASE = 'database',\n PARSE = 'parse',\n QUERY = 'query',\n INTERNAL = 'internal',\n}\n\n/**\n * Error codes are a public API contract and must remain stable across\n * minor/patch releases.\n */\nexport enum GtfsErrorCode {\n GTFS_DOWNLOAD_HTTP = 'GTFS_DOWNLOAD_HTTP',\n GTFS_DOWNLOAD_FAILED = 'GTFS_DOWNLOAD_FAILED',\n GTFS_ZIP_INVALID = 'GTFS_ZIP_INVALID',\n GTFS_REQUIRED_FIELD_MISSING = 'GTFS_REQUIRED_FIELD_MISSING',\n GTFS_INVALID_DATE = 'GTFS_INVALID_DATE',\n GTFS_CONFIG_INVALID = 'GTFS_CONFIG_INVALID',\n DB_OPEN_FAILED = 'DB_OPEN_FAILED',\n GTFS_DB_OPERATION_FAILED = 'GTFS_DB_OPERATION_FAILED',\n GTFS_JSON_INVALID = 'GTFS_JSON_INVALID',\n GTFS_UNSUPPORTED_FILE_TYPE = 'GTFS_UNSUPPORTED_FILE_TYPE',\n GTFS_CSV_PARSE_FAILED = 'GTFS_CSV_PARSE_FAILED',\n GTFS_QUERY_INVALID = 'GTFS_QUERY_INVALID',\n}\n\nexport enum GtfsWarningCode {\n GTFS_DUPLICATE_PRIMARY_KEY = 'GTFS_DUPLICATE_PRIMARY_KEY',\n}\n\nexport interface GtfsWarning {\n code: GtfsWarningCode;\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport interface ImportReport {\n errors: GtfsError[];\n warnings: GtfsWarning[];\n errorCountsByCode: Partial<Record<GtfsErrorCode, number>>;\n warningCountsByCode: Partial<Record<GtfsWarningCode, number>>;\n}\n\ninterface GtfsErrorOptions {\n code: GtfsErrorCode;\n category: GtfsErrorCategory;\n isOperational?: boolean;\n statusCode?: number;\n details?: Record<string, unknown>;\n cause?: unknown;\n}\n\nexport class GtfsError extends Error {\n code: GtfsErrorCode;\n category: GtfsErrorCategory;\n isOperational: boolean;\n statusCode?: number;\n details?: Record<string, unknown>;\n\n constructor(message: string, options: GtfsErrorOptions) {\n super(message, { cause: options.cause });\n this.name = 'GtfsError';\n this.code = options.code;\n this.category = options.category;\n this.isOperational = options.isOperational ?? true;\n this.statusCode = options.statusCode;\n this.details = options.details;\n }\n}\n\nexport function isGtfsError(error: unknown): error is GtfsError {\n if (!error || typeof error !== 'object') {\n return false;\n }\n\n const candidate = error as Partial<GtfsError> & { name?: unknown };\n return (\n candidate.name === 'GtfsError' &&\n typeof candidate.message === 'string' &&\n typeof candidate.code === 'string' &&\n typeof candidate.category === 'string' &&\n typeof candidate.isOperational === 'boolean'\n );\n}\n\nexport function isGtfsValidationError(error: unknown): error is GtfsError {\n return isGtfsError(error) && error.category === GtfsErrorCategory.VALIDATION;\n}\n\nexport function toGtfsError(\n error: unknown,\n fallback: Omit<GtfsErrorOptions, 'cause'> & { message: string },\n): GtfsError {\n if (isGtfsError(error)) {\n return error;\n }\n\n return new GtfsError(fallback.message, {\n ...fallback,\n cause: error,\n });\n}\n\nexport function createImportReport(): ImportReport {\n return {\n errors: [],\n warnings: [],\n errorCountsByCode: {},\n warningCountsByCode: {},\n };\n}\n\nexport function addImportError(report: ImportReport, error: GtfsError): void {\n report.errors.push(error);\n report.errorCountsByCode[error.code] =\n (report.errorCountsByCode[error.code] ?? 0) + 1;\n}\n\nexport function addImportWarning(\n report: ImportReport,\n warning: GtfsWarning,\n): void {\n report.warnings.push(warning);\n report.warningCountsByCode[warning.code] =\n (report.warningCountsByCode[warning.code] ?? 0) + 1;\n}\n\nexport function formatGtfsError(\n error: unknown,\n options: { verbosity: 'user' | 'developer' } = { verbosity: 'developer' },\n) {\n if (!isGtfsError(error)) {\n const message = error instanceof Error ? error.message : String(error);\n return options.verbosity === 'user' ? message : `UNKNOWN_ERROR: ${message}`;\n }\n\n if (options.verbosity === 'user') {\n return error.message;\n }\n\n return [\n `${error.code}: ${error.message}`,\n `category=${error.category}`,\n error.statusCode !== undefined ? `statusCode=${error.statusCode}` : null,\n error.details ? `details=${JSON.stringify(error.details)}` : null,\n ]\n .filter(Boolean)\n .join(' | ');\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\n/** Represents a GeoJSON coordinate pair [longitude, latitude] */\ntype Position = [number, number];\n\n/**\n * Validates if a string is valid JSON\n * @param {string} string - The string to validate as JSON\n * @returns {boolean} True if string is valid JSON, false otherwise\n * @example\n * isValidJSON('{\"key\": \"value\"}') // returns true\n * isValidJSON('invalid json') // returns false\n */\nexport function isValidJSON(string: string): boolean {\n try {\n JSON.parse(string);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Validates if an array of positions forms a valid LineString\n * @param {Position[]} [lineString] - Array of coordinate pairs\n * @returns {boolean} True if lineString is valid, false otherwise\n */\nfunction isValidLineString(lineString?: Position[]): boolean {\n if (!lineString || lineString.length <= 1) {\n return false;\n }\n\n // Reject linestrings with two identical points\n if (lineString.length === 2) {\n const [[x1, y1], [x2, y2]] = lineString;\n return !(x1 === x2 && y1 === y2);\n }\n\n return true;\n}\n\n/**\n * Consolidates shape groups into unique line segments\n * @param {Shape[][]} shapeGroups - Array of shape point groups\n * @returns {Position[][]} Array of consolidated line strings\n */\nfunction consolidateShapes(shapeGroups: Shape[][]): Position[][] {\n const keys = new Set<string>();\n const segmentsArray = shapeGroups.map((shapes) =>\n shapes.reduce<Position[][]>((memo, point, idx) => {\n if (idx > 0) {\n const prevPoint = shapes[idx - 1];\n memo.push([\n [prevPoint.shape_pt_lon, prevPoint.shape_pt_lat],\n [point.shape_pt_lon, point.shape_pt_lat],\n ]);\n }\n return memo;\n }, []),\n );\n\n const consolidatedLineStrings: Position[][] = [];\n\n for (const segments of segmentsArray) {\n consolidatedLineStrings.push([]);\n\n for (const segment of segments) {\n const key1 = segment.flat().join(',');\n const key2 = segment.reverse().flat().join(',');\n const currentLine = last(consolidatedLineStrings);\n\n if (!currentLine || keys.has(key1) || keys.has(key2)) {\n consolidatedLineStrings.push([]);\n continue;\n }\n\n if (currentLine.length === 0) {\n currentLine.push(segment[0]);\n }\n currentLine.push(segment[1]);\n keys.add(key1);\n keys.add(key2);\n }\n }\n\n return filter(consolidatedLineStrings, isValidLineString);\n}\n\n/**\n * Formats a color string to hex format\n * @param {string | null | undefined} color - Color string to format\n * @returns {string | undefined} Formatted hex color or undefined\n * @example\n * formatHexColor('FF0000') // returns '#FF0000'\n */\nfunction formatHexColor(color: string | null | undefined): string | undefined {\n if (!color) return undefined;\n return `#${color}`;\n}\n\n/**\n * Formats properties object by cleaning null values and formatting colors\n * @param {Record<string, unknown>} properties - Properties object to format\n * @returns {Record<string, unknown>} Formatted properties object\n */\nfunction formatProperties(\n properties: Record<string, unknown>,\n): Record<string, unknown> {\n const formattedProperties = cloneDeep(\n omitBy(properties, (value) => value == null),\n );\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 && Array.isArray(properties.routes)) {\n formattedProperties.routes = properties.routes.map(\n (route: Record<string, unknown>) => formatProperties(route),\n );\n }\n\n return formattedProperties;\n}\n\n/**\n * Converts GTFS shapes to GeoJSON Feature\n * @param {Shape[]} shapes - Array of GTFS shapes\n * @param {Record<string, unknown>} [properties={}] - Properties to add to the feature\n * @returns {Feature} GeoJSON Feature with MultiLineString geometry\n */\nexport function shapesToGeoJSONFeature(\n shapes: Shape[],\n properties: Record<string, unknown> = {},\n) {\n const shapeGroups = Object.values(groupBy(shapes, 'shape_id')).map(\n (shapeGroup) => sortBy(shapeGroup, 'shape_pt_sequence'),\n );\n\n const lineStrings = consolidateShapes(shapeGroups);\n\n return feature(\n {\n type: 'MultiLineString',\n coordinates: lineStrings,\n },\n formatProperties(properties),\n );\n}\n\n/**\n * Converts GTFS stops to GeoJSON FeatureCollection\n * @param {Stop[]} stops - Array of GTFS stops\n * @returns {FeatureCollection} GeoJSON FeatureCollection of Point features\n */\nexport function stopsToGeoJSONFeatureCollection(stops: Stop[]) {\n const features = compact(\n stops.map((stop) => {\n if (!stop.stop_lon || !stop.stop_lat) {\n return undefined;\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 GtfsRealtimeBindings from 'gtfs-realtime-bindings';\nimport mapSeries from 'promise-map-series';\nimport { get } from 'lodash-es';\nimport Database from 'better-sqlite3';\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 applyPrefixToValue,\n pluralize,\n setDefaultConfig,\n validateConfigForImport,\n} from './utils.ts';\nimport {\n addImportError,\n formatGtfsError,\n GtfsError,\n GtfsErrorCategory,\n GtfsErrorCode,\n ImportReport,\n toGtfsError,\n} from './errors.ts';\n\nimport {\n Config,\n ConfigAgency,\n ModelColumn,\n Model,\n} from '../types/global_interfaces.ts';\n\ninterface RealtimeUrlConfig {\n url: string;\n headers?: Record<string, string>;\n}\n\ninterface GtfsRealtimeTask {\n realtimeAlerts?: RealtimeUrlConfig;\n realtimeTripUpdates?: RealtimeUrlConfig;\n realtimeVehiclePositions?: RealtimeUrlConfig;\n downloadTimeout?: number;\n gtfsRealtimeExpirationSeconds: number;\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 report?: ImportReport;\n}\n\ninterface ProcessedEntity {\n id: string;\n alert?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n tripUpdate?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n vehicle?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\ninterface RealtimeData {\n entity: ProcessedEntity[];\n}\n\ninterface ProcessingResult {\n recordCount: number;\n errorCount: number;\n}\n\ninterface BatchProcessor<T> {\n (batch: T[]): Promise<ProcessingResult>;\n}\n\nconst BATCH_SIZE = 1000;\nconst MAX_RETRIES = 3;\nconst RETRY_DELAY = 1000;\n\n/**\n * Prepares a field value for database insertion\n */\nfunction prepareRealtimeFieldValue(\n entity: any, // eslint-disable-line @typescript-eslint/no-explicit-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 const baseValue =\n column.source === undefined\n ? column.default\n : get(entity, column.source, column.default);\n\n const timeAdjustedValue = baseValue?.__isLong__\n ? convertLongTimeToDate(baseValue)\n : baseValue;\n\n const prefixedValue = applyPrefixToValue(\n timeAdjustedValue,\n column.prefix,\n task.prefix,\n );\n\n return column.type === 'json' ? JSON.stringify(prefixedValue) : prefixedValue;\n}\n\n/**\n * Creates a prepared statement for a model\n */\nfunction createPreparedStatement(db: Database.Database, model: Model) {\n const columns = model.schema.map((column: ModelColumn) => column.name);\n const placeholders = model.schema.map(() => '?').join(', ');\n\n return db.prepare(\n `REPLACE INTO ${model.filenameBase} (${columns.join(', ')}) VALUES (${placeholders})`,\n );\n}\n\n/**\n * Processes entities in batches\n */\nasync function processBatch<T>(\n items: T[],\n batchSize: number,\n processor: BatchProcessor<T>,\n): Promise<ProcessingResult> {\n let totalRecordCount = 0;\n let totalErrorCount = 0;\n\n for (let i = 0; i < items.length; i += batchSize) {\n const batch = items.slice(i, i + batchSize);\n try {\n const result = await processor(batch);\n totalRecordCount += result.recordCount;\n totalErrorCount += result.errorCount;\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n totalErrorCount += batch.length;\n console.error(`Batch processing error: ${errorMessage}`);\n }\n }\n\n return { recordCount: totalRecordCount, errorCount: totalErrorCount };\n}\n\n/**\n * Fetches GTFS Realtime data\n */\nasync function fetchGtfsRealtimeData(\n type: 'alerts' | 'tripupdates' | 'vehiclepositions',\n task: GtfsRealtimeTask,\n): Promise<RealtimeData | null> {\n const urlConfig = getUrlConfig(type, task);\n\n if (!urlConfig) {\n return null;\n }\n\n task.log(`Importing - GTFS-Realtime from ${urlConfig.url}`);\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n try {\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 throw new GtfsError(`HTTP ${response.status}: ${response.statusText}`, {\n code: GtfsErrorCode.GTFS_DOWNLOAD_HTTP,\n category: GtfsErrorCategory.DOWNLOAD,\n statusCode: response.status,\n details: {\n url: urlConfig.url,\n status: response.status,\n statusText: response.statusText,\n },\n });\n }\n\n const buffer = await response.arrayBuffer();\n const message = GtfsRealtimeBindings.transit_realtime.FeedMessage.decode(\n new Uint8Array(buffer),\n );\n\n const feedMessage =\n GtfsRealtimeBindings.transit_realtime.FeedMessage.toObject(message, {\n enums: String,\n longs: String,\n bytes: String,\n defaults: false,\n arrays: true,\n objects: true,\n oneofs: true,\n }) as RealtimeData;\n\n return feedMessage;\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DOWNLOAD_FAILED,\n category: GtfsErrorCategory.DOWNLOAD,\n details: { type, url: urlConfig.url },\n });\n if (attempt === MAX_RETRIES) {\n if (task.ignoreErrors) {\n task.logError(\n `Failed to fetch ${type} after ${MAX_RETRIES} attempts: ${gtfsError.message}`,\n );\n if (task.report) {\n addImportError(task.report, gtfsError);\n }\n return null;\n }\n throw gtfsError;\n }\n\n task.logWarning(\n `Attempt ${attempt} failed for ${type}: ${gtfsError.message}`,\n );\n await new Promise((resolve) =>\n setTimeout(resolve, RETRY_DELAY * attempt),\n );\n }\n }\n\n return null;\n}\n\n/**\n * Gets URL configuration for a specific realtime type\n */\nfunction getUrlConfig(\n type: 'alerts' | 'tripupdates' | 'vehiclepositions',\n task: GtfsRealtimeTask,\n): RealtimeUrlConfig | undefined {\n switch (type) {\n case 'alerts':\n return task.realtimeAlerts;\n case 'tripupdates':\n return task.realtimeTripUpdates;\n case 'vehiclepositions':\n return task.realtimeVehiclePositions;\n default:\n return undefined;\n }\n}\n\n/**\n * Creates a processor for service alerts\n */\nfunction createServiceAlertsProcessor(\n db: Database.Database,\n task: GtfsRealtimeTask,\n): BatchProcessor<ProcessedEntity> {\n const alertStmt = createPreparedStatement(db, models.serviceAlerts as Model);\n const informedEntityStmt = createPreparedStatement(\n db,\n models.serviceAlertInformedEntities as Model,\n );\n\n return async (batch: ProcessedEntity[]): Promise<ProcessingResult> => {\n let recordCount = 0;\n let errorCount = 0;\n\n db.transaction(() => {\n for (const entity of batch) {\n try {\n // Process main alert\n const alertValues = (\n models.serviceAlerts.schema as ModelColumn[]\n ).map((column) => prepareRealtimeFieldValue(entity, column, task));\n alertStmt.run(alertValues);\n recordCount++;\n\n // Process informed entities\n if (entity.alert?.informedEntity?.length) {\n for (const informedEntity of entity.alert.informedEntity) {\n informedEntity.parent = entity;\n const entityValues = (\n models.serviceAlertInformedEntities.schema as ModelColumn[]\n ).map((column) =>\n prepareRealtimeFieldValue(informedEntity, column, task),\n );\n informedEntityStmt.run(entityValues);\n recordCount++;\n }\n }\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n errorCount++;\n task.logWarning(`Alert processing error: ${errorMessage}`);\n }\n }\n })();\n\n return { recordCount, errorCount };\n };\n}\n\n/**\n * Creates a processor for trip updates\n */\nfunction createTripUpdatesProcessor(\n db: Database.Database,\n task: GtfsRealtimeTask,\n): BatchProcessor<ProcessedEntity> {\n const tripUpdateStmt = createPreparedStatement(\n db,\n models.tripUpdates as Model,\n );\n const stopTimeStmt = createPreparedStatement(\n db,\n models.stopTimeUpdates as Model,\n );\n\n return async (batch: ProcessedEntity[]): Promise<ProcessingResult> => {\n let recordCount = 0;\n let errorCount = 0;\n\n db.transaction(() => {\n for (const entity of batch) {\n try {\n // Process main trip update\n const tripUpdateValues = (\n models.tripUpdates.schema as ModelColumn[]\n ).map((column) => prepareRealtimeFieldValue(entity, column, task));\n tripUpdateStmt.run(tripUpdateValues);\n recordCount++;\n\n // Process stop time updates\n if (entity.tripUpdate?.stopTimeUpdate?.length) {\n for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {\n stopTimeUpdate.parent = entity;\n const stopTimeValues = (\n models.stopTimeUpdates.schema as ModelColumn[]\n ).map((column) =>\n prepareRealtimeFieldValue(stopTimeUpdate, column, task),\n );\n stopTimeStmt.run(stopTimeValues);\n recordCount++;\n }\n }\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n errorCount++;\n task.logWarning(`Trip update processing error: ${errorMessage}`);\n }\n }\n })();\n\n return { recordCount, errorCount };\n };\n}\n\n/**\n * Creates a processor for vehicle positions\n */\nfunction createVehiclePositionsProcessor(\n db: Database.Database,\n task: GtfsRealtimeTask,\n): BatchProcessor<ProcessedEntity> {\n const vehiclePositionStmt = createPreparedStatement(\n db,\n models.vehiclePositions as Model,\n );\n\n return async (batch: ProcessedEntity[]): Promise<ProcessingResult> => {\n let recordCount = 0;\n let errorCount = 0;\n\n db.transaction(() => {\n for (const entity of batch) {\n try {\n const fieldValues = (\n models.vehiclePositions.schema as ModelColumn[]\n ).map((column) => prepareRealtimeFieldValue(entity, column, task));\n vehiclePositionStmt.run(fieldValues);\n recordCount++;\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n errorCount++;\n task.logWarning(`Vehicle position processing error: ${errorMessage}`);\n }\n }\n })();\n\n return { recordCount, errorCount };\n };\n}\n\n/**\n * Removes expired GTFS-Realtime data\n */\nfunction removeExpiredRealtimeData(config: Config): void {\n const db = openDb(config);\n\n log(config)(`Removing expired GTFS-Realtime data`);\n\n db.transaction(() => {\n const tables = [\n 'vehicle_positions',\n 'trip_updates',\n 'stop_time_updates',\n 'service_alerts',\n 'service_alert_informed_entities',\n ];\n\n for (const table of tables) {\n db.prepare(\n `DELETE FROM ${table} WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n }\n })();\n\n log(config)(`Removed expired GTFS-Realtime data\\r`, true);\n}\n\n/**\n * Updates GTFS Realtime data\n */\nexport async function updateGtfsRealtimeData(\n task: GtfsRealtimeTask,\n): Promise<void> {\n if (\n !task.realtimeAlerts &&\n !task.realtimeTripUpdates &&\n !task.realtimeVehiclePositions\n ) {\n return;\n }\n\n // Download all data types in parallel\n const [alertsData, tripUpdatesData, vehiclePositionsData] = await Promise.all(\n [\n task.realtimeAlerts?.url ? fetchGtfsRealtimeData('alerts', task) : null,\n task.realtimeTripUpdates?.url\n ? fetchGtfsRealtimeData('tripupdates', task)\n : null,\n task.realtimeVehiclePositions?.url\n ? fetchGtfsRealtimeData('vehiclepositions', task)\n : null,\n ],\n );\n\n const db = openDb({ sqlitePath: task.sqlitePath });\n\n const recordCounts = {\n alerts: 0,\n tripupdates: 0,\n vehiclepositions: 0,\n };\n\n // Process each data type with batching\n const processingPromises: Promise<void>[] = [];\n\n if (alertsData?.entity?.length) {\n processingPromises.push(\n processBatch(\n alertsData.entity,\n BATCH_SIZE,\n createServiceAlertsProcessor(db, task),\n ).then((result) => {\n recordCounts.alerts = result.recordCount;\n }),\n );\n }\n\n if (tripUpdatesData?.entity?.length) {\n processingPromises.push(\n processBatch(\n tripUpdatesData.entity,\n BATCH_SIZE,\n createTripUpdatesProcessor(db, task),\n ).then((result) => {\n recordCounts.tripupdates = result.recordCount;\n }),\n );\n }\n\n if (vehiclePositionsData?.entity?.length) {\n processingPromises.push(\n processBatch(\n vehiclePositionsData.entity,\n BATCH_SIZE,\n createVehiclePositionsProcessor(db, task),\n ).then((result) => {\n recordCounts.vehiclepositions = result.recordCount;\n }),\n );\n }\n\n // Wait for all processing to complete\n await Promise.all(processingPromises);\n\n task.log(\n `GTFS-Realtime import complete: ${recordCounts.alerts} alerts, ${recordCounts.tripupdates} trip updates, ${recordCounts.vehiclepositions} vehicle positions`,\n );\n}\n\n/**\n * Main function to update GTFS Realtime data\n */\nexport async function updateGtfsRealtime(initialConfig: Config): Promise<void> {\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 'agency',\n 'agencies',\n agencyCount,\n )} using SQLite database at ${config.sqlitePath}`,\n );\n\n removeExpiredRealtimeData(config);\n\n await mapSeries(config.agencies, async (agency: ConfigAgency) => {\n let task: GtfsRealtimeTask | undefined;\n try {\n 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 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 await updateGtfsRealtimeData(task);\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { sqlitePath: task?.sqlitePath ?? config.sqlitePath },\n });\n if (config.ignoreErrors) {\n logError(config)(formatGtfsError(gtfsError));\n if (task?.report) {\n addImportError(task.report, gtfsError);\n }\n } else {\n throw gtfsError;\n }\n }\n });\n\n log(config)(\n `Completed GTFS-Realtime refresh for ${pluralize(\n 'agency',\n 'agencies',\n agencyCount,\n )}\\n`,\n );\n } catch (error: unknown) {\n if ((error as Error & { code?: string }).code === 'SQLITE_CANTOPEN') {\n const dbOpenError = new GtfsError(\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 code: GtfsErrorCode.DB_OPEN_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: {\n sqlitePath: config.sqlitePath,\n dbCode: (error as Error & { code?: string }).code,\n },\n cause: error,\n },\n );\n logError(config)(dbOpenError.message);\n throw dbOpenError;\n }\n throw toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n });\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';\nimport { GtfsError, GtfsErrorCategory, GtfsErrorCode } from './errors.ts';\n\n/**\n * Validates the configuration object for GTFS import\n * @param config The configuration object to validate\n * @throws Error if agencies are missing or if agency lacks both url and path\n * @returns The validated config object\n */\nexport function validateConfigForImport(config: Config) {\n if (!config.agencies || config.agencies.length === 0) {\n throw new GtfsError('No `agencies` specified in config', {\n code: GtfsErrorCode.GTFS_CONFIG_INVALID,\n category: GtfsErrorCategory.CONFIG,\n details: { field: 'agencies' },\n });\n }\n\n for (const [index, agency] of config.agencies.entries()) {\n if (!agency.path && !agency.url) {\n throw new GtfsError(\n `No Agency \\`url\\` or \\`path\\` specified in config for agency index ${index}.`,\n {\n code: GtfsErrorCode.GTFS_CONFIG_INVALID,\n category: GtfsErrorCategory.CONFIG,\n details: { agencyIndex: index },\n },\n );\n }\n }\n\n return config;\n}\n\n/**\n * Initializes configuration with default values\n * @param initialConfig The user-provided configuration\n * @returns Merged 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 verbose: true,\n downloadTimeout: 30000,\n };\n\n return {\n ...defaults,\n ...initialConfig,\n };\n}\n\n/**\n * Converts a Long timestamp to ISO date string\n * @param longDate Object containing high, low, and unsigned values\n * @returns ISO formatted date string\n */\nexport function convertLongTimeToDate(longDate: {\n high: number;\n low: number;\n unsigned: boolean;\n}) {\n const { high, low, unsigned } = longDate;\n return new Date(\n Long.fromBits(low, high, unsigned).toNumber() * 1000,\n ).toISOString();\n}\n\n/**\n * Converts time string in HH:mm:ss format to seconds since midnight\n * @param time Time string in HH:mm:ss format\n * @returns Number of seconds since midnight, or null if invalid format\n */\nexport function calculateSecondsFromMidnight(time: string): number | null {\n if (!time || typeof time !== 'string') {\n return null;\n }\n\n const [hours, minutes, seconds] = time.split(':').map(Number);\n\n if ([hours, minutes, seconds].some(isNaN) || minutes >= 60 || seconds >= 60) {\n return null;\n }\n\n return hours * 3600 + minutes * 60 + seconds;\n}\n\n/**\n * Ensures time components have leading zeros (e.g., \"9:5:1\" -> \"09:05:01\")\n * @param time Time string in HH:mm:ss format\n * @returns Formatted time string with leading zeros, or null if invalid format\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\n/**\n * Formats SQL SELECT clause from array of field names or field mapping object\n * @param fields Array of field names or object mapping source to alias\n * @returns Formatted SELECT clause\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\n/**\n * Formats SQL JOIN clause from array of join configurations\n * @param joinObject Array of join options\n * @returns Formatted JOIN clause\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\n/**\n * Converts degrees to radians\n * @param angle Angle in degrees\n * @returns Angle in radians\n */\nfunction degree2radian(angle: number) {\n return (angle * Math.PI) / 180;\n}\n\n/**\n * Converts radians to degrees\n * @param angle Angle in radians\n * @returns Angle in degrees\n */\nfunction radian2degree(angle: number) {\n return (angle / Math.PI) * 180;\n}\n\nconst EARTH_RADIUS_METERS = 6371000;\n\n/**\n * Creates SQL WHERE clause for geographic bounding box search\n * @param latitudeDegree Center latitude in degrees\n * @param longitudeDegree Center longitude in degrees\n * @param boundingBoxSideMeters Size of bounding box in meters\n * @returns SQL WHERE clause for bounding box search\n */\nexport function formatWhereClauseBoundingBox(\n latitudeDegree: number | string,\n longitudeDegree: number | string,\n boundingBoxSideMeters: number,\n): string {\n const lat = Number(latitudeDegree);\n const lon = Number(longitudeDegree);\n\n if (\n isNaN(lat) ||\n isNaN(lon) ||\n lat < -90 ||\n lat > 90 ||\n lon < -180 ||\n lon > 180\n ) {\n throw new GtfsError('Invalid latitude or longitude values', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { latitudeDegree, longitudeDegree, boundingBoxSideMeters },\n });\n }\n\n const latitudeRadian = degree2radian(lat);\n const radiusFromLatitude = Math.cos(latitudeRadian) * EARTH_RADIUS_METERS;\n\n const halfSide = boundingBoxSideMeters / 2;\n const deltaLatitude = radian2degree(halfSide / EARTH_RADIUS_METERS);\n const deltaLongitude = radian2degree(halfSide / radiusFromLatitude);\n\n return [\n `stop_lat BETWEEN ${lat - deltaLatitude} AND ${lat + deltaLatitude}`,\n `stop_lon BETWEEN ${lon - deltaLongitude} AND ${lon + deltaLongitude}`,\n ].join(' AND ');\n}\n\n/**\n * Formats SQL WHERE clause for a single key-value pair\n * @param key Column name\n * @param value Single value, array of values, or null\n * @returns Formatted WHERE clause condition\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\n/**\n * Formats complete SQL WHERE clause from query object\n * @param query Object containing column-value pairs\n * @returns Formatted WHERE clause or empty string if no conditions\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\n/**\n * Formats SQL ORDER BY clause from array of sorting criteria\n * @param orderBy Array of [column, direction] tuples\n * @returns Formatted ORDER BY clause\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\n/**\n * Gets day of week name from YYYYMMDD date number\n * @param date Date in YYYYMMDD format\n * @returns Lowercase day name (sunday-saturday)\n */\nexport function getDayOfWeekFromDate(date: number): string {\n const DAYS_OF_WEEK = [\n 'sunday',\n 'monday',\n 'tuesday',\n 'wednesday',\n 'thursday',\n 'friday',\n 'saturday',\n ] as const;\n\n if (!Number.isInteger(date) || date.toString().length !== 8) {\n throw new GtfsError('Date must be in YYYYMMDD format', {\n code: GtfsErrorCode.GTFS_INVALID_DATE,\n category: GtfsErrorCategory.VALIDATION,\n details: { value: date },\n });\n }\n\n const year = Math.floor(date / 10000);\n const month = Math.floor((date % 10000) / 100);\n const day = date % 100;\n\n const dateObj = new Date(year, month - 1, day);\n\n if (dateObj.toString() === 'Invalid Date') {\n throw new GtfsError('Invalid date', {\n code: GtfsErrorCode.GTFS_INVALID_DATE,\n category: GtfsErrorCategory.VALIDATION,\n details: { value: date },\n });\n }\n\n return DAYS_OF_WEEK[dateObj.getDay()];\n}\n\n/**\n * Formats a numeric value according to the decimal precision rules of the specified currency,\n * without any currency symbols or separators.\n * @param value The numeric value to format (e.g., 10.5)\n * @param currency The ISO 4217 currency code (e.g., 'USD', 'JPY', 'EUR')\n * @returns The formatted string with appropriate decimal places\n * Examples:\n * - formatCurrency(10.5, 'USD') => '10.50' // USD uses 2 decimal places\n * - formatCurrency(10.5, 'JPY') => '10' // JPY uses 0 decimal places\n * - formatCurrency(10.523, 'BHD') => '10.523' // BHD uses 3 decimal places\n */\nexport function formatCurrency(value: number, currency: string) {\n const parts = new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n }).formatToParts(value);\n\n const integerPart =\n parts.find((part) => part.type === 'integer')?.value ?? '0';\n const fractionPart =\n parts.find((part) => part.type === 'fraction')?.value ?? '';\n\n return `${integerPart}${fractionPart !== '' ? `.${fractionPart}` : ''}`;\n}\n\n/**\n * Gets the timestamp column name for a given column name\n * @param columnName The column name\n * @returns The timestamp column name\n */\nexport function getTimestampColumnName(columnName: string) {\n return columnName.endsWith('time')\n ? `${columnName}stamp`\n : `${columnName}_timestamp`;\n}\n\n/**\n * Applies a prefix to a value if the column should be prefixed and the value is not null\n * @param value The value to prefix\n * @param columnShouldBePrefixed Whether the column should be prefixed\n * @param prefix The prefix to apply\n * @returns The value with the prefix applied if the column should be prefixed and the value is not null\n */\nexport function applyPrefixToValue(\n value: string,\n columnShouldBePrefixed?: boolean,\n prefix?: string,\n) {\n if (!columnShouldBePrefixed || prefix === undefined || value === null) {\n return value;\n }\n\n return `${prefix}${value}`;\n}\n\n/**\n * Pluralizes a word based on the count\n * @param singularWord The singular word\n * @param pluralWord The plural word\n * @param count The count of the word\n * @returns The pluralized word\n */\nexport function pluralize(\n singularWord: string,\n pluralWord: string,\n count: number,\n) {\n return count === 1 ? singularWord : pluralWord;\n}\n","import path from 'node:path';\nimport { writeFile } from 'node:fs/promises';\n\nimport { without, compact } from 'lodash-es';\nimport { stringify } from 'csv-stringify';\nimport sqlString from 'sqlstring-sqlite';\nimport Database from 'better-sqlite3';\nimport mapSeries from 'promise-map-series';\n\nimport * as models from '../models/models.ts';\nimport { openDb } from './db.ts';\nimport { prepDirectory, generateFolderName, untildify } from './file-utils.ts';\nimport { log, logWarning } from './log-utils.ts';\nimport { formatCurrency, pluralize, setDefaultConfig } from './utils.ts';\n\nimport { Config, Model, SqlValue } 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 {\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 'agencies',\n agencyCount,\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) as Model[]).filter(\n (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.prepare(`SELECT * FROM ${tableName};`).all() as Array<\n Record<string, SqlValue>\n >;\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\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 } else if (model.filenameBase === 'fare_attributes') {\n for (const line of lines) {\n line.price = formatCurrency(\n line.price as number,\n line.currency_type as string,\n );\n }\n } else if (model.filenameBase === 'fare_products') {\n for (const line of lines) {\n line.amount = formatCurrency(\n line.amount as number,\n line.currency as string,\n );\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 as string);\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', 'agencies', agencyCount)}\\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 type {\n JoinOptions,\n QueryOptions,\n SqlOrderBy,\n SqlWhere,\n SqlValue,\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?: string[];\n orderBy?: SqlOrderBy;\n join?: JoinOptions[];\n options?: QueryOptions;\n },\n) {\n const defaultOptions: {\n query: SqlWhere;\n fields: string[];\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 Array<Record<string, SqlValue>>;\n}\n","import { omit, pick } from 'lodash-es';\n\nimport type {\n QueryOptions,\n Route,\n SqlOrderBy,\n QueryResult,\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<Fields extends keyof Route>(\n query: SqlWhere = {},\n fields: Fields[] = [],\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 const routeQuery = omit(query, ['stop_id', 'service_id']);\n const tripQuery = pick(query, ['stop_id', 'service_id']) as {\n stop_id?: string;\n service_id?: string;\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 QueryResult<Route, Fields>[];\n}\n","import { compact, omit, pick } from 'lodash-es';\nimport { FeatureCollection } from 'geojson';\nimport { featureCollection } from '@turf/helpers';\n\nimport type {\n QueryOptions,\n Shape,\n SqlOrderBy,\n QueryResult,\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 | number }) {\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<Fields extends keyof Shape>(\n query: SqlWhere = {},\n fields: Fields[] = [],\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 = pick(query, [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n ]) as {\n route_id?: string;\n trip_id?: string;\n service_id?: string;\n direction_id?: number;\n };\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 QueryResult<Shape, Fields>[];\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(shapeQuery, [], [], options);\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 type {\n QueryOptions,\n SqlOrderBy,\n QueryResult,\n SqlWhere,\n Stop,\n SqlValue,\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]: SqlValue }) {\n const whereClause = formatWhereClauses(query);\n return `SELECT trip_id FROM trips ${whereClause}`;\n}\n\nfunction buildStoptimeSubquery(query: { [key: string]: SqlValue }) {\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<Fields extends keyof Stop>(\n query: SqlWhere = {},\n fields: Fields[] = [],\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 let 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 const stopQuery = omit(query, stopQueryOmitKeys);\n\n const tripQuery = pick(query, [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n 'shape_id',\n ]) as {\n route_id?: string;\n trip_id?: string;\n service_id?: string;\n direction_id?: number;\n shape_id?: string;\n };\n\n const whereClauses = Object.entries(stopQuery).map(([key, value]) =>\n formatWhereClause(key, value as SqlValue),\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 // Add distance-based sorting if bounding_box_side_m is set and no other orderBy is set\n if (orderBy.length === 0) {\n orderByClause = `ORDER BY (((stop_lat - ${query.stop_lat}) * (stop_lat - ${query.stop_lat})) + ((stop_lon - ${query.stop_lon}) * (stop_lon - ${query.stop_lon}))) ASC`;\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 QueryResult<Stop, Fields>[];\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 type {\n QueryOptions,\n SqlOrderBy,\n QueryResult,\n SqlWhere,\n StopTime,\n SqlValue,\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 { GtfsError, GtfsErrorCategory, GtfsErrorCode } from '../errors.ts';\nimport { getServiceIdsByDate } from './calendars.ts';\n\n/*\n * Returns an array of stoptimes that match the query parameters.\n */\nexport function getStoptimes<Fields extends keyof StopTime>(\n query: SqlWhere = {},\n fields: Fields[] = [],\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 const stoptimeQuery = omit(query, stoptimeQueryOmitKeys);\n const whereClauses = Object.entries(stoptimeQuery).map(([key, value]) =>\n formatWhereClause(key, value as SqlValue),\n );\n\n if (query.date) {\n if (typeof query.date !== 'number') {\n throw new GtfsError('`date` must be a number in yyyymmdd format', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { field: 'date', value: query.date },\n });\n }\n\n const serviceIds = getServiceIdsByDate(query.date, options);\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 GtfsError('`start_time` must be a string in HH:mm:ss format', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { field: 'start_time', value: query.start_time },\n });\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 GtfsError('`end_time` must be a string in HH:mm:ss format', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { field: 'end_time', value: query.end_time },\n });\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 QueryResult<StopTime, Fields>[];\n}\n","import { omit } from 'lodash-es';\nimport sqlString from 'sqlstring-sqlite';\nimport type {\n QueryOptions,\n SqlOrderBy,\n QueryResult,\n SqlWhere,\n Trip,\n SqlValue,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n} from '../utils.ts';\nimport { GtfsError, GtfsErrorCategory, GtfsErrorCode } from '../errors.ts';\nimport { getServiceIdsByDate } from './calendars.ts';\n\n/*\n * Returns an array of all trips that match the query parameters.\n */\nexport function getTrips<Fields extends keyof Trip>(\n query: SqlWhere = {},\n fields: Fields[] = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'trips';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const tripQueryOmitKeys = ['date'];\n\n const tripQuery = omit(query, tripQueryOmitKeys);\n\n const whereClauses = Object.entries(tripQuery).map(([key, value]) =>\n formatWhereClause(key, value as SqlValue),\n );\n\n if (query.date) {\n if (typeof query.date !== 'number') {\n throw new GtfsError('`date` must be a number in yyyymmdd format', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { field: 'date', value: query.date },\n });\n }\n\n const serviceIds = getServiceIdsByDate(query.date, options);\n\n whereClauses.push(\n `service_id IN (${serviceIds.map((id) => sqlString.escape(id)).join(',')})`,\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 QueryResult<Trip, Fields>[];\n}\n"],"mappings":"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,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACF;;;ACtJO,IAAM,YAAY;AAAA,EACvB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AAAA,IACN;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACF;;;ACjDO,IAAM,iBAAiB;AAAA,EAC5B,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AAAA,IACN;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACF;;;AClGO,IAAM,mBAAmB;AAAA,EAC9B,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AAAA,IACN;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACF;;;AC5BO,IAAM,mBAAmB;AAAA,EAC9B,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AAAA,IACN;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACF;;;AC7GO,IAAM,WAAW;AAAA,EACtB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AAAA,IACN;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,EACF;AACF;;;ACnDA,OAAO,cAAc;;;ACsDd,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,SAAiB,SAA2B;AACtD,UAAM,SAAS,EAAE,OAAO,QAAQ,MAAM,CAAC;AACvC,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AACpB,SAAK,WAAW,QAAQ;AACxB,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,aAAa,QAAQ;AAC1B,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;;;ADjEA,IAAM,MAA4C,CAAC;AAEnD,SAAS,QAAQ,YAAoB;AACnC,QAAM,KAAK,IAAI,SAAS,UAAU,UAAU,CAAC;AAC7C,KAAG,OAAO,oBAAoB;AAC9B,KAAG,OAAO,mBAAmB;AAC7B,KAAG,OAAO,qBAAqB;AAC/B,MAAI,UAAU,IAAI;AAElB,SAAO;AACT;AAEO,SAAS,OACd,SAAiE,MAC9C;AAEnB,MAAI,QAAQ;AACV,UAAM,EAAE,aAAa,YAAY,GAAG,IAAI;AAGxC,QAAI,IAAI;AACN,aAAO;AAAA,IACT;AAGA,QAAI,IAAI,UAAU,GAAG;AACnB,aAAO,IAAI,UAAU;AAAA,IACvB;AAGA,WAAO,QAAQ,UAAU;AAAA,EAC3B;AAGA,MAAI,OAAO,KAAK,GAAG,EAAE,WAAW,GAAG;AACjC,WAAO,QAAQ,UAAU;AAAA,EAC3B;AAGA,MAAI,OAAO,KAAK,GAAG,EAAE,WAAW,GAAG;AACjC,UAAM,WAAW,OAAO,KAAK,GAAG,EAAE,CAAC;AACnC,WAAO,IAAI,QAAQ;AAAA,EACrB;AAEA,MAAI,OAAO,KAAK,GAAG,EAAE,SAAS,GAAG;AAC/B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QACA,SAAS,EAAE,mBAAmB,OAAO,KAAK,GAAG,EAAE,OAAO;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,UAAU,uCAAuC;AAAA,IACzD;AAAA,IACA;AAAA,EACF,CAAC;AACH;;;AElEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAAC;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS,yBAAyB;;;ACV3C,OAAO,0BAA0B;AACjC,OAAO,eAAe;AACtB,SAAS,WAAW;;;ACFpB,OAAO,eAAe;AACtB,OAAO,UAAU;AA8CV,SAAS,iBAAiB,eAAuB;AACtD,QAAM,WAAW;AAAA,IACf,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,cAAc;AAAA,IACd,+BAA+B;AAAA,IAC/B,SAAS;AAAA,IACT,iBAAiB;AAAA,EACnB;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;AAgRO,SAAS,eAAe,OAAe,UAAkB;AAC9D,QAAM,QAAQ,IAAI,KAAK,aAAa,QAAW;AAAA,IAC7C,OAAO;AAAA,IACP;AAAA,EACF,CAAC,EAAE,cAAc,KAAK;AAEtB,QAAM,cACJ,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,SAAS,GAAG,SAAS;AAC1D,QAAM,eACJ,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,UAAU,GAAG,SAAS;AAE3D,SAAO,GAAG,WAAW,GAAG,iBAAiB,KAAK,IAAI,YAAY,KAAK,EAAE;AACvE;AAuCO,SAAS,UACd,cACA,YACA,OACA;AACA,SAAO,UAAU,IAAI,eAAe;AACtC;;;ACtYA,OAAOC,WAAU;AACjB,SAAS,aAAAC,kBAAiB;AAE1B,SAAS,SAAS,WAAAC,gBAAe;AACjC,SAAS,iBAAiB;AAC1B,OAAOC,gBAAe;AAEtB,OAAOC,gBAAe;AAUtB,IAAM,cAAc,CAAC,IAAuB,WAAmB;AAC7D,MAAI;AACF,WAAO,GAAG,QAAQ,iCAAiC,EAAE,IAAI;AAAA,EAG3D,QAAQ;AACN,QAAI,OAAO,eAAe,YAAY;AACpC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,aAAa,OAAO,kBAA0B;AACzD,QAAM,SAAS,iBAAiB,aAAa;AAC7C,QAAM,KAAK,OAAO,MAAM;AAIxB,QAAM,WAAW,YAAY,IAAI,MAAM;AACvC,QAAM,cAAc,SAAS;AAC7B,MAAI,gBAAgB,GAAG;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF,WAAW,cAAc,GAAG;AAC1B,eAAW,MAAM;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM;AAAA,IACR,4BAA4B;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,6BAA6B,OAAO,UAAU;AAAA,EACjD;AAEA,QAAM,aAAa,mBAAmB,SAAS,CAAC,EAAE,WAAW;AAC7D,QAAM,oBAAoBC,MAAK,KAAK,QAAQ,IAAI,GAAG,eAAe,UAAU;AAC5E,QAAM,aAAa,UAAU,OAAO,cAAc,iBAAiB;AAEnE,QAAM,cAAc,UAAU;AAG9B,QAAM,iBAAkB,OAAO,OAAO,cAAM,EAAc;AAAA,IACxD,CAAC,UAAU,MAAM,cAAc;AAAA,EACjC;AACA,QAAM,gBAAgB,MAAMC;AAAA,IAC1B;AAAA,IACA,OAAO,UAAiB;AACtB,YAAM,WAAWD,MAAK;AAAA,QACpB;AAAA,QACA,GAAG,MAAM,YAAY,IAAI,MAAM,iBAAiB;AAAA,MAClD;AACA,YAAM,YAAYE,WAAU,SAAS,MAAM,YAAY;AACvD,YAAM,QAAQ,GAAG,QAAQ,iBAAiB,SAAS,GAAG,EAAE,IAAI;AAI5D,UAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,YAAI,CAAC,MAAM,aAAa;AACtB,cAAI,MAAM;AAAA,YACR,wBAAwB,MAAM,YAAY,IAAI,MAAM,iBAAiB;AAAA,UACvE;AAAA,QACF;AAEA;AAAA,MACF;AAEA,UAAI,MAAM,sBAAsB,OAAO;AACrC,cAAM,iBAAiB,CAAC;AAGxB,YAAI,MAAM,iBAAiB,UAAU;AACnC,gBAAM,qBAAqB,GACxB;AAAA,YACC;AAAA,UACF,EACC,IAAI;AACP,cAAI,CAAC,sBAAsB,mBAAmB,WAAW,GAAG;AAC1D,2BAAe,KAAK,WAAW;AAAA,UACjC;AAAA,QACF,WAAW,MAAM,iBAAiB,mBAAmB;AACnD,qBAAW,QAAQ,OAAO;AACxB,iBAAK,QAAQ;AAAA,cACX,KAAK;AAAA,cACL,KAAK;AAAA,YACP;AAAA,UACF;AAAA,QACF,WAAW,MAAM,iBAAiB,iBAAiB;AACjD,qBAAW,QAAQ,OAAO;AACxB,iBAAK,SAAS;AAAA,cACZ,KAAK;AAAA,cACL,KAAK;AAAA,YACP;AAAA,UACF;AAAA,QACF;AAEA,cAAM,UAAU;AAAA,UACd,MAAM,OAAO,IAAI,CAAC,WAAW,OAAO,IAAI;AAAA,UACxC,GAAG;AAAA,QACL;AACA,cAAM,WAAW,MAAM,UAAU,OAAO,EAAE,SAAS,QAAQ,KAAK,CAAC;AACjE,cAAMC,WAAU,UAAU,QAAQ;AAAA,MACpC,WAAW,MAAM,sBAAsB,WAAW;AAChD,cAAM,WAAW,QAAQ,CAAC,EAAE,WAAW;AACvC,cAAMA,WAAU,UAAU,QAAkB;AAAA,MAC9C,OAAO;AACL,cAAM,IAAI;AAAA,UACR,kCAAkC,MAAM,iBAAiB;AAAA,QAC3D;AAAA,MACF;AAEA,UAAI,MAAM;AAAA,QACR,eAAe,MAAM,YAAY,IAAI,MAAM,iBAAiB;AAAA,MAC9D;AAEA,aAAO,GAAG,MAAM,YAAY,IAAI,MAAM,iBAAiB;AAAA,IACzD;AAAA,EACF;AAEA,MAAIC,SAAQ,aAAa,EAAE,WAAW,GAAG;AACvC,QAAI,MAAM;AAAA,MACR;AAAA,IACF;AACA;AAAA,EACF;AAEA,MAAI,MAAM,EAAE,4BAA4B,UAAU,EAAE;AAEpD,MAAI,MAAM;AAAA,IACR,6BAA6B,UAAU,UAAU,YAAY,WAAW,CAAC;AAAA;AAAA,EAC3E;AACF;;;AC7JA,OAAOC,gBAAe;;;ACAtB,SAAS,QAAAC,OAAM,YAAY;;;ACA3B,SAAS,WAAAC,UAAS,QAAAC,OAAM,QAAAC,aAAY;AAEpC,SAAS,qBAAAC,0BAAyB;;;ACFlC,SAAS,QAAAC,OAAM,SAAS,QAAAC,aAAY;;;ACApC,SAAS,QAAAC,aAAY;AACrB,OAAOC,gBAAe;;;ACDtB,SAAS,QAAAC,aAAY;AACrB,OAAOC,gBAAe;;;AnFUtB,IAAM,KAAK,IAAI,YAAY;AAE3B,IAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI,CAAC,EACrC,MAAM,sCAAsC,EAC5C,KAAK,EACL,OAAO,KAAK;AAAA,EACX,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AACR,CAAC,EACA,OAAO,cAAc;AAAA,EACpB,UAAU;AAAA,EACV,MAAM;AACR,CAAC,EACA,UAAU;AAEb,IAAM,cAAc,CAAC,QAAQ,oBAAoB;AAC/C,UAAQ,OAAO,MAAM;AAAA,EAAK,YAAY,KAAK,CAAC;AAAA,CAAI;AAChD,UAAQ,MAAM,GAAG,OAAO,KAAK,CAAC;AAC9B,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,cAAc,YAAY;AAC9B,QAAM,SAAS,MAAM,UAAU,IAAI;AACnC,QAAM,WAAW,MAAgB;AACjC,UAAQ,KAAK;AACf;AAEA,YAAY,EAAE,MAAM,WAAW;","names":["argv","path","existsSync","readFile","rm","mapSeries","omit","path","writeFile","compact","sqlString","mapSeries","path","mapSeries","sqlString","writeFile","compact","sqlString","omit","compact","omit","pick","featureCollection","omit","pick","omit","sqlString","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/rider-categories.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-informed_entities.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/models/tides/devices.ts","../../src/models/tides/fare-transactions.ts","../../src/models/tides/operators.ts","../../src/models/tides/passenger-events.ts","../../src/models/tides/station-activities.ts","../../src/models/tides/stop-visits.ts","../../src/models/tides/train-cars.ts","../../src/models/tides/trips-performed.ts","../../src/models/tides/vehicle-train-cars.ts","../../src/models/tides/vehicle-locations.ts","../../src/models/tides/vehicles.ts","../../src/lib/db.ts","../../src/lib/errors.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","../../src/lib/gtfs/trips.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';\nimport type { Config } from '../types/global_interfaces.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 as Config);\n process.exit();\n};\n\nsetupExport().catch(handleError);\n","import path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { mkdir, readFile, rm } from 'node:fs/promises';\nimport { omit, snakeCase } from 'lodash-es';\nimport sanitize from 'sanitize-filename';\nimport StreamZip from 'node-stream-zip';\nimport type { Config } from '../types/global_interfaces.ts';\n\nimport { log } from './log-utils.ts';\n\nconst homeDirectory = homedir();\n\n/** Configuration command line arguments interface */\ninterface ConfigArgs {\n configPath?: string;\n gtfsPath?: string;\n gtfsUrl?: string;\n sqlitePath?: string;\n}\n\n/**\n * Attempts to parse and load configuration from various sources\n * Priority: 1. CLI config path 2. CLI direct args 3. ./config.json\n * @param {ConfigArgs} argv - Command line arguments\n * @throws {Error} If configuration cannot be found or parsed\n * @returns {Promise<Record<string, any>>} Parsed configuration object\n * @example\n * const config = await getConfig({ configPath: './my-config.json' });\n */\nexport async function getConfig(argv: ConfigArgs): Promise<Config> {\n let config;\n let data;\n\n try {\n if (argv.configPath) {\n const configPath = path.resolve(untildify(argv.configPath));\n data = await readFile(configPath, 'utf8');\n config = Object.assign(JSON.parse(data), argv);\n } else if (argv.gtfsPath || argv.gtfsUrl || argv.sqlitePath) {\n const agencies = [\n ...(argv.gtfsPath ? [{ path: argv.gtfsPath }] : []),\n ...(argv.gtfsUrl ? [{ url: argv.gtfsUrl }] : []),\n ];\n\n config = {\n agencies,\n ...omit(argv, ['path', 'url']),\n };\n } else if (existsSync(path.resolve('./config.json'))) {\n data = await readFile(path.resolve('./config.json'), 'utf8');\n config = Object.assign(JSON.parse(data), argv);\n log(config)('Using configuration from ./config.json');\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 } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(\n `Cannot parse configuration file. Check to ensure that it is valid JSON. Error: ${error.message}`,\n { cause: error },\n );\n }\n throw error;\n }\n}\n\n/**\n * Prepares a directory for saving files by clearing its contents\n * @param {string} exportPath - Path to the directory to prepare\n * @returns {Promise<void>}\n * @example\n * await prepDirectory('./output');\n */\nexport async function prepDirectory(exportPath: string): Promise<void> {\n await rm(exportPath, { recursive: true, force: true });\n await mkdir(exportPath, { recursive: true });\n}\n\n/**\n * Extracts contents of a zip file to specified directory\n * @param {string} zipfilePath - Path to the zip file\n * @param {string} exportPath - Directory to extract contents to\n * @returns {Promise<void>}\n * @throws {Error} If zip file cannot be opened or extracted\n * @example\n * await unzip('./data.zip', './extracted');\n */\nexport async function unzip(\n zipfilePath: string,\n exportPath: string,\n): Promise<void> {\n try {\n const zip = new StreamZip.async({ file: zipfilePath });\n await zip.extract(null, exportPath);\n await zip.close();\n } catch (error) {\n throw new Error(\n `Failed to extract zip file: ${error instanceof Error ? error.message : 'Unknown error'}`,\n { cause: error },\n );\n }\n}\n\n/**\n * Generates a safe folder name from input string\n * Converts to snake_case and removes unsafe characters\n * @param {string} folderName - Input string to convert to folder name\n * @returns {string} Sanitized folder name\n * @example\n * generateFolderName('My Folder!') // returns 'my_folder'\n */\nexport function generateFolderName(folderName: string): string {\n if (!folderName || typeof folderName !== 'string') {\n throw new Error('Folder name must be a non-empty string');\n }\n return snakeCase(sanitize(folderName));\n}\n\n/**\n * Converts a tilde path to a full path\n * @param pathWithTilde The path to convert\n * @returns The full path\n */\nexport function untildify(pathWithTilde: string): string {\n return homeDirectory\n ? pathWithTilde.replace(/^~(?=$|\\/|\\\\)/, homeDirectory)\n : pathWithTilde;\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/** Function type for logging with optional line overwrite */\ntype LogFunction = (text: string, overwrite?: boolean) => void;\n\n/**\n * Creates a logging function based on configuration settings\n * @param {Config} config - Configuration object containing logging preferences\n * @returns {LogFunction} Logging function that writes to stdout, or noop if verbose is false\n * @example\n * const logger = log({ verbose: true });\n * logger('Processing...', true); // Overwrites current line\n * logger('Done!'); // Writes on new line\n */\nexport function log(config: Config): LogFunction {\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 = false): void => {\n if (overwrite && 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 * Creates a warning logging function\n * @param {Config} config - Configuration object containing logging preferences\n * @returns {(text: string) => void} Function that logs formatted warning messages\n * @example\n * const warnLogger = logWarning(config);\n * warnLogger('Resource not found'); // Outputs yellow warning message\n */\nexport function logWarning(config: Config): (text: string) => void {\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string): void => {\n process.stdout.write(`\\n${formatWarning(text)}\\n`);\n };\n}\n\n/**\n * Creates an error logging function\n * @param {Config} config - Configuration object containing logging preferences\n * @returns {(text: string) => void} Function that logs formatted error messages\n * @example\n * const errorLogger = logError(config);\n * errorLogger('Failed to connect'); // Outputs red error message\n */\nexport function logError(config: Config): (text: string) => void {\n if (config.logFunction) {\n return config.logFunction;\n }\n\n return (text: string): void => {\n process.stdout.write(`\\n${formatError(text)}\\n`);\n };\n}\n\n/**\n * Formats warning text with yellow color and underline\n * @param {string} text - The warning message to format\n * @returns {string} Formatted warning message in yellow with underlined \"Warning\" prefix\n * @example\n * const formattedWarning = formatWarning('Resource not found');\n * console.log(formattedWarning); // Yellow \"Warning: Resource not found\"\n */\nexport function formatWarning(text: string): string {\n return colors.yellow(`${colors.underline('Warning')}: ${text}`);\n}\n\n/**\n * Formats error text with red color and underline\n * @param {Error | string} error - The error object or message to format\n * @returns {string} Formatted error message in red with underlined \"Error\" prefix\n * @example\n * const formattedError = formatError(new Error('Connection failed'));\n * console.log(formattedError); // Red \"Error: Connection failed\"\n */\nexport function formatError(error: Error | string): string {\n const messageText = error instanceof Error ? error.message : error;\n const cleanMessage = messageText.replace(/^Error:\\s*/i, '');\n\n return colors.red(`${colors.underline('Error')}: ${cleanMessage}`);\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 stripBomStream from 'strip-bom-stream';\nimport { temporaryDirectory } from 'tempy';\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 { untildify, 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 getTimestampColumnName,\n padLeadingZeros,\n applyPrefixToValue,\n pluralize,\n setDefaultConfig,\n validateConfigForImport,\n} from './utils.ts';\nimport {\n addImportError,\n addImportWarning,\n createImportReport,\n formatGtfsError,\n GtfsError,\n GtfsErrorCategory,\n GtfsErrorCode,\n GtfsWarningCode,\n ImportReport,\n toGtfsError,\n} from './errors.ts';\n\nimport {\n Config,\n ConfigAgency,\n Model,\n SqlValue,\n TableNames,\n} from '../types/global_interfaces.ts';\n\ninterface GtfsImportTask {\n exclude?: TableNames[];\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: object;\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 report?: ImportReport;\n}\n\nfunction reportTaskError(task: GtfsImportTask, error: GtfsError): void {\n if (task.report) {\n addImportError(task.report, error);\n }\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 downloadGtfsFiles = async (task: GtfsImportTask): Promise<void> => {\n if (!task.url) {\n throw new GtfsError('No `url` specified in config', {\n code: GtfsErrorCode.GTFS_CONFIG_INVALID,\n category: GtfsErrorCategory.CONFIG,\n });\n }\n\n task.log(`Downloading GTFS from ${task.url}`);\n\n task.path = `${task.downloadDir}/gtfs.zip`;\n\n try {\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 GtfsError(\n `Unable to download GTFS from ${task.url}. Got status ${response.status}.`,\n {\n code: GtfsErrorCode.GTFS_DOWNLOAD_HTTP,\n category: GtfsErrorCategory.DOWNLOAD,\n statusCode: response.status,\n details: {\n url: task.url,\n status: response.status,\n statusText: response.statusText,\n },\n },\n );\n }\n\n const buffer = await response.arrayBuffer();\n await writeFile(task.path, Buffer.from(buffer));\n task.log('Download successful');\n } catch (error: unknown) {\n throw toGtfsError(error, {\n message: `Unable to download GTFS from ${task.url}.`,\n code: GtfsErrorCode.GTFS_DOWNLOAD_FAILED,\n category: GtfsErrorCategory.DOWNLOAD,\n details: { url: task.url },\n });\n }\n};\n\nconst extractGtfsFiles = async (task: GtfsImportTask): Promise<void> => {\n if (!task.path) {\n throw new GtfsError('No `path` specified in config', {\n code: GtfsErrorCode.GTFS_CONFIG_INVALID,\n category: GtfsErrorCategory.CONFIG,\n details: { field: 'path' },\n });\n }\n\n const gtfsPath = untildify(task.path);\n task.log(`Importing static 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 GtfsError(\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 code: GtfsErrorCode.GTFS_ZIP_INVALID,\n category: GtfsErrorCategory.ZIP,\n details: { path: task.path, folderCount: folders.length },\n },\n );\n } else if (folders.length === 0) {\n throw new GtfsError(\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 code: GtfsErrorCode.GTFS_ZIP_INVALID,\n category: GtfsErrorCategory.ZIP,\n details: { path: task.path },\n },\n );\n }\n\n const subfolderName = folders[0];\n const directoryTextFiles = await getTextFiles(subfolderName);\n\n if (directoryTextFiles.length === 0) {\n throw new GtfsError(\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 code: GtfsErrorCode.GTFS_ZIP_INVALID,\n category: GtfsErrorCategory.ZIP,\n details: { path: task.path, subfolderName },\n },\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: unknown) {\n const wrappedError = toGtfsError(error, {\n message: `Unable to unzip file ${task.path}`,\n code: GtfsErrorCode.GTFS_ZIP_INVALID,\n category: GtfsErrorCategory.ZIP,\n details: { path: task.path },\n });\n task.logError(formatGtfsError(wrappedError));\n throw wrappedError;\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 (error: unknown) {\n throw new GtfsError(\n `Unable to load files from path \\`${gtfsPath}\\` defined in configuration. Verify that path exists and contains GTFS files.`,\n {\n code: GtfsErrorCode.GTFS_DOWNLOAD_FAILED,\n category: GtfsErrorCategory.DOWNLOAD,\n details: { path: gtfsPath },\n cause: error,\n },\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 sqlColumnCreateStatements = [];\n\n for (const column of model.schema) {\n const checks = [];\n if (column.min !== undefined && column.max) {\n checks.push(\n `${column.name} >= ${column.min} AND ${column.name} <= ${column.max}`,\n );\n } else if (column.min) {\n checks.push(`${column.name} >= ${column.min}`);\n } else if (column.max) {\n checks.push(`${column.name} <= ${column.max}`);\n }\n\n if (column.type === 'integer') {\n checks.push(\n `(TYPEOF(${column.name}) = 'integer' OR ${column.name} IS NULL)`,\n );\n } else if (column.type === 'real') {\n checks.push(\n `(TYPEOF(${column.name}) = 'real' OR ${column.name} IS NULL)`,\n );\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 const checkClause =\n checks.length > 0 ? `CHECK(${checks.join(' AND ')})` : '';\n\n sqlColumnCreateStatements.push(\n `${column.name} ${column.type} ${checkClause} ${required} ${columnDefault} ${columnCollation}`,\n );\n\n // Add an additional timestamp column for time columns\n if (column.type === 'time') {\n sqlColumnCreateStatements.push(\n `${getTimestampColumnName(column.name)} INTEGER GENERATED ALWAYS AS (\n CASE\n WHEN ${column.name} IS NULL OR ${column.name} = '' THEN NULL\n ELSE CAST(\n substr(${column.name}, 1, instr(${column.name}, ':') - 1) * 3600 +\n substr(${column.name}, instr(${column.name}, ':') + 1, 2) * 60 +\n substr(${column.name}, -2) AS INTEGER\n )\n END\n ) STORED`,\n );\n }\n }\n\n // Find Primary Key fields\n const primaryColumns = model.schema.filter((column) => column.primary);\n\n if (primaryColumns.length > 0) {\n sqlColumnCreateStatements.push(\n `PRIMARY KEY (${primaryColumns.map(({ name }) => name).join(', ')})`,\n );\n }\n\n db.prepare(`DROP TABLE IF EXISTS ${model.filenameBase};`).run();\n\n db.prepare(\n `CREATE TABLE ${model.filenameBase} (${sqlColumnCreateStatements.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) {\n if (column.index) {\n db.prepare(\n `CREATE INDEX idx_${model.filenameBase}_${column.name} ON ${model.filenameBase} (${column.name});`,\n ).run();\n }\n\n if (column.type === 'time') {\n // Index all timestamp columns\n const timestampColumnName = getTimestampColumnName(column.name);\n db.prepare(\n `CREATE INDEX idx_${model.filenameBase}_${timestampColumnName} ON ${model.filenameBase} (${timestampColumnName});`,\n ).run();\n }\n }\n }\n};\n\nconst formatGtfsLine = (\n line: { [x: string]: string | null },\n model: Model,\n totalLineCount: number,\n): Record<string, string | null> => {\n const lineNumber = totalLineCount + 1;\n const formattedLine: Record<string, string | null> = {};\n const filenameBase = model.filenameBase;\n const filenameExtension = model.filenameExtension;\n\n for (const { name, type, required } of model.schema) {\n let value: string | null = line[name];\n\n // Early null check\n if (value === '' || value === undefined || value === null) {\n formattedLine[name] = null;\n\n if (required) {\n throw new GtfsError(\n `Missing required value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`,\n {\n code: GtfsErrorCode.GTFS_REQUIRED_FIELD_MISSING,\n category: GtfsErrorCategory.VALIDATION,\n details: {\n file: `${filenameBase}.${filenameExtension}`,\n line: lineNumber,\n column: name,\n },\n },\n );\n }\n continue;\n }\n\n if (type === 'date') {\n // Handle YYYY-MM-DD format\n value = value?.toString().replace(/-/g, '');\n if (value.length !== 8) {\n throw new GtfsError(\n `Invalid date in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`,\n {\n code: GtfsErrorCode.GTFS_INVALID_DATE,\n category: GtfsErrorCategory.VALIDATION,\n details: {\n file: `${filenameBase}.${filenameExtension}`,\n line: lineNumber,\n column: name,\n value,\n },\n },\n );\n }\n } else if (type === 'time') {\n value = padLeadingZeros(value);\n }\n\n if (type === 'json') {\n value = JSON.stringify(value);\n }\n\n formattedLine[name] = value;\n }\n\n return formattedLine;\n};\n\nconst BATCH_SIZE = 100_000;\n\nconst importGtfsFiles = async (\n db: Database.Database,\n task: GtfsImportTask,\n): Promise<void> => {\n await 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 // Skip any models that are excluded by config\n if (task.exclude && task.exclude.includes(model.filenameBase)) {\n task.log(`Skipping - ${filename}\\r`);\n resolve();\n return;\n }\n\n // Skip gtfs-realtime models not present in static GTFS\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 // Create a list of all columns\n const columns = model.schema;\n\n // Create a map of which columns need prefixing\n const prefixedColumns = new Set(\n columns\n .filter((column) => column.prefix)\n .map((column) => column.name),\n );\n\n const prepareStatement = `INSERT ${task.ignoreDuplicates ? 'OR IGNORE' : ''} INTO ${\n model.filenameBase\n } (${columns.map(({ name }) => name).join(', ')}) VALUES (${columns\n .map(({ name }) => `@${name}`)\n .join(', ')})`;\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]: unknown; geojson?: string },\n ).map(([columnName, value]) => [\n columnName,\n applyPrefixToValue(\n value as string,\n prefixedColumns.has(columnName),\n task.prefix,\n ),\n ]),\n );\n insert.run(prefixedLine);\n }\n } catch (error: unknown) {\n if (\n (error as Error & { code?: string }).code ===\n 'SQLITE_CONSTRAINT_PRIMARYKEY'\n ) {\n const primaryColumns = columns.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 if (task.report) {\n addImportWarning(task.report, {\n code: GtfsWarningCode.GTFS_DUPLICATE_PRIMARY_KEY,\n message: `Duplicate values for primary key found in ${filename}.`,\n details: {\n file: filename,\n line: Number(rowNumber) + 1,\n columns: primaryColumns.map((column) => column.name),\n },\n });\n }\n }\n\n task.logWarning(\n `Check ${filename} for invalid data on line ${rowNumber + 1}.`,\n );\n throw toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: {\n file: filename,\n line: Number(rowNumber) + 1,\n sqlitePath: task.sqlitePath,\n dbCode: (error as { code?: unknown }).code,\n },\n });\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]: SqlValue; geojson?: string }[] = [];\n\n parser.on('readable', () => {\n try {\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 insertLines(lines);\n lines = [];\n\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n }\n }\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n });\n if (task.ignoreErrors) {\n reportTaskError(task, gtfsError);\n task.logError(\n `Error processing ${filename}: ${gtfsError.message}`,\n );\n resolve();\n } else {\n reject(gtfsError);\n }\n }\n });\n\n parser.on('end', () => {\n try {\n if (lines.length > 0) {\n try {\n insertLines(lines);\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message:\n error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { file: filename, sqlitePath: task.sqlitePath },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Error inserting data for ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n return;\n } else {\n reject(gtfsError);\n return;\n }\n }\n }\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n resolve();\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { file: filename, sqlitePath: task.sqlitePath },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Error finalizing ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n } else {\n reject(gtfsError);\n }\n }\n });\n\n parser.on('error', (error: unknown) => {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Parser error for ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n } else {\n reject(gtfsError);\n }\n });\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 if (task.ignoreErrors) {\n task.logError(`Invalid JSON in ${filename}`);\n reportTaskError(\n task,\n new GtfsError(`Invalid JSON in ${filename}`, {\n code: GtfsErrorCode.GTFS_JSON_INVALID,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n }),\n );\n resolve();\n return;\n } else {\n reject(\n new GtfsError(`Invalid JSON in ${filename}`, {\n code: GtfsErrorCode.GTFS_JSON_INVALID,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n }),\n );\n return;\n }\n }\n totalLineCount += 1;\n const line = formatGtfsLine(\n { geojson: data },\n model,\n totalLineCount,\n );\n try {\n insertLines([line]);\n task.log(\n `Importing - ${filename} - ${totalLineCount} lines imported\\r`,\n true,\n );\n resolve();\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message:\n error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { file: filename, sqlitePath: task.sqlitePath },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Error inserting data for ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n } else {\n reject(gtfsError);\n }\n }\n })\n .catch((error: unknown) => {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n details: { file: filename },\n });\n if (task.ignoreErrors) {\n task.logError(\n `Error reading ${filename}: ${gtfsError.message}`,\n );\n reportTaskError(task, gtfsError);\n resolve();\n } else {\n reject(gtfsError);\n }\n });\n } else {\n if (task.ignoreErrors) {\n task.logError(\n `Unsupported file type: ${model.filenameExtension} for ${filename}`,\n );\n resolve();\n } else {\n reject(\n new GtfsError(\n `Unsupported file type: ${model.filenameExtension}`,\n {\n code: GtfsErrorCode.GTFS_UNSUPPORTED_FILE_TYPE,\n category: GtfsErrorCategory.PARSE,\n details: {\n file: filename,\n extension: model.filenameExtension,\n },\n },\n ),\n );\n }\n }\n }),\n );\n task.log(`Static GTFS import complete`);\n};\n\n/**\n * Function to import GTFS files into the database\n *\n * @param initialConfig\n */\nexport async function importGtfs(initialConfig: Config): Promise<ImportReport>;\nexport async function importGtfs(initialConfig: Config): Promise<void>;\nexport async function importGtfs(\n initialConfig: Config,\n): Promise<void | ImportReport> {\n // Start timer\n const startTime = process.hrtime.bigint();\n\n const config = setDefaultConfig(initialConfig);\n validateConfigForImport(config);\n const report = config.includeImportReport ? createImportReport() : undefined;\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', 'files', agencyCount)} 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 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 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 report,\n };\n\n if ('url' in agency) {\n Object.assign(task, { url: agency.url });\n\n await downloadGtfsFiles(task);\n } else {\n Object.assign(task, {\n path: agency.path,\n });\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: unknown) {\n const wrappedError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n });\n if (config.ignoreErrors) {\n logError(config)(formatGtfsError(wrappedError));\n if (report) {\n addImportError(report, wrappedError);\n }\n } else {\n throw wrappedError;\n }\n }\n });\n\n log(config)(`Creating DB indexes`);\n createGtfsIndexes(db);\n\n const endTime = process.hrtime.bigint();\n const elapsedSeconds = Number(endTime - startTime) / 1_000_000_000;\n\n log(config)(\n `Completed GTFS import in ${elapsedSeconds.toFixed(1)} seconds\\n`,\n );\n } catch (error: unknown) {\n if ((error as Error & { code?: string }).code === 'SQLITE_CANTOPEN') {\n const dbOpenError = new GtfsError(\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 code: GtfsErrorCode.DB_OPEN_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: {\n sqlitePath: config.sqlitePath,\n dbCode: (error as Error & { code?: string }).code,\n },\n cause: error,\n },\n );\n logError(config)(dbOpenError.message);\n throw dbOpenError;\n }\n throw toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_CSV_PARSE_FAILED,\n category: GtfsErrorCategory.PARSE,\n });\n }\n\n if (report) {\n return report;\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 { riderCategories } from './gtfs/rider-categories.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 { serviceAlertInformedEntities } from './gtfs-realtime/service-alert-informed_entities.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\nexport { devices } from './tides/devices.ts';\nexport { fareTransactions } from './tides/fare-transactions.ts';\nexport { operators } from './tides/operators.ts';\nexport { passengerEvents } from './tides/passenger-events.ts';\nexport { stationActivities } from './tides/station-activities.ts';\nexport { stopVisits } from './tides/stop-visits.ts';\nexport { trainCars } from './tides/train-cars.ts';\nexport { tripsPerformed } from './tides/trips-performed.ts';\nexport { vehicleTrainCars } from './tides/vehicle-train-cars.ts';\nexport { vehicleLocations } from './tides/vehicle-locations.ts';\nexport { vehicles } from './tides/vehicles.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 name: 'cemv_support',\n type: 'integer',\n min: 0,\n max: 2,\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 primary: 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: 'time',\n },\n {\n name: 'prior_notice_start_day',\n type: 'integer',\n min: 0,\n },\n {\n name: 'prior_notice_start_time',\n type: 'time',\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: 'rider_category_id',\n type: 'text',\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 primary: true,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'origin_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'destination_id',\n type: 'text',\n primary: true,\n prefix: true,\n },\n {\n name: 'contains_id',\n type: 'text',\n primary: true,\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: 'time',\n required: true,\n primary: true,\n },\n {\n name: 'end_time',\n type: 'time',\n required: true,\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 primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n prefix: true,\n index: true,\n primary: 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 riderCategories = {\n filenameBase: 'rider_categories',\n filenameExtension: 'txt',\n schema: [\n {\n name: 'rider_category_id',\n type: 'text',\n primary: true,\n required: true,\n prefix: true,\n },\n {\n name: 'rider_category_name',\n type: 'text',\n required: true,\n },\n {\n name: 'is_default_fare_category',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'eligibility_url',\n type: 'text',\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 name: 'cemv_support',\n type: 'integer',\n min: 0,\n max: 2,\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 primary: true,\n prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n primary: 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: 'time',\n },\n {\n name: 'departure_time',\n type: 'time',\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: 'time',\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 prefix: 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 name: 'stop_access',\n type: 'integer',\n min: 0,\n max: 1,\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: 'time',\n primary: true,\n },\n {\n name: 'end_time',\n type: 'time',\n primary: true,\n },\n {\n name: 'service_id',\n type: 'text',\n required: true,\n primary: 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 name: 'cars_allowed',\n type: 'integer',\n min: 0,\n max: 2,\n },\n {\n name: 'safe_duration_factor',\n type: 'real',\n },\n {\n name: 'safe_duration_offset',\n type: 'real',\n },\n ],\n};\n","export const timetables = {\n filenameBase: 'timetables',\n filenameExtension: 'txt',\n nonstandard: true,\n schema: [\n {\n name: 'timetable_id',\n type: 'text',\n prefix: true,\n required: true,\n primary: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n required: true,\n primary: 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: 'time',\n },\n {\n name: 'end_time',\n type: 'time',\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 required: 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: 'timetable_id',\n type: 'text',\n index: true,\n prefix: true,\n required: true,\n primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n required: true,\n primary: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n min: 0,\n index: true,\n required: true,\n primary: 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 required: true,\n },\n {\n name: 'symbol',\n type: 'text',\n },\n {\n name: 'note',\n type: 'text',\n nocase: true,\n required: 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 required: true,\n primary: true,\n },\n {\n name: 'timetable_id',\n type: 'text',\n prefix: true,\n primary: true,\n },\n {\n name: 'route_id',\n type: 'text',\n prefix: true,\n primary: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n prefix: true,\n primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n prefix: true,\n primary: true,\n },\n {\n name: 'stop_sequence',\n type: 'integer',\n min: 0,\n primary: 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: 'time',\n },\n {\n name: 'service_departure_time',\n type: 'time',\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: 'time',\n },\n {\n name: 'alighting_time',\n type: 'time',\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: 'time',\n },\n {\n name: 'ridership_end_time',\n type: 'time',\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: 'id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n prefix: true,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.vehicle.id',\n default: null,\n prefix: true,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'tripUpdate.trip.tripId',\n default: null,\n prefix: true,\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 prefix: true,\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 prefix: true,\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 prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n source: 'stopId',\n default: null,\n prefix: true,\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: 'id',\n type: 'text',\n required: true,\n primary: true,\n index: true,\n source: 'id',\n prefix: true,\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 prefix: true,\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 prefix: true,\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 prefix: true,\n },\n {\n name: 'active_period',\n type: 'json',\n source: 'alert.activePeriod',\n },\n {\n name: 'cause',\n type: 'text',\n source: 'alert.cause',\n },\n {\n name: 'effect',\n type: 'text',\n source: 'alert.effect',\n },\n {\n name: 'url',\n type: 'text',\n source: 'alert.url.translation[0].text',\n default: '',\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: 'header_text',\n type: 'text',\n required: true,\n source: 'alert.headerText.translation[0].text',\n default: '',\n },\n {\n name: 'description_text',\n type: 'text',\n required: true,\n source: 'alert.descriptionText.translation[0].text',\n default: '',\n },\n {\n name: 'tts_header_text',\n type: 'text',\n source: 'alert.ttsHeaderText.translation[0].text',\n },\n {\n name: 'tts_description_text',\n type: 'text',\n source: 'alert.ttsDescriptionText.translation[0].text',\n },\n {\n name: 'severity_level',\n type: 'text',\n source: 'alert.severityLevel',\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 serviceAlertInformedEntities = {\n filenameBase: 'service_alert_informed_entities',\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 prefix: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n index: true,\n source: 'stopId',\n default: null,\n prefix: true,\n },\n {\n name: 'route_id',\n type: 'text',\n index: true,\n source: 'routeId',\n default: null,\n prefix: true,\n },\n {\n name: 'route_type',\n type: 'integer',\n index: true,\n source: 'routeType',\n default: null,\n },\n {\n name: 'trip_id',\n type: 'text',\n index: true,\n source: 'trip.tripId',\n default: null,\n prefix: true,\n },\n {\n name: 'direction_id',\n type: 'integer',\n index: true,\n source: 'directionId',\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: 'deadhead_id',\n type: 'text',\n required: true,\n index: true,\n primary: true,\n prefix: true,\n },\n {\n name: 'arrival_time',\n type: 'time',\n required: true,\n },\n {\n name: 'departure_time',\n type: 'time',\n required: 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 primary: 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","export const devices = {\n filenameBase: 'devices',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'device_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'vehicle_id',\n type: 'text',\n },\n {\n name: 'train_car_id',\n type: 'text',\n },\n {\n name: 'device_type',\n type: 'text',\n },\n {\n name: 'device_vendor',\n type: 'text',\n },\n {\n name: 'device_model',\n type: 'text',\n },\n {\n name: 'device_location',\n type: 'text',\n },\n ],\n};\n","export const fareTransactions = {\n filenameBase: 'fare_transactions',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'transaction_id',\n type: 'text',\n required: true,\n index: true,\n },\n {\n name: 'service_date',\n type: 'date',\n required: true,\n },\n {\n name: 'event_timestamp',\n type: 'text',\n required: true,\n },\n {\n name: 'location_ping_id',\n type: 'text',\n },\n {\n name: 'amount',\n type: 'real',\n required: true,\n },\n {\n name: 'currency_type',\n type: 'text',\n },\n {\n name: 'fare_action',\n type: 'text',\n required: true,\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n },\n {\n name: 'trip_id_scheduled',\n type: 'text',\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'trip_stop_sequence',\n type: 'integer',\n min: 1,\n },\n {\n name: 'scheduled_stop_sequence',\n type: 'integer',\n min: 0,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n },\n {\n name: 'device_id',\n type: 'text',\n },\n {\n name: 'fare_id',\n type: 'text',\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'num_riders',\n type: 'integer',\n min: 0,\n },\n {\n name: 'fare_media_id',\n type: 'text',\n },\n {\n name: 'rider_category',\n type: 'text',\n },\n {\n name: 'fare_product',\n type: 'text',\n },\n {\n name: 'fare_period',\n type: 'text',\n },\n {\n name: 'fare_capped',\n type: 'text',\n required: true,\n },\n {\n name: 'token_id',\n type: 'text',\n },\n {\n name: 'balance',\n type: 'real',\n },\n ],\n};\n","export const operators = {\n filenameBase: 'operators',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'operator_id',\n type: 'text',\n required: true,\n primary: true,\n },\n ],\n};\n","export const passengerEvents = {\n filenameBase: 'passenger_events',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'passenger_event_id',\n type: 'text',\n required: true,\n index: true,\n },\n {\n name: 'service_date',\n type: 'date',\n required: true,\n },\n {\n name: 'event_timestamp',\n type: 'text',\n required: true,\n },\n {\n name: 'location_ping_id',\n type: 'text',\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n },\n {\n name: 'trip_id_scheduled',\n type: 'text',\n },\n {\n name: 'trip_stop_sequence',\n type: 'integer',\n min: 1,\n },\n {\n name: 'scheduled_stop_sequence',\n type: 'integer',\n min: 0,\n },\n {\n name: 'event_type',\n type: 'text',\n required: true,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n },\n {\n name: 'device_id',\n type: 'text',\n },\n {\n name: 'train_car_id',\n type: 'text',\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'event_count',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const stationActivities = {\n filenameBase: 'station_activities',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'service_date',\n type: 'date',\n required: true,\n primary: true,\n },\n {\n name: 'stop_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'time_period_start',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'time_period_end',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'time_period_category',\n type: 'text',\n },\n {\n name: 'total_entries',\n type: 'integer',\n min: 0,\n },\n {\n name: 'total_exits',\n type: 'integer',\n min: 0,\n },\n {\n name: 'number_of_transactions',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_entries',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_exits',\n type: 'integer',\n min: 0,\n },\n {\n name: 'ramp_entries',\n type: 'integer',\n min: 0,\n },\n {\n name: 'ramp_exits',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","export const stopVisits = {\n filenameBase: 'stop_visits',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'service_date',\n type: 'date',\n required: true,\n primary: true,\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'trip_stop_sequence',\n type: 'integer',\n min: 1,\n required: true,\n primary: true,\n },\n {\n name: 'scheduled_stop_sequence',\n type: 'integer',\n min: 0,\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'vehicle_id',\n type: 'text',\n },\n {\n name: 'dwell',\n type: 'integer',\n min: 0,\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'timepoint',\n type: 'text',\n },\n {\n name: 'schedule_arrival_time',\n type: 'text',\n },\n {\n name: 'schedule_departure_time',\n type: 'text',\n },\n {\n name: 'actual_arrival_time',\n type: 'text',\n },\n {\n name: 'actual_departure_time',\n type: 'text',\n },\n {\n name: 'distance',\n type: 'integer',\n min: 0,\n },\n {\n name: 'boarding_1',\n type: 'integer',\n min: 0,\n },\n {\n name: 'alighting_1',\n type: 'integer',\n min: 0,\n },\n {\n name: 'boarding_2',\n type: 'integer',\n min: 0,\n },\n {\n name: 'alighting_2',\n type: 'integer',\n min: 0,\n },\n {\n name: 'departure_load',\n type: 'integer',\n min: 0,\n },\n {\n name: 'door_open',\n type: 'text',\n },\n {\n name: 'door_close',\n type: 'text',\n },\n {\n name: 'door_status',\n type: 'text',\n },\n {\n name: 'ramp_deployed_time',\n type: 'text',\n },\n {\n name: 'ramp_failure',\n type: 'text',\n },\n {\n name: 'kneel_deployed_time',\n type: 'integer',\n min: 0,\n },\n {\n name: 'lift_deployed_time',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_rack_deployed',\n type: 'text',\n },\n {\n name: 'bike_load',\n type: 'integer',\n min: 0,\n },\n {\n name: 'revenue',\n type: 'real',\n },\n {\n name: 'number_of_transactions',\n type: 'integer',\n min: 0,\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n },\n ],\n};\n","export const trainCars = {\n filenameBase: 'train_cars',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'train_car_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'model_name',\n type: 'text',\n },\n {\n name: 'facility_name',\n type: 'text',\n },\n {\n name: 'capacity_seated',\n type: 'integer',\n min: 0,\n },\n {\n name: 'capacity_wheelchair',\n type: 'integer',\n min: 0,\n },\n {\n name: 'capacity_bike',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_rack',\n type: 'text',\n },\n {\n name: 'capacity_standing',\n type: 'integer',\n min: 0,\n },\n {\n name: 'train_car_type',\n type: 'text',\n },\n ],\n};\n","export const tripsPerformed = {\n filenameBase: 'trips_performed',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'service_date',\n type: 'date',\n required: true,\n primary: true,\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n },\n {\n name: 'trip_id_scheduled',\n type: 'text',\n },\n {\n name: 'route_id',\n type: 'text',\n },\n {\n name: 'route_type',\n type: 'text',\n },\n {\n name: 'ntd_mode',\n type: 'text',\n },\n {\n name: 'route_type_agency',\n type: 'text',\n },\n {\n name: 'shape_id',\n type: 'text',\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'direction_id',\n type: 'integer',\n min: 0,\n max: 1,\n },\n {\n name: 'operator_id',\n type: 'text',\n },\n {\n name: 'block_id',\n type: 'text',\n },\n {\n name: 'trip_start_stop_id',\n type: 'text',\n },\n {\n name: 'trip_end_stop_id',\n type: 'text',\n },\n {\n name: 'schedule_trip_start',\n type: 'text',\n },\n {\n name: 'schedule_trip_end',\n type: 'text',\n },\n {\n name: 'actual_trip_start',\n type: 'text',\n },\n {\n name: 'actual_trip_end',\n type: 'text',\n },\n {\n name: 'trip_type',\n type: 'text',\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n },\n ],\n};\n","export const vehicleTrainCars = {\n filenameBase: 'vehicle_train_cars',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'train_car_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'train_car_order',\n type: 'integer',\n min: 0,\n },\n {\n name: 'operator_id',\n type: 'text',\n },\n ],\n};\n","export const vehicleLocations = {\n filenameBase: 'vehicle_locations',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'location_ping_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'service_date',\n type: 'date',\n },\n {\n name: 'event_timestamp',\n type: 'text',\n required: true,\n },\n {\n name: 'trip_id_performed',\n type: 'text',\n },\n {\n name: 'trip_id_scheduled',\n type: 'text',\n },\n {\n name: 'trip_stop_sequence',\n type: 'integer',\n min: 1,\n },\n {\n name: 'scheduled_stop_sequence',\n type: 'integer',\n min: 0,\n },\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n },\n {\n name: 'device_id',\n type: 'text',\n },\n {\n name: 'pattern_id',\n type: 'text',\n },\n {\n name: 'stop_id',\n type: 'text',\n },\n {\n name: 'current_status',\n type: 'text',\n },\n {\n name: 'latitude',\n type: 'real',\n min: -90,\n max: 90,\n },\n {\n name: 'longitude',\n type: 'real',\n min: -180,\n max: 180,\n },\n {\n name: 'gps_quality',\n type: 'text',\n },\n {\n name: 'heading',\n type: 'real',\n min: 0,\n max: 360,\n },\n {\n name: 'speed',\n type: 'real',\n min: 0,\n },\n {\n name: 'odometer',\n type: 'real',\n min: 0,\n },\n {\n name: 'schedule_deviation',\n type: 'integer',\n },\n {\n name: 'headway_deviation',\n type: 'integer',\n },\n {\n name: 'trip_type',\n type: 'text',\n },\n {\n name: 'schedule_relationship',\n type: 'text',\n },\n ],\n};\n","export const vehicles = {\n filenameBase: 'vehicles',\n filenameExtension: 'txt',\n nonstandard: true,\n extension: 'tides',\n schema: [\n {\n name: 'vehicle_id',\n type: 'text',\n required: true,\n primary: true,\n },\n {\n name: 'vehicle_start',\n type: 'text',\n },\n {\n name: 'vehicle_end',\n type: 'text',\n },\n {\n name: 'model_name',\n type: 'text',\n },\n {\n name: 'facility_name',\n type: 'text',\n },\n {\n name: 'capacity_seated',\n type: 'integer',\n min: 0,\n },\n {\n name: 'capacity_wheelchair',\n type: 'integer',\n min: 0,\n },\n {\n name: 'capacity_bike',\n type: 'integer',\n min: 0,\n },\n {\n name: 'bike_rack',\n type: 'text',\n },\n {\n name: 'capacity_standing',\n type: 'integer',\n min: 0,\n },\n ],\n};\n","import fs from 'fs';\n\nimport Database from 'better-sqlite3';\n\nimport { untildify } from './file-utils.ts';\nimport { GtfsError, GtfsErrorCategory, GtfsErrorCode } from './errors.ts';\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 GtfsError(\n 'Multiple databases open, please specify which one to use.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { openDatabaseCount: Object.keys(dbs).length },\n },\n );\n }\n\n throw new GtfsError('Unable to find database connection.', {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n });\n}\n\nexport function closeDb(db: Database.Database | null = null): void {\n if (Object.keys(dbs).length === 0) {\n throw new GtfsError(\n 'No database connection. Call `openDb(config)` before using any methods.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n },\n );\n }\n\n if (!db) {\n if (Object.keys(dbs).length > 1) {\n throw new GtfsError(\n 'Multiple database connections. Pass the db you want to close as a parameter to `closeDb`.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { openDatabaseCount: Object.keys(dbs).length },\n },\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 GtfsError(\n 'No database connection. Call `openDb(config)` before using any methods.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n },\n );\n }\n\n if (!db) {\n if (Object.keys(dbs).length > 1) {\n throw new GtfsError(\n 'Multiple database connections. Pass the db you want to delete as a parameter to `deleteDb`.',\n {\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { openDatabaseCount: Object.keys(dbs).length },\n },\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","export enum GtfsErrorCategory {\n CONFIG = 'config',\n DOWNLOAD = 'download',\n ZIP = 'zip',\n VALIDATION = 'validation',\n DATABASE = 'database',\n PARSE = 'parse',\n QUERY = 'query',\n INTERNAL = 'internal',\n}\n\n/**\n * Error codes are a public API contract and must remain stable across\n * minor/patch releases.\n */\nexport enum GtfsErrorCode {\n GTFS_DOWNLOAD_HTTP = 'GTFS_DOWNLOAD_HTTP',\n GTFS_DOWNLOAD_FAILED = 'GTFS_DOWNLOAD_FAILED',\n GTFS_ZIP_INVALID = 'GTFS_ZIP_INVALID',\n GTFS_REQUIRED_FIELD_MISSING = 'GTFS_REQUIRED_FIELD_MISSING',\n GTFS_INVALID_DATE = 'GTFS_INVALID_DATE',\n GTFS_CONFIG_INVALID = 'GTFS_CONFIG_INVALID',\n DB_OPEN_FAILED = 'DB_OPEN_FAILED',\n GTFS_DB_OPERATION_FAILED = 'GTFS_DB_OPERATION_FAILED',\n GTFS_JSON_INVALID = 'GTFS_JSON_INVALID',\n GTFS_UNSUPPORTED_FILE_TYPE = 'GTFS_UNSUPPORTED_FILE_TYPE',\n GTFS_CSV_PARSE_FAILED = 'GTFS_CSV_PARSE_FAILED',\n GTFS_QUERY_INVALID = 'GTFS_QUERY_INVALID',\n}\n\nexport enum GtfsWarningCode {\n GTFS_DUPLICATE_PRIMARY_KEY = 'GTFS_DUPLICATE_PRIMARY_KEY',\n}\n\nexport interface GtfsWarning {\n code: GtfsWarningCode;\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport interface ImportReport {\n errors: GtfsError[];\n warnings: GtfsWarning[];\n errorCountsByCode: Partial<Record<GtfsErrorCode, number>>;\n warningCountsByCode: Partial<Record<GtfsWarningCode, number>>;\n}\n\ninterface GtfsErrorOptions {\n code: GtfsErrorCode;\n category: GtfsErrorCategory;\n isOperational?: boolean;\n statusCode?: number;\n details?: Record<string, unknown>;\n cause?: unknown;\n}\n\nexport class GtfsError extends Error {\n code: GtfsErrorCode;\n category: GtfsErrorCategory;\n isOperational: boolean;\n statusCode?: number;\n details?: Record<string, unknown>;\n\n constructor(message: string, options: GtfsErrorOptions) {\n super(message, { cause: options.cause });\n this.name = 'GtfsError';\n this.code = options.code;\n this.category = options.category;\n this.isOperational = options.isOperational ?? true;\n this.statusCode = options.statusCode;\n this.details = options.details;\n }\n}\n\nexport function isGtfsError(error: unknown): error is GtfsError {\n if (!error || typeof error !== 'object') {\n return false;\n }\n\n const candidate = error as Partial<GtfsError> & { name?: unknown };\n return (\n candidate.name === 'GtfsError' &&\n typeof candidate.message === 'string' &&\n typeof candidate.code === 'string' &&\n typeof candidate.category === 'string' &&\n typeof candidate.isOperational === 'boolean'\n );\n}\n\nexport function isGtfsValidationError(error: unknown): error is GtfsError {\n return isGtfsError(error) && error.category === GtfsErrorCategory.VALIDATION;\n}\n\nexport function toGtfsError(\n error: unknown,\n fallback: Omit<GtfsErrorOptions, 'cause'> & { message: string },\n): GtfsError {\n if (isGtfsError(error)) {\n return error;\n }\n\n return new GtfsError(fallback.message, {\n ...fallback,\n cause: error,\n });\n}\n\nexport function createImportReport(): ImportReport {\n return {\n errors: [],\n warnings: [],\n errorCountsByCode: {},\n warningCountsByCode: {},\n };\n}\n\nexport function addImportError(report: ImportReport, error: GtfsError): void {\n report.errors.push(error);\n report.errorCountsByCode[error.code] =\n (report.errorCountsByCode[error.code] ?? 0) + 1;\n}\n\nexport function addImportWarning(\n report: ImportReport,\n warning: GtfsWarning,\n): void {\n report.warnings.push(warning);\n report.warningCountsByCode[warning.code] =\n (report.warningCountsByCode[warning.code] ?? 0) + 1;\n}\n\nexport function formatGtfsError(\n error: unknown,\n options: { verbosity: 'user' | 'developer' } = { verbosity: 'developer' },\n) {\n if (!isGtfsError(error)) {\n const message = error instanceof Error ? error.message : String(error);\n return options.verbosity === 'user' ? message : `UNKNOWN_ERROR: ${message}`;\n }\n\n if (options.verbosity === 'user') {\n return error.message;\n }\n\n return [\n `${error.code}: ${error.message}`,\n `category=${error.category}`,\n error.statusCode !== undefined ? `statusCode=${error.statusCode}` : null,\n error.details ? `details=${JSON.stringify(error.details)}` : null,\n ]\n .filter(Boolean)\n .join(' | ');\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\n/** Represents a GeoJSON coordinate pair [longitude, latitude] */\ntype Position = [number, number];\n\n/**\n * Validates if a string is valid JSON\n * @param {string} string - The string to validate as JSON\n * @returns {boolean} True if string is valid JSON, false otherwise\n * @example\n * isValidJSON('{\"key\": \"value\"}') // returns true\n * isValidJSON('invalid json') // returns false\n */\nexport function isValidJSON(string: string): boolean {\n try {\n JSON.parse(string);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Validates if an array of positions forms a valid LineString\n * @param {Position[]} [lineString] - Array of coordinate pairs\n * @returns {boolean} True if lineString is valid, false otherwise\n */\nfunction isValidLineString(lineString?: Position[]): boolean {\n if (!lineString || lineString.length <= 1) {\n return false;\n }\n\n // Reject linestrings with two identical points\n if (lineString.length === 2) {\n const [[x1, y1], [x2, y2]] = lineString;\n return !(x1 === x2 && y1 === y2);\n }\n\n return true;\n}\n\n/**\n * Consolidates shape groups into unique line segments\n * @param {Shape[][]} shapeGroups - Array of shape point groups\n * @returns {Position[][]} Array of consolidated line strings\n */\nfunction consolidateShapes(shapeGroups: Shape[][]): Position[][] {\n const keys = new Set<string>();\n const segmentsArray = shapeGroups.map((shapes) =>\n shapes.reduce<Position[][]>((memo, point, idx) => {\n if (idx > 0) {\n const prevPoint = shapes[idx - 1];\n memo.push([\n [prevPoint.shape_pt_lon, prevPoint.shape_pt_lat],\n [point.shape_pt_lon, point.shape_pt_lat],\n ]);\n }\n return memo;\n }, []),\n );\n\n const consolidatedLineStrings: Position[][] = [];\n\n for (const segments of segmentsArray) {\n consolidatedLineStrings.push([]);\n\n for (const segment of segments) {\n const key1 = segment.flat().join(',');\n const key2 = segment.reverse().flat().join(',');\n const currentLine = last(consolidatedLineStrings);\n\n if (!currentLine || keys.has(key1) || keys.has(key2)) {\n consolidatedLineStrings.push([]);\n continue;\n }\n\n if (currentLine.length === 0) {\n currentLine.push(segment[0]);\n }\n currentLine.push(segment[1]);\n keys.add(key1);\n keys.add(key2);\n }\n }\n\n return filter(consolidatedLineStrings, isValidLineString);\n}\n\n/**\n * Formats a color string to hex format\n * @param {string | null | undefined} color - Color string to format\n * @returns {string | undefined} Formatted hex color or undefined\n * @example\n * formatHexColor('FF0000') // returns '#FF0000'\n */\nfunction formatHexColor(color: string | null | undefined): string | undefined {\n if (!color) return undefined;\n return `#${color}`;\n}\n\n/**\n * Formats properties object by cleaning null values and formatting colors\n * @param {Record<string, unknown>} properties - Properties object to format\n * @returns {Record<string, unknown>} Formatted properties object\n */\nfunction formatProperties(\n properties: Record<string, unknown>,\n): Record<string, unknown> {\n const formattedProperties = cloneDeep(\n omitBy(properties, (value) => value == null),\n );\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 && Array.isArray(properties.routes)) {\n formattedProperties.routes = properties.routes.map(\n (route: Record<string, unknown>) => formatProperties(route),\n );\n }\n\n return formattedProperties;\n}\n\n/**\n * Converts GTFS shapes to GeoJSON Feature\n * @param {Shape[]} shapes - Array of GTFS shapes\n * @param {Record<string, unknown>} [properties={}] - Properties to add to the feature\n * @returns {Feature} GeoJSON Feature with MultiLineString geometry\n */\nexport function shapesToGeoJSONFeature(\n shapes: Shape[],\n properties: Record<string, unknown> = {},\n) {\n const shapeGroups = Object.values(groupBy(shapes, 'shape_id')).map(\n (shapeGroup) => sortBy(shapeGroup, 'shape_pt_sequence'),\n );\n\n const lineStrings = consolidateShapes(shapeGroups);\n\n return feature(\n {\n type: 'MultiLineString',\n coordinates: lineStrings,\n },\n formatProperties(properties),\n );\n}\n\n/**\n * Converts GTFS stops to GeoJSON FeatureCollection\n * @param {Stop[]} stops - Array of GTFS stops\n * @returns {FeatureCollection} GeoJSON FeatureCollection of Point features\n */\nexport function stopsToGeoJSONFeatureCollection(stops: Stop[]) {\n const features = compact(\n stops.map((stop) => {\n if (!stop.stop_lon || !stop.stop_lat) {\n return undefined;\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 GtfsRealtimeBindings from 'gtfs-realtime-bindings';\nimport mapSeries from 'promise-map-series';\nimport { get } from 'lodash-es';\nimport Database from 'better-sqlite3';\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 applyPrefixToValue,\n pluralize,\n setDefaultConfig,\n validateConfigForImport,\n} from './utils.ts';\nimport {\n addImportError,\n formatGtfsError,\n GtfsError,\n GtfsErrorCategory,\n GtfsErrorCode,\n ImportReport,\n toGtfsError,\n} from './errors.ts';\n\nimport {\n Config,\n ConfigAgency,\n ModelColumn,\n Model,\n} from '../types/global_interfaces.ts';\n\ninterface RealtimeUrlConfig {\n url: string;\n headers?: Record<string, string>;\n}\n\ninterface GtfsRealtimeTask {\n realtimeAlerts?: RealtimeUrlConfig;\n realtimeTripUpdates?: RealtimeUrlConfig;\n realtimeVehiclePositions?: RealtimeUrlConfig;\n downloadTimeout?: number;\n gtfsRealtimeExpirationSeconds: number;\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 report?: ImportReport;\n}\n\ninterface ProcessedEntity {\n id: string;\n alert?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n tripUpdate?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n vehicle?: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\ninterface RealtimeData {\n entity: ProcessedEntity[];\n}\n\ninterface ProcessingResult {\n recordCount: number;\n errorCount: number;\n}\n\ninterface BatchProcessor<T> {\n (batch: T[]): Promise<ProcessingResult>;\n}\n\nconst BATCH_SIZE = 1000;\nconst MAX_RETRIES = 3;\nconst RETRY_DELAY = 1000;\n\n/**\n * Prepares a field value for database insertion\n */\nfunction prepareRealtimeFieldValue(\n entity: any, // eslint-disable-line @typescript-eslint/no-explicit-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 const baseValue =\n column.source === undefined\n ? column.default\n : get(entity, column.source, column.default);\n\n const timeAdjustedValue = baseValue?.__isLong__\n ? convertLongTimeToDate(baseValue)\n : baseValue;\n\n const prefixedValue = applyPrefixToValue(\n timeAdjustedValue,\n column.prefix,\n task.prefix,\n );\n\n return column.type === 'json' ? JSON.stringify(prefixedValue) : prefixedValue;\n}\n\n/**\n * Creates a prepared statement for a model\n */\nfunction createPreparedStatement(db: Database.Database, model: Model) {\n const columns = model.schema.map((column: ModelColumn) => column.name);\n const placeholders = model.schema.map(() => '?').join(', ');\n\n return db.prepare(\n `REPLACE INTO ${model.filenameBase} (${columns.join(', ')}) VALUES (${placeholders})`,\n );\n}\n\n/**\n * Processes entities in batches\n */\nasync function processBatch<T>(\n items: T[],\n batchSize: number,\n processor: BatchProcessor<T>,\n): Promise<ProcessingResult> {\n let totalRecordCount = 0;\n let totalErrorCount = 0;\n\n for (let i = 0; i < items.length; i += batchSize) {\n const batch = items.slice(i, i + batchSize);\n try {\n const result = await processor(batch);\n totalRecordCount += result.recordCount;\n totalErrorCount += result.errorCount;\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n totalErrorCount += batch.length;\n console.error(`Batch processing error: ${errorMessage}`);\n }\n }\n\n return { recordCount: totalRecordCount, errorCount: totalErrorCount };\n}\n\n/**\n * Fetches GTFS Realtime data\n */\nasync function fetchGtfsRealtimeData(\n type: 'alerts' | 'tripupdates' | 'vehiclepositions',\n task: GtfsRealtimeTask,\n): Promise<RealtimeData | null> {\n const urlConfig = getUrlConfig(type, task);\n\n if (!urlConfig) {\n return null;\n }\n\n task.log(`Importing - GTFS-Realtime from ${urlConfig.url}`);\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n try {\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 throw new GtfsError(`HTTP ${response.status}: ${response.statusText}`, {\n code: GtfsErrorCode.GTFS_DOWNLOAD_HTTP,\n category: GtfsErrorCategory.DOWNLOAD,\n statusCode: response.status,\n details: {\n url: urlConfig.url,\n status: response.status,\n statusText: response.statusText,\n },\n });\n }\n\n const buffer = await response.arrayBuffer();\n const message = GtfsRealtimeBindings.transit_realtime.FeedMessage.decode(\n new Uint8Array(buffer),\n );\n\n const feedMessage =\n GtfsRealtimeBindings.transit_realtime.FeedMessage.toObject(message, {\n enums: String,\n longs: String,\n bytes: String,\n defaults: false,\n arrays: true,\n objects: true,\n oneofs: true,\n }) as RealtimeData;\n\n return feedMessage;\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DOWNLOAD_FAILED,\n category: GtfsErrorCategory.DOWNLOAD,\n details: { type, url: urlConfig.url },\n });\n if (attempt === MAX_RETRIES) {\n if (task.ignoreErrors) {\n task.logError(\n `Failed to fetch ${type} after ${MAX_RETRIES} attempts: ${gtfsError.message}`,\n );\n if (task.report) {\n addImportError(task.report, gtfsError);\n }\n return null;\n }\n throw gtfsError;\n }\n\n task.logWarning(\n `Attempt ${attempt} failed for ${type}: ${gtfsError.message}`,\n );\n await new Promise((resolve) =>\n setTimeout(resolve, RETRY_DELAY * attempt),\n );\n }\n }\n\n return null;\n}\n\n/**\n * Gets URL configuration for a specific realtime type\n */\nfunction getUrlConfig(\n type: 'alerts' | 'tripupdates' | 'vehiclepositions',\n task: GtfsRealtimeTask,\n): RealtimeUrlConfig | undefined {\n switch (type) {\n case 'alerts':\n return task.realtimeAlerts;\n case 'tripupdates':\n return task.realtimeTripUpdates;\n case 'vehiclepositions':\n return task.realtimeVehiclePositions;\n default:\n return undefined;\n }\n}\n\n/**\n * Creates a processor for service alerts\n */\nfunction createServiceAlertsProcessor(\n db: Database.Database,\n task: GtfsRealtimeTask,\n): BatchProcessor<ProcessedEntity> {\n const alertStmt = createPreparedStatement(db, models.serviceAlerts as Model);\n const informedEntityStmt = createPreparedStatement(\n db,\n models.serviceAlertInformedEntities as Model,\n );\n\n return async (batch: ProcessedEntity[]): Promise<ProcessingResult> => {\n let recordCount = 0;\n let errorCount = 0;\n\n db.transaction(() => {\n for (const entity of batch) {\n try {\n // Process main alert\n const alertValues = (\n models.serviceAlerts.schema as ModelColumn[]\n ).map((column) => prepareRealtimeFieldValue(entity, column, task));\n alertStmt.run(alertValues);\n recordCount++;\n\n // Process informed entities\n if (entity.alert?.informedEntity?.length) {\n for (const informedEntity of entity.alert.informedEntity) {\n informedEntity.parent = entity;\n const entityValues = (\n models.serviceAlertInformedEntities.schema as ModelColumn[]\n ).map((column) =>\n prepareRealtimeFieldValue(informedEntity, column, task),\n );\n informedEntityStmt.run(entityValues);\n recordCount++;\n }\n }\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n errorCount++;\n task.logWarning(`Alert processing error: ${errorMessage}`);\n }\n }\n })();\n\n return { recordCount, errorCount };\n };\n}\n\n/**\n * Creates a processor for trip updates\n */\nfunction createTripUpdatesProcessor(\n db: Database.Database,\n task: GtfsRealtimeTask,\n): BatchProcessor<ProcessedEntity> {\n const tripUpdateStmt = createPreparedStatement(\n db,\n models.tripUpdates as Model,\n );\n const stopTimeStmt = createPreparedStatement(\n db,\n models.stopTimeUpdates as Model,\n );\n\n return async (batch: ProcessedEntity[]): Promise<ProcessingResult> => {\n let recordCount = 0;\n let errorCount = 0;\n\n db.transaction(() => {\n for (const entity of batch) {\n try {\n // Process main trip update\n const tripUpdateValues = (\n models.tripUpdates.schema as ModelColumn[]\n ).map((column) => prepareRealtimeFieldValue(entity, column, task));\n tripUpdateStmt.run(tripUpdateValues);\n recordCount++;\n\n // Process stop time updates\n if (entity.tripUpdate?.stopTimeUpdate?.length) {\n for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {\n stopTimeUpdate.parent = entity;\n const stopTimeValues = (\n models.stopTimeUpdates.schema as ModelColumn[]\n ).map((column) =>\n prepareRealtimeFieldValue(stopTimeUpdate, column, task),\n );\n stopTimeStmt.run(stopTimeValues);\n recordCount++;\n }\n }\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n errorCount++;\n task.logWarning(`Trip update processing error: ${errorMessage}`);\n }\n }\n })();\n\n return { recordCount, errorCount };\n };\n}\n\n/**\n * Creates a processor for vehicle positions\n */\nfunction createVehiclePositionsProcessor(\n db: Database.Database,\n task: GtfsRealtimeTask,\n): BatchProcessor<ProcessedEntity> {\n const vehiclePositionStmt = createPreparedStatement(\n db,\n models.vehiclePositions as Model,\n );\n\n return async (batch: ProcessedEntity[]): Promise<ProcessingResult> => {\n let recordCount = 0;\n let errorCount = 0;\n\n db.transaction(() => {\n for (const entity of batch) {\n try {\n const fieldValues = (\n models.vehiclePositions.schema as ModelColumn[]\n ).map((column) => prepareRealtimeFieldValue(entity, column, task));\n vehiclePositionStmt.run(fieldValues);\n recordCount++;\n } catch (error: unknown) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n errorCount++;\n task.logWarning(`Vehicle position processing error: ${errorMessage}`);\n }\n }\n })();\n\n return { recordCount, errorCount };\n };\n}\n\n/**\n * Removes expired GTFS-Realtime data\n */\nfunction removeExpiredRealtimeData(config: Config): void {\n const db = openDb(config);\n\n log(config)(`Removing expired GTFS-Realtime data`);\n\n db.transaction(() => {\n const tables = [\n 'vehicle_positions',\n 'trip_updates',\n 'stop_time_updates',\n 'service_alerts',\n 'service_alert_informed_entities',\n ];\n\n for (const table of tables) {\n db.prepare(\n `DELETE FROM ${table} WHERE expiration_timestamp <= strftime('%s','now')`,\n ).run();\n }\n })();\n\n log(config)(`Removed expired GTFS-Realtime data\\r`, true);\n}\n\n/**\n * Updates GTFS Realtime data\n */\nexport async function updateGtfsRealtimeData(\n task: GtfsRealtimeTask,\n): Promise<void> {\n if (\n !task.realtimeAlerts &&\n !task.realtimeTripUpdates &&\n !task.realtimeVehiclePositions\n ) {\n return;\n }\n\n // Download all data types in parallel\n const [alertsData, tripUpdatesData, vehiclePositionsData] = await Promise.all(\n [\n task.realtimeAlerts?.url ? fetchGtfsRealtimeData('alerts', task) : null,\n task.realtimeTripUpdates?.url\n ? fetchGtfsRealtimeData('tripupdates', task)\n : null,\n task.realtimeVehiclePositions?.url\n ? fetchGtfsRealtimeData('vehiclepositions', task)\n : null,\n ],\n );\n\n const db = openDb({ sqlitePath: task.sqlitePath });\n\n const recordCounts = {\n alerts: 0,\n tripupdates: 0,\n vehiclepositions: 0,\n };\n\n // Process each data type with batching\n const processingPromises: Promise<void>[] = [];\n\n if (alertsData?.entity?.length) {\n processingPromises.push(\n processBatch(\n alertsData.entity,\n BATCH_SIZE,\n createServiceAlertsProcessor(db, task),\n ).then((result) => {\n recordCounts.alerts = result.recordCount;\n }),\n );\n }\n\n if (tripUpdatesData?.entity?.length) {\n processingPromises.push(\n processBatch(\n tripUpdatesData.entity,\n BATCH_SIZE,\n createTripUpdatesProcessor(db, task),\n ).then((result) => {\n recordCounts.tripupdates = result.recordCount;\n }),\n );\n }\n\n if (vehiclePositionsData?.entity?.length) {\n processingPromises.push(\n processBatch(\n vehiclePositionsData.entity,\n BATCH_SIZE,\n createVehiclePositionsProcessor(db, task),\n ).then((result) => {\n recordCounts.vehiclepositions = result.recordCount;\n }),\n );\n }\n\n // Wait for all processing to complete\n await Promise.all(processingPromises);\n\n task.log(\n `GTFS-Realtime import complete: ${recordCounts.alerts} alerts, ${recordCounts.tripupdates} trip updates, ${recordCounts.vehiclepositions} vehicle positions`,\n );\n}\n\n/**\n * Main function to update GTFS Realtime data\n */\nexport async function updateGtfsRealtime(initialConfig: Config): Promise<void> {\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 'agency',\n 'agencies',\n agencyCount,\n )} using SQLite database at ${config.sqlitePath}`,\n );\n\n removeExpiredRealtimeData(config);\n\n await mapSeries(config.agencies, async (agency: ConfigAgency) => {\n let task: GtfsRealtimeTask | undefined;\n try {\n 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 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 await updateGtfsRealtimeData(task);\n } catch (error: unknown) {\n const gtfsError = toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: { sqlitePath: task?.sqlitePath ?? config.sqlitePath },\n });\n if (config.ignoreErrors) {\n logError(config)(formatGtfsError(gtfsError));\n if (task?.report) {\n addImportError(task.report, gtfsError);\n }\n } else {\n throw gtfsError;\n }\n }\n });\n\n log(config)(\n `Completed GTFS-Realtime refresh for ${pluralize(\n 'agency',\n 'agencies',\n agencyCount,\n )}\\n`,\n );\n } catch (error: unknown) {\n if ((error as Error & { code?: string }).code === 'SQLITE_CANTOPEN') {\n const dbOpenError = new GtfsError(\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 code: GtfsErrorCode.DB_OPEN_FAILED,\n category: GtfsErrorCategory.DATABASE,\n details: {\n sqlitePath: config.sqlitePath,\n dbCode: (error as Error & { code?: string }).code,\n },\n cause: error,\n },\n );\n logError(config)(dbOpenError.message);\n throw dbOpenError;\n }\n throw toGtfsError(error, {\n message: error instanceof Error ? error.message : String(error),\n code: GtfsErrorCode.GTFS_DB_OPERATION_FAILED,\n category: GtfsErrorCategory.DATABASE,\n });\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';\nimport { GtfsError, GtfsErrorCategory, GtfsErrorCode } from './errors.ts';\n\n/**\n * Validates the configuration object for GTFS import\n * @param config The configuration object to validate\n * @throws Error if agencies are missing or if agency lacks both url and path\n * @returns The validated config object\n */\nexport function validateConfigForImport(config: Config) {\n if (!config.agencies || config.agencies.length === 0) {\n throw new GtfsError('No `agencies` specified in config', {\n code: GtfsErrorCode.GTFS_CONFIG_INVALID,\n category: GtfsErrorCategory.CONFIG,\n details: { field: 'agencies' },\n });\n }\n\n for (const [index, agency] of config.agencies.entries()) {\n if (!agency.path && !agency.url) {\n throw new GtfsError(\n `No Agency \\`url\\` or \\`path\\` specified in config for agency index ${index}.`,\n {\n code: GtfsErrorCode.GTFS_CONFIG_INVALID,\n category: GtfsErrorCategory.CONFIG,\n details: { agencyIndex: index },\n },\n );\n }\n }\n\n return config;\n}\n\n/**\n * Initializes configuration with default values\n * @param initialConfig The user-provided configuration\n * @returns Merged 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 verbose: true,\n downloadTimeout: 30000,\n };\n\n return {\n ...defaults,\n ...initialConfig,\n };\n}\n\n/**\n * Converts a Long timestamp to ISO date string\n * @param longDate Object containing high, low, and unsigned values\n * @returns ISO formatted date string\n */\nexport function convertLongTimeToDate(longDate: {\n high: number;\n low: number;\n unsigned: boolean;\n}) {\n const { high, low, unsigned } = longDate;\n return new Date(\n Long.fromBits(low, high, unsigned).toNumber() * 1000,\n ).toISOString();\n}\n\n/**\n * Converts time string in HH:mm:ss format to seconds since midnight\n * @param time Time string in HH:mm:ss format\n * @returns Number of seconds since midnight, or null if invalid format\n */\nexport function calculateSecondsFromMidnight(time: string): number | null {\n if (!time || typeof time !== 'string') {\n return null;\n }\n\n const [hours, minutes, seconds] = time.split(':').map(Number);\n\n if ([hours, minutes, seconds].some(isNaN) || minutes >= 60 || seconds >= 60) {\n return null;\n }\n\n return hours * 3600 + minutes * 60 + seconds;\n}\n\n/**\n * Ensures time components have leading zeros (e.g., \"9:5:1\" -> \"09:05:01\")\n * @param time Time string in HH:mm:ss format\n * @returns Formatted time string with leading zeros, or null if invalid format\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\n/**\n * Formats SQL SELECT clause from array of field names or field mapping object\n * @param fields Array of field names or object mapping source to alias\n * @returns Formatted SELECT clause\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\n/**\n * Formats SQL JOIN clause from array of join configurations\n * @param joinObject Array of join options\n * @returns Formatted JOIN clause\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\n/**\n * Converts degrees to radians\n * @param angle Angle in degrees\n * @returns Angle in radians\n */\nfunction degree2radian(angle: number) {\n return (angle * Math.PI) / 180;\n}\n\n/**\n * Converts radians to degrees\n * @param angle Angle in radians\n * @returns Angle in degrees\n */\nfunction radian2degree(angle: number) {\n return (angle / Math.PI) * 180;\n}\n\nconst EARTH_RADIUS_METERS = 6371000;\n\n/**\n * Creates SQL WHERE clause for geographic bounding box search\n * @param latitudeDegree Center latitude in degrees\n * @param longitudeDegree Center longitude in degrees\n * @param boundingBoxSideMeters Size of bounding box in meters\n * @returns SQL WHERE clause for bounding box search\n */\nexport function formatWhereClauseBoundingBox(\n latitudeDegree: number | string,\n longitudeDegree: number | string,\n boundingBoxSideMeters: number,\n): string {\n const lat = Number(latitudeDegree);\n const lon = Number(longitudeDegree);\n\n if (\n isNaN(lat) ||\n isNaN(lon) ||\n lat < -90 ||\n lat > 90 ||\n lon < -180 ||\n lon > 180\n ) {\n throw new GtfsError('Invalid latitude or longitude values', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { latitudeDegree, longitudeDegree, boundingBoxSideMeters },\n });\n }\n\n const latitudeRadian = degree2radian(lat);\n const radiusFromLatitude = Math.cos(latitudeRadian) * EARTH_RADIUS_METERS;\n\n const halfSide = boundingBoxSideMeters / 2;\n const deltaLatitude = radian2degree(halfSide / EARTH_RADIUS_METERS);\n const deltaLongitude = radian2degree(halfSide / radiusFromLatitude);\n\n return [\n `stop_lat BETWEEN ${lat - deltaLatitude} AND ${lat + deltaLatitude}`,\n `stop_lon BETWEEN ${lon - deltaLongitude} AND ${lon + deltaLongitude}`,\n ].join(' AND ');\n}\n\n/**\n * Formats SQL WHERE clause for a single key-value pair\n * @param key Column name\n * @param value Single value, array of values, or null\n * @returns Formatted WHERE clause condition\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\n/**\n * Formats complete SQL WHERE clause from query object\n * @param query Object containing column-value pairs\n * @returns Formatted WHERE clause or empty string if no conditions\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\n/**\n * Formats SQL ORDER BY clause from array of sorting criteria\n * @param orderBy Array of [column, direction] tuples\n * @returns Formatted ORDER BY clause\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\n/**\n * Gets day of week name from YYYYMMDD date number\n * @param date Date in YYYYMMDD format\n * @returns Lowercase day name (sunday-saturday)\n */\nexport function getDayOfWeekFromDate(date: number): string {\n const DAYS_OF_WEEK = [\n 'sunday',\n 'monday',\n 'tuesday',\n 'wednesday',\n 'thursday',\n 'friday',\n 'saturday',\n ] as const;\n\n if (!Number.isInteger(date) || date.toString().length !== 8) {\n throw new GtfsError('Date must be in YYYYMMDD format', {\n code: GtfsErrorCode.GTFS_INVALID_DATE,\n category: GtfsErrorCategory.VALIDATION,\n details: { value: date },\n });\n }\n\n const year = Math.floor(date / 10000);\n const month = Math.floor((date % 10000) / 100);\n const day = date % 100;\n\n const dateObj = new Date(year, month - 1, day);\n\n if (dateObj.toString() === 'Invalid Date') {\n throw new GtfsError('Invalid date', {\n code: GtfsErrorCode.GTFS_INVALID_DATE,\n category: GtfsErrorCategory.VALIDATION,\n details: { value: date },\n });\n }\n\n return DAYS_OF_WEEK[dateObj.getDay()];\n}\n\n/**\n * Formats a numeric value according to the decimal precision rules of the specified currency,\n * without any currency symbols or separators.\n * @param value The numeric value to format (e.g., 10.5)\n * @param currency The ISO 4217 currency code (e.g., 'USD', 'JPY', 'EUR')\n * @returns The formatted string with appropriate decimal places\n * Examples:\n * - formatCurrency(10.5, 'USD') => '10.50' // USD uses 2 decimal places\n * - formatCurrency(10.5, 'JPY') => '10' // JPY uses 0 decimal places\n * - formatCurrency(10.523, 'BHD') => '10.523' // BHD uses 3 decimal places\n */\nexport function formatCurrency(value: number, currency: string) {\n const parts = new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n }).formatToParts(value);\n\n const integerPart =\n parts.find((part) => part.type === 'integer')?.value ?? '0';\n const fractionPart =\n parts.find((part) => part.type === 'fraction')?.value ?? '';\n\n return `${integerPart}${fractionPart !== '' ? `.${fractionPart}` : ''}`;\n}\n\n/**\n * Gets the timestamp column name for a given column name\n * @param columnName The column name\n * @returns The timestamp column name\n */\nexport function getTimestampColumnName(columnName: string) {\n return columnName.endsWith('time')\n ? `${columnName}stamp`\n : `${columnName}_timestamp`;\n}\n\n/**\n * Applies a prefix to a value if the column should be prefixed and the value is not null\n * @param value The value to prefix\n * @param columnShouldBePrefixed Whether the column should be prefixed\n * @param prefix The prefix to apply\n * @returns The value with the prefix applied if the column should be prefixed and the value is not null\n */\nexport function applyPrefixToValue(\n value: string,\n columnShouldBePrefixed?: boolean,\n prefix?: string,\n) {\n if (!columnShouldBePrefixed || prefix === undefined || value === null) {\n return value;\n }\n\n return `${prefix}${value}`;\n}\n\n/**\n * Pluralizes a word based on the count\n * @param singularWord The singular word\n * @param pluralWord The plural word\n * @param count The count of the word\n * @returns The pluralized word\n */\nexport function pluralize(\n singularWord: string,\n pluralWord: string,\n count: number,\n) {\n return count === 1 ? singularWord : pluralWord;\n}\n","import path from 'node:path';\nimport { writeFile } from 'node:fs/promises';\n\nimport { without, compact } from 'lodash-es';\nimport { stringify } from 'csv-stringify';\nimport sqlString from 'sqlstring-sqlite';\nimport Database from 'better-sqlite3';\nimport mapSeries from 'promise-map-series';\n\nimport * as models from '../models/models.ts';\nimport { openDb } from './db.ts';\nimport { prepDirectory, generateFolderName, untildify } from './file-utils.ts';\nimport { log, logWarning } from './log-utils.ts';\nimport { formatCurrency, pluralize, setDefaultConfig } from './utils.ts';\n\nimport { Config, Model, SqlValue } 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 {\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 'agencies',\n agencyCount,\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) as Model[]).filter(\n (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.prepare(`SELECT * FROM ${tableName};`).all() as Array<\n Record<string, SqlValue>\n >;\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\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 } else if (model.filenameBase === 'fare_attributes') {\n for (const line of lines) {\n line.price = formatCurrency(\n line.price as number,\n line.currency_type as string,\n );\n }\n } else if (model.filenameBase === 'fare_products') {\n for (const line of lines) {\n line.amount = formatCurrency(\n line.amount as number,\n line.currency as string,\n );\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 as string);\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', 'agencies', agencyCount)}\\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 type {\n JoinOptions,\n QueryOptions,\n SqlOrderBy,\n SqlWhere,\n SqlValue,\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?: string[];\n orderBy?: SqlOrderBy;\n join?: JoinOptions[];\n options?: QueryOptions;\n },\n) {\n const defaultOptions: {\n query: SqlWhere;\n fields: string[];\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 Array<Record<string, SqlValue>>;\n}\n","import { omit, pick } from 'lodash-es';\n\nimport type {\n QueryOptions,\n Route,\n SqlOrderBy,\n QueryResult,\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<Fields extends keyof Route>(\n query: SqlWhere = {},\n fields: Fields[] = [],\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 const routeQuery = omit(query, ['stop_id', 'service_id']);\n const tripQuery = pick(query, ['stop_id', 'service_id']) as {\n stop_id?: string;\n service_id?: string;\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 QueryResult<Route, Fields>[];\n}\n","import { compact, omit, pick } from 'lodash-es';\nimport { FeatureCollection } from 'geojson';\nimport { featureCollection } from '@turf/helpers';\n\nimport type {\n QueryOptions,\n Shape,\n SqlOrderBy,\n QueryResult,\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 | number }) {\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<Fields extends keyof Shape>(\n query: SqlWhere = {},\n fields: Fields[] = [],\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 = pick(query, [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n ]) as {\n route_id?: string;\n trip_id?: string;\n service_id?: string;\n direction_id?: number;\n };\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 QueryResult<Shape, Fields>[];\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(shapeQuery, [], [], options);\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 type {\n QueryOptions,\n SqlOrderBy,\n QueryResult,\n SqlWhere,\n Stop,\n SqlValue,\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]: SqlValue }) {\n const whereClause = formatWhereClauses(query);\n return `SELECT trip_id FROM trips ${whereClause}`;\n}\n\nfunction buildStoptimeSubquery(query: { [key: string]: SqlValue }) {\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<Fields extends keyof Stop>(\n query: SqlWhere = {},\n fields: Fields[] = [],\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 let 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 const stopQuery = omit(query, stopQueryOmitKeys);\n\n const tripQuery = pick(query, [\n 'route_id',\n 'trip_id',\n 'service_id',\n 'direction_id',\n 'shape_id',\n ]) as {\n route_id?: string;\n trip_id?: string;\n service_id?: string;\n direction_id?: number;\n shape_id?: string;\n };\n\n const whereClauses = Object.entries(stopQuery).map(([key, value]) =>\n formatWhereClause(key, value as SqlValue),\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 // Add distance-based sorting if bounding_box_side_m is set and no other orderBy is set\n if (orderBy.length === 0) {\n orderByClause = `ORDER BY (((stop_lat - ${query.stop_lat}) * (stop_lat - ${query.stop_lat})) + ((stop_lon - ${query.stop_lon}) * (stop_lon - ${query.stop_lon}))) ASC`;\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 QueryResult<Stop, Fields>[];\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 type {\n QueryOptions,\n SqlOrderBy,\n QueryResult,\n SqlWhere,\n StopTime,\n SqlValue,\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 { GtfsError, GtfsErrorCategory, GtfsErrorCode } from '../errors.ts';\nimport { getServiceIdsByDate } from './calendars.ts';\n\n/*\n * Returns an array of stoptimes that match the query parameters.\n */\nexport function getStoptimes<Fields extends keyof StopTime>(\n query: SqlWhere = {},\n fields: Fields[] = [],\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 const stoptimeQuery = omit(query, stoptimeQueryOmitKeys);\n const whereClauses = Object.entries(stoptimeQuery).map(([key, value]) =>\n formatWhereClause(key, value as SqlValue),\n );\n\n if (query.date) {\n if (typeof query.date !== 'number') {\n throw new GtfsError('`date` must be a number in yyyymmdd format', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { field: 'date', value: query.date },\n });\n }\n\n const serviceIds = getServiceIdsByDate(query.date, options);\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 GtfsError('`start_time` must be a string in HH:mm:ss format', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { field: 'start_time', value: query.start_time },\n });\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 GtfsError('`end_time` must be a string in HH:mm:ss format', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { field: 'end_time', value: query.end_time },\n });\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 QueryResult<StopTime, Fields>[];\n}\n","import { omit } from 'lodash-es';\nimport sqlString from 'sqlstring-sqlite';\nimport type {\n QueryOptions,\n SqlOrderBy,\n QueryResult,\n SqlWhere,\n Trip,\n SqlValue,\n} from '../../types/global_interfaces.ts';\nimport { openDb } from '../db.ts';\nimport {\n formatOrderByClause,\n formatSelectClause,\n formatWhereClause,\n} from '../utils.ts';\nimport { GtfsError, GtfsErrorCategory, GtfsErrorCode } from '../errors.ts';\nimport { getServiceIdsByDate } from './calendars.ts';\n\n/*\n * Returns an array of all trips that match the query parameters.\n */\nexport function getTrips<Fields extends keyof Trip>(\n query: SqlWhere = {},\n fields: Fields[] = [],\n orderBy: SqlOrderBy = [],\n options: QueryOptions = {},\n) {\n const db = options.db ?? openDb();\n const tableName = 'trips';\n const selectClause = formatSelectClause(fields);\n let whereClause = '';\n const orderByClause = formatOrderByClause(orderBy);\n\n const tripQueryOmitKeys = ['date'];\n\n const tripQuery = omit(query, tripQueryOmitKeys);\n\n const whereClauses = Object.entries(tripQuery).map(([key, value]) =>\n formatWhereClause(key, value as SqlValue),\n );\n\n if (query.date) {\n if (typeof query.date !== 'number') {\n throw new GtfsError('`date` must be a number in yyyymmdd format', {\n code: GtfsErrorCode.GTFS_QUERY_INVALID,\n category: GtfsErrorCategory.QUERY,\n details: { field: 'date', value: query.date },\n });\n }\n\n const serviceIds = getServiceIdsByDate(query.date, options);\n\n whereClauses.push(\n `service_id IN (${serviceIds.map((id) => sqlString.escape(id)).join(',')})`,\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 QueryResult<Trip, Fields>[];\n}\n"],"mappings":"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,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,MACE,MAAM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","names":["argv","path","existsSync","readFile","rm","mapSeries","omit","path","writeFile","compact","sqlString","mapSeries","path","mapSeries","sqlString","writeFile","compact","sqlString","omit","compact","omit","pick","featureCollection","omit","pick","omit","sqlString","omit","sqlString"]}
|