@golemio/pid
Version:
Golemio PID Module
317 lines • 15.7 kB
JavaScript
"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