diff --git a/docs/plans/escala-dry-pos-b2.md b/docs/plans/escala-dry-pos-b2.md index 0fc73029..2b8ec5bb 100644 --- a/docs/plans/escala-dry-pos-b2.md +++ b/docs/plans/escala-dry-pos-b2.md @@ -1,7 +1,7 @@ # Escala e DRY pós-B2 (geometrias + scripts CLI) -Status: Fase 1 entregue com B3 (2026-07-19); Fases 2–3 pendentes -Atualizado em: 2026-07-27 (`capture-review-debts` pós-B8+: `scripts/lib/topology.mjs` resolve por precedente onde o helper da F2 vive — `scripts/lib/`, não `src/lib/`; 2026-07-26 pós-B8 F2: 5º call site; 2026-07-20 pós-A8: `build-bahia-demographics.mjs` reforça o gatilho da F2 como 4º call site) +Status: Fases 1–3 entregues (F1 com B3 em 2026-07-19; F2 em P3-H/`scripts/lib/cli.mjs`; F3 em #28) +Atualizado em: 2026-07-31 (F3: `bahiaGeometryModuleFactory.ts` + wrappers mun/TI) Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item B5) Responsável: — diff --git a/src/lib/bahiaGeometriesTypes.ts b/src/lib/bahiaGeometriesTypes.ts index 6e601405..379d32ec 100644 --- a/src/lib/bahiaGeometriesTypes.ts +++ b/src/lib/bahiaGeometriesTypes.ts @@ -2,7 +2,10 @@ import type { Feature, MultiPolygon, Polygon } from 'geojson' import type { GeometryCollection, Topology } from 'topojson-specification' /** Every committed mesh is polygonal; only the properties differ. */ -type BahiaFeature = Feature +export type BahiaFeature> = Feature< + Polygon | MultiPolygon, + Properties +> type BahiaMunicipalityProperties = { codarea: string diff --git a/src/lib/bahiaGeometryModuleFactory.ts b/src/lib/bahiaGeometryModuleFactory.ts new file mode 100644 index 00000000..08217a7e --- /dev/null +++ b/src/lib/bahiaGeometryModuleFactory.ts @@ -0,0 +1,75 @@ +import { feature } from 'topojson-client' + +import type { BahiaFeature } from '@/lib/bahiaGeometriesTypes' +import type { GeometryCollection, Topology } from 'topojson-specification' + +type GeometryModuleBase, TObjectName extends string> = { + topology: Topology<{ [key in TObjectName]: GeometryCollection }> + features: readonly BahiaFeature[] +} + +type IndexedGeometryModule< + Properties extends Record, + TObjectName extends string, + KeyProperty extends keyof Properties & string, +> = GeometryModuleBase & { + getFeatureByKey: (key: Properties[KeyProperty]) => BahiaFeature | 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 BahiaFeature[] + + 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..ef4819da 100644 --- a/src/lib/bahiaMunicipalityGeometries.ts +++ b/src/lib/bahiaMunicipalityGeometries.ts @@ -1,23 +1,23 @@ -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< + BahiaMunicipalityFeature['properties'], + 'municipalities', + 'codarea' +>({ + topology: municipalityTopologyJson as unknown as MunicipalityTopology, + objectName: 'municipalities', + keyProperty: 'codarea', +}) export const municipalityGeometryModule: MunicipalityGeometryModule = { topology, - features: municipalityFeatures, - getMunicipalityFeature: (codarea: string) => municipalityByCodarea.get(codarea), + features, + getMunicipalityFeature: getFeatureByKey, } diff --git a/src/lib/bahiaTerritoryGeometries.ts b/src/lib/bahiaTerritoryGeometries.ts index 548f5f73..68dc3ee5 100644 --- a/src/lib/bahiaTerritoryGeometries.ts +++ b/src/lib/bahiaTerritoryGeometries.ts @@ -1,18 +1,20 @@ -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< + BahiaTerritoryFeature['properties'], + 'territories' +>({ + topology: territoryTopologyJson as unknown as TerritoryTopology, + objectName: 'territories', +}) export const territoryGeometryModule: TerritoryGeometryModule = { topology, - features: territoryFeatures, + features, }