zenit-sdk 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,41 +1,17 @@
1
1
  import {
2
- ChevronLeft,
3
- ChevronRight,
4
- Eye,
5
- EyeOff,
6
- FloatingChatBox,
7
- Layers,
8
- Upload,
9
- X,
10
- ZenitFeatureFilterPanel,
11
- ZenitLayerManager,
12
- ZenitMap,
13
- ZoomIn,
14
2
  applyFilteredGeoJSONStrategy,
15
3
  applyLayerOverrides,
16
4
  centroidFromBBox,
17
- clampNumber,
18
- clampOpacity,
19
5
  computeBBoxFromFeature,
20
6
  createChatService,
21
7
  extractMapDto,
22
- getAccentByLayerId,
23
- getEffectiveLayerOpacity,
24
- getLayerColor,
25
- getLayerZoomOpacityFactor,
26
- getStyleByLayerId,
27
- getZoomOpacityFactor,
28
8
  initLayerStates,
29
- isPolygonLayer,
30
9
  normalizeMapCenter,
31
10
  normalizeMapLayers,
32
11
  resetOverrides,
33
- resolveLayerAccent,
34
12
  sendMessage,
35
- sendMessageStream,
36
- useSendMessage,
37
- useSendMessageStream
38
- } from "./chunk-RGS6AZWV.mjs";
13
+ sendMessageStream
14
+ } from "./chunk-4Y7JCMGR.mjs";
39
15
 
40
16
  // src/http/HttpClient.ts
41
17
  var HttpClient = class {
@@ -1034,27 +1010,15 @@ function normalizeBbox(input) {
1034
1010
  return null;
1035
1011
  }
1036
1012
  export {
1037
- ChevronLeft,
1038
- ChevronRight,
1039
1013
  DEFAULT_MAX_FEATURES_FULL_GEOJSON,
1040
- Eye,
1041
- EyeOff,
1042
1014
  FilterEngine,
1043
- FloatingChatBox,
1044
1015
  HttpClient,
1045
- Layers,
1046
- Upload,
1047
- X,
1048
1016
  ZenitAuthClient,
1049
1017
  ZenitCatalogNotSupportedError,
1050
1018
  ZenitClient,
1051
- ZenitFeatureFilterPanel,
1052
- ZenitLayerManager,
1053
1019
  ZenitLayersClient,
1054
- ZenitMap,
1055
1020
  ZenitMapsClient,
1056
1021
  ZenitSdkAuthClient,
1057
- ZoomIn,
1058
1022
  applyFilteredGeoJSONStrategy,
1059
1023
  applyLayerOverrides,
1060
1024
  applyPrefiltersToFeatureCollection,
@@ -1063,33 +1027,21 @@ export {
1063
1027
  buildLayerFilters,
1064
1028
  buildLimitedMessage,
1065
1029
  centroidFromBBox,
1066
- clampNumber,
1067
- clampOpacity,
1068
1030
  computeBBoxFromFeature,
1069
1031
  createChatService,
1070
1032
  decorateFeaturesWithLayerId,
1071
1033
  extractMapDto,
1072
1034
  filterEngine,
1073
- getAccentByLayerId,
1074
1035
  getCatalogSupport,
1075
- getEffectiveLayerOpacity,
1076
- getLayerColor,
1077
- getLayerZoomOpacityFactor,
1078
- getStyleByLayerId,
1079
- getZoomOpacityFactor,
1080
1036
  initLayerStates,
1081
- isPolygonLayer,
1082
1037
  normalizeBbox,
1083
1038
  normalizeMapCenter,
1084
1039
  normalizeMapLayers,
1085
1040
  resetOverrides,
1086
- resolveLayerAccent,
1087
1041
  resolveLayerStrategy,
1088
1042
  sendMessage,
1089
1043
  sendMessageStream,
1090
1044
  shouldSkipGeojsonDownload,
1091
- shouldUseFilterMultiple,
1092
- useSendMessage,
1093
- useSendMessageStream
1045
+ shouldUseFilterMultiple
1094
1046
  };
1095
1047
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/http/HttpClient.ts","../src/auth/ZenitAuthClient.ts","../src/sdkAuth/ZenitSdkAuthClient.ts","../src/maps/ZenitMapsClient.ts","../src/layers/catalogSupport.ts","../src/engine/PrefilterEngine.ts","../src/layers/ZenitLayersClient.ts","../src/config/ZenitSdkConfig.ts","../src/engine/FilterEngine.ts","../src/ai/normalize.ts"],"sourcesContent":["export interface ZenitSdkError {\r\n success: false;\r\n statusCode: number;\r\n timestamp?: string;\r\n path?: string;\r\n method?: string;\r\n error?: string;\r\n message: string;\r\n}\r\n\r\ntype TokenResolver = () => { accessToken?: string; sdkToken?: string };\r\ntype AuthorizationHeaderResolver = () => Record<string, string>;\r\n\r\nexport interface HttpClientOptions {\r\n baseUrl: string;\r\n resolveTokens?: TokenResolver;\r\n resolveAuthorizationHeader?: AuthorizationHeaderResolver;\r\n}\r\n\r\n/**\r\n * Minimal fetch-based HTTP client for the Zenit SDK.\r\n * Responsible for setting base URL, auth headers and error normalization.\r\n *\r\n * - El header `Authorization` se usa para JWT de usuario o JWT obtenido vía `/sdk-auth/exchange`.\r\n * - El header `X-SDK-Token` se usa para enviar el token SDK crudo a endpoints como\r\n * `/sdk-auth/validate` y `/sdk-auth/exchange`.\r\n */\r\nexport class HttpClient {\r\n private readonly baseUrl: string;\r\n private readonly resolveTokens?: TokenResolver;\r\n private readonly resolveAuthorizationHeader: AuthorizationHeaderResolver;\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\r\n this.resolveTokens = options.resolveTokens;\r\n this.resolveAuthorizationHeader = options.resolveAuthorizationHeader ?? (() => ({}));\r\n }\r\n\r\n async get<T>(path: string, options: RequestInit = {}): Promise<T> {\r\n const headers = {\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, { ...options, method: 'GET', headers });\r\n }\r\n\r\n async post<T>(path: string, body?: unknown, options: RequestInit = {}): Promise<T> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, {\r\n ...options,\r\n method: 'POST',\r\n headers,\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n });\r\n }\r\n\r\n async put<T>(path: string, body?: unknown, options: RequestInit = {}): Promise<T> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, {\r\n ...options,\r\n method: 'PUT',\r\n headers,\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n });\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown, options: RequestInit = {}): Promise<T> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, {\r\n ...options,\r\n method: 'PATCH',\r\n headers,\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n });\r\n }\r\n\r\n async delete<T>(path: string, options: RequestInit = {}): Promise<T> {\r\n const headers = {\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, { ...options, method: 'DELETE', headers });\r\n }\r\n\r\n private async request<T>(path: string, options: RequestInit): Promise<T> {\r\n const url = `${this.baseUrl}${path}`;\r\n const tokenState = this.resolveTokens?.();\r\n\r\n // Usamos Record<string, string> para que TypeScript permita indexar con 'Authorization' y 'X-SDK-Token'\r\n const headers: Record<string, string> = {\r\n ...(options.headers as Record<string, string> | undefined),\r\n };\r\n\r\n if (!headers['Authorization'] && tokenState?.accessToken) {\r\n headers['Authorization'] = `Bearer ${tokenState.accessToken}`;\r\n }\r\n\r\n if (tokenState?.sdkToken) {\r\n headers['X-SDK-Token'] = tokenState.sdkToken;\r\n }\r\n\r\n const response = await fetch(url, {\r\n ...options,\r\n headers,\r\n });\r\n\r\n const contentType = response.headers.get('content-type');\r\n const isJson = contentType?.includes('application/json');\r\n const payload = isJson ? await response.json() : await response.text();\r\n\r\n if (!response.ok) {\r\n const normalizedError: ZenitSdkError = {\r\n success: false,\r\n statusCode: response.status,\r\n message: typeof payload === 'string' ? payload : payload?.message || 'Unknown error',\r\n timestamp: typeof payload === 'object' ? payload.timestamp : undefined,\r\n path: typeof payload === 'object' ? payload.path : undefined,\r\n method: typeof payload === 'object' ? payload.method : undefined,\r\n error: typeof payload === 'object' ? payload.error : undefined,\r\n };\r\n throw normalizedError;\r\n }\r\n\r\n return payload as T;\r\n }\r\n}\r\n","import { HttpClient } from '../http/HttpClient';\r\nimport type {\r\n LoginRequest,\r\n LoginResponse,\r\n MeResponse,\r\n RefreshResponse,\r\n ValidateResponse\r\n} from './AuthTypes';\r\nimport type { ZenitSdkConfig } from '../config/ZenitSdkConfig';\r\n\r\n/**\r\n * Client to manage user authentication endpoints.\r\n */\r\nexport class ZenitAuthClient {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly updateTokens: (tokens: { accessToken?: string; refreshToken?: string }) => void,\r\n private readonly config: ZenitSdkConfig\r\n ) {}\r\n\r\n async login(credentials: LoginRequest): Promise<LoginResponse> {\r\n try {\r\n const response = await this.http.post<LoginResponse>('/auth/login', credentials);\r\n const accessToken = (response as any)?.accessToken ?? (response as any)?.data?.accessToken;\r\n const refreshToken = (response as any)?.refreshToken ?? (response as any)?.data?.refreshToken;\r\n this.updateTokens({ accessToken, refreshToken });\r\n return response;\r\n } catch (error) {\r\n this.config.onAuthError?.(error as any);\r\n throw error;\r\n }\r\n }\r\n\r\n async refresh(refreshToken?: string): Promise<RefreshResponse> {\r\n // Zenit allows refresh via httpOnly cookie or Authorization header; the SDK uses the header when a token is available.\r\n const tokenToUse = refreshToken || this.config.refreshToken;\r\n const headers = tokenToUse ? { Authorization: `Bearer ${tokenToUse}` } : undefined;\r\n const response = await this.http.post<RefreshResponse>('/auth/refresh', undefined, { headers });\r\n const accessToken = (response as any)?.accessToken ?? (response as any)?.data?.accessToken;\r\n const nextRefreshToken = (response as any)?.refreshToken ?? (response as any)?.data?.refreshToken;\r\n this.updateTokens({ accessToken, refreshToken: nextRefreshToken });\r\n return response;\r\n }\r\n\r\n async me(): Promise<MeResponse> {\r\n return this.http.get<MeResponse>('/auth/me');\r\n }\r\n\r\n async validate(): Promise<ValidateResponse> {\r\n return this.http.get<ValidateResponse>('/auth/validate');\r\n }\r\n}\r\n","import { HttpClient } from '../http/HttpClient';\r\nimport type { ZenitSdkConfig } from '../config/ZenitSdkConfig';\r\nimport type { SdkTokenExchangeResponse, SdkTokenValidateResponse } from './SdkAuthTypes';\r\n\r\n/**\r\n * Client to manage SDK token validation and exchange endpoints.\r\n */\r\nexport class ZenitSdkAuthClient {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly updateAccessToken: (token?: string) => void,\r\n private readonly config: ZenitSdkConfig\r\n ) {}\r\n\r\n /**\r\n * Validate an SDK token. If no token argument is provided, it falls back to config.sdkToken.\r\n */\r\n async validateSdkToken(token?: string): Promise<SdkTokenValidateResponse> {\r\n const sdkToken = token || this.config.sdkToken;\r\n return this.http.post<SdkTokenValidateResponse>('/sdk-auth/validate', { token: sdkToken });\r\n }\r\n\r\n /**\r\n * Exchange an SDK token for an access token. Token can come from method args or config.sdkToken.\r\n */\r\n async exchangeSdkToken(token?: string): Promise<SdkTokenExchangeResponse> {\r\n const sdkToken = token || this.config.sdkToken;\r\n const response = await this.http.post<SdkTokenExchangeResponse>('/sdk-auth/exchange', { token: sdkToken });\r\n const accessToken = (response as any)?.accessToken ?? (response as any)?.data?.accessToken;\r\n this.updateAccessToken(accessToken);\r\n return response;\r\n }\r\n}\r\n","import { HttpClient } from '../http/HttpClient';\r\nimport type { MapDto } from './types';\r\n\r\nexport class ZenitMapsClient {\r\n constructor(private readonly httpClient: HttpClient) {}\r\n\r\n async getMap(mapId: number | string, includeLayers = true): Promise<MapDto> {\r\n const include = includeLayers ? '?includeLayers=true' : '';\r\n return this.httpClient.get<MapDto>(`/maps/${mapId}${include}`);\r\n }\r\n}\r\n","export type CatalogSupportReason =\r\n | 'supported'\r\n | 'unsupported-geometry'\r\n | 'unknown-geometry';\r\n\r\nexport type CatalogSupport = {\r\n supported: boolean;\r\n reason: CatalogSupportReason;\r\n layerType?: string;\r\n geometryType?: string;\r\n};\r\n\r\nfunction isPolygonLike(value?: string): boolean {\r\n if (!value) {\r\n return false;\r\n }\r\n\r\n const normalized = value.toLowerCase();\r\n return normalized === 'polygon' || normalized === 'multipolygon';\r\n}\r\n\r\nexport function getCatalogSupport(args: {\r\n layerType?: string;\r\n geometryType?: string;\r\n}): CatalogSupport {\r\n const { layerType, geometryType } = args;\r\n\r\n if (layerType !== undefined) {\r\n const supported = isPolygonLike(layerType);\r\n return {\r\n supported,\r\n reason: supported ? 'supported' : 'unsupported-geometry',\r\n layerType,\r\n geometryType,\r\n };\r\n }\r\n\r\n if (geometryType !== undefined) {\r\n const supported = isPolygonLike(geometryType);\r\n return {\r\n supported,\r\n reason: supported ? 'supported' : 'unsupported-geometry',\r\n geometryType,\r\n };\r\n }\r\n\r\n return {\r\n supported: false,\r\n reason: 'unknown-geometry',\r\n };\r\n}\r\n\r\nexport class ZenitCatalogNotSupportedError extends Error {\r\n name = 'ZenitCatalogNotSupportedError';\r\n support: CatalogSupport;\r\n\r\n constructor(support: CatalogSupport, message?: string) {\r\n super(message ?? 'Catalog is not supported for this layer geometry');\r\n this.support = support;\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n","import type { GeoJsonFeature, GeoJsonFeatureCollection } from '../layers/types';\r\n\r\ntype PrefilterValue = string | number | boolean;\r\nexport type Prefilters = Record<string, unknown> | null | undefined;\r\n\r\nconst normalizeString = (value: string): string => value.trim().toLowerCase();\r\n\r\nconst isPrefilterValue = (value: unknown): value is PrefilterValue =>\r\n typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';\r\n\r\nconst matchesPrefilterValue = (candidate: unknown, expected: PrefilterValue): boolean => {\r\n if (typeof expected === 'string') {\r\n if (candidate === null || candidate === undefined) return false;\r\n return normalizeString(String(candidate)) === normalizeString(expected);\r\n }\r\n\r\n return candidate === expected;\r\n};\r\n\r\nconst shouldApplyPrefilters = (prefilters: Prefilters): prefilters is Record<string, unknown> =>\r\n !!prefilters && Object.keys(prefilters).length > 0;\r\n\r\nconst featureMatchesPrefilters = (\r\n feature: GeoJsonFeature,\r\n prefilters: Record<string, unknown>\r\n): boolean => {\r\n const properties = (feature.properties ?? {}) as Record<string, unknown>;\r\n\r\n return Object.entries(prefilters).every(([key, expected]) => {\r\n if (!isPrefilterValue(expected)) return true;\r\n return matchesPrefilterValue(properties[key], expected);\r\n });\r\n};\r\n\r\nexport const applyPrefiltersToFeatureCollection = (\r\n featureCollection: GeoJsonFeatureCollection,\r\n prefilters: Prefilters\r\n): GeoJsonFeatureCollection => {\r\n if (!shouldApplyPrefilters(prefilters)) return featureCollection;\r\n\r\n const nextFeatures = featureCollection.features.filter((feature) =>\r\n featureMatchesPrefilters(feature, prefilters)\r\n );\r\n\r\n return {\r\n ...featureCollection,\r\n features: nextFeatures,\r\n };\r\n};\r\n\r\nexport const decorateFeaturesWithLayerId = (\r\n featureCollection: GeoJsonFeatureCollection,\r\n layerId: number | string\r\n): GeoJsonFeatureCollection => {\r\n let shouldClone = false;\r\n\r\n featureCollection.features.forEach((feature) => {\r\n const existing = (feature.properties as { __zenit_layerId?: number | string } | undefined)\r\n ?.__zenit_layerId;\r\n if (existing !== layerId) {\r\n shouldClone = true;\r\n }\r\n });\r\n\r\n if (!shouldClone) {\r\n return featureCollection;\r\n }\r\n\r\n return {\r\n ...featureCollection,\r\n features: featureCollection.features.map((feature) => ({\r\n ...feature,\r\n properties: {\r\n ...(feature.properties ?? {}),\r\n __zenit_layerId: layerId,\r\n },\r\n })),\r\n };\r\n};\r\n","import { HttpClient } from '../http/HttpClient';\r\nimport {\r\n ZenitCatalogNotSupportedError,\r\n getCatalogSupport,\r\n} from './catalogSupport';\r\nimport { decorateFeaturesWithLayerId } from '../engine/PrefilterEngine';\r\nimport type {\r\n ApiResponseData,\r\n FilterMultipleMetadata,\r\n FilterMultipleLayerMeta,\r\n FilterMultipleWithFallbackResult,\r\n GeoJsonBBoxRequest,\r\n GeoJsonFeatureCollection,\r\n GeoJsonGeometryCollection,\r\n GeoJsonIntersectRequest,\r\n GeoJsonRequestOptions,\r\n LayerAoi,\r\n LayerDto,\r\n LayerMetadata,\r\n LayerFeaturesCatalogDto,\r\n LayerFilters,\r\n LoadLayerDataParams,\r\n LoadLayerDataResult,\r\n ResolveLayerStrategyParams,\r\n ResolveLayerStrategyResult,\r\n} from './types';\r\n\r\nfunction parseQueryParams(options: GeoJsonRequestOptions = {}): URLSearchParams {\r\n const params = new URLSearchParams();\r\n if (options.maxFeatures !== undefined) {\r\n params.set('maxFeatures', String(options.maxFeatures));\r\n }\r\n if (options.simplify !== undefined) {\r\n params.set('simplify', String(options.simplify));\r\n }\r\n return params;\r\n}\r\n\r\nfunction serializeFilterValue(value: unknown): string | undefined {\r\n if (Array.isArray(value)) {\r\n const serialized = value.map(String).filter((item) => item.trim().length > 0).join(',');\r\n return serialized.length > 0 ? serialized : undefined;\r\n }\r\n\r\n if (value === undefined || value === null) {\r\n return undefined;\r\n }\r\n\r\n const serialized = String(value);\r\n return serialized.trim().length > 0 ? serialized : undefined;\r\n}\r\n\r\nexport function buildLayerFilters(filters?: LayerFilters): URLSearchParams {\r\n const query = new URLSearchParams();\r\n\r\n if (!filters) {\r\n return query;\r\n }\r\n\r\n Object.entries(filters).forEach(([key, value]) => {\r\n const serialized = serializeFilterValue(value);\r\n if (serialized !== undefined) {\r\n query.set(key, serialized);\r\n }\r\n });\r\n\r\n return query;\r\n}\r\n\r\nexport function buildFilterMultipleParams(params: {\r\n layerIds: Array<number | string>;\r\n filters?: LayerFilters;\r\n}): URLSearchParams {\r\n const query = buildLayerFilters(params.filters);\r\n\r\n if (!Array.isArray(params.layerIds) || params.layerIds.length === 0) {\r\n throw new Error('layerIds is required and cannot be empty');\r\n }\r\n\r\n query.set('layerIds', params.layerIds.map((id) => String(id)).join(','));\r\n return query;\r\n\r\n}\r\n\r\nfunction asOptionalNumber(value: unknown): number | undefined {\r\n return typeof value === 'number' && Number.isFinite(value)\r\n ? value\r\n : undefined;\r\n}\r\n\r\nfunction createEmptyFeatureCollection(): GeoJsonFeatureCollection {\r\n return { type: 'FeatureCollection', features: [] };\r\n}\r\n\r\nfunction hasFilters(filters?: LayerFilters): boolean {\r\n return buildLayerFilters(filters).size > 0;\r\n}\r\n\r\nfunction mergeLayerFilters(\r\n base?: LayerFilters,\r\n extra?: LayerFilters\r\n): LayerFilters | undefined {\r\n if (!base && !extra) return undefined;\r\n const merged: LayerFilters = { ...(base ?? {}), ...(extra ?? {}) };\r\n return hasFilters(merged) ? merged : undefined;\r\n}\r\n\r\nexport const DEFAULT_MAX_FEATURES_FULL_GEOJSON = 50000;\r\n\r\nfunction normalizeLayerType(layerType?: string): string | undefined {\r\n return typeof layerType === 'string' ? layerType.toLowerCase() : undefined;\r\n}\r\n\r\nexport function shouldUseFilterMultiple(layerType?: string): boolean {\r\n return normalizeLayerType(layerType) === 'multipolygon';\r\n}\r\n\r\nexport function shouldSkipGeojsonDownload(\r\n layerType?: string,\r\n totalFeatures?: number,\r\n thresholds: { maxFeatures: number; allowLargeGeojson?: boolean } = {\r\n maxFeatures: DEFAULT_MAX_FEATURES_FULL_GEOJSON,\r\n }\r\n): boolean {\r\n if (thresholds.allowLargeGeojson) {\r\n return false;\r\n }\r\n const normalizedType = normalizeLayerType(layerType);\r\n if (normalizedType === 'mixed') {\r\n return true;\r\n }\r\n\r\n if (typeof totalFeatures === 'number' && totalFeatures > thresholds.maxFeatures) {\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\nfunction parseBbox(value: unknown): GeoJsonBBoxRequest['bbox'] | undefined {\r\n if (!value || typeof value !== 'object') {\r\n return undefined;\r\n }\r\n const candidate = value as Partial<GeoJsonBBoxRequest['bbox']>;\r\n if (\r\n typeof candidate.minLon === 'number' &&\r\n typeof candidate.minLat === 'number' &&\r\n typeof candidate.maxLon === 'number' &&\r\n typeof candidate.maxLat === 'number'\r\n ) {\r\n return {\r\n minLon: candidate.minLon,\r\n minLat: candidate.minLat,\r\n maxLon: candidate.maxLon,\r\n maxLat: candidate.maxLat,\r\n };\r\n }\r\n\r\n if (Array.isArray(value) && value.length === 4) {\r\n const [minLon, minLat, maxLon, maxLat] = value;\r\n if (\r\n typeof minLon === 'number' &&\r\n typeof minLat === 'number' &&\r\n typeof maxLon === 'number' &&\r\n typeof maxLat === 'number'\r\n ) {\r\n return { minLon, minLat, maxLon, maxLat };\r\n }\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nfunction buildBboxFromFeatureCollection(\r\n featureCollection: GeoJsonFeatureCollection\r\n): GeoJsonBBoxRequest['bbox'] | undefined {\r\n const coords: Array<[number, number]> = [];\r\n\r\n const collect = (candidate: unknown) => {\r\n if (!Array.isArray(candidate)) return;\r\n if (\r\n candidate.length === 2 &&\r\n typeof candidate[0] === 'number' &&\r\n typeof candidate[1] === 'number' &&\r\n Number.isFinite(candidate[0]) &&\r\n Number.isFinite(candidate[1])\r\n ) {\r\n coords.push([candidate[0], candidate[1]]);\r\n return;\r\n }\r\n\r\n candidate.forEach((item) => collect(item));\r\n };\r\n\r\n featureCollection.features.forEach((feature) => {\r\n collect((feature as { geometry?: { coordinates?: unknown } }).geometry?.coordinates);\r\n });\r\n\r\n if (coords.length === 0) return undefined;\r\n\r\n const [firstLon, firstLat] = coords[0];\r\n const bbox = { minLon: firstLon, minLat: firstLat, maxLon: firstLon, maxLat: firstLat };\r\n\r\n coords.forEach(([lon, lat]) => {\r\n bbox.minLon = Math.min(bbox.minLon, lon);\r\n bbox.minLat = Math.min(bbox.minLat, lat);\r\n bbox.maxLon = Math.max(bbox.maxLon, lon);\r\n bbox.maxLat = Math.max(bbox.maxLat, lat);\r\n });\r\n\r\n return bbox;\r\n}\r\n\r\nfunction buildGeometryCollectionFromFeatureCollection(\r\n featureCollection: GeoJsonFeatureCollection\r\n): GeoJsonGeometryCollection {\r\n return {\r\n type: 'GeometryCollection',\r\n geometries: featureCollection.features\r\n .map((feature) => feature.geometry)\r\n .filter((geometry) => geometry !== undefined && geometry !== null),\r\n };\r\n}\r\n\r\nexport function buildAoiFromFeatureCollection(\r\n featureCollection: GeoJsonFeatureCollection,\r\n metadata?: FilterMultipleMetadata\r\n): LayerAoi | null {\r\n const metadataBbox = parseBbox(metadata?.bbox);\r\n const derivedBbox = metadataBbox ?? buildBboxFromFeatureCollection(featureCollection);\r\n const hasFeatures = featureCollection.features.length > 0;\r\n\r\n const geometry = hasFeatures\r\n ? buildGeometryCollectionFromFeatureCollection(featureCollection)\r\n : undefined;\r\n\r\n if (!derivedBbox && !geometry) {\r\n return null;\r\n }\r\n\r\n return { bbox: derivedBbox, geometry };\r\n}\r\n\r\nfunction splitFeatureCollectionByLayerId(\r\n featureCollection: GeoJsonFeatureCollection,\r\n layerIds: Array<number | string>\r\n): Record<string, GeoJsonFeatureCollection> {\r\n const grouped: Record<string, GeoJsonFeatureCollection> = {};\r\n layerIds.forEach((layerId) => {\r\n grouped[String(layerId)] = createEmptyFeatureCollection();\r\n });\r\n\r\n featureCollection.features.forEach((feature) => {\r\n const properties = feature.properties as Record<string, unknown> | undefined;\r\n const layerId =\r\n (properties?.layerId as number | string | undefined) ??\r\n (properties?.layer_id as number | string | undefined) ??\r\n (properties?.__zenit_layerId as number | string | undefined);\r\n if (layerId === undefined || layerId === null) {\r\n return;\r\n }\r\n\r\n const key = String(layerId);\r\n if (!grouped[key]) {\r\n grouped[key] = createEmptyFeatureCollection();\r\n }\r\n grouped[key] = {\r\n ...grouped[key],\r\n features: [...grouped[key].features, feature],\r\n };\r\n });\r\n\r\n return grouped;\r\n}\r\n\r\nexport function resolveLayerStrategy(\r\n params: ResolveLayerStrategyParams\r\n): ResolveLayerStrategyResult {\r\n const {\r\n layerDetail,\r\n bbox,\r\n filterBBox,\r\n filteredGeoJSON,\r\n isVisible = true,\r\n maxFeaturesFullGeojson,\r\n allowLargeGeojson,\r\n } = params;\r\n\r\n if (!isVisible) {\r\n return { strategy: 'geojson', effectiveBBox: bbox };\r\n }\r\n\r\n if (filteredGeoJSON && layerDetail.layerType !== 'multipolygon') {\r\n return {\r\n strategy: 'intersect',\r\n intersectionGeometry: buildGeometryCollectionFromFeatureCollection(filteredGeoJSON),\r\n };\r\n }\r\n\r\n const shouldSkipGeojson = shouldSkipGeojsonDownload(layerDetail.layerType, layerDetail.totalFeatures, {\r\n maxFeatures: maxFeaturesFullGeojson ?? DEFAULT_MAX_FEATURES_FULL_GEOJSON,\r\n allowLargeGeojson,\r\n });\r\n\r\n if (shouldSkipGeojson && (filterBBox ?? bbox)) {\r\n return { strategy: 'bbox', effectiveBBox: filterBBox ?? bbox };\r\n }\r\n\r\n if ((layerDetail.totalFeatures ?? 0) > 5000 && (filterBBox ?? bbox)) {\r\n return { strategy: 'bbox', effectiveBBox: filterBBox ?? bbox };\r\n }\r\n\r\n return { strategy: 'geojson', effectiveBBox: bbox };\r\n}\r\n\r\nexport function buildLimitedMessage(metadata?: LayerMetadata): string | undefined {\r\n if (!metadata) {\r\n return undefined;\r\n }\r\n\r\n const explicit = metadata.limitedMessage;\r\n if (typeof explicit === 'string' && explicit.trim().length > 0) {\r\n return explicit;\r\n }\r\n\r\n const limit = typeof metadata.limit === 'number' ? metadata.limit : undefined;\r\n const total =\r\n typeof metadata.totalFeatures === 'number'\r\n ? metadata.totalFeatures\r\n : undefined;\r\n\r\n if (limit !== undefined && total !== undefined && total > limit) {\r\n return `Mostrando ${limit.toLocaleString()} de ${total.toLocaleString()} elementos por límite de capa.`;\r\n }\r\n\r\n if (metadata.limited && limit !== undefined) {\r\n return `Mostrando un máximo de ${limit.toLocaleString()} elementos por límite de capa.`;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nexport class ZenitLayersClient {\r\n constructor(private readonly httpClient: HttpClient) {}\r\n\r\n async getLayer(layerId: number | string): Promise<ApiResponseData<LayerDto>> {\r\n const response = await this.httpClient.get<ApiResponseData<LayerDto>>(\r\n `/layers/${layerId}`\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerGeoJson(\r\n layerId: number | string,\r\n options: GeoJsonRequestOptions = {}\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n const params = parseQueryParams(options);\r\n const suffix = params.size > 0 ? `?${params.toString()}` : '';\r\n\r\n const response = await this.httpClient.get<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${layerId}/geojson${suffix}`\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerFeaturesCatalog(\r\n layerId: number | string,\r\n options?: { layerType?: string; geometryType?: string; strict?: boolean }\r\n ): Promise<ApiResponseData<LayerFeaturesCatalogDto>> {\r\n if (options?.strict) {\r\n const support = getCatalogSupport({\r\n layerType: options.layerType,\r\n geometryType: options.geometryType,\r\n });\r\n\r\n if (!support.supported) {\r\n throw new ZenitCatalogNotSupportedError(\r\n support,\r\n support.reason === 'unknown-geometry'\r\n ? 'Catalog support cannot be determined without a geometry type'\r\n : 'Catalog is only supported for polygon or multipolygon geometries'\r\n );\r\n }\r\n }\r\n\r\n const response = await this.httpClient.get<ApiResponseData<LayerFeaturesCatalogDto>>(\r\n `/layers/${layerId}/features/catalog`\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerFeatures(\r\n layerId: number | string,\r\n featureIds: Array<number | string>\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n if (!Array.isArray(featureIds) || featureIds.length === 0) {\r\n throw new Error('featureIds is required and cannot be empty');\r\n }\r\n\r\n const query = featureIds.map(String).join(',');\r\n const response = await this.httpClient.get<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${layerId}/features?featureIds=${encodeURIComponent(query)}`\r\n );\r\n\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async filterLayerFeatures(\r\n layerId: number | string,\r\n filters: LayerFilters\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n const query = buildLayerFilters(filters);\r\n\r\n const suffix = query.toString();\r\n const response = await this.httpClient.get<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${layerId}/features/filter${suffix ? `?${suffix}` : ''}`\r\n );\r\n\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async filterMultipleLayersFeatures(params: {\r\n layerIds: Array<number | string>;\r\n filters?: LayerFilters;\r\n }): Promise<ApiResponseData<GeoJsonFeatureCollection, FilterMultipleMetadata>> {\r\n const query = buildFilterMultipleParams(params);\r\n\r\n const suffix = query.toString();\r\n const response = await this.httpClient.get<\r\n ApiResponseData<GeoJsonFeatureCollection, FilterMultipleMetadata>\r\n >(`/layers/features/filter-multiple${suffix ? `?${suffix}` : ''}`);\r\n\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async filterMultiple(params: {\r\n layerIds: Array<number | string>;\r\n filters?: LayerFilters;\r\n }): Promise<ApiResponseData<GeoJsonFeatureCollection, FilterMultipleMetadata>> {\r\n return this.filterMultipleLayersFeatures(params);\r\n }\r\n\r\n /**\r\n * Resilient filter-multiple helper:\r\n * - Usa filter-multiple SOLO en capas multipolygon.\r\n * - Para otras capas aplica filterLayerFeatures o getLayerGeoJson según haya filtros.\r\n * - Nunca falla toda la operación por una capa inválida.\r\n *\r\n * Para mejor detección de layerType, pasa layerMetas con el layerType de cada capa.\r\n */\r\n async filterMultipleWithFallback(params: {\r\n layerIds: Array<number | string>;\r\n filters?: LayerFilters;\r\n layerMetas?: FilterMultipleLayerMeta[];\r\n maxFeaturesFullGeojson?: number;\r\n allowLargeGeojson?: boolean;\r\n }): Promise<FilterMultipleWithFallbackResult> {\r\n const layerIds = params.layerIds ?? [];\r\n const perLayer: Record<string, GeoJsonFeatureCollection> = {};\r\n const warnings: string[] = [];\r\n const hasLayerMetas = (params.layerMetas ?? []).length > 0;\r\n const maxFeaturesFullGeojson =\r\n params.maxFeaturesFullGeojson ?? DEFAULT_MAX_FEATURES_FULL_GEOJSON;\r\n const allowLargeGeojson = params.allowLargeGeojson ?? false;\r\n\r\n layerIds.forEach((layerId) => {\r\n perLayer[String(layerId)] = createEmptyFeatureCollection();\r\n });\r\n\r\n if (layerIds.length === 0) {\r\n return { perLayer };\r\n }\r\n\r\n const globalFilters = hasFilters(params.filters) ? params.filters : undefined;\r\n const metaIndex = new Map<string, FilterMultipleLayerMeta>();\r\n (params.layerMetas ?? []).forEach((meta) => {\r\n metaIndex.set(String(meta.layerId), meta);\r\n });\r\n\r\n let multipolygonIds: Array<number | string> = [];\r\n let otherIds: Array<number | string> = [];\r\n const layerIdsWithData = new Set<string>();\r\n let aoi: LayerAoi | null = null;\r\n\r\n const pushWarning = (message: string) => {\r\n warnings.push(message);\r\n console.warn(message);\r\n };\r\n\r\n const buildSkipWarning = (\r\n layerId: number | string,\r\n layerType?: string,\r\n totalFeatures?: number,\r\n reason?: string\r\n ) => {\r\n const typeLabel = layerType ?? 'unknown';\r\n const totalLabel =\r\n typeof totalFeatures === 'number' ? ` totalFeatures=${totalFeatures}` : '';\r\n const reasonLabel = reason ? ` ${reason}` : '';\r\n return `Layer ${layerId} skipped: layerType=${typeLabel}${totalLabel}${reasonLabel}`;\r\n };\r\n\r\n if (hasLayerMetas) {\r\n layerIds.forEach((layerId) => {\r\n const meta = metaIndex.get(String(layerId));\r\n if (shouldUseFilterMultiple(meta?.layerType)) {\r\n multipolygonIds.push(layerId);\r\n } else {\r\n otherIds.push(layerId);\r\n }\r\n });\r\n } else {\r\n multipolygonIds = [...layerIds];\r\n }\r\n\r\n let metadata: FilterMultipleMetadata | undefined;\r\n\r\n if (multipolygonIds.length > 0) {\r\n try {\r\n const response = await this.filterMultipleLayersFeatures({\r\n layerIds: multipolygonIds,\r\n filters: globalFilters,\r\n });\r\n metadata = response.metadata;\r\n const geojson = response.data ?? createEmptyFeatureCollection();\r\n if (globalFilters) {\r\n aoi = buildAoiFromFeatureCollection(geojson, metadata);\r\n }\r\n const perLayerFromMultiple = splitFeatureCollectionByLayerId(geojson, layerIds);\r\n\r\n Object.entries(perLayerFromMultiple).forEach(([layerKey, collection]) => {\r\n if (collection.features.length === 0) {\r\n return;\r\n }\r\n perLayer[layerKey] = decorateFeaturesWithLayerId(collection, layerKey);\r\n layerIdsWithData.add(layerKey);\r\n });\r\n } catch {\r\n if (hasLayerMetas) {\r\n otherIds = [...new Set([...otherIds, ...multipolygonIds])];\r\n } else {\r\n otherIds = [...layerIds];\r\n }\r\n multipolygonIds = [];\r\n }\r\n }\r\n\r\n if (otherIds.length > 0) {\r\n const pendingIds = otherIds.filter(\r\n (layerId) => !layerIdsWithData.has(String(layerId))\r\n );\r\n const resolved = await Promise.all(\r\n pendingIds.map(async (layerId) => {\r\n const meta = metaIndex.get(String(layerId));\r\n const layerType = meta?.layerType;\r\n const totalFeatures = meta?.totalFeatures;\r\n const layerFilters = mergeLayerFilters(globalFilters, meta?.prefilters);\r\n const canUseIntersect =\r\n !!globalFilters && !shouldUseFilterMultiple(layerType) && !!aoi?.geometry;\r\n\r\n if (canUseIntersect) {\r\n const intersectionGeometry = aoi?.geometry;\r\n if (!intersectionGeometry) {\r\n pushWarning(\r\n buildSkipWarning(\r\n layerId,\r\n layerType,\r\n totalFeatures,\r\n 'no AOI geometry available'\r\n )\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n\r\n try {\r\n const response = await this.getLayerGeoJsonIntersect({\r\n id: layerId,\r\n geometry: intersectionGeometry,\r\n });\r\n if (aoi?.bbox) {\r\n console.debug(\r\n `Layer ${layerId} fetched by intersect using AOI bbox=${JSON.stringify(\r\n aoi.bbox\r\n )}`\r\n );\r\n } else {\r\n console.debug(`Layer ${layerId} fetched by intersect using AOI geometry`);\r\n }\r\n const geojson = response.data ?? createEmptyFeatureCollection();\r\n return {\r\n layerId,\r\n geojson: decorateFeaturesWithLayerId(geojson, layerId),\r\n };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n pushWarning(\r\n buildSkipWarning(\r\n layerId,\r\n layerType,\r\n totalFeatures,\r\n `intersect failed: ${message}`\r\n )\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n }\r\n\r\n if (layerFilters && (hasLayerMetas ? shouldUseFilterMultiple(layerType) : true)) {\r\n try {\r\n const response = await this.filterLayerFeatures(layerId, layerFilters);\r\n const geojson = response.data ?? createEmptyFeatureCollection();\r\n return {\r\n layerId,\r\n geojson: decorateFeaturesWithLayerId(geojson, layerId),\r\n };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n pushWarning(\r\n `Layer ${layerId} filter failed: ${message}`\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n }\r\n\r\n if (\r\n shouldSkipGeojsonDownload(layerType, totalFeatures, {\r\n maxFeatures: maxFeaturesFullGeojson,\r\n allowLargeGeojson,\r\n })\r\n ) {\r\n pushWarning(\r\n buildSkipWarning(\r\n layerId,\r\n layerType,\r\n totalFeatures,\r\n 'not supported by filter endpoint and too large for /geojson; use intersect with AOI'\r\n )\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n\r\n try {\r\n const response = await this.getLayerGeoJson(layerId);\r\n const geojson = response.data ?? createEmptyFeatureCollection();\r\n return {\r\n layerId,\r\n geojson: decorateFeaturesWithLayerId(geojson, layerId),\r\n };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n pushWarning(\r\n buildSkipWarning(layerId, layerType, totalFeatures, `error=${message}`)\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n })\r\n );\r\n\r\n resolved.forEach(({ layerId, geojson }) => {\r\n perLayer[String(layerId)] = geojson;\r\n });\r\n }\r\n\r\n const mergedMetadata =\r\n warnings.length > 0\r\n ? {\r\n ...(metadata ?? {}),\r\n warnings: [...(metadata?.warnings ?? []), ...warnings],\r\n }\r\n : metadata;\r\n\r\n return { perLayer, metadata: mergedMetadata, aoi };\r\n }\r\n\r\n async getLayerGeoJsonBBox(\r\n request: GeoJsonBBoxRequest\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n const params = new URLSearchParams({\r\n minLon: String(request.bbox.minLon),\r\n minLat: String(request.bbox.minLat),\r\n maxLon: String(request.bbox.maxLon),\r\n maxLat: String(request.bbox.maxLat),\r\n });\r\n\r\n parseQueryParams(request).forEach((value, key) => params.set(key, value));\r\n\r\n const response = await this.httpClient.get<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${request.id}/geojson/bbox?${params.toString()}`\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerGeoJsonIntersect(\r\n request: GeoJsonIntersectRequest\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n const params = parseQueryParams(request);\r\n const suffix = params.size > 0 ? `?${params.toString()}` : '';\r\n\r\n const response = await this.httpClient.post<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${request.id}/geojson/intersects${suffix}`,\r\n { geometry: request.geometry }\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerTileTemplate(layerId: number | string): Promise<string> {\r\n const response = await this.httpClient.get<ApiResponseData<string | { template: string }>>(\r\n `/layers/${layerId}/tiles/template`\r\n );\r\n const unwrapped = this.unwrapResponse(response);\r\n if (typeof unwrapped.data === 'string') {\r\n return unwrapped.data;\r\n }\r\n if (unwrapped.data && typeof (unwrapped.data as { template?: string }).template === 'string') {\r\n return (unwrapped.data as { template: string }).template;\r\n }\r\n throw new Error('Invalid tile template response');\r\n }\r\n\r\n async loadLayerData(\r\n params: LoadLayerDataParams\r\n ): Promise<LoadLayerDataResult> {\r\n const { id, layerDetail, bbox, filterBBox, filteredGeoJSON, isVisible = true, ...options } = params;\r\n const resolution = resolveLayerStrategy({\r\n layerDetail,\r\n bbox,\r\n filterBBox,\r\n filteredGeoJSON,\r\n isVisible,\r\n maxFeaturesFullGeojson: params.maxFeaturesFullGeojson,\r\n allowLargeGeojson: params.allowLargeGeojson,\r\n });\r\n\r\n const response = await this.fetchByStrategy(id, resolution, options);\r\n\r\n const totalFeatures =\r\n asOptionalNumber(response.totalFeatures) ??\r\n asOptionalNumber(response.metadata?.totalFeatures) ??\r\n asOptionalNumber(layerDetail.totalFeatures);\r\n\r\n const limitedMessage =\r\n response.limitedMessage ?? buildLimitedMessage(response.metadata as LayerMetadata | undefined);\r\n\r\n return {\r\n geojson: response.data,\r\n strategy: resolution.strategy,\r\n limitedMessage,\r\n totalFeatures,\r\n metadata: response.metadata as LayerMetadata | undefined,\r\n };\r\n }\r\n\r\n async loadFilteredFeatures(params: {\r\n layerIds: Array<number | string>;\r\n filters: LayerFilters;\r\n }): Promise<{\r\n geojson: GeoJsonFeatureCollection;\r\n metadata?: FilterMultipleMetadata;\r\n totalFeatures?: number;\r\n }> {\r\n const response = await this.filterMultipleLayersFeatures(params);\r\n return {\r\n geojson: response.data,\r\n metadata: response.metadata,\r\n totalFeatures: response.metadata?.totalFeatures ?? response.totalFeatures,\r\n };\r\n }\r\n\r\n private async fetchByStrategy(\r\n layerId: number | string,\r\n resolution: ResolveLayerStrategyResult,\r\n options: GeoJsonRequestOptions\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection, LayerMetadata>> {\r\n switch (resolution.strategy) {\r\n case 'bbox': {\r\n if (!resolution.effectiveBBox) {\r\n throw new Error('Bounding box is required for bbox strategy');\r\n }\r\n return this.getLayerGeoJsonBBox({ id: layerId, bbox: resolution.effectiveBBox, ...options });\r\n }\r\n case 'intersect': {\r\n if (!resolution.intersectionGeometry) {\r\n throw new Error('Geometry is required for intersect strategy');\r\n }\r\n return this.getLayerGeoJsonIntersect({\r\n id: layerId,\r\n geometry: resolution.intersectionGeometry,\r\n ...options,\r\n });\r\n }\r\n case 'geojson':\r\n default:\r\n return this.getLayerGeoJson(layerId, options);\r\n }\r\n }\r\n\r\n private unwrapResponse<TData, TMetadata = LayerMetadata>(\r\n response: ApiResponseData<TData, TMetadata>\r\n ): ApiResponseData<TData, TMetadata> {\r\n if (!response || typeof response !== 'object' || !('data' in response)) {\r\n throw new Error('Invalid API response: missing data field');\r\n }\r\n if ('success' in response && response.success === false) {\r\n throw new Error(response.message ?? 'Request was not successful');\r\n }\r\n return response;\r\n }\r\n}\r\n","import { HttpClient, ZenitSdkError } from '../http/HttpClient';\r\nimport { ZenitAuthClient } from '../auth/ZenitAuthClient';\r\nimport { ZenitSdkAuthClient } from '../sdkAuth/ZenitSdkAuthClient';\r\nimport { ZenitMapsClient } from '../maps/ZenitMapsClient';\r\nimport { ZenitLayersClient } from '../layers/ZenitLayersClient';\r\n\r\nexport interface ZenitSdkConfig {\r\n // baseUrl: debe apuntar al prefijo de API de Zenit (ej: https://api.mi-zenit.com/api/v1).\r\n baseUrl: string;\r\n // sdkToken: token SDK que se puede validar o intercambiar por JWT.\r\n sdkToken?: string;\r\n // accessToken y refreshToken: tokens de usuario en caso de que el integrador ya los tenga (opcional).\r\n accessToken?: string;\r\n refreshToken?: string;\r\n // onAuthError: callback para manejar errores de login.\r\n onAuthError?(error: ZenitSdkError): void;\r\n // onTokenRefreshed: callback para actualizar tokens en el cliente que consuma el SDK.\r\n onTokenRefreshed?(tokens: { accessToken: string; refreshToken?: string }): void;\r\n}\r\n\r\nexport class ZenitClient {\r\n private accessToken?: string;\r\n private refreshToken?: string;\r\n private sdkToken?: string;\r\n private readonly httpClient: HttpClient;\r\n\r\n readonly auth: ZenitAuthClient;\r\n readonly sdkAuth: ZenitSdkAuthClient;\r\n readonly maps: ZenitMapsClient;\r\n readonly layers: ZenitLayersClient;\r\n\r\n constructor(private readonly config: ZenitSdkConfig) {\r\n this.accessToken = config.accessToken;\r\n this.refreshToken = config.refreshToken;\r\n this.sdkToken = config.sdkToken;\r\n this.httpClient = new HttpClient({\r\n baseUrl: config.baseUrl,\r\n resolveTokens: () => ({ accessToken: this.accessToken, sdkToken: this.sdkToken }),\r\n resolveAuthorizationHeader: this.getAuthorizationHeader.bind(this)\r\n });\r\n\r\n this.auth = new ZenitAuthClient(this.httpClient, this.updateTokens.bind(this), config);\r\n this.sdkAuth = new ZenitSdkAuthClient(\r\n this.httpClient,\r\n this.updateAccessTokenFromSdkExchange.bind(this),\r\n config\r\n );\r\n this.maps = new ZenitMapsClient(this.httpClient);\r\n this.layers = new ZenitLayersClient(this.httpClient);\r\n }\r\n\r\n /**\r\n * Update tokens in memory and propagate to config callbacks.\r\n */\r\n private updateTokens(tokens: { accessToken?: string; refreshToken?: string }) {\r\n if (tokens.accessToken) {\r\n this.setAccessToken(tokens.accessToken);\r\n }\r\n if (tokens.refreshToken) {\r\n this.setRefreshToken(tokens.refreshToken);\r\n }\r\n this.config.onTokenRefreshed?.({\r\n accessToken: this.accessToken || '',\r\n refreshToken: this.refreshToken\r\n });\r\n }\r\n\r\n // Se usa cuando /sdk-auth/exchange devuelve un accessToken; pasa a ser el accessToken principal del SDK.\r\n private updateAccessTokenFromSdkExchange(token?: string) {\r\n if (token) {\r\n this.setAccessToken(token);\r\n }\r\n }\r\n\r\n setAccessToken(token: string) {\r\n this.accessToken = token;\r\n this.config.accessToken = token;\r\n }\r\n\r\n setRefreshToken(token: string) {\r\n this.refreshToken = token;\r\n this.config.refreshToken = token;\r\n }\r\n\r\n getAuthorizationHeader(): Record<string, string> {\r\n const header: Record<string, string> = {};\r\n\r\n if (this.accessToken) {\r\n header.Authorization = `Bearer ${this.accessToken}`;\r\n }\r\n\r\n return header;\r\n }\r\n\r\n getHttpClient(): HttpClient {\r\n return this.httpClient;\r\n }\r\n}\r\n","import type { Bbox, GeoJsonPolygon, GeoJsonRequestOptions, LayerFilters } from '../layers/types';\r\n\r\nexport type FilterEngineRequest =\r\n | {\r\n type: 'filter-multiple';\r\n layerIds: Array<number | string>;\r\n filters: LayerFilters;\r\n }\r\n | {\r\n type: 'filter-layer';\r\n layerId: number | string;\r\n filters: LayerFilters;\r\n }\r\n | {\r\n type: 'geojson';\r\n layerId: number | string;\r\n options?: GeoJsonRequestOptions;\r\n }\r\n | {\r\n type: 'bbox';\r\n layerId: number | string;\r\n bbox: Bbox;\r\n options?: GeoJsonRequestOptions;\r\n }\r\n | {\r\n type: 'intersect';\r\n layerId: number | string;\r\n geometry: GeoJsonPolygon;\r\n options?: GeoJsonRequestOptions;\r\n };\r\n\r\nexport interface FilterEngineDecision {\r\n nextRequest: FilterEngineRequest;\r\n reason?: string;\r\n}\r\n\r\nexport interface FilterEngineParams {\r\n layerIds?: Array<number | string>;\r\n layerId?: number | string;\r\n filters?: LayerFilters;\r\n bbox?: Bbox;\r\n geometry?: GeoJsonPolygon;\r\n options?: GeoJsonRequestOptions;\r\n request?: FilterEngineRequest;\r\n}\r\n\r\nexport class FilterEngine {\r\n decide(params: FilterEngineParams): FilterEngineDecision {\r\n if (params.request) {\r\n return { nextRequest: params.request };\r\n }\r\n\r\n if (params.filters && params.layerIds && params.layerIds.length > 1) {\r\n return {\r\n nextRequest: {\r\n type: 'filter-multiple',\r\n layerIds: params.layerIds,\r\n filters: params.filters,\r\n },\r\n reason: 'filters+layerIds',\r\n };\r\n }\r\n\r\n if (params.filters && params.layerId !== undefined) {\r\n return {\r\n nextRequest: {\r\n type: 'filter-layer',\r\n layerId: params.layerId,\r\n filters: params.filters,\r\n },\r\n reason: 'filters+layerId',\r\n };\r\n }\r\n\r\n if (params.bbox && params.layerId !== undefined) {\r\n return {\r\n nextRequest: {\r\n type: 'bbox',\r\n layerId: params.layerId,\r\n bbox: params.bbox,\r\n options: params.options,\r\n },\r\n reason: 'bbox+layerId',\r\n };\r\n }\r\n\r\n if (params.geometry && params.layerId !== undefined) {\r\n return {\r\n nextRequest: {\r\n type: 'intersect',\r\n layerId: params.layerId,\r\n geometry: params.geometry,\r\n options: params.options,\r\n },\r\n reason: 'geometry+layerId',\r\n };\r\n }\r\n\r\n if (params.layerId !== undefined) {\r\n return {\r\n nextRequest: {\r\n type: 'geojson',\r\n layerId: params.layerId,\r\n options: params.options,\r\n },\r\n reason: 'layerId',\r\n };\r\n }\r\n\r\n throw new Error('FilterEngine could not resolve a next request');\r\n }\r\n}\r\n\r\nexport const filterEngine = new FilterEngine();\r\n","import type { Bbox } from '../layers/types';\r\n\r\n/**\r\n * Normalizes a bbox input to a standard Bbox object format.\r\n *\r\n * Accepts:\r\n * - Array tuple: [minLon, minLat, maxLon, maxLat]\r\n * - Object: { minLon, minLat, maxLon, maxLat }\r\n *\r\n * Returns:\r\n * - A valid Bbox object with { minLon, minLat, maxLon, maxLat }\r\n * - null if the input is invalid or contains non-finite numbers\r\n *\r\n * @param input - The bbox to normalize (can be array or object)\r\n * @returns A normalized Bbox object or null if invalid\r\n */\r\nexport function normalizeBbox(\r\n input: unknown\r\n): Bbox | null {\r\n if (!input) return null;\r\n\r\n // Case 1: Array tuple [minLon, minLat, maxLon, maxLat]\r\n if (Array.isArray(input)) {\r\n if (input.length !== 4) {\r\n console.warn('[normalizeBbox] Array must have exactly 4 elements, got:', input.length);\r\n return null;\r\n }\r\n\r\n const [minLon, minLat, maxLon, maxLat] = input;\r\n\r\n // Validate all are finite numbers\r\n if (\r\n typeof minLon !== 'number' ||\r\n typeof minLat !== 'number' ||\r\n typeof maxLon !== 'number' ||\r\n typeof maxLat !== 'number' ||\r\n !Number.isFinite(minLon) ||\r\n !Number.isFinite(minLat) ||\r\n !Number.isFinite(maxLon) ||\r\n !Number.isFinite(maxLat)\r\n ) {\r\n console.warn('[normalizeBbox] Array contains non-finite numbers:', input);\r\n return null;\r\n }\r\n\r\n // Validate min < max\r\n if (minLon >= maxLon || minLat >= maxLat) {\r\n console.warn('[normalizeBbox] Invalid bbox: min must be < max', {\r\n minLon,\r\n maxLon,\r\n minLat,\r\n maxLat,\r\n });\r\n return null;\r\n }\r\n\r\n return { minLon, minLat, maxLon, maxLat };\r\n }\r\n\r\n // Case 2: Object with keys { minLon, minLat, maxLon, maxLat }\r\n if (typeof input === 'object') {\r\n const candidate = input as Partial<Bbox>;\r\n\r\n const { minLon, minLat, maxLon, maxLat } = candidate;\r\n\r\n // Validate all keys exist and are finite numbers\r\n if (\r\n typeof minLon !== 'number' ||\r\n typeof minLat !== 'number' ||\r\n typeof maxLon !== 'number' ||\r\n typeof maxLat !== 'number' ||\r\n !Number.isFinite(minLon) ||\r\n !Number.isFinite(minLat) ||\r\n !Number.isFinite(maxLon) ||\r\n !Number.isFinite(maxLat)\r\n ) {\r\n console.warn('[normalizeBbox] Object missing valid bbox keys or contains non-finite numbers:', input);\r\n return null;\r\n }\r\n\r\n // Validate min < max\r\n if (minLon >= maxLon || minLat >= maxLat) {\r\n console.warn('[normalizeBbox] Invalid bbox: min must be < max', {\r\n minLon,\r\n maxLon,\r\n minLat,\r\n maxLat,\r\n });\r\n return null;\r\n }\r\n\r\n return { minLon, minLat, maxLon, maxLat };\r\n }\r\n\r\n console.warn('[normalizeBbox] Unsupported bbox format:', typeof input);\r\n return null;\r\n}\r\n"],"mappings":"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","names":["serialized"]}
1
+ {"version":3,"sources":["../src/http/HttpClient.ts","../src/auth/ZenitAuthClient.ts","../src/sdkAuth/ZenitSdkAuthClient.ts","../src/maps/ZenitMapsClient.ts","../src/layers/catalogSupport.ts","../src/engine/PrefilterEngine.ts","../src/layers/ZenitLayersClient.ts","../src/config/ZenitSdkConfig.ts","../src/engine/FilterEngine.ts","../src/ai/normalize.ts"],"sourcesContent":["export interface ZenitSdkError {\r\n success: false;\r\n statusCode: number;\r\n timestamp?: string;\r\n path?: string;\r\n method?: string;\r\n error?: string;\r\n message: string;\r\n}\r\n\r\ntype TokenResolver = () => { accessToken?: string; sdkToken?: string };\r\ntype AuthorizationHeaderResolver = () => Record<string, string>;\r\n\r\nexport interface HttpClientOptions {\r\n baseUrl: string;\r\n resolveTokens?: TokenResolver;\r\n resolveAuthorizationHeader?: AuthorizationHeaderResolver;\r\n}\r\n\r\n/**\r\n * Minimal fetch-based HTTP client for the Zenit SDK.\r\n * Responsible for setting base URL, auth headers and error normalization.\r\n *\r\n * - El header `Authorization` se usa para JWT de usuario o JWT obtenido vía `/sdk-auth/exchange`.\r\n * - El header `X-SDK-Token` se usa para enviar el token SDK crudo a endpoints como\r\n * `/sdk-auth/validate` y `/sdk-auth/exchange`.\r\n */\r\nexport class HttpClient {\r\n private readonly baseUrl: string;\r\n private readonly resolveTokens?: TokenResolver;\r\n private readonly resolveAuthorizationHeader: AuthorizationHeaderResolver;\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\r\n this.resolveTokens = options.resolveTokens;\r\n this.resolveAuthorizationHeader = options.resolveAuthorizationHeader ?? (() => ({}));\r\n }\r\n\r\n async get<T>(path: string, options: RequestInit = {}): Promise<T> {\r\n const headers = {\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, { ...options, method: 'GET', headers });\r\n }\r\n\r\n async post<T>(path: string, body?: unknown, options: RequestInit = {}): Promise<T> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, {\r\n ...options,\r\n method: 'POST',\r\n headers,\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n });\r\n }\r\n\r\n async put<T>(path: string, body?: unknown, options: RequestInit = {}): Promise<T> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, {\r\n ...options,\r\n method: 'PUT',\r\n headers,\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n });\r\n }\r\n\r\n async patch<T>(path: string, body?: unknown, options: RequestInit = {}): Promise<T> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, {\r\n ...options,\r\n method: 'PATCH',\r\n headers,\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n });\r\n }\r\n\r\n async delete<T>(path: string, options: RequestInit = {}): Promise<T> {\r\n const headers = {\r\n ...(options.headers as Record<string, string> | undefined),\r\n ...this.resolveAuthorizationHeader(),\r\n };\r\n\r\n return this.request<T>(path, { ...options, method: 'DELETE', headers });\r\n }\r\n\r\n private async request<T>(path: string, options: RequestInit): Promise<T> {\r\n const url = `${this.baseUrl}${path}`;\r\n const tokenState = this.resolveTokens?.();\r\n\r\n // Usamos Record<string, string> para que TypeScript permita indexar con 'Authorization' y 'X-SDK-Token'\r\n const headers: Record<string, string> = {\r\n ...(options.headers as Record<string, string> | undefined),\r\n };\r\n\r\n if (!headers['Authorization'] && tokenState?.accessToken) {\r\n headers['Authorization'] = `Bearer ${tokenState.accessToken}`;\r\n }\r\n\r\n if (tokenState?.sdkToken) {\r\n headers['X-SDK-Token'] = tokenState.sdkToken;\r\n }\r\n\r\n const response = await fetch(url, {\r\n ...options,\r\n headers,\r\n });\r\n\r\n const contentType = response.headers.get('content-type');\r\n const isJson = contentType?.includes('application/json');\r\n const payload = isJson ? await response.json() : await response.text();\r\n\r\n if (!response.ok) {\r\n const normalizedError: ZenitSdkError = {\r\n success: false,\r\n statusCode: response.status,\r\n message: typeof payload === 'string' ? payload : payload?.message || 'Unknown error',\r\n timestamp: typeof payload === 'object' ? payload.timestamp : undefined,\r\n path: typeof payload === 'object' ? payload.path : undefined,\r\n method: typeof payload === 'object' ? payload.method : undefined,\r\n error: typeof payload === 'object' ? payload.error : undefined,\r\n };\r\n throw normalizedError;\r\n }\r\n\r\n return payload as T;\r\n }\r\n}\r\n","import { HttpClient } from '../http/HttpClient';\r\nimport type {\r\n LoginRequest,\r\n LoginResponse,\r\n MeResponse,\r\n RefreshResponse,\r\n ValidateResponse\r\n} from './AuthTypes';\r\nimport type { ZenitSdkConfig } from '../config/ZenitSdkConfig';\r\n\r\n/**\r\n * Client to manage user authentication endpoints.\r\n */\r\nexport class ZenitAuthClient {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly updateTokens: (tokens: { accessToken?: string; refreshToken?: string }) => void,\r\n private readonly config: ZenitSdkConfig\r\n ) {}\r\n\r\n async login(credentials: LoginRequest): Promise<LoginResponse> {\r\n try {\r\n const response = await this.http.post<LoginResponse>('/auth/login', credentials);\r\n const accessToken = (response as any)?.accessToken ?? (response as any)?.data?.accessToken;\r\n const refreshToken = (response as any)?.refreshToken ?? (response as any)?.data?.refreshToken;\r\n this.updateTokens({ accessToken, refreshToken });\r\n return response;\r\n } catch (error) {\r\n this.config.onAuthError?.(error as any);\r\n throw error;\r\n }\r\n }\r\n\r\n async refresh(refreshToken?: string): Promise<RefreshResponse> {\r\n // Zenit allows refresh via httpOnly cookie or Authorization header; the SDK uses the header when a token is available.\r\n const tokenToUse = refreshToken || this.config.refreshToken;\r\n const headers = tokenToUse ? { Authorization: `Bearer ${tokenToUse}` } : undefined;\r\n const response = await this.http.post<RefreshResponse>('/auth/refresh', undefined, { headers });\r\n const accessToken = (response as any)?.accessToken ?? (response as any)?.data?.accessToken;\r\n const nextRefreshToken = (response as any)?.refreshToken ?? (response as any)?.data?.refreshToken;\r\n this.updateTokens({ accessToken, refreshToken: nextRefreshToken });\r\n return response;\r\n }\r\n\r\n async me(): Promise<MeResponse> {\r\n return this.http.get<MeResponse>('/auth/me');\r\n }\r\n\r\n async validate(): Promise<ValidateResponse> {\r\n return this.http.get<ValidateResponse>('/auth/validate');\r\n }\r\n}\r\n","import { HttpClient } from '../http/HttpClient';\r\nimport type { ZenitSdkConfig } from '../config/ZenitSdkConfig';\r\nimport type { SdkTokenExchangeResponse, SdkTokenValidateResponse } from './SdkAuthTypes';\r\n\r\n/**\r\n * Client to manage SDK token validation and exchange endpoints.\r\n */\r\nexport class ZenitSdkAuthClient {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly updateAccessToken: (token?: string) => void,\r\n private readonly config: ZenitSdkConfig\r\n ) {}\r\n\r\n /**\r\n * Validate an SDK token. If no token argument is provided, it falls back to config.sdkToken.\r\n */\r\n async validateSdkToken(token?: string): Promise<SdkTokenValidateResponse> {\r\n const sdkToken = token || this.config.sdkToken;\r\n return this.http.post<SdkTokenValidateResponse>('/sdk-auth/validate', { token: sdkToken });\r\n }\r\n\r\n /**\r\n * Exchange an SDK token for an access token. Token can come from method args or config.sdkToken.\r\n */\r\n async exchangeSdkToken(token?: string): Promise<SdkTokenExchangeResponse> {\r\n const sdkToken = token || this.config.sdkToken;\r\n const response = await this.http.post<SdkTokenExchangeResponse>('/sdk-auth/exchange', { token: sdkToken });\r\n const accessToken = (response as any)?.accessToken ?? (response as any)?.data?.accessToken;\r\n this.updateAccessToken(accessToken);\r\n return response;\r\n }\r\n}\r\n","import { HttpClient } from '../http/HttpClient';\r\nimport type { MapDto } from './types';\r\n\r\nexport class ZenitMapsClient {\r\n constructor(private readonly httpClient: HttpClient) {}\r\n\r\n async getMap(mapId: number | string, includeLayers = true): Promise<MapDto> {\r\n const include = includeLayers ? '?includeLayers=true' : '';\r\n return this.httpClient.get<MapDto>(`/maps/${mapId}${include}`);\r\n }\r\n}\r\n","export type CatalogSupportReason =\r\n | 'supported'\r\n | 'unsupported-geometry'\r\n | 'unknown-geometry';\r\n\r\nexport type CatalogSupport = {\r\n supported: boolean;\r\n reason: CatalogSupportReason;\r\n layerType?: string;\r\n geometryType?: string;\r\n};\r\n\r\nfunction isPolygonLike(value?: string): boolean {\r\n if (!value) {\r\n return false;\r\n }\r\n\r\n const normalized = value.toLowerCase();\r\n return normalized === 'polygon' || normalized === 'multipolygon';\r\n}\r\n\r\nexport function getCatalogSupport(args: {\r\n layerType?: string;\r\n geometryType?: string;\r\n}): CatalogSupport {\r\n const { layerType, geometryType } = args;\r\n\r\n if (layerType !== undefined) {\r\n const supported = isPolygonLike(layerType);\r\n return {\r\n supported,\r\n reason: supported ? 'supported' : 'unsupported-geometry',\r\n layerType,\r\n geometryType,\r\n };\r\n }\r\n\r\n if (geometryType !== undefined) {\r\n const supported = isPolygonLike(geometryType);\r\n return {\r\n supported,\r\n reason: supported ? 'supported' : 'unsupported-geometry',\r\n geometryType,\r\n };\r\n }\r\n\r\n return {\r\n supported: false,\r\n reason: 'unknown-geometry',\r\n };\r\n}\r\n\r\nexport class ZenitCatalogNotSupportedError extends Error {\r\n name = 'ZenitCatalogNotSupportedError';\r\n support: CatalogSupport;\r\n\r\n constructor(support: CatalogSupport, message?: string) {\r\n super(message ?? 'Catalog is not supported for this layer geometry');\r\n this.support = support;\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n","import type { GeoJsonFeature, GeoJsonFeatureCollection } from '../layers/types';\r\n\r\ntype PrefilterValue = string | number | boolean;\r\nexport type Prefilters = Record<string, unknown> | null | undefined;\r\n\r\nconst normalizeString = (value: string): string => value.trim().toLowerCase();\r\n\r\nconst isPrefilterValue = (value: unknown): value is PrefilterValue =>\r\n typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';\r\n\r\nconst matchesPrefilterValue = (candidate: unknown, expected: PrefilterValue): boolean => {\r\n if (typeof expected === 'string') {\r\n if (candidate === null || candidate === undefined) return false;\r\n return normalizeString(String(candidate)) === normalizeString(expected);\r\n }\r\n\r\n return candidate === expected;\r\n};\r\n\r\nconst shouldApplyPrefilters = (prefilters: Prefilters): prefilters is Record<string, unknown> =>\r\n !!prefilters && Object.keys(prefilters).length > 0;\r\n\r\nconst featureMatchesPrefilters = (\r\n feature: GeoJsonFeature,\r\n prefilters: Record<string, unknown>\r\n): boolean => {\r\n const properties = (feature.properties ?? {}) as Record<string, unknown>;\r\n\r\n return Object.entries(prefilters).every(([key, expected]) => {\r\n if (!isPrefilterValue(expected)) return true;\r\n return matchesPrefilterValue(properties[key], expected);\r\n });\r\n};\r\n\r\nexport const applyPrefiltersToFeatureCollection = (\r\n featureCollection: GeoJsonFeatureCollection,\r\n prefilters: Prefilters\r\n): GeoJsonFeatureCollection => {\r\n if (!shouldApplyPrefilters(prefilters)) return featureCollection;\r\n\r\n const nextFeatures = featureCollection.features.filter((feature) =>\r\n featureMatchesPrefilters(feature, prefilters)\r\n );\r\n\r\n return {\r\n ...featureCollection,\r\n features: nextFeatures,\r\n };\r\n};\r\n\r\nexport const decorateFeaturesWithLayerId = (\r\n featureCollection: GeoJsonFeatureCollection,\r\n layerId: number | string\r\n): GeoJsonFeatureCollection => {\r\n let shouldClone = false;\r\n\r\n featureCollection.features.forEach((feature) => {\r\n const existing = (feature.properties as { __zenit_layerId?: number | string } | undefined)\r\n ?.__zenit_layerId;\r\n if (existing !== layerId) {\r\n shouldClone = true;\r\n }\r\n });\r\n\r\n if (!shouldClone) {\r\n return featureCollection;\r\n }\r\n\r\n return {\r\n ...featureCollection,\r\n features: featureCollection.features.map((feature) => ({\r\n ...feature,\r\n properties: {\r\n ...(feature.properties ?? {}),\r\n __zenit_layerId: layerId,\r\n },\r\n })),\r\n };\r\n};\r\n","import { HttpClient } from '../http/HttpClient';\r\nimport {\r\n ZenitCatalogNotSupportedError,\r\n getCatalogSupport,\r\n} from './catalogSupport';\r\nimport { decorateFeaturesWithLayerId } from '../engine/PrefilterEngine';\r\nimport type {\r\n ApiResponseData,\r\n FilterMultipleMetadata,\r\n FilterMultipleLayerMeta,\r\n FilterMultipleWithFallbackResult,\r\n GeoJsonBBoxRequest,\r\n GeoJsonFeatureCollection,\r\n GeoJsonGeometryCollection,\r\n GeoJsonIntersectRequest,\r\n GeoJsonRequestOptions,\r\n LayerAoi,\r\n LayerDto,\r\n LayerMetadata,\r\n LayerFeaturesCatalogDto,\r\n LayerFilters,\r\n LoadLayerDataParams,\r\n LoadLayerDataResult,\r\n ResolveLayerStrategyParams,\r\n ResolveLayerStrategyResult,\r\n} from './types';\r\n\r\nfunction parseQueryParams(options: GeoJsonRequestOptions = {}): URLSearchParams {\r\n const params = new URLSearchParams();\r\n if (options.maxFeatures !== undefined) {\r\n params.set('maxFeatures', String(options.maxFeatures));\r\n }\r\n if (options.simplify !== undefined) {\r\n params.set('simplify', String(options.simplify));\r\n }\r\n return params;\r\n}\r\n\r\nfunction serializeFilterValue(value: unknown): string | undefined {\r\n if (Array.isArray(value)) {\r\n const serialized = value.map(String).filter((item) => item.trim().length > 0).join(',');\r\n return serialized.length > 0 ? serialized : undefined;\r\n }\r\n\r\n if (value === undefined || value === null) {\r\n return undefined;\r\n }\r\n\r\n const serialized = String(value);\r\n return serialized.trim().length > 0 ? serialized : undefined;\r\n}\r\n\r\nexport function buildLayerFilters(filters?: LayerFilters): URLSearchParams {\r\n const query = new URLSearchParams();\r\n\r\n if (!filters) {\r\n return query;\r\n }\r\n\r\n Object.entries(filters).forEach(([key, value]) => {\r\n const serialized = serializeFilterValue(value);\r\n if (serialized !== undefined) {\r\n query.set(key, serialized);\r\n }\r\n });\r\n\r\n return query;\r\n}\r\n\r\nexport function buildFilterMultipleParams(params: {\r\n layerIds: Array<number | string>;\r\n filters?: LayerFilters;\r\n}): URLSearchParams {\r\n const query = buildLayerFilters(params.filters);\r\n\r\n if (!Array.isArray(params.layerIds) || params.layerIds.length === 0) {\r\n throw new Error('layerIds is required and cannot be empty');\r\n }\r\n\r\n query.set('layerIds', params.layerIds.map((id) => String(id)).join(','));\r\n return query;\r\n\r\n}\r\n\r\nfunction asOptionalNumber(value: unknown): number | undefined {\r\n return typeof value === 'number' && Number.isFinite(value)\r\n ? value\r\n : undefined;\r\n}\r\n\r\nfunction createEmptyFeatureCollection(): GeoJsonFeatureCollection {\r\n return { type: 'FeatureCollection', features: [] };\r\n}\r\n\r\nfunction hasFilters(filters?: LayerFilters): boolean {\r\n return buildLayerFilters(filters).size > 0;\r\n}\r\n\r\nfunction mergeLayerFilters(\r\n base?: LayerFilters,\r\n extra?: LayerFilters\r\n): LayerFilters | undefined {\r\n if (!base && !extra) return undefined;\r\n const merged: LayerFilters = { ...(base ?? {}), ...(extra ?? {}) };\r\n return hasFilters(merged) ? merged : undefined;\r\n}\r\n\r\nexport const DEFAULT_MAX_FEATURES_FULL_GEOJSON = 50000;\r\n\r\nfunction normalizeLayerType(layerType?: string): string | undefined {\r\n return typeof layerType === 'string' ? layerType.toLowerCase() : undefined;\r\n}\r\n\r\nexport function shouldUseFilterMultiple(layerType?: string): boolean {\r\n return normalizeLayerType(layerType) === 'multipolygon';\r\n}\r\n\r\nexport function shouldSkipGeojsonDownload(\r\n layerType?: string,\r\n totalFeatures?: number,\r\n thresholds: { maxFeatures: number; allowLargeGeojson?: boolean } = {\r\n maxFeatures: DEFAULT_MAX_FEATURES_FULL_GEOJSON,\r\n }\r\n): boolean {\r\n if (thresholds.allowLargeGeojson) {\r\n return false;\r\n }\r\n const normalizedType = normalizeLayerType(layerType);\r\n if (normalizedType === 'mixed') {\r\n return true;\r\n }\r\n\r\n if (typeof totalFeatures === 'number' && totalFeatures > thresholds.maxFeatures) {\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\nfunction parseBbox(value: unknown): GeoJsonBBoxRequest['bbox'] | undefined {\r\n if (!value || typeof value !== 'object') {\r\n return undefined;\r\n }\r\n const candidate = value as Partial<GeoJsonBBoxRequest['bbox']>;\r\n if (\r\n typeof candidate.minLon === 'number' &&\r\n typeof candidate.minLat === 'number' &&\r\n typeof candidate.maxLon === 'number' &&\r\n typeof candidate.maxLat === 'number'\r\n ) {\r\n return {\r\n minLon: candidate.minLon,\r\n minLat: candidate.minLat,\r\n maxLon: candidate.maxLon,\r\n maxLat: candidate.maxLat,\r\n };\r\n }\r\n\r\n if (Array.isArray(value) && value.length === 4) {\r\n const [minLon, minLat, maxLon, maxLat] = value;\r\n if (\r\n typeof minLon === 'number' &&\r\n typeof minLat === 'number' &&\r\n typeof maxLon === 'number' &&\r\n typeof maxLat === 'number'\r\n ) {\r\n return { minLon, minLat, maxLon, maxLat };\r\n }\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nfunction buildBboxFromFeatureCollection(\r\n featureCollection: GeoJsonFeatureCollection\r\n): GeoJsonBBoxRequest['bbox'] | undefined {\r\n const coords: Array<[number, number]> = [];\r\n\r\n const collect = (candidate: unknown) => {\r\n if (!Array.isArray(candidate)) return;\r\n if (\r\n candidate.length === 2 &&\r\n typeof candidate[0] === 'number' &&\r\n typeof candidate[1] === 'number' &&\r\n Number.isFinite(candidate[0]) &&\r\n Number.isFinite(candidate[1])\r\n ) {\r\n coords.push([candidate[0], candidate[1]]);\r\n return;\r\n }\r\n\r\n candidate.forEach((item) => collect(item));\r\n };\r\n\r\n featureCollection.features.forEach((feature) => {\r\n collect((feature as { geometry?: { coordinates?: unknown } }).geometry?.coordinates);\r\n });\r\n\r\n if (coords.length === 0) return undefined;\r\n\r\n const [firstLon, firstLat] = coords[0];\r\n const bbox = { minLon: firstLon, minLat: firstLat, maxLon: firstLon, maxLat: firstLat };\r\n\r\n coords.forEach(([lon, lat]) => {\r\n bbox.minLon = Math.min(bbox.minLon, lon);\r\n bbox.minLat = Math.min(bbox.minLat, lat);\r\n bbox.maxLon = Math.max(bbox.maxLon, lon);\r\n bbox.maxLat = Math.max(bbox.maxLat, lat);\r\n });\r\n\r\n return bbox;\r\n}\r\n\r\nfunction buildGeometryCollectionFromFeatureCollection(\r\n featureCollection: GeoJsonFeatureCollection\r\n): GeoJsonGeometryCollection {\r\n return {\r\n type: 'GeometryCollection',\r\n geometries: featureCollection.features\r\n .map((feature) => feature.geometry)\r\n .filter((geometry) => geometry !== undefined && geometry !== null),\r\n };\r\n}\r\n\r\nexport function buildAoiFromFeatureCollection(\r\n featureCollection: GeoJsonFeatureCollection,\r\n metadata?: FilterMultipleMetadata\r\n): LayerAoi | null {\r\n const metadataBbox = parseBbox(metadata?.bbox);\r\n const derivedBbox = metadataBbox ?? buildBboxFromFeatureCollection(featureCollection);\r\n const hasFeatures = featureCollection.features.length > 0;\r\n\r\n const geometry = hasFeatures\r\n ? buildGeometryCollectionFromFeatureCollection(featureCollection)\r\n : undefined;\r\n\r\n if (!derivedBbox && !geometry) {\r\n return null;\r\n }\r\n\r\n return { bbox: derivedBbox, geometry };\r\n}\r\n\r\nfunction splitFeatureCollectionByLayerId(\r\n featureCollection: GeoJsonFeatureCollection,\r\n layerIds: Array<number | string>\r\n): Record<string, GeoJsonFeatureCollection> {\r\n const grouped: Record<string, GeoJsonFeatureCollection> = {};\r\n layerIds.forEach((layerId) => {\r\n grouped[String(layerId)] = createEmptyFeatureCollection();\r\n });\r\n\r\n featureCollection.features.forEach((feature) => {\r\n const properties = feature.properties as Record<string, unknown> | undefined;\r\n const layerId =\r\n (properties?.layerId as number | string | undefined) ??\r\n (properties?.layer_id as number | string | undefined) ??\r\n (properties?.__zenit_layerId as number | string | undefined);\r\n if (layerId === undefined || layerId === null) {\r\n return;\r\n }\r\n\r\n const key = String(layerId);\r\n if (!grouped[key]) {\r\n grouped[key] = createEmptyFeatureCollection();\r\n }\r\n grouped[key] = {\r\n ...grouped[key],\r\n features: [...grouped[key].features, feature],\r\n };\r\n });\r\n\r\n return grouped;\r\n}\r\n\r\nexport function resolveLayerStrategy(\r\n params: ResolveLayerStrategyParams\r\n): ResolveLayerStrategyResult {\r\n const {\r\n layerDetail,\r\n bbox,\r\n filterBBox,\r\n filteredGeoJSON,\r\n isVisible = true,\r\n maxFeaturesFullGeojson,\r\n allowLargeGeojson,\r\n } = params;\r\n\r\n if (!isVisible) {\r\n return { strategy: 'geojson', effectiveBBox: bbox };\r\n }\r\n\r\n if (filteredGeoJSON && layerDetail.layerType !== 'multipolygon') {\r\n return {\r\n strategy: 'intersect',\r\n intersectionGeometry: buildGeometryCollectionFromFeatureCollection(filteredGeoJSON),\r\n };\r\n }\r\n\r\n const shouldSkipGeojson = shouldSkipGeojsonDownload(layerDetail.layerType, layerDetail.totalFeatures, {\r\n maxFeatures: maxFeaturesFullGeojson ?? DEFAULT_MAX_FEATURES_FULL_GEOJSON,\r\n allowLargeGeojson,\r\n });\r\n\r\n if (shouldSkipGeojson && (filterBBox ?? bbox)) {\r\n return { strategy: 'bbox', effectiveBBox: filterBBox ?? bbox };\r\n }\r\n\r\n if ((layerDetail.totalFeatures ?? 0) > 5000 && (filterBBox ?? bbox)) {\r\n return { strategy: 'bbox', effectiveBBox: filterBBox ?? bbox };\r\n }\r\n\r\n return { strategy: 'geojson', effectiveBBox: bbox };\r\n}\r\n\r\nexport function buildLimitedMessage(metadata?: LayerMetadata): string | undefined {\r\n if (!metadata) {\r\n return undefined;\r\n }\r\n\r\n const explicit = metadata.limitedMessage;\r\n if (typeof explicit === 'string' && explicit.trim().length > 0) {\r\n return explicit;\r\n }\r\n\r\n const limit = typeof metadata.limit === 'number' ? metadata.limit : undefined;\r\n const total =\r\n typeof metadata.totalFeatures === 'number'\r\n ? metadata.totalFeatures\r\n : undefined;\r\n\r\n if (limit !== undefined && total !== undefined && total > limit) {\r\n return `Mostrando ${limit.toLocaleString()} de ${total.toLocaleString()} elementos por límite de capa.`;\r\n }\r\n\r\n if (metadata.limited && limit !== undefined) {\r\n return `Mostrando un máximo de ${limit.toLocaleString()} elementos por límite de capa.`;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nexport class ZenitLayersClient {\r\n constructor(private readonly httpClient: HttpClient) {}\r\n\r\n async getLayer(layerId: number | string): Promise<ApiResponseData<LayerDto>> {\r\n const response = await this.httpClient.get<ApiResponseData<LayerDto>>(\r\n `/layers/${layerId}`\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerGeoJson(\r\n layerId: number | string,\r\n options: GeoJsonRequestOptions = {}\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n const params = parseQueryParams(options);\r\n const suffix = params.size > 0 ? `?${params.toString()}` : '';\r\n\r\n const response = await this.httpClient.get<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${layerId}/geojson${suffix}`\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerFeaturesCatalog(\r\n layerId: number | string,\r\n options?: { layerType?: string; geometryType?: string; strict?: boolean }\r\n ): Promise<ApiResponseData<LayerFeaturesCatalogDto>> {\r\n if (options?.strict) {\r\n const support = getCatalogSupport({\r\n layerType: options.layerType,\r\n geometryType: options.geometryType,\r\n });\r\n\r\n if (!support.supported) {\r\n throw new ZenitCatalogNotSupportedError(\r\n support,\r\n support.reason === 'unknown-geometry'\r\n ? 'Catalog support cannot be determined without a geometry type'\r\n : 'Catalog is only supported for polygon or multipolygon geometries'\r\n );\r\n }\r\n }\r\n\r\n const response = await this.httpClient.get<ApiResponseData<LayerFeaturesCatalogDto>>(\r\n `/layers/${layerId}/features/catalog`\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerFeatures(\r\n layerId: number | string,\r\n featureIds: Array<number | string>\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n if (!Array.isArray(featureIds) || featureIds.length === 0) {\r\n throw new Error('featureIds is required and cannot be empty');\r\n }\r\n\r\n const query = featureIds.map(String).join(',');\r\n const response = await this.httpClient.get<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${layerId}/features?featureIds=${encodeURIComponent(query)}`\r\n );\r\n\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async filterLayerFeatures(\r\n layerId: number | string,\r\n filters: LayerFilters\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n const query = buildLayerFilters(filters);\r\n\r\n const suffix = query.toString();\r\n const response = await this.httpClient.get<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${layerId}/features/filter${suffix ? `?${suffix}` : ''}`\r\n );\r\n\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async filterMultipleLayersFeatures(params: {\r\n layerIds: Array<number | string>;\r\n filters?: LayerFilters;\r\n }): Promise<ApiResponseData<GeoJsonFeatureCollection, FilterMultipleMetadata>> {\r\n const query = buildFilterMultipleParams(params);\r\n\r\n const suffix = query.toString();\r\n const response = await this.httpClient.get<\r\n ApiResponseData<GeoJsonFeatureCollection, FilterMultipleMetadata>\r\n >(`/layers/features/filter-multiple${suffix ? `?${suffix}` : ''}`);\r\n\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async filterMultiple(params: {\r\n layerIds: Array<number | string>;\r\n filters?: LayerFilters;\r\n }): Promise<ApiResponseData<GeoJsonFeatureCollection, FilterMultipleMetadata>> {\r\n return this.filterMultipleLayersFeatures(params);\r\n }\r\n\r\n /**\r\n * Resilient filter-multiple helper:\r\n * - Usa filter-multiple SOLO en capas multipolygon.\r\n * - Para otras capas aplica filterLayerFeatures o getLayerGeoJson según haya filtros.\r\n * - Nunca falla toda la operación por una capa inválida.\r\n *\r\n * Para mejor detección de layerType, pasa layerMetas con el layerType de cada capa.\r\n */\r\n async filterMultipleWithFallback(params: {\r\n layerIds: Array<number | string>;\r\n filters?: LayerFilters;\r\n layerMetas?: FilterMultipleLayerMeta[];\r\n maxFeaturesFullGeojson?: number;\r\n allowLargeGeojson?: boolean;\r\n }): Promise<FilterMultipleWithFallbackResult> {\r\n const layerIds = params.layerIds ?? [];\r\n const perLayer: Record<string, GeoJsonFeatureCollection> = {};\r\n const warnings: string[] = [];\r\n const hasLayerMetas = (params.layerMetas ?? []).length > 0;\r\n const maxFeaturesFullGeojson =\r\n params.maxFeaturesFullGeojson ?? DEFAULT_MAX_FEATURES_FULL_GEOJSON;\r\n const allowLargeGeojson = params.allowLargeGeojson ?? false;\r\n\r\n layerIds.forEach((layerId) => {\r\n perLayer[String(layerId)] = createEmptyFeatureCollection();\r\n });\r\n\r\n if (layerIds.length === 0) {\r\n return { perLayer };\r\n }\r\n\r\n const globalFilters = hasFilters(params.filters) ? params.filters : undefined;\r\n const metaIndex = new Map<string, FilterMultipleLayerMeta>();\r\n (params.layerMetas ?? []).forEach((meta) => {\r\n metaIndex.set(String(meta.layerId), meta);\r\n });\r\n\r\n let multipolygonIds: Array<number | string> = [];\r\n let otherIds: Array<number | string> = [];\r\n const layerIdsWithData = new Set<string>();\r\n let aoi: LayerAoi | null = null;\r\n\r\n const pushWarning = (message: string) => {\r\n warnings.push(message);\r\n console.warn(message);\r\n };\r\n\r\n const buildSkipWarning = (\r\n layerId: number | string,\r\n layerType?: string,\r\n totalFeatures?: number,\r\n reason?: string\r\n ) => {\r\n const typeLabel = layerType ?? 'unknown';\r\n const totalLabel =\r\n typeof totalFeatures === 'number' ? ` totalFeatures=${totalFeatures}` : '';\r\n const reasonLabel = reason ? ` ${reason}` : '';\r\n return `Layer ${layerId} skipped: layerType=${typeLabel}${totalLabel}${reasonLabel}`;\r\n };\r\n\r\n if (hasLayerMetas) {\r\n layerIds.forEach((layerId) => {\r\n const meta = metaIndex.get(String(layerId));\r\n if (shouldUseFilterMultiple(meta?.layerType)) {\r\n multipolygonIds.push(layerId);\r\n } else {\r\n otherIds.push(layerId);\r\n }\r\n });\r\n } else {\r\n multipolygonIds = [...layerIds];\r\n }\r\n\r\n let metadata: FilterMultipleMetadata | undefined;\r\n\r\n if (multipolygonIds.length > 0) {\r\n try {\r\n const response = await this.filterMultipleLayersFeatures({\r\n layerIds: multipolygonIds,\r\n filters: globalFilters,\r\n });\r\n metadata = response.metadata;\r\n const geojson = response.data ?? createEmptyFeatureCollection();\r\n if (globalFilters) {\r\n aoi = buildAoiFromFeatureCollection(geojson, metadata);\r\n }\r\n const perLayerFromMultiple = splitFeatureCollectionByLayerId(geojson, layerIds);\r\n\r\n Object.entries(perLayerFromMultiple).forEach(([layerKey, collection]) => {\r\n if (collection.features.length === 0) {\r\n return;\r\n }\r\n perLayer[layerKey] = decorateFeaturesWithLayerId(collection, layerKey);\r\n layerIdsWithData.add(layerKey);\r\n });\r\n } catch {\r\n if (hasLayerMetas) {\r\n otherIds = [...new Set([...otherIds, ...multipolygonIds])];\r\n } else {\r\n otherIds = [...layerIds];\r\n }\r\n multipolygonIds = [];\r\n }\r\n }\r\n\r\n if (otherIds.length > 0) {\r\n const pendingIds = otherIds.filter(\r\n (layerId) => !layerIdsWithData.has(String(layerId))\r\n );\r\n const resolved = await Promise.all(\r\n pendingIds.map(async (layerId) => {\r\n const meta = metaIndex.get(String(layerId));\r\n const layerType = meta?.layerType;\r\n const totalFeatures = meta?.totalFeatures;\r\n const layerFilters = mergeLayerFilters(globalFilters, meta?.prefilters);\r\n const canUseIntersect =\r\n !!globalFilters && !shouldUseFilterMultiple(layerType) && !!aoi?.geometry;\r\n\r\n if (canUseIntersect) {\r\n const intersectionGeometry = aoi?.geometry;\r\n if (!intersectionGeometry) {\r\n pushWarning(\r\n buildSkipWarning(\r\n layerId,\r\n layerType,\r\n totalFeatures,\r\n 'no AOI geometry available'\r\n )\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n\r\n try {\r\n const response = await this.getLayerGeoJsonIntersect({\r\n id: layerId,\r\n geometry: intersectionGeometry,\r\n });\r\n if (aoi?.bbox) {\r\n console.debug(\r\n `Layer ${layerId} fetched by intersect using AOI bbox=${JSON.stringify(\r\n aoi.bbox\r\n )}`\r\n );\r\n } else {\r\n console.debug(`Layer ${layerId} fetched by intersect using AOI geometry`);\r\n }\r\n const geojson = response.data ?? createEmptyFeatureCollection();\r\n return {\r\n layerId,\r\n geojson: decorateFeaturesWithLayerId(geojson, layerId),\r\n };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n pushWarning(\r\n buildSkipWarning(\r\n layerId,\r\n layerType,\r\n totalFeatures,\r\n `intersect failed: ${message}`\r\n )\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n }\r\n\r\n if (layerFilters && (hasLayerMetas ? shouldUseFilterMultiple(layerType) : true)) {\r\n try {\r\n const response = await this.filterLayerFeatures(layerId, layerFilters);\r\n const geojson = response.data ?? createEmptyFeatureCollection();\r\n return {\r\n layerId,\r\n geojson: decorateFeaturesWithLayerId(geojson, layerId),\r\n };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n pushWarning(\r\n `Layer ${layerId} filter failed: ${message}`\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n }\r\n\r\n if (\r\n shouldSkipGeojsonDownload(layerType, totalFeatures, {\r\n maxFeatures: maxFeaturesFullGeojson,\r\n allowLargeGeojson,\r\n })\r\n ) {\r\n pushWarning(\r\n buildSkipWarning(\r\n layerId,\r\n layerType,\r\n totalFeatures,\r\n 'not supported by filter endpoint and too large for /geojson; use intersect with AOI'\r\n )\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n\r\n try {\r\n const response = await this.getLayerGeoJson(layerId);\r\n const geojson = response.data ?? createEmptyFeatureCollection();\r\n return {\r\n layerId,\r\n geojson: decorateFeaturesWithLayerId(geojson, layerId),\r\n };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : 'Unknown error';\r\n pushWarning(\r\n buildSkipWarning(layerId, layerType, totalFeatures, `error=${message}`)\r\n );\r\n return { layerId, geojson: createEmptyFeatureCollection() };\r\n }\r\n })\r\n );\r\n\r\n resolved.forEach(({ layerId, geojson }) => {\r\n perLayer[String(layerId)] = geojson;\r\n });\r\n }\r\n\r\n const mergedMetadata =\r\n warnings.length > 0\r\n ? {\r\n ...(metadata ?? {}),\r\n warnings: [...(metadata?.warnings ?? []), ...warnings],\r\n }\r\n : metadata;\r\n\r\n return { perLayer, metadata: mergedMetadata, aoi };\r\n }\r\n\r\n async getLayerGeoJsonBBox(\r\n request: GeoJsonBBoxRequest\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n const params = new URLSearchParams({\r\n minLon: String(request.bbox.minLon),\r\n minLat: String(request.bbox.minLat),\r\n maxLon: String(request.bbox.maxLon),\r\n maxLat: String(request.bbox.maxLat),\r\n });\r\n\r\n parseQueryParams(request).forEach((value, key) => params.set(key, value));\r\n\r\n const response = await this.httpClient.get<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${request.id}/geojson/bbox?${params.toString()}`\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerGeoJsonIntersect(\r\n request: GeoJsonIntersectRequest\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection>> {\r\n const params = parseQueryParams(request);\r\n const suffix = params.size > 0 ? `?${params.toString()}` : '';\r\n\r\n const response = await this.httpClient.post<ApiResponseData<GeoJsonFeatureCollection>>(\r\n `/layers/${request.id}/geojson/intersects${suffix}`,\r\n { geometry: request.geometry }\r\n );\r\n return this.unwrapResponse(response);\r\n }\r\n\r\n async getLayerTileTemplate(layerId: number | string): Promise<string> {\r\n const response = await this.httpClient.get<ApiResponseData<string | { template: string }>>(\r\n `/layers/${layerId}/tiles/template`\r\n );\r\n const unwrapped = this.unwrapResponse(response);\r\n if (typeof unwrapped.data === 'string') {\r\n return unwrapped.data;\r\n }\r\n if (unwrapped.data && typeof (unwrapped.data as { template?: string }).template === 'string') {\r\n return (unwrapped.data as { template: string }).template;\r\n }\r\n throw new Error('Invalid tile template response');\r\n }\r\n\r\n async loadLayerData(\r\n params: LoadLayerDataParams\r\n ): Promise<LoadLayerDataResult> {\r\n const { id, layerDetail, bbox, filterBBox, filteredGeoJSON, isVisible = true, ...options } = params;\r\n const resolution = resolveLayerStrategy({\r\n layerDetail,\r\n bbox,\r\n filterBBox,\r\n filteredGeoJSON,\r\n isVisible,\r\n maxFeaturesFullGeojson: params.maxFeaturesFullGeojson,\r\n allowLargeGeojson: params.allowLargeGeojson,\r\n });\r\n\r\n const response = await this.fetchByStrategy(id, resolution, options);\r\n\r\n const totalFeatures =\r\n asOptionalNumber(response.totalFeatures) ??\r\n asOptionalNumber(response.metadata?.totalFeatures) ??\r\n asOptionalNumber(layerDetail.totalFeatures);\r\n\r\n const limitedMessage =\r\n response.limitedMessage ?? buildLimitedMessage(response.metadata as LayerMetadata | undefined);\r\n\r\n return {\r\n geojson: response.data,\r\n strategy: resolution.strategy,\r\n limitedMessage,\r\n totalFeatures,\r\n metadata: response.metadata as LayerMetadata | undefined,\r\n };\r\n }\r\n\r\n async loadFilteredFeatures(params: {\r\n layerIds: Array<number | string>;\r\n filters: LayerFilters;\r\n }): Promise<{\r\n geojson: GeoJsonFeatureCollection;\r\n metadata?: FilterMultipleMetadata;\r\n totalFeatures?: number;\r\n }> {\r\n const response = await this.filterMultipleLayersFeatures(params);\r\n return {\r\n geojson: response.data,\r\n metadata: response.metadata,\r\n totalFeatures: response.metadata?.totalFeatures ?? response.totalFeatures,\r\n };\r\n }\r\n\r\n private async fetchByStrategy(\r\n layerId: number | string,\r\n resolution: ResolveLayerStrategyResult,\r\n options: GeoJsonRequestOptions\r\n ): Promise<ApiResponseData<GeoJsonFeatureCollection, LayerMetadata>> {\r\n switch (resolution.strategy) {\r\n case 'bbox': {\r\n if (!resolution.effectiveBBox) {\r\n throw new Error('Bounding box is required for bbox strategy');\r\n }\r\n return this.getLayerGeoJsonBBox({ id: layerId, bbox: resolution.effectiveBBox, ...options });\r\n }\r\n case 'intersect': {\r\n if (!resolution.intersectionGeometry) {\r\n throw new Error('Geometry is required for intersect strategy');\r\n }\r\n return this.getLayerGeoJsonIntersect({\r\n id: layerId,\r\n geometry: resolution.intersectionGeometry,\r\n ...options,\r\n });\r\n }\r\n case 'geojson':\r\n default:\r\n return this.getLayerGeoJson(layerId, options);\r\n }\r\n }\r\n\r\n private unwrapResponse<TData, TMetadata = LayerMetadata>(\r\n response: ApiResponseData<TData, TMetadata>\r\n ): ApiResponseData<TData, TMetadata> {\r\n if (!response || typeof response !== 'object' || !('data' in response)) {\r\n throw new Error('Invalid API response: missing data field');\r\n }\r\n if ('success' in response && response.success === false) {\r\n throw new Error(response.message ?? 'Request was not successful');\r\n }\r\n return response;\r\n }\r\n}\r\n","import { HttpClient, ZenitSdkError } from '../http/HttpClient';\r\nimport { ZenitAuthClient } from '../auth/ZenitAuthClient';\r\nimport { ZenitSdkAuthClient } from '../sdkAuth/ZenitSdkAuthClient';\r\nimport { ZenitMapsClient } from '../maps/ZenitMapsClient';\r\nimport { ZenitLayersClient } from '../layers/ZenitLayersClient';\r\n\r\nexport interface ZenitSdkConfig {\r\n // baseUrl: debe apuntar al prefijo de API de Zenit (ej: https://api.mi-zenit.com/api/v1).\r\n baseUrl: string;\r\n // sdkToken: token SDK que se puede validar o intercambiar por JWT.\r\n sdkToken?: string;\r\n // accessToken y refreshToken: tokens de usuario en caso de que el integrador ya los tenga (opcional).\r\n accessToken?: string;\r\n refreshToken?: string;\r\n // onAuthError: callback para manejar errores de login.\r\n onAuthError?(error: ZenitSdkError): void;\r\n // onTokenRefreshed: callback para actualizar tokens en el cliente que consuma el SDK.\r\n onTokenRefreshed?(tokens: { accessToken: string; refreshToken?: string }): void;\r\n}\r\n\r\nexport class ZenitClient {\r\n private accessToken?: string;\r\n private refreshToken?: string;\r\n private sdkToken?: string;\r\n private readonly httpClient: HttpClient;\r\n\r\n readonly auth: ZenitAuthClient;\r\n readonly sdkAuth: ZenitSdkAuthClient;\r\n readonly maps: ZenitMapsClient;\r\n readonly layers: ZenitLayersClient;\r\n\r\n constructor(private readonly config: ZenitSdkConfig) {\r\n this.accessToken = config.accessToken;\r\n this.refreshToken = config.refreshToken;\r\n this.sdkToken = config.sdkToken;\r\n this.httpClient = new HttpClient({\r\n baseUrl: config.baseUrl,\r\n resolveTokens: () => ({ accessToken: this.accessToken, sdkToken: this.sdkToken }),\r\n resolveAuthorizationHeader: this.getAuthorizationHeader.bind(this)\r\n });\r\n\r\n this.auth = new ZenitAuthClient(this.httpClient, this.updateTokens.bind(this), config);\r\n this.sdkAuth = new ZenitSdkAuthClient(\r\n this.httpClient,\r\n this.updateAccessTokenFromSdkExchange.bind(this),\r\n config\r\n );\r\n this.maps = new ZenitMapsClient(this.httpClient);\r\n this.layers = new ZenitLayersClient(this.httpClient);\r\n }\r\n\r\n /**\r\n * Update tokens in memory and propagate to config callbacks.\r\n */\r\n private updateTokens(tokens: { accessToken?: string; refreshToken?: string }) {\r\n if (tokens.accessToken) {\r\n this.setAccessToken(tokens.accessToken);\r\n }\r\n if (tokens.refreshToken) {\r\n this.setRefreshToken(tokens.refreshToken);\r\n }\r\n this.config.onTokenRefreshed?.({\r\n accessToken: this.accessToken || '',\r\n refreshToken: this.refreshToken\r\n });\r\n }\r\n\r\n // Se usa cuando /sdk-auth/exchange devuelve un accessToken; pasa a ser el accessToken principal del SDK.\r\n private updateAccessTokenFromSdkExchange(token?: string) {\r\n if (token) {\r\n this.setAccessToken(token);\r\n }\r\n }\r\n\r\n setAccessToken(token: string) {\r\n this.accessToken = token;\r\n this.config.accessToken = token;\r\n }\r\n\r\n setRefreshToken(token: string) {\r\n this.refreshToken = token;\r\n this.config.refreshToken = token;\r\n }\r\n\r\n getAuthorizationHeader(): Record<string, string> {\r\n const header: Record<string, string> = {};\r\n\r\n if (this.accessToken) {\r\n header.Authorization = `Bearer ${this.accessToken}`;\r\n }\r\n\r\n return header;\r\n }\r\n\r\n getHttpClient(): HttpClient {\r\n return this.httpClient;\r\n }\r\n}\r\n","import type { Bbox, GeoJsonPolygon, GeoJsonRequestOptions, LayerFilters } from '../layers/types';\r\n\r\nexport type FilterEngineRequest =\r\n | {\r\n type: 'filter-multiple';\r\n layerIds: Array<number | string>;\r\n filters: LayerFilters;\r\n }\r\n | {\r\n type: 'filter-layer';\r\n layerId: number | string;\r\n filters: LayerFilters;\r\n }\r\n | {\r\n type: 'geojson';\r\n layerId: number | string;\r\n options?: GeoJsonRequestOptions;\r\n }\r\n | {\r\n type: 'bbox';\r\n layerId: number | string;\r\n bbox: Bbox;\r\n options?: GeoJsonRequestOptions;\r\n }\r\n | {\r\n type: 'intersect';\r\n layerId: number | string;\r\n geometry: GeoJsonPolygon;\r\n options?: GeoJsonRequestOptions;\r\n };\r\n\r\nexport interface FilterEngineDecision {\r\n nextRequest: FilterEngineRequest;\r\n reason?: string;\r\n}\r\n\r\nexport interface FilterEngineParams {\r\n layerIds?: Array<number | string>;\r\n layerId?: number | string;\r\n filters?: LayerFilters;\r\n bbox?: Bbox;\r\n geometry?: GeoJsonPolygon;\r\n options?: GeoJsonRequestOptions;\r\n request?: FilterEngineRequest;\r\n}\r\n\r\nexport class FilterEngine {\r\n decide(params: FilterEngineParams): FilterEngineDecision {\r\n if (params.request) {\r\n return { nextRequest: params.request };\r\n }\r\n\r\n if (params.filters && params.layerIds && params.layerIds.length > 1) {\r\n return {\r\n nextRequest: {\r\n type: 'filter-multiple',\r\n layerIds: params.layerIds,\r\n filters: params.filters,\r\n },\r\n reason: 'filters+layerIds',\r\n };\r\n }\r\n\r\n if (params.filters && params.layerId !== undefined) {\r\n return {\r\n nextRequest: {\r\n type: 'filter-layer',\r\n layerId: params.layerId,\r\n filters: params.filters,\r\n },\r\n reason: 'filters+layerId',\r\n };\r\n }\r\n\r\n if (params.bbox && params.layerId !== undefined) {\r\n return {\r\n nextRequest: {\r\n type: 'bbox',\r\n layerId: params.layerId,\r\n bbox: params.bbox,\r\n options: params.options,\r\n },\r\n reason: 'bbox+layerId',\r\n };\r\n }\r\n\r\n if (params.geometry && params.layerId !== undefined) {\r\n return {\r\n nextRequest: {\r\n type: 'intersect',\r\n layerId: params.layerId,\r\n geometry: params.geometry,\r\n options: params.options,\r\n },\r\n reason: 'geometry+layerId',\r\n };\r\n }\r\n\r\n if (params.layerId !== undefined) {\r\n return {\r\n nextRequest: {\r\n type: 'geojson',\r\n layerId: params.layerId,\r\n options: params.options,\r\n },\r\n reason: 'layerId',\r\n };\r\n }\r\n\r\n throw new Error('FilterEngine could not resolve a next request');\r\n }\r\n}\r\n\r\nexport const filterEngine = new FilterEngine();\r\n","import type { Bbox } from '../layers/types';\r\n\r\n/**\r\n * Normalizes a bbox input to a standard Bbox object format.\r\n *\r\n * Accepts:\r\n * - Array tuple: [minLon, minLat, maxLon, maxLat]\r\n * - Object: { minLon, minLat, maxLon, maxLat }\r\n *\r\n * Returns:\r\n * - A valid Bbox object with { minLon, minLat, maxLon, maxLat }\r\n * - null if the input is invalid or contains non-finite numbers\r\n *\r\n * @param input - The bbox to normalize (can be array or object)\r\n * @returns A normalized Bbox object or null if invalid\r\n */\r\nexport function normalizeBbox(\r\n input: unknown\r\n): Bbox | null {\r\n if (!input) return null;\r\n\r\n // Case 1: Array tuple [minLon, minLat, maxLon, maxLat]\r\n if (Array.isArray(input)) {\r\n if (input.length !== 4) {\r\n console.warn('[normalizeBbox] Array must have exactly 4 elements, got:', input.length);\r\n return null;\r\n }\r\n\r\n const [minLon, minLat, maxLon, maxLat] = input;\r\n\r\n // Validate all are finite numbers\r\n if (\r\n typeof minLon !== 'number' ||\r\n typeof minLat !== 'number' ||\r\n typeof maxLon !== 'number' ||\r\n typeof maxLat !== 'number' ||\r\n !Number.isFinite(minLon) ||\r\n !Number.isFinite(minLat) ||\r\n !Number.isFinite(maxLon) ||\r\n !Number.isFinite(maxLat)\r\n ) {\r\n console.warn('[normalizeBbox] Array contains non-finite numbers:', input);\r\n return null;\r\n }\r\n\r\n // Validate min < max\r\n if (minLon >= maxLon || minLat >= maxLat) {\r\n console.warn('[normalizeBbox] Invalid bbox: min must be < max', {\r\n minLon,\r\n maxLon,\r\n minLat,\r\n maxLat,\r\n });\r\n return null;\r\n }\r\n\r\n return { minLon, minLat, maxLon, maxLat };\r\n }\r\n\r\n // Case 2: Object with keys { minLon, minLat, maxLon, maxLat }\r\n if (typeof input === 'object') {\r\n const candidate = input as Partial<Bbox>;\r\n\r\n const { minLon, minLat, maxLon, maxLat } = candidate;\r\n\r\n // Validate all keys exist and are finite numbers\r\n if (\r\n typeof minLon !== 'number' ||\r\n typeof minLat !== 'number' ||\r\n typeof maxLon !== 'number' ||\r\n typeof maxLat !== 'number' ||\r\n !Number.isFinite(minLon) ||\r\n !Number.isFinite(minLat) ||\r\n !Number.isFinite(maxLon) ||\r\n !Number.isFinite(maxLat)\r\n ) {\r\n console.warn('[normalizeBbox] Object missing valid bbox keys or contains non-finite numbers:', input);\r\n return null;\r\n }\r\n\r\n // Validate min < max\r\n if (minLon >= maxLon || minLat >= maxLat) {\r\n console.warn('[normalizeBbox] Invalid bbox: min must be < max', {\r\n minLon,\r\n maxLon,\r\n minLat,\r\n maxLat,\r\n });\r\n return null;\r\n }\r\n\r\n return { minLon, minLat, maxLon, maxLat };\r\n }\r\n\r\n console.warn('[normalizeBbox] Unsupported bbox format:', typeof input);\r\n return null;\r\n}\r\n"],"mappings":"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","names":["serialized"]}