feat: implement billing, usage tracking, and administrative geocoding features in API with infrastructure updates

This commit is contained in:
Hamza-Ayed
2026-07-28 04:43:23 +03:00
parent 2f7c2066f7
commit dc9d546733
133 changed files with 3599 additions and 356 deletions
+4
View File
@@ -7,6 +7,10 @@ export declare class CandidateRoad {
lengthMeters: number;
confidence: number;
status: string;
source: string;
name: string;
highway: string;
oneway: number;
discoveredAt: Date;
reviewedAt: Date;
}
+20
View File
@@ -20,6 +20,10 @@ let CandidateRoad = class CandidateRoad {
lengthMeters;
confidence;
status;
source;
name;
highway;
oneway;
discoveredAt;
reviewedAt;
};
@@ -62,6 +66,22 @@ __decorate([
(0, typeorm_1.Column)({ default: 'pending' }),
__metadata("design:type", String)
], CandidateRoad.prototype, "status", void 0);
__decorate([
(0, typeorm_1.Column)({ default: 'telemetry' }),
__metadata("design:type", String)
], CandidateRoad.prototype, "source", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'varchar', length: 255, nullable: true }),
__metadata("design:type", String)
], CandidateRoad.prototype, "name", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'varchar', length: 32, nullable: true }),
__metadata("design:type", String)
], CandidateRoad.prototype, "highway", void 0);
__decorate([
(0, typeorm_1.Column)({ type: 'smallint', default: 0 }),
__metadata("design:type", Number)
], CandidateRoad.prototype, "oneway", void 0);
__decorate([
(0, typeorm_1.CreateDateColumn)(),
__metadata("design:type", Date)
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"candidate-road.entity.js","sourceRoot":"","sources":["../../src/maps/candidate-road.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAA0F;AASnF,IAAM,aAAa,GAAnB,MAAM,aAAa;IAExB,EAAE,CAAS;IAWX,QAAQ,CAAM;IAKd,iBAAiB,CAAS;IAK1B,WAAW,CAAS;IAKpB,YAAY,CAAS;IAKrB,YAAY,CAAS;IAKrB,UAAU,CAAS;IAKnB,MAAM,CAAS;IAGf,YAAY,CAAO;IAGnB,UAAU,CAAO;CAClB,CAAA;AAlDY,sCAAa;AAExB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;yCACpB;AAWX;IAPC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,WAAW;QACjB,kBAAkB,EAAE,YAAY;QAChC,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,KAAK;KAChB,CAAC;IACD,IAAA,eAAK,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;+CACX;AAKd;IADC,IAAA,gBAAM,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;wDACJ;AAK1B;IADC,IAAA,gBAAM,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;kDACV;AAKpB;IADC,IAAA,gBAAM,EAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;mDACX;AAKrB;IADC,IAAA,gBAAM,EAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;mDACX;AAKrB;IADC,IAAA,gBAAM,EAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;iDACb;AAKnB;IADC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;;6CAChB;AAGf;IADC,IAAA,0BAAgB,GAAE;8BACL,IAAI;mDAAC;AAGnB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;8BAClC,IAAI;iDAAC;wBAjDN,aAAa;IADzB,IAAA,gBAAM,EAAC,iBAAiB,CAAC;GACb,aAAa,CAkDzB"}
{"version":3,"file":"candidate-road.entity.js","sourceRoot":"","sources":["../../src/maps/candidate-road.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAA0F;AASnF,IAAM,aAAa,GAAnB,MAAM,aAAa;IAExB,EAAE,CAAS;IAWX,QAAQ,CAAM;IAKd,iBAAiB,CAAS;IAK1B,WAAW,CAAS;IAKpB,YAAY,CAAS;IAKrB,YAAY,CAAS;IAKrB,UAAU,CAAS;IAKnB,MAAM,CAAS;IAKf,MAAM,CAAS;IAKf,IAAI,CAAS;IAKb,OAAO,CAAS;IAMhB,MAAM,CAAS;IAGf,YAAY,CAAO;IAGnB,UAAU,CAAO;CAClB,CAAA;AAvEY,sCAAa;AAExB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;yCACpB;AAWX;IAPC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,WAAW;QACjB,kBAAkB,EAAE,YAAY;QAChC,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,KAAK;KAChB,CAAC;IACD,IAAA,eAAK,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;+CACX;AAKd;IADC,IAAA,gBAAM,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;wDACJ;AAK1B;IADC,IAAA,gBAAM,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;kDACV;AAKpB;IADC,IAAA,gBAAM,EAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;mDACX;AAKrB;IADC,IAAA,gBAAM,EAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;mDACX;AAKrB;IADC,IAAA,gBAAM,EAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;iDACb;AAKnB;IADC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;;6CAChB;AAKf;IADC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;;6CAClB;AAKf;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2CAC5C;AAKb;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CACxC;AAMhB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;6CAC1B;AAGf;IADC,IAAA,0BAAgB,GAAE;8BACL,IAAI;mDAAC;AAGnB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;8BAClC,IAAI;iDAAC;wBAtEN,aAAa;IADzB,IAAA,gBAAM,EAAC,iBAAiB,CAAC;GACb,aAAa,CAuEzB"}
+10 -2
View File
@@ -1,16 +1,24 @@
import type { Response } from 'express';
import { MapsService } from './maps.service';
export declare class MapsController {
private readonly mapsService;
constructor(mapsService: MapsService);
syncRoutes(): Promise<{
success: boolean;
message: string;
}>;
getStyleJson(theme: string, res: Response): Promise<any>;
getRoute(query: any): Promise<{
routeName: any;
tags: any;
distance: any;
duration: number;
trafficAwareDuration: number;
duration: any;
trafficFactor: number;
startName: string;
endName: string;
points: any;
bbox: any;
instructions: any;
alternatives: any;
}>;
getConfig(): Promise<{
+104 -1
View File
@@ -1,10 +1,43 @@
"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);
};
@@ -15,6 +48,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.MapsController = void 0;
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const maps_service_1 = require("./maps.service");
const api_key_guard_1 = require("../common/guards/api-key.guard");
let MapsController = class MapsController {
@@ -22,6 +57,55 @@ let MapsController = class MapsController {
constructor(mapsService) {
this.mapsService = mapsService;
}
async syncRoutes() {
return this.mapsService.requestRoutingSync();
}
async getStyleJson(theme, res) {
const isDark = theme === 'obsidian';
const filename = isDark ? 'style-dark.json' : 'style.json';
const fallbackFilename = 'style.json';
const pathsToCheck = [
path.join('/data', filename),
path.join(process.cwd(), '../../', filename),
path.join(process.cwd(), filename),
path.join('/data', fallbackFilename),
path.join(process.cwd(), '../../', fallbackFilename),
path.join(process.cwd(), fallbackFilename),
];
let stylePath = '';
for (const p of pathsToCheck) {
if (fs.existsSync(p)) {
stylePath = p;
break;
}
}
if (!stylePath) {
return res.status(404).send('Style not found');
}
try {
const styleRaw = fs.readFileSync(stylePath, 'utf8');
const styleObj = JSON.parse(styleRaw);
if (theme === 'light') {
styleObj.layers.forEach((layer) => {
if (layer.id === 'background') {
layer.paint['background-color'] = '#FFFFFF';
}
});
}
else if (theme === 'obsidian') {
styleObj.layers.forEach((layer) => {
if (layer.id === 'background') {
layer.paint['background-color'] = '#101014';
}
});
}
res.setHeader('Content-Type', 'application/json');
res.send(styleObj);
}
catch (e) {
res.status(500).send('Error parsing style.json');
}
}
async getRoute(query) {
const waypoints = [];
if (query.fromLat && query.fromLng) {
@@ -45,13 +129,32 @@ let MapsController = class MapsController {
waypoints.push([parseFloat(query.toLat), parseFloat(query.toLng)]);
}
const profile = query.profile || 'car';
return this.mapsService.getRoute(waypoints, profile);
const steps = query.steps === 'true';
const locale = query.locale || 'en';
const alternatives = query.alternatives === 'true';
return this.mapsService.getRoute(waypoints, profile, steps, locale, alternatives);
}
async getConfig() {
return this.mapsService.getMapConfig();
}
};
exports.MapsController = MapsController;
__decorate([
(0, common_1.Post)('sync-routes'),
(0, swagger_1.ApiOperation)({ summary: 'Request GraphHopper routing sync 🔄' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], MapsController.prototype, "syncRoutes", null);
__decorate([
(0, common_1.Get)('style.json'),
(0, swagger_1.ApiOperation)({ summary: 'Get MapLibre style JSON 🎨' }),
__param(0, (0, common_1.Query)('theme')),
__param(1, (0, common_1.Res)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", Promise)
], MapsController.prototype, "getStyleJson", null);
__decorate([
(0, common_1.Get)('route'),
(0, swagger_1.ApiOperation)({ summary: 'Calculate a route with dynamic waypoints 🚗' }),
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"maps.controller.js","sourceRoot":"","sources":["../../src/maps/maps.controller.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"maps.controller.js","sourceRoot":"","sources":["../../src/maps/maps.controller.ts"],"names":[],"mappings":"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"}
+15 -5
View File
@@ -1,26 +1,36 @@
import { ConfigService } from '@nestjs/config';
import { Repository } from 'typeorm';
import { Repository, DataSource } from 'typeorm';
import { RoadSegmentStat } from './road-stat.entity';
import { TrafficGridService } from './traffic-grid.service';
import { GeocodingService } from '../geocoding/geocoding.service';
import { RedisService } from '../common/redis.service';
export declare class MapsService {
private configService;
private roadStatRepo;
private trafficGrid;
private geocodingService;
private dataSource;
private redisService;
private readonly graphHopperUrl;
constructor(configService: ConfigService, roadStatRepo: Repository<RoadSegmentStat>, trafficGrid: TrafficGridService, geocodingService: GeocodingService);
getRoute(waypoints: [number, number][], profile?: string): Promise<{
constructor(configService: ConfigService, roadStatRepo: Repository<RoadSegmentStat>, trafficGrid: TrafficGridService, geocodingService: GeocodingService, dataSource: DataSource, redisService: RedisService);
requestRoutingSync(): Promise<{
success: boolean;
message: string;
}>;
getRoute(waypoints: [number, number][], profile?: string, steps?: boolean, locale?: string, alternatives?: boolean): Promise<{
routeName: any;
tags: any;
distance: any;
duration: number;
trafficAwareDuration: number;
duration: any;
trafficFactor: number;
startName: string;
endName: string;
points: any;
bbox: any;
instructions: any;
alternatives: any;
}>;
private getRouteName;
private decodePolyline;
getMapConfig(): Promise<{
center: number[];
+122 -22
View File
@@ -14,6 +14,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MapsService = void 0;
const common_1 = require("@nestjs/common");
@@ -24,20 +25,29 @@ const axios_1 = __importDefault(require("axios"));
const road_stat_entity_1 = require("./road-stat.entity");
const traffic_grid_service_1 = require("./traffic-grid.service");
const geocoding_service_1 = require("../geocoding/geocoding.service");
const redis_service_1 = require("../common/redis.service");
let MapsService = class MapsService {
configService;
roadStatRepo;
trafficGrid;
geocodingService;
dataSource;
redisService;
graphHopperUrl;
constructor(configService, roadStatRepo, trafficGrid, geocodingService) {
constructor(configService, roadStatRepo, trafficGrid, geocodingService, dataSource, redisService) {
this.configService = configService;
this.roadStatRepo = roadStatRepo;
this.trafficGrid = trafficGrid;
this.geocodingService = geocodingService;
this.dataSource = dataSource;
this.redisService = redisService;
this.graphHopperUrl = this.configService.get('GRAPH_HOPPER_URL', 'http://routing:8080');
}
async getRoute(waypoints, profile = 'car') {
async requestRoutingSync() {
await this.redisService.set('routing_sync_requested', '1');
return { success: true, message: 'Routing sync requested and scheduled for the next minute.' };
}
async getRoute(waypoints, profile = 'car', steps = false, locale = 'en', alternatives = false) {
if (waypoints.length < 2) {
throw new common_1.HttpException('At least two waypoints are required', common_1.HttpStatus.BAD_REQUEST);
}
@@ -68,19 +78,69 @@ let MapsService = class MapsService {
const payload = {
points: ghPoints,
profile: profile,
locale: 'en',
locale: locale === 'en' ? 'ar' : locale,
calc_points: true,
points_encoded: true,
instructions: steps || true,
};
if (waypoints.length === 2) {
let closureCount = 0;
try {
const closedSegments = await this.dataSource.query(`
SELECT ST_AsGeoJSON(
ST_Transform(ST_Buffer(ST_Transform(geometry::geometry, 3857), 15), 4326), 6
) AS geojson
FROM road_segment_stats
WHERE "isClosed" = true AND geometry IS NOT NULL
LIMIT 50
`);
const features = closedSegments
.map((s, i) => {
try {
return { type: 'Feature', id: `closed_${i}`, geometry: JSON.parse(s.geojson), properties: {} };
}
catch {
return null;
}
})
.filter(Boolean);
if (features.length > 0) {
payload['custom_model'] = {
priority: features.map((f) => ({ if: `in_${f.id}`, multiply_by: '0' })),
areas: { type: 'FeatureCollection', features },
};
payload['ch.disable'] = true;
closureCount = features.length;
console.log(`🚧 Routing: avoiding ${closureCount} closed segment(s).`);
}
}
catch (closureError) {
console.warn('⚠️ Could not load road closures for routing:', closureError.message);
}
if (alternatives && waypoints.length === 2) {
payload.algorithm = 'alternative_route';
payload['ch.disable'] = true;
payload['alternative_route.max_paths'] = 2;
payload['alternative_route.max_weight_factor'] = 1.6;
payload['alternative_route.max_share_factor'] = 0.6;
}
console.log(`Routing Request: ${waypoints.length} points via ${profile} on ${this.graphHopperUrl}`);
const response = await axios_1.default.post(`${this.graphHopperUrl}/route`, payload, { timeout: 10000 });
console.log(`Routing Request: ${waypoints.length} points via ${profile} on ${this.graphHopperUrl} | Steps: ${steps} | Locale: ${locale}`);
let response;
try {
response = await axios_1.default.post(`${this.graphHopperUrl}/route`, payload, { timeout: 10000 });
}
catch (routeErr) {
if (closureCount > 0 && payload['custom_model']) {
const detail = routeErr.response ? JSON.stringify(routeErr.response.data) : routeErr.message;
console.warn(`⚠️ Closure-aware routing failed (${detail}). Retrying without closures...`);
delete payload['custom_model'];
if (!(alternatives && waypoints.length === 2))
delete payload['ch.disable'];
response = await axios_1.default.post(`${this.graphHopperUrl}/route`, payload, { timeout: 10000 });
}
else {
throw routeErr;
}
}
console.log('Routing SUCCESS');
const paths = response.data.paths;
if (!paths || paths.length === 0)
@@ -93,22 +153,45 @@ let MapsService = class MapsService {
const trafficFactor = this.trafficGrid.getTrafficFactor(coords, hr, dow);
const baseDuration = route.time / 1000;
const trafficAwareDuration = baseDuration * trafficFactor;
const alternatives = paths.slice(1).map(alt => ({
distance: alt.distance,
duration: Math.round(alt.time / 1000),
points: alt.points,
bbox: alt.bbox
}));
const processedPaths = paths.map((p, index) => {
const pCoords = this.decodePolyline(p.points);
const pTrafficFactor = this.trafficGrid.getTrafficFactor(pCoords, hr, dow);
const pDuration = Math.round((p.time / 1000) * pTrafficFactor);
const routeName = this.getRouteName(p.instructions);
const tags = [];
if (index === 0)
tags.push('FASTEST');
if (paths.length > 1) {
const isShortest = paths.every((other) => p.distance <= other.distance);
if (isShortest)
tags.push('SHORTEST');
if (index > 0 && !isShortest)
tags.push('ALTERNATIVE');
}
return {
routeName: routeName ? `عبر ${routeName}` : `المسار ${index + 1}`,
tags,
distance: p.distance,
duration: pDuration,
points: p.points,
bbox: p.bbox,
instructions: steps ? p.instructions : undefined
};
});
const mainRoute = processedPaths[0];
const altRoutes = processedPaths.slice(1);
return {
distance: route.distance,
duration: Math.round(baseDuration),
trafficAwareDuration: Math.round(trafficAwareDuration),
routeName: mainRoute.routeName,
tags: mainRoute.tags,
distance: mainRoute.distance,
duration: mainRoute.duration,
trafficFactor: Math.round(trafficFactor * 100) / 100,
startName,
endName,
points: route.points,
bbox: route.bbox,
alternatives: alternatives
points: mainRoute.points,
bbox: mainRoute.bbox,
instructions: mainRoute.instructions,
alternatives: altRoutes
};
}
catch (error) {
@@ -117,6 +200,25 @@ let MapsService = class MapsService {
throw new common_1.HttpException(`Routing Failure: ${msg}`, common_1.HttpStatus.BAD_GATEWAY);
}
}
getRouteName(instructions) {
if (!instructions || instructions.length === 0)
return null;
const streetDistances = {};
for (const inst of instructions) {
if (inst.street_name && inst.street_name.trim() !== '') {
streetDistances[inst.street_name] = (streetDistances[inst.street_name] || 0) + (inst.distance || 0);
}
}
let longestStreet = null;
let maxDist = 0;
for (const [street, dist] of Object.entries(streetDistances)) {
if (dist > maxDist) {
maxDist = dist;
longestStreet = street;
}
}
return longestStreet;
}
decodePolyline(encoded) {
const points = [];
let index = 0, len = encoded.length;
@@ -155,9 +257,7 @@ exports.MapsService = MapsService;
exports.MapsService = MapsService = __decorate([
(0, common_1.Injectable)(),
__param(1, (0, typeorm_1.InjectRepository)(road_stat_entity_1.RoadSegmentStat)),
__metadata("design:paramtypes", [config_1.ConfigService,
typeorm_2.Repository,
traffic_grid_service_1.TrafficGridService,
geocoding_service_1.GeocodingService])
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, traffic_grid_service_1.TrafficGridService,
geocoding_service_1.GeocodingService, typeof (_c = typeof typeorm_2.DataSource !== "undefined" && typeorm_2.DataSource) === "function" ? _c : Object, redis_service_1.RedisService])
], MapsService);
//# sourceMappingURL=maps.service.js.map
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -9,6 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var TrafficGridService_1;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrafficGridService = void 0;
const common_1 = require("@nestjs/common");
@@ -118,6 +119,6 @@ let TrafficGridService = TrafficGridService_1 = class TrafficGridService {
exports.TrafficGridService = TrafficGridService;
exports.TrafficGridService = TrafficGridService = TrafficGridService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [typeorm_1.DataSource])
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_1.DataSource !== "undefined" && typeorm_1.DataSource) === "function" ? _a : Object])
], TrafficGridService);
//# sourceMappingURL=traffic-grid.service.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"traffic-grid.service.js","sourceRoot":"","sources":["../../src/maps/traffic-grid.service.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"traffic-grid.service.js","sourceRoot":"","sources":["../../src/maps/traffic-grid.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,2CAAkE;AAClE,qCAAqC;AAO9B,IAAM,kBAAkB,0BAAxB,MAAM,kBAAkB;IAOT;IANH,MAAM,GAAG,IAAI,eAAM,CAAC,oBAAkB,CAAC,IAAI,CAAC,CAAC;IAGtD,IAAI,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC7B,iBAAiB,GAAG,CAAC,CAAC;IAEvC,YAAoB,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAE9C,KAAK,CAAC,YAAY;QAChB,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;IAC3B,CAAC;IAMD,KAAK,CAAC,WAAW;QACf,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QACvE,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAE7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;;;;;;;;;OASxC,CAAC,CAAC;YAEH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,KAAK,GAAG,CAAC,CAAC;YAEd,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBACxE,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;gBAG9D,MAAM,GAAG,GAAG,GAAG,EAAE,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;gBACtD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gBAC3B,KAAK,EAAE,CAAC;YACV,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,cAAc,KAAK,WAAW,IAAI,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,CAAC;QAC3H,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAMD,gBAAgB,CAAC,MAA0B,EAAE,EAAU,EAAE,GAAW;QAClE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QAErC,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,OAAO,GAAG,CAAC,CAAC;QAGhB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAChE,MAAM,GAAG,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC;YAEjC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,MAAM,EAAE,CAAC;gBACX,WAAW,IAAI,MAAM,CAAC;gBACtB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAED,IAAI,OAAO,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QAG9B,IAAI,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;QACxC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,CAAC;IAKO,aAAa,CAAC,GAAW,EAAE,GAAW,EAAE,SAAiB;QAC/D,MAAM,MAAM,GAAG,kCAAkC,CAAC;QAClD,IAAI,MAAM,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;QAC9B,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;QAChC,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,EAAE,GAAG,CAAC,CAAC;QAEX,OAAO,MAAM,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YACjC,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,GAAG,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChC,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;oBAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;oBAAC,MAAM,GAAG,GAAG,CAAC;gBAAC,CAAC;qBACnD,CAAC;oBAAC,MAAM,GAAG,GAAG,CAAC;gBAAC,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChC,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;oBAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;oBAAC,MAAM,GAAG,GAAG,CAAC;gBAAC,CAAC;qBACnD,CAAC;oBAAC,MAAM,GAAG,GAAG,CAAC;gBAAC,CAAC;YACxB,CAAC;YAED,MAAM,GAAG,CAAC,MAAM,CAAC;YACjB,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;gBACZ,GAAG,EAAE,CAAC;YACR,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC;gBACrB,GAAG,GAAG,CAAC,CAAC;gBACR,EAAE,GAAG,CAAC,CAAC;YACT,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AApHY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;yDAQqB,oBAAU,oBAAV,oBAAU;GAP/B,kBAAkB,CAoH9B"}