A tour's waypoint can stand for a place of its trip, chosen on purpose from "Trip places" in the planner: searchable, nearest to the tour first, grouped into near the tour and the rest, and a place already in the tour says so. A pick adds the stop on the place's spot as one step of the history; the row names it after the place and says it is a place of the trip. The point keeps its own coordinates, the place stays a place of its own and its days are left alone. Moving the point or "Unlink from the place" drops the link; removing it never touches the place. tour_waypoints.linked_place_id (migration 044900) references places with ON DELETE SET NULL, so a deleted place only unlinks. A save checks the links inside its transaction: a tour of the trip is refused, a place that is gone or of another trip leaves the point unlinked, the same either way. The trip copy points the links at the copied places, the GPX export writes the linked stops as named waypoints, and get_tour_plan names them. nearnessToLine in @trek/shared measures a point against a route, for the picker and for the search along a route that comes next.
@trek/shared
Single source of truth for TREK's API contracts, expressed as Zod schemas and consumed by both the server (request validation + inferred DTO types) and the client (typed requests/responses).
This package is part of the incremental NestJS + React 19 migration (see the "Brownfield Rewrite" board). It is intentionally dormant until modules start importing it — adding it changes nothing for users.
Rules
- One folder per domain:
src/<domain>/<domain>.schema.ts(+.spec.ts). - Domain-agnostic building blocks live in
src/common/. - A route is only considered migrated once its contract lives here.
- Schemas are the source of truth; server DTOs and client types are inferred from them
(
z.infer<typeof schema>), never hand-duplicated.
Consumption (dev)
Both apps resolve @trek/shared to this package's TypeScript source:
- Server (
tsx): viapathsinserver/tsconfig.json. - Client (
vite): viaresolve.aliasinclient/vite.config.ts(+pathsfor the type-checker).
Production packaging (Docker / workspace wiring) is introduced in card F2, when the server first depends on this package at runtime. Until then prod builds are untouched.
Not yet here
The canonical error envelope is finalised in card F5 (it must match TREK's current Express error responses byte-for-byte), so it is deliberately not invented in F1.