From b33727ec7538c18947162cffdc5622b00b45a0ac Mon Sep 17 00:00:00 2001 From: Maurice Date: Thu, 15 Oct 2026 23:25:16 +0200 Subject: [PATCH] Tours: no non-null assertion, useless escape or awaited loop in the tour and trip copy paths --- server/scripts/eslint-baseline.json | 2 +- server/src/nest/tours/tours.service.ts | 10 +++++----- server/src/nest/trips/trips.service.ts | 5 ++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/server/scripts/eslint-baseline.json b/server/scripts/eslint-baseline.json index 2094e62c1..64cc40db0 100644 --- a/server/scripts/eslint-baseline.json +++ b/server/scripts/eslint-baseline.json @@ -1,7 +1,7 @@ { "src": { "@typescript-eslint/no-explicit-any": 90, - "@typescript-eslint/no-non-null-assertion": 265, + "@typescript-eslint/no-non-null-assertion": 264, "@typescript-eslint/no-require-imports": 18, "@typescript-eslint/no-unsafe-function-type": 1, "@typescript-eslint/no-unused-vars": 36, diff --git a/server/src/nest/tours/tours.service.ts b/server/src/nest/tours/tours.service.ts index 3184aad53..b7d5186fb 100644 --- a/server/src/nest/tours/tours.service.ts +++ b/server/src/nest/tours/tours.service.ts @@ -159,17 +159,17 @@ export class ToursService { return rows.map((r) => this.toItem(r)); } - /** One saved tour plus the persisted routing controls needed by the editor. */ /** The days every tour of the trip sits on, for the MCP read tools. */ async listTourDays(tripId: number): Promise { return await this.toursRepo.listTourDays(tripId); } + /** One saved tour plus the persisted routing controls needed by the editor. */ async getTour(tripId: string, placeId: string): Promise { const tid = toRowId(tripId); const pid = toRowId(placeId); const row = tid !== null && pid !== null ? await this.toursRepo.findInTrip(tid, pid) : undefined; - if (!row) throw new NotFoundException('Tour not found'); + if (!row || tid === null) throw new NotFoundException('Tour not found'); let waypoints: TourWaypoint[] = await this.waypointsRepo.listForPlace(row.place_id); // GPX tours created before tour_waypoints existed still belong in this @@ -177,7 +177,7 @@ export class ToursService { // expose their saved geometry endpoints as controls; the first edit/save // replaces them with normal persisted tour_waypoints transactionally. if (waypoints.length < 2) { - const place = await this.placesRepo.findInTrip(row.place_id, tid!); + const place = await this.placesRepo.findInTrip(row.place_id, tid); const geometry = parseRouteGeometry(place?.route_geometry); if (geometry.length >= 2) { const start = geometry[0]; @@ -189,7 +189,7 @@ export class ToursService { } } - return { tour: this.toItem(row), waypoints, provenance: await this.provenanceOf(tid!, row.place_id) }; + return { tour: this.toItem(row), waypoints, provenance: await this.provenanceOf(tid, row.place_id) }; } /** @@ -548,7 +548,7 @@ export class ToursService { /** The file name a GPX import keeps: the name as uploaded, without a path, cut to what the column shows. */ function gpxFileName(name: string | undefined): string | null { - const base = name?.split(/[\/]/).pop()?.trim(); + const base = name?.split('/').pop()?.trim(); return base ? base.slice(0, 255) : null; } diff --git a/server/src/nest/trips/trips.service.ts b/server/src/nest/trips/trips.service.ts index 38823e482..94d03dc46 100644 --- a/server/src/nest/trips/trips.service.ts +++ b/server/src/nest/trips/trips.service.ts @@ -738,13 +738,16 @@ export class TripsService { // The facet row goes first, since the waypoints and the import record reference it. const oldTours = await this.toursRepo.listRowsForTrip(Number(sourceTripId)); const copiedTours = new Set(); + const copiedSources: Array<[number, number]> = []; for (const { place_id, ...tour } of oldTours) { const newPlaceId = placeMap.get(place_id); if (!newPlaceId) continue; await this.toursRepo.insertCopy(newPlaceId, tour, placeMap); - await this.toursRepo.copySource(place_id, newPlaceId); + copiedSources.push([place_id, newPlaceId]); copiedTours.add(place_id); } + // The import records after the facets they reference; the order among them does not matter. + await Promise.all(copiedSources.map(([from, to]) => this.toursRepo.copySource(from, to))); const waypointsByPlace = new Map(); for (const { place_id, ...waypoint } of await this.tourWaypointsRepo.listForTrip(Number(sourceTripId))) {