feat(geoportal-v2): find proxy fallback chain — by-ref → search

Per Marius's greenlight + gis-api shipping POST? GET /api/v1/parcela/by-ref
imminent.

src/lib/gis-api-client.ts:
  Added gisApi.parcela.byRef({siruta, cadastralRef, layerId}) thin
  wrapper. Same return shape as parcela.get; gis-api will 404 when no
  match and 403 on scope=none.

src/app/api/gis/parcela/find/route.ts:
  Chain rewrite. Three named helpers — tryByRef + trySearch — keep the
  main handler short and the fallback semantics obvious:

    1. tryByRef(siruta, cad, layerId)
         200 → return canonical record (instant — single indexed query
         on gis_core)
         404 → endpoint not deployed yet OR row genuinely absent. Fall
         through.
         403 / 5xx → propagate.

    2. trySearch(siruta, cad, layerId)
         The previous logic, moved verbatim. Uses search's response
         siruta field for in-memory filter (no N+1 parcela.get).
         Still capped at gis-api's max 50; returns
         search_limit_exceeded when the target siruta falls past it.

    3. 404 not_found — both layers exhausted.

When gis-api's by-ref is live, common-cadref cases (61745 / 232
features) resolve in one round-trip. Before then, by-ref returns 404
and we fall through to search — same behaviour as before for the
non-bottleneck cases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude VM
2026-05-20 15:10:59 +03:00
parent 653cffeee3
commit 100896a564
2 changed files with 117 additions and 65 deletions
+16
View File
@@ -245,6 +245,22 @@ export const gisApi = {
request<unknown>(`/api/v1/parcela/${encodeURIComponent(id)}`, {
accessToken: opts.accessToken,
}),
// GET /api/v1/parcela/by-ref?siruta&cad&layerId — indexed lookup that
// skips the cadref-trigram-then-filter dance. Use when a click arrives
// without a uuid in the tile properties (PMTiles overview today). Same
// response shape as parcela.get; 404 when no match; 403 on scope=none.
byRef: (
body: { siruta: string; cadastralRef: string; layerId: string },
opts: GisApiCallOpts = {},
) =>
request<unknown>("/api/v1/parcela/by-ref", {
query: {
siruta: body.siruta,
cad: body.cadastralRef,
layerId: body.layerId,
},
accessToken: opts.accessToken,
}),
},
search: (q: string, limit = 50, opts: GisApiCallOpts = {}) =>