From ce6773848542c4209d686f613de5a264b01d0d4b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 31 Jul 2026 01:38:03 +0000 Subject: [PATCH] refactor(B5): shared geometry module factory for mun/TI (F3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract buildGeometryModuleFromTopology to collapse the duplicate topojson.feature → features → optional Map pipeline in municipality and territory geometry submodules. F2 (ensureCachedDownload) was already delivered in scripts/lib/cli.mjs via P3-H. Closes #28 --- src/lib/bahiaGeometryModuleFactory.ts | 85 ++++++++++++++++++++++++++ src/lib/bahiaMunicipalityGeometries.ts | 20 +++--- src/lib/bahiaTerritoryGeometries.ts | 13 ++-- 3 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 src/lib/bahiaGeometryModuleFactory.ts diff --git a/src/lib/bahiaGeometryModuleFactory.ts b/src/lib/bahiaGeometryModuleFactory.ts new file mode 100644 index 00000000..1a36558a --- /dev/null +++ b/src/lib/bahiaGeometryModuleFactory.ts @@ -0,0 +1,85 @@ +import { feature } from 'topojson-client' + +import type { Feature, MultiPolygon, Polygon } from 'geojson' +import type { GeometryCollection, Topology } from 'topojson-specification' + +type PolygonalFeature> = Feature< + Polygon | MultiPolygon, + Properties +> + +type GeometryModuleBase< + Properties extends Record, + TObjectName extends string, +> = { + topology: Topology<{ [key in TObjectName]: GeometryCollection }> + features: readonly PolygonalFeature[] +} + +type IndexedGeometryModule< + Properties extends Record, + TObjectName extends string, + KeyProperty extends keyof Properties & string, +> = GeometryModuleBase & { + getFeatureByKey: (key: Properties[KeyProperty]) => PolygonalFeature | undefined +} + +type BuildGeometryModuleOptions< + Properties extends Record, + TObjectName extends string, + KeyProperty extends keyof Properties & string, +> = { + topology: Topology<{ [key in TObjectName]: GeometryCollection }> + objectName: TObjectName + keyProperty?: KeyProperty +} + +export function buildGeometryModuleFromTopology< + Properties extends Record, + TObjectName extends string, + KeyProperty extends keyof Properties & string, +>( + options: BuildGeometryModuleOptions & { + keyProperty: KeyProperty + }, +): IndexedGeometryModule + +export function buildGeometryModuleFromTopology< + Properties extends Record, + TObjectName extends string, +>( + options: BuildGeometryModuleOptions, +): GeometryModuleBase + +export function buildGeometryModuleFromTopology< + Properties extends Record, + TObjectName extends string, + KeyProperty extends keyof Properties & string, +>({ + topology, + objectName, + keyProperty, +}: BuildGeometryModuleOptions): + | GeometryModuleBase + | IndexedGeometryModule { + const features = feature(topology, topology.objects[objectName]) + .features as PolygonalFeature[] + + const base: GeometryModuleBase = { + topology, + features, + } + + if (!keyProperty) { + return base + } + + const featuresByKey = new Map( + features.map((entry) => [entry.properties[keyProperty], entry]), + ) + + return { + ...base, + getFeatureByKey: (key) => featuresByKey.get(key), + } +} diff --git a/src/lib/bahiaMunicipalityGeometries.ts b/src/lib/bahiaMunicipalityGeometries.ts index da8f41e6..8c956f68 100644 --- a/src/lib/bahiaMunicipalityGeometries.ts +++ b/src/lib/bahiaMunicipalityGeometries.ts @@ -1,23 +1,19 @@ -import { feature } from 'topojson-client' - import type { BahiaMunicipalityFeature, MunicipalityGeometryModule, MunicipalityTopology, } from '@/lib/bahiaGeometriesTypes' +import { buildGeometryModuleFromTopology } from '@/lib/bahiaGeometryModuleFactory' import municipalityTopologyJson from '@/lib/geometries/bahia-municipalities.topo.json' -const topology = municipalityTopologyJson as unknown as MunicipalityTopology - -const municipalityFeatures = feature(topology, topology.objects.municipalities) - .features as BahiaMunicipalityFeature[] - -const municipalityByCodarea = new Map( - municipalityFeatures.map((entry) => [entry.properties.codarea, entry]), -) +const { topology, features, getFeatureByKey } = buildGeometryModuleFromTopology({ + topology: municipalityTopologyJson as unknown as MunicipalityTopology, + objectName: 'municipalities', + keyProperty: 'codarea', +}) export const municipalityGeometryModule: MunicipalityGeometryModule = { topology, - features: municipalityFeatures, - getMunicipalityFeature: (codarea: string) => municipalityByCodarea.get(codarea), + features: features as readonly BahiaMunicipalityFeature[], + getMunicipalityFeature: getFeatureByKey, } diff --git a/src/lib/bahiaTerritoryGeometries.ts b/src/lib/bahiaTerritoryGeometries.ts index 548f5f73..e5c8c51b 100644 --- a/src/lib/bahiaTerritoryGeometries.ts +++ b/src/lib/bahiaTerritoryGeometries.ts @@ -1,18 +1,17 @@ -import { feature } from 'topojson-client' - import type { BahiaTerritoryFeature, TerritoryGeometryModule, TerritoryTopology, } from '@/lib/bahiaGeometriesTypes' +import { buildGeometryModuleFromTopology } from '@/lib/bahiaGeometryModuleFactory' import territoryTopologyJson from '@/lib/geometries/bahia-identity-territories.topo.json' -const topology = territoryTopologyJson as unknown as TerritoryTopology - -const territoryFeatures = feature(topology, topology.objects.territories) - .features as BahiaTerritoryFeature[] +const { topology, features } = buildGeometryModuleFromTopology({ + topology: territoryTopologyJson as unknown as TerritoryTopology, + objectName: 'territories', +}) export const territoryGeometryModule: TerritoryGeometryModule = { topology, - features: territoryFeatures, + features: features as readonly BahiaTerritoryFeature[], }