UNPKG

@golemio/pid

Version:
317 lines • 15.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GTFSTripsModel = void 0; const PassengerTransferEnums_1 = require("../../../helpers/PassengerTransferEnums"); const const_1 = require("../../../schema-definitions/const"); const ropid_gtfs_1 = require("../../../schema-definitions/ropid-gtfs"); const TripDto_1 = require("../../../schema-definitions/ropid-gtfs/models/TripDto"); const Geo_1 = require("@golemio/core/dist/output-gateway/Geo"); const ioc_1 = require("@golemio/core/dist/output-gateway/ioc/"); const models_1 = require("@golemio/core/dist/output-gateway/models"); const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors"); const sequelize_1 = __importDefault(require("@golemio/core/dist/shared/sequelize")); const GtfsTripScheduleRepository_1 = require("../data-access/GtfsTripScheduleRepository"); class GTFSTripsModel extends models_1.SequelizeModel { constructor() { super(ropid_gtfs_1.RopidGTFS.trips.name, ropid_gtfs_1.RopidGTFS.trips.pgTableName, TripDto_1.TripDto.attributeModel, { schema: const_1.PG_SCHEMA, }); this.Associate = (models) => { this.sequelizeModel.hasMany(models.GTFSStopTimesModel.sequelizeModel, { as: "has_stop_id", foreignKey: "trip_id", }); this.sequelizeModel.hasMany(models.GTFSStopTimesModel.sequelizeModel, { as: "stop_times", foreignKey: "trip_id", }); this.sequelizeModel.belongsTo(models.GTFSCalendarModel.sequelizeModel, { as: "service", foreignKey: "service_id", }); this.sequelizeModel.belongsTo(models.GTFSRoutesModel.sequelizeModel, { as: "route", foreignKey: "route_id", }); this.sequelizeModel.hasMany(models.GTFSShapesModel.sequelizeModel, { as: "shapes", foreignKey: "shape_id", sourceKey: "shape_id", }); this.sequelizeModel.belongsToMany(models.GTFSStopModel.sequelizeModel, { as: "stops", foreignKey: "trip_id", otherKey: "stop_id", through: models.GTFSStopTimesModel.sequelizeModel, }); this.sequelizeModel.hasOne(this.tripScheduleRepository.sequelizeModel, { as: "schedule", foreignKey: "trip_id", sourceKey: "trip_id", scope: { [sequelize_1.default.Op.and]: [sequelize_1.default.literal(`start_timestamp::date = CURRENT_DATE`)], }, }); }; /** Retrieves all gtfs trips * @param {object} options Options object with params * @param {number} [options.limit] Limit * @param {number} [options.offset] Offset * @param {boolean} [options.route] Enhance response with route data * @param {string} [options.stopId] Filter routes by specific stop * @param {string} [options.date] Filter by specific date in the 'YYYY-MM-DD' format * @returns Array of the retrieved records */ this.GetAll = async (options = {}) => { const { limit, offset, stopId, date } = options; try { const include = []; if (stopId) { include.push({ as: "has_stop_id", attributes: [], duplicating: false, model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.stop_times.pgTableName], where: { stop_id: stopId, }, }); } if (date) { include.push({ as: "service", attributes: [], model: this.dbConnector .getConnection() .models[ropid_gtfs_1.RopidGTFS.calendar.pgTableName].scope({ method: ["forDate", date] }), }); } const data = await this.sequelizeModel.findAll({ include, attributes: { exclude: ["headsign_icons"], }, limit, offset, order: [["trip_id", "DESC"]], }); return data; } catch (err) { throw new golemio_errors_1.GeneralError("Database error", "GTFSTripsModel", err, 500); } }; /** Retrieves specific GTFS trip * @param {string} id Id of the trip * @param {object} [options] Options object with params * @param {boolean} [options.route] Enhance response with route data * @param {boolean} [options.shapes] Enhance response with shape data * @param {boolean} [options.service] Enhance response with service data * @param {boolean} [options.stops] Enhance response with stop data * @param {boolean} [options.stopTimes] Enhance response with stop times data * @param {string} [options.date] Filter by specific date in the 'YYYY-MM-DD' format * @returns Object of the retrieved record or null */ this.GetOne = async (id, options = {}) => { const { route, stopTimes, stops, shapes } = options; let trip; try { trip = await this.sequelizeModel.findByPk(id, { include: this.GetInclusions(options) }); } catch (err) { throw new golemio_errors_1.GeneralError("Database error", "GTFSTripsModel", err, 500); } return trip ? this.ConvertItem(trip, { route, stops, shapes, stopTimes }) : null; }; this.getOneForPublicGtfsLookup = async (id, options = {}) => { try { const tripEntity = await this.sequelizeModel.findByPk(id, { attributes: ["trip_id", "shape_id", "trip_headsign", "wheelchair_accessible"], include: this.getInclusionsForPublicGtfsLookup(options), }); return tripEntity ? tripEntity.toJSON() : null; } catch (err) { throw new golemio_errors_1.GeneralError("Cannot get GTFS trip from database", this.constructor.name, err, 500); } }; /** Prepare ORM query with selected params * @param {object} options Options object with params * @param {boolean} [options.route] Enhance response with route data * @param {boolean} [options.shapes] Enhance response with shape data * @param {boolean} [options.service] Enhance response with service data * @param {boolean} [options.stops] Enhance response with stop data * @param {boolean} [options.stopTimes] Enhance response with stop times data * @param {string} [options.date] Filter by specific date in the 'YYYY-MM-DD' format * @returns Array of inclusions */ this.GetInclusions = (options) => { const { stops, stopTimes, shapes, service, route, date } = options; const include = []; // stop_times and stops both selected to include, nest them together if (stops && stopTimes) { include.push({ as: "stop_times", attributes: { exclude: ["arrival_time_seconds", "departure_time_seconds", "timepoint"], }, include: [ { as: "stop", model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.stops.pgTableName], }, ], order: [["stop_sequence", "ASC"]], separate: true, model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.stop_times.pgTableName], }); // Only stops or only stop times selected to include } else { stops && include.push({ as: "stops", model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.stops.pgTableName], through: { attributes: [] }, }); stopTimes && include.push({ as: "stop_times", attributes: { exclude: ["arrival_time_seconds", "departure_time_seconds", "timepoint"], }, order: [["stop_sequence", "ASC"]], separate: true, model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.stop_times.pgTableName], }); } shapes && include.push({ as: "shapes", model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.shapes.pgTableName], }); if (date || service) { include.push({ as: "service", model: this.dbConnector .getConnection() .models[ropid_gtfs_1.RopidGTFS.calendar.pgTableName].scope({ method: ["forDate", date] }), }); } route && include.push({ as: "route", model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.routes.pgTableName], }); return include; }; this.getInclusionsForPublicGtfsLookup = (options) => { const { shouldIncludeStopTimes, shouldIncludeShapes } = options; const include = []; include.push({ as: "route", attributes: ["route_id", "route_short_name", "route_type"], model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.routes.pgTableName], }); include.push({ as: "schedule", attributes: ["run_number"], model: this.dbConnector.getConnection().models[this.tripScheduleRepository.tableName], }); if (shouldIncludeStopTimes) { include.push({ as: "stop_times", attributes: [ "stop_sequence", "shape_dist_traveled", [sequelize_1.default.literal(`EXTRACT(EPOCH FROM "arrival_time"::INTERVAL)::int`), "arrival_time_seconds"], [sequelize_1.default.literal(`EXTRACT(EPOCH FROM "departure_time"::INTERVAL)::int`), "departure_time_seconds"], ], include: [ { as: "stop", attributes: ["stop_name", "zone_id", "stop_lon", "stop_lat", "wheelchair_boarding"], required: true, model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.stops.pgTableName], }, ], where: { // exclude no stop waypoints drop_off_type: { [sequelize_1.default.Op.ne]: PassengerTransferEnums_1.GtfsStopTimeDropOffType.NoDropOff.toString() }, pickup_type: { [sequelize_1.default.Op.ne]: PassengerTransferEnums_1.GtfsStopTimePickupType.NoPickup.toString() }, }, order: [["stop_sequence", "ASC"]], separate: true, model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.stop_times.pgTableName], }); } if (shouldIncludeShapes) { include.push({ as: "shapes", attributes: ["shape_dist_traveled", "shape_pt_lon", "shape_pt_lat"], model: this.dbConnector.getConnection().models[ropid_gtfs_1.RopidGTFS.shapes.pgTableName], }); } return include; }; /** * Convert a single db result to proper output format with all its included sub-elements * @param {object} trip Trip object * @param {object} options Options object with params * @param {boolean} [options.shapes] If shapes were included in filter then convert shapes payload * @param {boolean} [options.stops] If stops were included in filter then convert stops payload * @returns A converted item of the result */ this.ConvertItem = (trip, options) => { const { stop_times: stopTimesItems = [], stops: stopItems = [], shapes: shapeItems = [], ...item } = trip.toJSON(); return { ...item, ...(options.route && { route: { ...item.route, is_night: item.route.is_night === "1", is_regional: item.route.is_regional === "1", is_substitute_transport: item.route.is_substitute_transport === "1", }, }), ...(options.stops && options.stopTimes && { stop_times: stopTimesItems.map((stopTime) => { // exclude computed fields from stop time const { arrival_time_seconds, departure_time_seconds, ...convertedStopTime } = stopTime; convertedStopTime.stop = this.BuildResponse(stopTime.stop, "stop_lon", "stop_lat"); return convertedStopTime; }), }), ...(options.stops && !options.stopTimes && { stops: stopItems.map((stop) => this.BuildResponse(stop, "stop_lon", "stop_lat")), }), ...(!options.stops && options.stopTimes && { stop_times: stopTimesItems.map((stopTime) => { // exclude computed fields from stop time const { arrival_time_seconds, departure_time_seconds, ...convertedStopTime } = stopTime; return convertedStopTime; }), }), ...(options.shapes && { shapes: shapeItems.map((shape) => this.BuildResponse(shape, "shape_pt_lon", "shape_pt_lat")), }), }; }; /** * Builds the correct format of a response data */ this.BuildResponse = (responseObject, longLoc, latLoc) => { return (0, Geo_1.buildGeojsonFeature)(responseObject, longLoc, latLoc, true); }; this.dbConnector = ioc_1.OutputGatewayContainer.resolve(ioc_1.ContainerToken.PostgresDatabase); this.tripScheduleRepository = new GtfsTripScheduleRepository_1.GtfsTripScheduleRepository(); } } exports.GTFSTripsModel = GTFSTripsModel; //# sourceMappingURL=GTFSTripsModel.js.map