diff --git a/src/externalClients/layersClient/geometryParser.ts b/src/externalClients/layersClient/geometryParser.ts index e9c6637..a8ddfbe 100644 --- a/src/externalClients/layersClient/geometryParser.ts +++ b/src/externalClients/layersClient/geometryParser.ts @@ -37,6 +37,7 @@ export function geographyToGeoJSON(geography: RawGeography): Geometry { return lineString(coords.map(toPosition)).geometry as LineString; case 'POLYGON': + case 'AREA': if (coords.length < 4) { throw new Error(`Polygon requires >=4 coordinates (closed ring), got ${coords.length}`); } diff --git a/src/externalClients/layersClient/layersClient.ts b/src/externalClients/layersClient/layersClient.ts index 8512e96..1c1c27e 100644 --- a/src/externalClients/layersClient/layersClient.ts +++ b/src/externalClients/layersClient/layersClient.ts @@ -1,6 +1,7 @@ import axios from 'axios'; import { trace } from '@opentelemetry/api'; import { asyncCallWithSpan } from '@map-colonies/tracing-utils'; +import type { Logger } from '@map-colonies/js-logger'; import type { LayerObject, ThirdPartyResponse } from '../../types'; import { getSyncConfig } from '../../common/syncConfig'; import { SERVICE_NAME } from '../../common/constants'; @@ -38,10 +39,17 @@ interface GraphQLResponse { const tracer = trace.getTracer(SERVICE_NAME); -function toLayerObject(raw: RawLayerObject): LayerObject { +function toLayerObject(logger: Logger, raw: RawLayerObject): LayerObject { + let geom; + try { + geom = geographyToGeoJSON(raw.geography); + } catch (err) { + logger.error({ msg: 'geographyToGeoJSON failed', geography: raw.geography, err }); + throw err; + } return { id: raw.id, - geom: geographyToGeoJSON(raw.geography), + geom, properties: { createdBy: raw.createdBy, creationTime: raw.creationTime, @@ -56,7 +64,7 @@ function toLayerObject(raw: RawLayerObject): LayerObject { }; } -export async function fetchPage(layerName: string, sequence: string): Promise { +export async function fetchPage(logger: Logger, layerName: string, sequence: string): Promise { const config = getSyncConfig(); return asyncCallWithSpan( @@ -84,7 +92,7 @@ export async function fetchPage(layerName: string, sequence: string): Promise !o.deleted).map(toLayerObject); + const objects = rawObjects.filter((o) => !o.deleted).map((raw) => toLayerObject(logger, raw)); const { sequence: nextSequence, deletedEntitiesCount, fetchedEntitiesCount, deletedEntitiesIds } = json.extensions; return { diff --git a/src/handler/layerSyncHandler.ts b/src/handler/layerSyncHandler.ts index 4747d3b..3f48b4d 100644 --- a/src/handler/layerSyncHandler.ts +++ b/src/handler/layerSyncHandler.ts @@ -19,7 +19,7 @@ export async function fetchAndSyncLayerPage(logger: Logger, entry: ScheduleEntry try { logger.info(`Fetching page for layer "${entry.layerName}" - status: ${state.status}, lastSequence: ${state.lastSequence}`); - const response = await layerClient.fetchPage(entry.layerName, state.lastSequence); + const response = await layerClient.fetchPage(logger, entry.layerName, state.lastSequence); logger.info(`Received ${response.fetchedCount} objects, ${response.deletedCount} deleted for layer "${entry.layerName}"`); diff --git a/tests/unit/externalClients/geometryParser.spec.ts b/tests/unit/externalClients/geometryParser.spec.ts index be9343f..a02937d 100644 --- a/tests/unit/externalClients/geometryParser.spec.ts +++ b/tests/unit/externalClients/geometryParser.spec.ts @@ -80,6 +80,27 @@ describe('geographyToGeoJSON', () => { ]; expect(() => geographyToGeoJSON(geo('POLYGON', ring))).toThrow(/Polygon requires >=4/); }); + + it('accepts AREA alias as Polygon', () => { + const ring = [ + { latitude: 0, longitude: 0 }, + { latitude: 0, longitude: 1 }, + { latitude: 1, longitude: 1 }, + { latitude: 0, longitude: 0 }, + ]; + const result = geographyToGeoJSON(geo('AREA', ring)); + expect(result).toEqual({ + type: 'Polygon', + coordinates: [ + [ + [0, 0], + [1, 0], + [1, 1], + [0, 0], + ], + ], + }); + }); }); describe('error cases', () => { diff --git a/tests/unit/handler/layerSyncHandler.spec.ts b/tests/unit/handler/layerSyncHandler.spec.ts index 1c82fde..7991ed8 100644 --- a/tests/unit/handler/layerSyncHandler.spec.ts +++ b/tests/unit/handler/layerSyncHandler.spec.ts @@ -98,7 +98,7 @@ describe('layerSyncHandler', () => { const entry: ScheduleEntry = { layerName: 'obstacles', nextRunAt: 0 }; await fetchAndSyncLayerPage(makeLogger(), entry); - expect(layerClient.fetchPage).toHaveBeenCalledWith('obstacles', '5'); + expect(layerClient.fetchPage).toHaveBeenCalledWith(expect.anything(), 'obstacles', '5'); expect(layerDataRepository.insertObjects).toHaveBeenCalledWith('obstacles', objects); expect(layerDataRepository.deleteDeprecatedObjects).toHaveBeenCalledWith('obstacles', ['old-1']); expect(syncStateRepository.updateSequence).toHaveBeenCalledWith('obstacles', '10');