@golemio/pid
Version:
Golemio PID Module
310 lines • 16.8 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TripWithLastPositionRepository = void 0;
const const_1 = require("../../../../schema-definitions/const");
const NotPublicVehiclesRedisRepository_1 = require("../cache/NotPublicVehiclesRedisRepository");
const ProcessedPositionRepository_1 = require("./ProcessedPositionRepository");
const VehicleTypeRepository_1 = require("../VehicleTypeRepository");
const VehicleDescriptorRepository_1 = require("../VehicleDescriptorRepository");
const OgVehiclePositionsToken_1 = require("../../ioc/OgVehiclePositionsToken");
const models_1 = require("../../../../schema-definitions/vehicle-descriptors/models");
const vehicle_positions_1 = require("../../../../schema-definitions/vehicle-positions");
const views_1 = require("../../../../schema-definitions/vehicle-positions/models/views");
const Geo_1 = require("@golemio/core/dist/output-gateway/Geo");
const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
const moment_timezone_1 = __importDefault(require("@golemio/core/dist/shared/moment-timezone"));
const sequelize_1 = __importStar(require("@golemio/core/dist/shared/sequelize"));
const const_2 = require("../../../../const");
const RouteTypeEnums_1 = require("../../../../helpers/RouteTypeEnums");
const PositionOutputMapper_1 = require("../helpers/PositionOutputMapper");
const tsyringe_1 = require("@golemio/core/dist/shared/tsyringe");
const AbstractBasicRepository_1 = require("@golemio/core/dist/helpers/data-access/postgres/repositories/AbstractBasicRepository");
const CoreToken_1 = require("@golemio/core/dist/helpers/ioc/CoreToken");
let TripWithLastPositionRepository = class TripWithLastPositionRepository extends AbstractBasicRepository_1.AbstractBasicRepository {
constructor(connector, logger, notPublicVehiclesRepository, processedPositionRepository, vehicleTypeRepository, vehicleDescriptorRepository) {
super(connector, logger);
this.notPublicVehiclesRepository = notPublicVehiclesRepository;
this.processedPositionRepository = processedPositionRepository;
this.vehicleTypeRepository = vehicleTypeRepository;
this.vehicleDescriptorRepository = vehicleDescriptorRepository;
this.schema = const_1.PG_SCHEMA;
this.tableName = views_1.TripWithLastPositionModel.tableName;
/** Retrieves all vehicle trips
* @param {object} options Options object with params
* @param {number} [options.limit] Limit
* @param {number} [options.offset] Offset
* @param {string} [options.routeId] Filter trips by specific route id
* @param {string} [options.routeShortName] Filter trips by specific route short name
* @param {string} [options.tripId] Filter trips by specific trip id
* @param {boolean} [options.includeNotTracking] Should include not tracking vehicle positions (those off a trip)
* @returns Array of the retrieved records
*/
this.GetAll = async (options) => {
const { limit, offset, updatedSince } = options;
const minUpdatedAt = (0, moment_timezone_1.default)().subtract(10, "minutes");
// updatedSince cannot be more than 10 minutes ago
const maxUpdatedAt = updatedSince && (0, moment_timezone_1.default)(updatedSince).isSameOrAfter(minUpdatedAt) ? updatedSince.toISOString() : null;
const include = this.composeIncludes(options);
let notPublicWhereConditions = [];
if (options.includeNotPublic) {
notPublicWhereConditions = await this.getNotPublicWhereConditions();
}
try {
const rows = await this.sequelizeModel.findAll({
attributes: {
exclude: ["id", "vehicle_type_id"],
},
include,
limit,
offset,
where: {
[sequelize_1.Op.and]: [
{
state_position: {
[sequelize_1.Op.in]: this.determinePossibleStatePositions(options.includeNotTracking, options.includeNotPublic),
},
},
{
[sequelize_1.Op.or]: [{ gtfs_trip_id: { [sequelize_1.Op.ne]: null } }, ...notPublicWhereConditions],
},
maxUpdatedAt
? {
updated_at: {
[sequelize_1.Op.gt]: maxUpdatedAt,
},
}
: {},
options.cisTripNumber ? { cis_trip_number: options.cisTripNumber } : {},
options.routeId ? { gtfs_route_id: options.routeId } : {},
options.routeShortName ? { gtfs_route_short_name: options.routeShortName } : {},
options.tripId ? { gtfs_trip_id: options.tripId } : {},
],
},
});
if (rows.length === 0) {
return {
data: (0, Geo_1.buildGeojsonFeatureCollection)([]),
metadata: {
maxUpdatedAt: maxUpdatedAt || new Date().toISOString(),
},
};
}
let returnData = [];
let maxUpdatedAtData = null;
for (const row of rows) {
returnData.push(PositionOutputMapper_1.PositionOutputMapper.mapTripModelToDto(row));
if (maxUpdatedAtData === null || row.updated_at > maxUpdatedAtData) {
maxUpdatedAtData = row.updated_at;
}
}
return {
data: (0, Geo_1.buildGeojsonFeatureCollection)(returnData),
metadata: {
maxUpdatedAt: maxUpdatedAtData?.toISOString() || new Date().toISOString(),
},
};
}
catch (err) {
throw new golemio_errors_1.GeneralError("Database error", "VehiclepositionsTripsModel", err, 500);
}
};
/** Retrieves specific vehicle trip
* @param {string} id Id of the trip
* @param {object} [options] Options object with params
* @param {string} [options.includeNotTracking] Returns last known trip even if it is not tracked at time
* @param {boolean} [options.includePositions] Should include all vehicle positions
* @returns Object of the retrieved record or null
*/
this.GetOneByGTFSTripId = async (id, options) => {
try {
const include = this.composeIncludes(options);
const data = await this.sequelizeModel.findOne({
attributes: {
exclude: ["id", "vehicle_type_id"],
include: ["updated_at"],
},
include,
where: {
gtfs_trip_id: id,
},
order: [["updated_at", "DESC"]],
});
if (!data) {
return null;
}
if (data.lat === null || data.lng === null) {
throw new golemio_errors_1.GeneralError("Missing lat or lng", this.constructor.name, undefined, 500, "pid");
}
return PositionOutputMapper_1.PositionOutputMapper.mapTripModelToDto(data);
}
catch (err) {
throw new golemio_errors_1.GeneralError("Database error", "VehiclePositionsTripsModel", err, 500);
}
};
this.composeIncludes = (options) => {
const possibleStatePositions = this.determinePossibleStatePositions(options.includeNotTracking, options.includeNotPublic);
const include = [
{
as: "vehicle_type",
model: this.connector.getConnection().models[vehicle_positions_1.VehiclePositions.vehicleTypes.pgTableName],
},
{
as: "vehicle_descriptor",
model: this.connector.getConnection().models[models_1.DescriptorModel.tableName],
attributes: ["is_air_conditioned", "has_usb_chargers"],
},
];
if (options.includePositions) {
include.push({
attributes: {
exclude: ["trips_id", "state_position"],
},
as: "all_positions",
model: this.connector.getConnection().models[views_1.ProcessedPositionModel.tableName],
where: {
state_position: {
[sequelize_1.Op.in]: possibleStatePositions,
},
},
});
}
return include;
};
this.determinePossibleStatePositions = (includeNotTracking, includeNotPublic) => {
const possibleStatePosition = [const_2.StatePositionEnum.AT_STOP, const_2.StatePositionEnum.ON_TRACK];
if (includeNotTracking) {
possibleStatePosition.push(const_2.StatePositionEnum.AFTER_TRACK, const_2.StatePositionEnum.AFTER_TRACK_DELAYED, const_2.StatePositionEnum.BEFORE_TRACK, const_2.StatePositionEnum.BEFORE_TRACK_DELAYED, const_2.StatePositionEnum.CANCELED, const_2.StatePositionEnum.OFF_TRACK);
}
if (includeNotPublic) {
possibleStatePosition.push(const_2.StatePositionEnum.NOT_PUBLIC);
}
return possibleStatePosition;
};
this.getNotPublicWhereConditions = async () => {
const conditions = [];
// Fetch not-public vehicles config from Redis
const { tram: { registrationNumbers: tramRegistrationNumbers }, road: { registrationNumbers: roadRegistrationNumbers }, routeIds: allowedRouteNames, } = await this.notPublicVehiclesRepository.getConfig();
// Add tram vehicles condition only if we have tram registration numbers
if (tramRegistrationNumbers && tramRegistrationNumbers.length > 0) {
conditions.push({
[sequelize_1.Op.and]: [
{ gtfs_route_type: RouteTypeEnums_1.GTFSRouteTypeEnum.TRAM },
{ vehicle_registration_number: { [sequelize_1.Op.in]: tramRegistrationNumbers } },
],
});
}
// Add road vehicles condition only if we have road registration numbers
if (roadRegistrationNumbers && roadRegistrationNumbers.length > 0) {
conditions.push({
[sequelize_1.Op.and]: [
{
gtfs_route_type: {
[sequelize_1.Op.in]: [RouteTypeEnums_1.GTFSRouteTypeEnum.BUS, RouteTypeEnums_1.GTFSRouteTypeEnum.TROLLEYBUS],
},
},
{ vehicle_registration_number: { [sequelize_1.Op.in]: roadRegistrationNumbers } },
],
});
}
// Add route names condition only if we have route IDs
if (allowedRouteNames && allowedRouteNames.length > 0) {
conditions.push({
origin_route_name: { [sequelize_1.Op.in]: allowedRouteNames },
});
}
return conditions;
};
this.sequelizeModel = connector.getConnection().define(this.tableName, views_1.TripWithLastPositionModel.attributeModel, {
schema: this.schema,
});
// Set up associations
this.sequelizeModel.hasMany(this.processedPositionRepository.sequelizeModel, {
as: "all_positions",
foreignKey: "trips_id",
scope: {
lat: { [sequelize_1.Op.not]: null },
lng: { [sequelize_1.Op.not]: null },
},
});
this.sequelizeModel.belongsTo(this.vehicleTypeRepository.sequelizeModel, {
as: "vehicle_type",
foreignKey: "vehicle_type_id",
});
this.sequelizeModel.belongsTo(this.vehicleDescriptorRepository.sequelizeModel, {
as: "vehicle_descriptor",
foreignKey: "vehicle_registration_number",
targetKey: "registration_number",
scope: {
[sequelize_1.default.Op.and]: [
sequelize_1.default.literal(`${views_1.TripWithLastPositionModel.tableName}.gtfs_route_type = vehicle_descriptor.gtfs_route_type`),
],
},
});
}
GetOne() {
throw new Error("Not implemented");
}
};
exports.TripWithLastPositionRepository = TripWithLastPositionRepository;
exports.TripWithLastPositionRepository = TripWithLastPositionRepository = __decorate([
(0, tsyringe_1.injectable)(),
__param(0, (0, tsyringe_1.inject)(CoreToken_1.CoreToken.PostgresConnector)),
__param(1, (0, tsyringe_1.inject)(CoreToken_1.CoreToken.Logger)),
__param(2, (0, tsyringe_1.inject)(OgVehiclePositionsToken_1.OgVehiclePositionsToken.NotPublicVehiclesRedisRepository)),
__param(3, (0, tsyringe_1.inject)(OgVehiclePositionsToken_1.OgVehiclePositionsToken.ProcessedPositionRepository)),
__param(4, (0, tsyringe_1.inject)(OgVehiclePositionsToken_1.OgVehiclePositionsToken.VehicleTypeRepository)),
__param(5, (0, tsyringe_1.inject)(OgVehiclePositionsToken_1.OgVehiclePositionsToken.VehicleDescriptorRepository)),
__metadata("design:paramtypes", [Object, Object, NotPublicVehiclesRedisRepository_1.NotPublicVehiclesRedisRepository,
ProcessedPositionRepository_1.ProcessedPositionRepository,
VehicleTypeRepository_1.VehicleTypeRepository,
VehicleDescriptorRepository_1.VehicleDescriptorRepository])
], TripWithLastPositionRepository);
//# sourceMappingURL=TripWithLastPositionRepository.js.map