@ignfab/geocontext 0.9.5 → 0.9.7

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.
Files changed (128) hide show
  1. package/README.md +349 -259
  2. package/dist/gpf/adminexpress.d.ts +17 -8
  3. package/dist/gpf/adminexpress.js +40 -17
  4. package/dist/gpf/adminexpress.js.map +1 -1
  5. package/dist/gpf/altitude.d.ts +21 -9
  6. package/dist/gpf/altitude.js +5 -5
  7. package/dist/gpf/altitude.js.map +1 -1
  8. package/dist/gpf/geocode.d.ts +25 -4
  9. package/dist/gpf/geocode.js +5 -5
  10. package/dist/gpf/geocode.js.map +1 -1
  11. package/dist/gpf/parcellaire-express.d.ts +19 -9
  12. package/dist/gpf/parcellaire-express.js +59 -26
  13. package/dist/gpf/parcellaire-express.js.map +1 -1
  14. package/dist/gpf/urbanisme.d.ts +24 -16
  15. package/dist/gpf/urbanisme.js +81 -33
  16. package/dist/gpf/urbanisme.js.map +1 -1
  17. package/dist/gpf/{wfs.js → wfs-schema-catalog.js} +1 -1
  18. package/dist/gpf/wfs-schema-catalog.js.map +1 -0
  19. package/dist/helpers/RateLimiter.d.ts +44 -0
  20. package/dist/helpers/RateLimiter.js +52 -0
  21. package/dist/helpers/RateLimiter.js.map +1 -0
  22. package/dist/helpers/distance.d.ts +2 -1
  23. package/dist/helpers/distance.js +2 -1
  24. package/dist/helpers/distance.js.map +1 -1
  25. package/dist/helpers/errors/toolError.d.ts +30 -0
  26. package/dist/helpers/errors/toolError.js +193 -0
  27. package/dist/helpers/errors/toolError.js.map +1 -0
  28. package/dist/helpers/errors/zodErrorMapFr.d.ts +20 -0
  29. package/dist/helpers/errors/zodErrorMapFr.js +191 -0
  30. package/dist/helpers/errors/zodErrorMapFr.js.map +1 -0
  31. package/dist/helpers/http.d.ts +67 -7
  32. package/dist/helpers/http.js +458 -84
  33. package/dist/helpers/http.js.map +1 -1
  34. package/dist/helpers/jsonSchema.d.ts +20 -2
  35. package/dist/helpers/jsonSchema.js +12 -0
  36. package/dist/helpers/jsonSchema.js.map +1 -1
  37. package/dist/helpers/schemas.d.ts +4 -4
  38. package/dist/helpers/wfs_engine/attributeFilter.d.ts +51 -0
  39. package/dist/helpers/wfs_engine/attributeFilter.js +258 -0
  40. package/dist/helpers/wfs_engine/attributeFilter.js.map +1 -0
  41. package/dist/helpers/wfs_engine/byId.d.ts +76 -0
  42. package/dist/helpers/wfs_engine/byId.js +106 -0
  43. package/dist/helpers/wfs_engine/byId.js.map +1 -0
  44. package/dist/helpers/wfs_engine/execution.d.ts +72 -0
  45. package/dist/helpers/wfs_engine/execution.js +95 -0
  46. package/dist/helpers/wfs_engine/execution.js.map +1 -0
  47. package/dist/helpers/wfs_engine/features.d.ts +64 -0
  48. package/dist/helpers/wfs_engine/features.js +138 -0
  49. package/dist/helpers/wfs_engine/features.js.map +1 -0
  50. package/dist/helpers/wfs_engine/geometry.d.ts +16 -0
  51. package/dist/helpers/wfs_engine/geometry.js +44 -0
  52. package/dist/helpers/wfs_engine/geometry.js.map +1 -0
  53. package/dist/helpers/wfs_engine/properties.d.ts +51 -0
  54. package/dist/helpers/wfs_engine/properties.js +128 -0
  55. package/dist/helpers/wfs_engine/properties.js.map +1 -0
  56. package/dist/helpers/wfs_engine/queryPreparation.d.ts +32 -0
  57. package/dist/helpers/wfs_engine/queryPreparation.js +149 -0
  58. package/dist/helpers/wfs_engine/queryPreparation.js.map +1 -0
  59. package/dist/helpers/wfs_engine/request.d.ts +94 -0
  60. package/dist/helpers/wfs_engine/request.js +197 -0
  61. package/dist/helpers/wfs_engine/request.js.map +1 -0
  62. package/dist/helpers/wfs_engine/response.d.ts +80 -0
  63. package/dist/helpers/wfs_engine/response.js +135 -0
  64. package/dist/helpers/wfs_engine/response.js.map +1 -0
  65. package/dist/helpers/wfs_engine/schema.d.ts +209 -0
  66. package/dist/helpers/{wfs_internal → wfs_engine}/schema.js +50 -10
  67. package/dist/helpers/wfs_engine/schema.js.map +1 -0
  68. package/dist/helpers/wfs_engine/spatialCql.d.ts +46 -0
  69. package/dist/helpers/wfs_engine/spatialCql.js +54 -0
  70. package/dist/helpers/wfs_engine/spatialCql.js.map +1 -0
  71. package/dist/helpers/wfs_engine/spatialFilter.d.ts +14 -0
  72. package/dist/helpers/wfs_engine/spatialFilter.js +131 -0
  73. package/dist/helpers/wfs_engine/spatialFilter.js.map +1 -0
  74. package/dist/index.js +65 -23
  75. package/dist/index.js.map +1 -1
  76. package/dist/logger.d.ts +1 -1
  77. package/dist/logger.js +4 -1
  78. package/dist/logger.js.map +1 -1
  79. package/dist/tools/AdminexpressTool.d.ts +42 -33
  80. package/dist/tools/AdminexpressTool.js +19 -3
  81. package/dist/tools/AdminexpressTool.js.map +1 -1
  82. package/dist/tools/AltitudeTool.d.ts +35 -44
  83. package/dist/tools/AltitudeTool.js +19 -8
  84. package/dist/tools/AltitudeTool.js.map +1 -1
  85. package/dist/tools/AssietteSupTool.d.ts +51 -34
  86. package/dist/tools/AssietteSupTool.js +18 -2
  87. package/dist/tools/AssietteSupTool.js.map +1 -1
  88. package/dist/tools/BaseTool.d.ts +17 -0
  89. package/dist/tools/BaseTool.js +41 -0
  90. package/dist/tools/BaseTool.js.map +1 -0
  91. package/dist/tools/CadastreTool.d.ts +53 -33
  92. package/dist/tools/CadastreTool.js +18 -2
  93. package/dist/tools/CadastreTool.js.map +1 -1
  94. package/dist/tools/GeocodeTool.d.ts +53 -37
  95. package/dist/tools/GeocodeTool.js +17 -2
  96. package/dist/tools/GeocodeTool.js.map +1 -1
  97. package/dist/tools/GpfWfsDescribeTypeTool.d.ts +66 -94
  98. package/dist/tools/GpfWfsDescribeTypeTool.js +26 -15
  99. package/dist/tools/GpfWfsDescribeTypeTool.js.map +1 -1
  100. package/dist/tools/GpfWfsGetFeatureByIdTool.d.ts +89 -0
  101. package/dist/tools/GpfWfsGetFeatureByIdTool.js +99 -0
  102. package/dist/tools/GpfWfsGetFeatureByIdTool.js.map +1 -0
  103. package/dist/tools/GpfWfsGetFeaturesTool.d.ts +89 -123
  104. package/dist/tools/GpfWfsGetFeaturesTool.js +31 -144
  105. package/dist/tools/GpfWfsGetFeaturesTool.js.map +1 -1
  106. package/dist/tools/GpfWfsSearchTypesTool.d.ts +41 -32
  107. package/dist/tools/GpfWfsSearchTypesTool.js +18 -3
  108. package/dist/tools/GpfWfsSearchTypesTool.js.map +1 -1
  109. package/dist/tools/UrbanismeTool.d.ts +42 -33
  110. package/dist/tools/UrbanismeTool.js +18 -2
  111. package/dist/tools/UrbanismeTool.js.map +1 -1
  112. package/package.json +51 -24
  113. package/dist/gpf/wfs.js.map +0 -1
  114. package/dist/helpers/wfs.d.ts +0 -27
  115. package/dist/helpers/wfs.js +0 -55
  116. package/dist/helpers/wfs.js.map +0 -1
  117. package/dist/helpers/wfs_internal/compile.d.ts +0 -46
  118. package/dist/helpers/wfs_internal/compile.js +0 -595
  119. package/dist/helpers/wfs_internal/compile.js.map +0 -1
  120. package/dist/helpers/wfs_internal/request.d.ts +0 -38
  121. package/dist/helpers/wfs_internal/request.js +0 -92
  122. package/dist/helpers/wfs_internal/request.js.map +0 -1
  123. package/dist/helpers/wfs_internal/response.d.ts +0 -21
  124. package/dist/helpers/wfs_internal/response.js +0 -29
  125. package/dist/helpers/wfs_internal/response.js.map +0 -1
  126. package/dist/helpers/wfs_internal/schema.d.ts +0 -167
  127. package/dist/helpers/wfs_internal/schema.js.map +0 -1
  128. /package/dist/gpf/{wfs.d.ts → wfs-schema-catalog.d.ts} +0 -0
@@ -1,16 +1,25 @@
1
1
  /**
2
- * Get administrative units (commune, departement,...) intersecting a given location
2
+ * Administrative units lookup via the Géoplateforme WFS service.
3
3
  *
4
- * @param {number} lon
5
- * @param {number} lat
6
- * @param {(url: string) => Promise<any>} [fetcher]
7
- * @returns {object[]}
4
+ * This module uses the structured WFS engine for request execution and
5
+ * response mapping, resolving geometry property names dynamically from
6
+ * the embedded catalog.
8
7
  */
9
- export function getAdminUnits(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): object[];
8
+ import { type FlatItem } from '../helpers/wfs_engine/response.js';
9
+ type AdminUnit = FlatItem;
10
10
  /**
11
11
  * ADMINEXPRESS-COG.LATEST:{type}
12
12
  *
13
13
  * https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
14
14
  */
15
- export const ADMINEXPRESS_SOURCE: "G\u00E9oplateforme (WFS, ADMINEXPRESS-COG.LATEST)";
16
- export const ADMINEXPRESS_TYPES: string[];
15
+ export declare const ADMINEXPRESS_SOURCE = "G\u00E9oplateforme (WFS, ADMINEXPRESS-COG.LATEST)";
16
+ export declare const ADMINEXPRESS_TYPES: string[];
17
+ /**
18
+ * Get administrative units (commune, departement,...) intersecting a given location.
19
+ *
20
+ * @param lon Longitude of the query point.
21
+ * @param lat Latitude of the query point.
22
+ * @returns Administrative units covering the requested point.
23
+ */
24
+ export declare function getAdminUnits(lon: number, lat: number): Promise<AdminUnit[]>;
25
+ export {};
@@ -1,5 +1,16 @@
1
- import { fetchWfsFeatures, mapWfsFeature } from '../helpers/wfs.js';
1
+ /**
2
+ * Administrative units lookup via the Géoplateforme WFS service.
3
+ *
4
+ * This module uses the structured WFS engine for request execution and
5
+ * response mapping, resolving geometry property names dynamically from
6
+ * the embedded catalog.
7
+ */
2
8
  import logger from '../logger.js';
9
+ import { getFeatureType } from '../helpers/wfs_engine/execution.js';
10
+ import { fetchWfsMultiTypename } from '../helpers/wfs_engine/execution.js';
11
+ import { getGeometryProperty } from '../helpers/wfs_engine/properties.js';
12
+ import { compileIntersectsPointSpatialFilter } from '../helpers/wfs_engine/spatialCql.js';
13
+ import { mapToFlatItems } from '../helpers/wfs_engine/response.js';
3
14
  /**
4
15
  * ADMINEXPRESS-COG.LATEST:{type}
5
16
  *
@@ -7,28 +18,40 @@ import logger from '../logger.js';
7
18
  */
8
19
  export const ADMINEXPRESS_SOURCE = "Géoplateforme (WFS, ADMINEXPRESS-COG.LATEST)";
9
20
  export const ADMINEXPRESS_TYPES = [
10
- 'commune',
21
+ 'arrondissement',
22
+ 'arrondissement_municipal',
11
23
  'canton',
12
24
  'collectivite_territoriale',
13
- 'epci',
25
+ 'commune',
26
+ 'commune_associee_ou_deleguee',
14
27
  'departement',
15
- 'region',
16
- 'arrondissement'
28
+ 'epci',
29
+ 'region'
17
30
  ];
31
+ const ADMINEXPRESS_TYPENAMES = ADMINEXPRESS_TYPES.map((type) => `ADMINEXPRESS-COG.LATEST:${type}`);
18
32
  /**
19
- * Get administrative units (commune, departement,...) intersecting a given location
33
+ * Get administrative units (commune, departement,...) intersecting a given location.
20
34
  *
21
- * @param {number} lon
22
- * @param {number} lat
23
- * @param {(url: string) => Promise<any>} [fetcher]
24
- * @returns {object[]}
35
+ * @param lon Longitude of the query point.
36
+ * @param lat Latitude of the query point.
37
+ * @returns Administrative units covering the requested point.
25
38
  */
26
- export async function getAdminUnits(lon, lat, fetcher) {
27
- logger.info(`[adminexpress] getAdminUnits(${lon},${lat})...`);
28
- // Using EWKT format with SRID=4326 prefix for standard lon,lat order
29
- const cql_filter = `INTERSECTS(geometrie,SRID=4326;POINT(${lon} ${lat}))`;
30
- const typeNames = ADMINEXPRESS_TYPES.map((type) => `ADMINEXPRESS-COG.LATEST:${type}`);
31
- const features = await fetchWfsFeatures(typeNames, cql_filter, 'ADMINEXPRESS', fetcher);
32
- return features.map((feature) => mapWfsFeature(feature, typeNames));
39
+ export async function getAdminUnits(lon, lat) {
40
+ logger.debug(`[gpf:adminexpress] getAdminUnits(${lon},${lat})...`);
41
+ const spatialFilter = { operator: "intersects_point", lon, lat };
42
+ // Resolve and compile one spatial filter per typename to avoid relying on
43
+ // cross-layer geometry property homogeneity.
44
+ const cqlFilters = await Promise.all(ADMINEXPRESS_TYPENAMES.map(async (typename) => {
45
+ const featureType = await getFeatureType(typename);
46
+ const geometryProperty = getGeometryProperty(featureType);
47
+ return compileIntersectsPointSpatialFilter(geometryProperty, spatialFilter);
48
+ }));
49
+ // Execute the multi-typename WFS query
50
+ const featureCollection = await fetchWfsMultiTypename({
51
+ typenames: ADMINEXPRESS_TYPENAMES,
52
+ cqlFilters,
53
+ errorLabel: 'ADMINEXPRESS',
54
+ });
55
+ return mapToFlatItems(featureCollection, ADMINEXPRESS_TYPENAMES);
33
56
  }
34
57
  //# sourceMappingURL=adminexpress.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adminexpress.js","sourceRoot":"","sources":["../../src/gpf/adminexpress.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,8CAA8C,CAAC;AAClF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAC9B,SAAS;IACT,QAAQ;IACR,2BAA2B;IAC3B,MAAM;IACN,aAAa;IACb,QAAQ;IACR,gBAAgB;CACnB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO;IACjD,MAAM,CAAC,IAAI,CAAC,gCAAgC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAE9D,qEAAqE;IACrE,MAAM,UAAU,GAAG,wCAAwC,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1E,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;IAEtF,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IACxF,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"adminexpress.js","sourceRoot":"","sources":["../../src/gpf/adminexpress.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,mCAAmC,EAAE,MAAM,qCAAqC,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAiB,MAAM,mCAAmC,CAAC;AAMlF;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,8CAA8C,CAAC;AAClF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAC9B,gBAAgB;IAChB,0BAA0B;IAC1B,QAAQ;IACR,2BAA2B;IAC3B,SAAS;IACT,8BAA8B;IAC9B,aAAa;IACb,MAAM;IACN,QAAQ;CACX,CAAC;AAEF,MAAM,sBAAsB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;AAEnG;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,GAAW;IACxD,MAAM,CAAC,KAAK,CAAC,oCAAoC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAEnE,MAAM,aAAa,GAAkB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IAEhF,0EAA0E;IAC1E,6CAA6C;IAC7C,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC/E,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC1D,OAAO,mCAAmC,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC,CAAC;IAEJ,uCAAuC;IACvC,MAAM,iBAAiB,GAAiC,MAAM,qBAAqB,CAAC;QAChF,SAAS,EAAE,sBAAsB;QACjC,UAAU;QACV,UAAU,EAAE,cAAc;KAC7B,CAAC,CAAC;IAEH,OAAO,cAAc,CAAC,iBAAiB,EAAE,sBAAsB,CAAC,CAAC;AACrE,CAAC"}
@@ -1,3 +1,20 @@
1
+ import type { JsonFetcher } from "../helpers/http.js";
2
+ export declare const ALTITUDE_SOURCE = "G\u00E9oplateforme (altim\u00E9trie)";
3
+ type RawElevation = {
4
+ lon: number;
5
+ lat: number;
6
+ z: number;
7
+ acc: string;
8
+ };
9
+ type RawAltitudeResponse = {
10
+ elevations?: RawElevation[];
11
+ };
12
+ type AltitudeResult = {
13
+ lon: number;
14
+ lat: number;
15
+ altitude: number;
16
+ accuracy: string;
17
+ };
1
18
  /**
2
19
  * Get altitude for a given location.
3
20
  *
@@ -5,13 +22,8 @@
5
22
  *
6
23
  * @param {number} lon
7
24
  * @param {number} lat
8
- * @param {(url: string) => Promise<any>} [fetcher]
9
- * @returns
25
+ * @param {JsonFetcher<RawAltitudeResponse>} [fetcher] - optional custom fetcher function
26
+ * @returns {Promise<AltitudeResult>}
10
27
  */
11
- export function getAltitudeByLocation(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<{
12
- lon: number;
13
- lat: number;
14
- altitude: any;
15
- accuracy: any;
16
- }>;
17
- export const ALTITUDE_SOURCE: "G\u00E9oplateforme (altim\u00E9trie)";
28
+ export declare function getAltitudeByLocation(lon: number, lat: number, fetcher?: JsonFetcher<RawAltitudeResponse>): Promise<AltitudeResult>;
29
+ export {};
@@ -1,4 +1,4 @@
1
- import { fetchJSON } from "../helpers/http.js";
1
+ import { fetchJSONGet } from "../helpers/http.js";
2
2
  import logger from "../logger.js";
3
3
  export const ALTITUDE_SOURCE = "Géoplateforme (altimétrie)";
4
4
  /**
@@ -8,11 +8,11 @@ export const ALTITUDE_SOURCE = "Géoplateforme (altimétrie)";
8
8
  *
9
9
  * @param {number} lon
10
10
  * @param {number} lat
11
- * @param {(url: string) => Promise<any>} [fetcher]
12
- * @returns
11
+ * @param {JsonFetcher<RawAltitudeResponse>} [fetcher] - optional custom fetcher function
12
+ * @returns {Promise<AltitudeResult>}
13
13
  */
14
- export async function getAltitudeByLocation(lon, lat, fetcher = fetchJSON) {
15
- logger.info(`getAltitudeByLocation(${lon},${lat})...`);
14
+ export async function getAltitudeByLocation(lon, lat, fetcher = fetchJSONGet) {
15
+ logger.debug(`[gpf:altitude] getAltitudeByLocation(${lon},${lat})...`);
16
16
  const url = `https://data.geopf.fr/altimetrie/1.0/calcul/alti/rest/elevation.json?lon=${lon}&lat=${lat}&resource=ign_rge_alti_wld`;
17
17
  const json = await fetcher(url);
18
18
  const elevation = json?.elevations?.[0];
@@ -1 +1 @@
1
- {"version":3,"file":"altitude.js","sourceRoot":"","sources":["../../src/gpf/altitude.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,MAAM,CAAC,MAAM,eAAe,GAAG,4BAA4B,CAAC;AAE5D;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,GAAG,SAAS;IACrE,MAAM,CAAC,IAAI,CAAC,yBAAyB,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAEvD,MAAM,GAAG,GAAG,4EAA4E,GAAG,QAAQ,GAAG,4BAA4B,CAAC;IAEnI,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;IAExC,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAClF,CAAC;IAED,OAAO;QACH,GAAG,EAAE,GAAG;QACR,GAAG,EAAE,GAAG;QACR,QAAQ,EAAE,SAAS,CAAC,CAAC;QACrB,QAAQ,EAAE,SAAS,CAAC,GAAG;KAC1B,CAAC;AAEN,CAAC"}
1
+ {"version":3,"file":"altitude.js","sourceRoot":"","sources":["../../src/gpf/altitude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,MAAM,CAAC,MAAM,eAAe,GAAG,4BAA4B,CAAC;AAoB5D;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAW,EAAE,GAAW,EAAE,UAA4C,YAAY;IAC1H,MAAM,CAAC,KAAK,CAAC,wCAAwC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAEvE,MAAM,GAAG,GAAG,4EAA4E,GAAG,QAAQ,GAAG,4BAA4B,CAAC;IAEnI,MAAM,IAAI,GAAwB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;IAExC,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAClF,CAAC;IAED,OAAO;QACH,GAAG,EAAE,GAAG;QACR,GAAG,EAAE,GAAG;QACR,QAAQ,EAAE,SAAS,CAAC,CAAC;QACrB,QAAQ,EAAE,SAAS,CAAC,GAAG;KAC1B,CAAC;AAEN,CAAC"}
@@ -1,3 +1,24 @@
1
+ import type { JsonFetcher } from "../helpers/http.js";
2
+ export declare const GEOCODE_SOURCE = "G\u00E9oplateforme (service d'autocompl\u00E9tion)";
3
+ type RawGeocodeResult = {
4
+ x: number;
5
+ y: number;
6
+ fulltext: string;
7
+ kind: string;
8
+ city: string;
9
+ zipcode: string;
10
+ };
11
+ type GeocodeResult = {
12
+ lon: number;
13
+ lat: number;
14
+ fulltext: string;
15
+ kind: string;
16
+ city: string;
17
+ zipcode: string;
18
+ };
19
+ type RawGeocodeResponse = {
20
+ results?: RawGeocodeResult[];
21
+ };
1
22
  /**
2
23
  * Get coordinates for a given location
3
24
  *
@@ -5,8 +26,8 @@
5
26
  *
6
27
  * @param {string} text
7
28
  * @param {number} [maximumResponses=3]
8
- * @param {(url: string) => Promise<any>} [fetcher]
9
- * @returns
29
+ * @param {JsonFetcher<RawGeocodeResponse>} [fetcher] - optional custom fetcher function
30
+ * @returns {Promise<GeocodeResult[]>}
10
31
  */
11
- export function geocode(text: string, maximumResponses?: number, fetcher?: (url: string) => Promise<any>): Promise<any>;
12
- export const GEOCODE_SOURCE: "G\u00E9oplateforme (service d'autocompl\u00E9tion)";
32
+ export declare function geocode(text: string, maximumResponses?: number, fetcher?: JsonFetcher<RawGeocodeResponse>): Promise<GeocodeResult[]>;
33
+ export {};
@@ -1,4 +1,4 @@
1
- import { fetchJSON } from "../helpers/http.js";
1
+ import { fetchJSONGet } from "../helpers/http.js";
2
2
  import logger from "../logger.js";
3
3
  export const GEOCODE_SOURCE = "Géoplateforme (service d'autocomplétion)";
4
4
  // https://data.geopf.fr/geocodage/completion/openapi does not provide all the necessary information yet
@@ -9,15 +9,15 @@ export const GEOCODE_SOURCE = "Géoplateforme (service d'autocomplétion)";
9
9
  *
10
10
  * @param {string} text
11
11
  * @param {number} [maximumResponses=3]
12
- * @param {(url: string) => Promise<any>} [fetcher]
13
- * @returns
12
+ * @param {JsonFetcher<RawGeocodeResponse>} [fetcher] - optional custom fetcher function
13
+ * @returns {Promise<GeocodeResult[]>}
14
14
  */
15
- export async function geocode(text, maximumResponses = 3, fetcher = fetchJSON) {
15
+ export async function geocode(text, maximumResponses = 3, fetcher = fetchJSONGet) {
16
16
  const normalizedText = typeof text === "string" ? text.trim() : "";
17
17
  if (!normalizedText) {
18
18
  return [];
19
19
  }
20
- logger.info(`geocode(${JSON.stringify(normalizedText)}, ${maximumResponses})...`);
20
+ logger.debug(`[gpf:geocode] geocode(${JSON.stringify(normalizedText)}, ${maximumResponses})...`);
21
21
  const url = 'https://data.geopf.fr/geocodage/completion/?' + new URLSearchParams({
22
22
  text: normalizedText,
23
23
  maximumResponses: String(maximumResponses)
@@ -1 +1 @@
1
- {"version":3,"file":"geocode.js","sourceRoot":"","sources":["../../src/gpf/geocode.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,MAAM,CAAC,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAEzE,wGAAwG;AAExG;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAI,EAAE,gBAAgB,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS;IACzE,MAAM,cAAc,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,KAAK,gBAAgB,MAAM,CAAC,CAAC;IAElF,MAAM,GAAG,GAAG,8CAA8C,GAAG,IAAI,eAAe,CAAC;QAC/E,IAAI,EAAE,cAAc;QACpB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,CAAC;KAC3C,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAC,EAAE;QAAC,OAAO;YACjC,GAAG,EAAE,IAAI,CAAC,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,CAAC;YACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAA;IAAA,CAAC,CAAC,CAAC;AACR,CAAC"}
1
+ {"version":3,"file":"geocode.js","sourceRoot":"","sources":["../../src/gpf/geocode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,MAAM,CAAC,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAwBzE,wGAAwG;AAExG;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,gBAAgB,GAAG,CAAC,EAAE,UAA2C,YAAY;IACrH,MAAM,cAAc,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnE,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,yBAAyB,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,KAAK,gBAAgB,MAAM,CAAC,CAAC;IAEjG,MAAM,GAAG,GAAG,8CAA8C,GAAG,IAAI,eAAe,CAAC;QAC/E,IAAI,EAAE,cAAc;QACpB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,CAAC;KAC3C,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,MAAM,IAAI,GAAuB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAC,EAAE;QAAC,OAAO;YACjC,GAAG,EAAE,IAAI,CAAC,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,CAAC;YACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAA;IAAA,CAAC,CAAC,CAAC;AACR,CAAC"}
@@ -1,13 +1,23 @@
1
1
  /**
2
- * Get items from CADASTRALPARCELS.PARCELLAIRE_EXPRESS near of a given location.
2
+ * Cadastral objects lookup via the Géoplateforme WFS service.
3
3
  *
4
- * @see https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
4
+ * This module uses the structured WFS engine for request execution and
5
+ * response mapping, resolving geometry property names dynamically from
6
+ * the embedded catalog.
7
+ */
8
+ import { type FlatItem } from '../helpers/wfs_engine/response.js';
9
+ type ParcellaireExpressItem = FlatItem & {
10
+ distance: number;
11
+ source: string;
12
+ };
13
+ export declare const PARCELLAIRE_EXPRESS_SOURCE = "G\u00E9oplateforme (WFS, CADASTRALPARCELS.PARCELLAIRE_EXPRESS)";
14
+ export declare const PARCELLAIRE_EXPRESS_TYPES: string[];
15
+ /**
16
+ * Get items from CADASTRALPARCELS.PARCELLAIRE_EXPRESS near a given location.
5
17
  *
6
- * @param {number} lon
7
- * @param {number} lat
8
- * @param {(url: string) => Promise<any>} [fetcher]
9
- * @returns
18
+ * @param lon Longitude of the query point.
19
+ * @param lat Latitude of the query point.
20
+ * @returns The nearest cadastral objects, at most one per cadastral type.
10
21
  */
11
- export function getParcellaireExpress(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<array<object>>;
12
- export const PARCELLAIRE_EXPRESS_SOURCE: "G\u00E9oplateforme (WFS, CADASTRALPARCELS.PARCELLAIRE_EXPRESS)";
13
- export const PARCELLAIRE_EXPRESS_TYPES: string[];
22
+ export declare function getParcellaireExpress(lon: number, lat: number): Promise<ParcellaireExpressItem[]>;
23
+ export {};
@@ -1,7 +1,16 @@
1
- import _ from 'lodash';
2
- import distance from '../helpers/distance.js';
3
- import { fetchWfsFeatures, mapWfsFeature, toGeoJsonPoint } from '../helpers/wfs.js';
1
+ /**
2
+ * Cadastral objects lookup via the Géoplateforme WFS service.
3
+ *
4
+ * This module uses the structured WFS engine for request execution and
5
+ * response mapping, resolving geometry property names dynamically from
6
+ * the embedded catalog.
7
+ */
4
8
  import logger from '../logger.js';
9
+ import distance from '../helpers/distance.js';
10
+ import { getFeatureType, fetchWfsMultiTypename } from '../helpers/wfs_engine/execution.js';
11
+ import { getGeometryProperty } from '../helpers/wfs_engine/properties.js';
12
+ import { compileDwithinSpatialFilter } from '../helpers/wfs_engine/spatialCql.js';
13
+ import { mapToFlatItemsWithGeometry } from '../helpers/wfs_engine/response.js';
5
14
  // CADASTRALPARCELS.PARCELLAIRE_EXPRESS:
6
15
  // https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
7
16
  export const PARCELLAIRE_EXPRESS_SOURCE = "Géoplateforme (WFS, CADASTRALPARCELS.PARCELLAIRE_EXPRESS)";
@@ -13,17 +22,22 @@ export const PARCELLAIRE_EXPRESS_TYPES = [
13
22
  'subdivision_fiscale',
14
23
  'localisant'
15
24
  ];
25
+ const PARCELLAIRE_EXPRESS_TYPENAMES = PARCELLAIRE_EXPRESS_TYPES.map((type) => `CADASTRALPARCELS.PARCELLAIRE_EXPRESS:${type}`);
16
26
  /**
17
27
  * Filter items by distance keeping the nearest for each type.
18
28
  *
19
- * @param {array<object>} items
20
- * @returns {array<object>}
29
+ * @param items Items sorted by type then distance.
30
+ * @returns One item per type (the nearest).
21
31
  */
22
32
  function filterByDistance(items) {
23
- const sortedItems = _.orderBy(items, ['type', 'distance'], ['asc', 'asc']);
33
+ const sorted = [...items].sort((a, b) => {
34
+ if (a.type !== b.type)
35
+ return a.type.localeCompare(b.type);
36
+ return a.distance - b.distance;
37
+ });
24
38
  const result = [];
25
39
  let lastType = null;
26
- for (const item of sortedItems) {
40
+ for (const item of sorted) {
27
41
  if (lastType === item.type) {
28
42
  continue;
29
43
  }
@@ -33,26 +47,45 @@ function filterByDistance(items) {
33
47
  return result;
34
48
  }
35
49
  /**
36
- * Get items from CADASTRALPARCELS.PARCELLAIRE_EXPRESS near of a given location.
37
- *
38
- * @see https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
50
+ * Get items from CADASTRALPARCELS.PARCELLAIRE_EXPRESS near a given location.
39
51
  *
40
- * @param {number} lon
41
- * @param {number} lat
42
- * @param {(url: string) => Promise<any>} [fetcher]
43
- * @returns
52
+ * @param lon Longitude of the query point.
53
+ * @param lat Latitude of the query point.
54
+ * @returns The nearest cadastral objects, at most one per cadastral type.
44
55
  */
45
- export async function getParcellaireExpress(lon, lat, fetcher) {
46
- logger.info(`getParcellaireExpress(${lon},${lat}) ...`);
47
- // Using EWKT format with SRID=4326 prefix for standard lon,lat order
48
- const cql_filter = `DWITHIN(geom,SRID=4326;POINT(${lon} ${lat}),10,meters)`;
49
- const typeNames = PARCELLAIRE_EXPRESS_TYPES.map((type) => `CADASTRALPARCELS.PARCELLAIRE_EXPRESS:${type}`);
50
- const sourceGeom = toGeoJsonPoint(lon, lat);
51
- const features = await fetchWfsFeatures(typeNames, cql_filter, 'PARCELLAIRE_EXPRESS', fetcher);
52
- return filterByDistance(features.map((feature) => ({
53
- ...mapWfsFeature(feature, typeNames),
54
- distance: distance(sourceGeom, feature.geometry),
55
- source: PARCELLAIRE_EXPRESS_SOURCE,
56
- })));
56
+ export async function getParcellaireExpress(lon, lat) {
57
+ logger.debug(`[gpf:parcellaire-express] getParcellaireExpress(${lon},${lat}) ...`);
58
+ const spatialFilter = {
59
+ operator: "dwithin_point",
60
+ lon,
61
+ lat,
62
+ distance_m: 10,
63
+ };
64
+ // Resolve and compile one spatial filter per typename to avoid relying on
65
+ // cross-layer geometry property homogeneity.
66
+ const cqlFilters = await Promise.all(PARCELLAIRE_EXPRESS_TYPENAMES.map(async (typename) => {
67
+ const featureType = await getFeatureType(typename);
68
+ const geometryProperty = getGeometryProperty(featureType);
69
+ return compileDwithinSpatialFilter(geometryProperty, spatialFilter);
70
+ }));
71
+ // Execute the multi-typename WFS query
72
+ const featureCollection = await fetchWfsMultiTypename({
73
+ typenames: PARCELLAIRE_EXPRESS_TYPENAMES,
74
+ cqlFilters,
75
+ errorLabel: 'PARCELLAIRE_EXPRESS',
76
+ });
77
+ // Map to flat items preserving geometry for distance calculation
78
+ const sourceGeom = { type: "Point", coordinates: [lon, lat] };
79
+ const items = mapToFlatItemsWithGeometry(featureCollection, PARCELLAIRE_EXPRESS_TYPENAMES);
80
+ // Calculate distances, strip temporary geometry, and filter
81
+ const enrichedItems = items.map((item) => {
82
+ const { _rawGeometry: _, ...rest } = item;
83
+ return {
84
+ ...rest,
85
+ distance: distance(sourceGeom, item._rawGeometry),
86
+ source: PARCELLAIRE_EXPRESS_SOURCE,
87
+ };
88
+ });
89
+ return filterByDistance(enrichedItems);
57
90
  }
58
91
  //# sourceMappingURL=parcellaire-express.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parcellaire-express.js","sourceRoot":"","sources":["../../src/gpf/parcellaire-express.js"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,wCAAwC;AACxC,kFAAkF;AAElF,MAAM,CAAC,MAAM,0BAA0B,GAAG,2DAA2D,CAAC;AACtG,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACrC,gBAAgB;IAChB,SAAS;IACT,SAAS;IACT,UAAU;IACV,qBAAqB;IACrB,YAAY;CACf,CAAC;AAEF;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,KAAK;IAC3B,MAAM,WAAW,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAE3E,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,IAAI,QAAQ,GAAG,IAAI,CAAC;IACpB,KAAM,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC9B,IAAK,QAAQ,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,SAAS;QACb,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;IACzB,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAGD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO;IACzD,MAAM,CAAC,IAAI,CAAC,yBAAyB,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC;IACxD,qEAAqE;IACrE,MAAM,UAAU,GAAG,gCAAgC,GAAG,IAAI,GAAG,cAAc,CAAC;IAC5E,MAAM,SAAS,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;IAE1G,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE5C,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAC;IAC/F,OAAO,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/C,GAAG,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC;QACpC,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC;QAChD,MAAM,EAAE,0BAA0B;KACrC,CAAC,CAAC,CAAC,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"parcellaire-express.js","sourceRoot":"","sources":["../../src/gpf/parcellaire-express.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,30 @@
1
1
  /**
2
- * Get urbanism infos for a given location
2
+ * Urban planning and SUP (servitudes d'utilité publique) lookup via the Géoplateforme WFS service.
3
3
  *
4
- * @param {number} lon
5
- * @param {number} lat
6
- * @param {(url: string) => Promise<any>} [fetcher]
7
- * @returns
4
+ * This module uses the structured WFS engine for request execution and
5
+ * response mapping, resolving geometry property names dynamically from
6
+ * the embedded catalog.
8
7
  */
9
- export function getUrbanisme(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<{}[]>;
8
+ import { type FlatItem } from '../helpers/wfs_engine/response.js';
9
+ type UrbanismeItem = FlatItem & {
10
+ distance: number;
11
+ };
12
+ export declare const URBANISME_TYPES: string[];
13
+ export declare const URBANISME_SOURCE = "G\u00E9oplateforme - (WFS G\u00E9oportail de l'Urbanisme)";
10
14
  /**
11
- * Get SUP infos for a given location
15
+ * Get urbanism infos for a given location.
12
16
  *
13
- * @param {number} lon
14
- * @param {number} lat
15
- * @param {(url: string) => Promise<any>} [fetcher]
16
- * @returns
17
+ * @param lon Longitude of the query point.
18
+ * @param lat Latitude of the query point.
19
+ * @returns Urban planning objects relevant to the requested point.
17
20
  */
18
- export function getAssiettesServitudes(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<{
19
- distance: number;
20
- }[]>;
21
- export const URBANISME_TYPES: string[];
22
- export const URBANISME_SOURCE: "G\u00E9oplateforme - (WFS G\u00E9oportail de l'Urbanisme)";
21
+ export declare function getUrbanisme(lon: number, lat: number): Promise<Record<string, unknown>[]>;
22
+ /**
23
+ * Get SUP infos for a given location.
24
+ *
25
+ * @param lon Longitude of the query point.
26
+ * @param lat Latitude of the query point.
27
+ * @returns SUP footprints relevant to the requested point.
28
+ */
29
+ export declare function getAssiettesServitudes(lon: number, lat: number): Promise<UrbanismeItem[]>;
30
+ export {};
@@ -1,6 +1,16 @@
1
- import distance from "../helpers/distance.js";
2
- import { fetchWfsFeatures, mapWfsFeature, toGeoJsonPoint } from "../helpers/wfs.js";
3
- import logger from "../logger.js";
1
+ /**
2
+ * Urban planning and SUP (servitudes d'utilité publique) lookup via the Géoplateforme WFS service.
3
+ *
4
+ * This module uses the structured WFS engine for request execution and
5
+ * response mapping, resolving geometry property names dynamically from
6
+ * the embedded catalog.
7
+ */
8
+ import logger from '../logger.js';
9
+ import distance from '../helpers/distance.js';
10
+ import { getFeatureType, fetchWfsMultiTypename } from '../helpers/wfs_engine/execution.js';
11
+ import { getGeometryProperty } from '../helpers/wfs_engine/properties.js';
12
+ import { compileDwithinSpatialFilter } from '../helpers/wfs_engine/spatialCql.js';
13
+ import { mapToFlatItemsWithGeometry } from '../helpers/wfs_engine/response.js';
4
14
  // https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
5
15
  export const URBANISME_TYPES = [
6
16
  'wfs_scot:scot',
@@ -33,25 +43,43 @@ function sanitizeUrbanismeItem(item) {
33
43
  return sanitized;
34
44
  }
35
45
  /**
36
- * Get urbanism infos for a given location
46
+ * Get urbanism infos for a given location.
37
47
  *
38
- * @param {number} lon
39
- * @param {number} lat
40
- * @param {(url: string) => Promise<any>} [fetcher]
41
- * @returns
48
+ * @param lon Longitude of the query point.
49
+ * @param lat Latitude of the query point.
50
+ * @returns Urban planning objects relevant to the requested point.
42
51
  */
43
- export async function getUrbanisme(lon, lat, fetcher) {
44
- logger.info(`getUrbanisme(${lon},${lat})...`);
45
- // Using EWKT format with SRID=4326 prefix for standard lon,lat order
46
- const cql_filter = `DWITHIN(the_geom,SRID=4326;POINT(${lon} ${lat}),30,meters)`;
47
- const sourceGeom = toGeoJsonPoint(lon, lat);
48
- const features = await fetchWfsFeatures(URBANISME_TYPES, cql_filter, 'Urbanisme', fetcher);
49
- return features.map((feature) => {
50
- const item = {
51
- ...mapWfsFeature(feature, URBANISME_TYPES),
52
- distance: distance(sourceGeom, feature.geometry),
52
+ export async function getUrbanisme(lon, lat) {
53
+ logger.debug(`[gpf:urbanisme] getUrbanisme(${lon},${lat})...`);
54
+ const spatialFilter = {
55
+ operator: "dwithin_point",
56
+ lon,
57
+ lat,
58
+ distance_m: 30,
59
+ };
60
+ // Resolve and compile one spatial filter per typename to avoid relying on
61
+ // cross-layer geometry property homogeneity.
62
+ const cqlFilters = await Promise.all(URBANISME_TYPES.map(async (typename) => {
63
+ const featureType = await getFeatureType(typename);
64
+ const geometryProperty = getGeometryProperty(featureType);
65
+ return compileDwithinSpatialFilter(geometryProperty, spatialFilter);
66
+ }));
67
+ // Execute the multi-typename WFS query
68
+ const featureCollection = await fetchWfsMultiTypename({
69
+ typenames: URBANISME_TYPES,
70
+ cqlFilters,
71
+ errorLabel: 'Urbanisme',
72
+ });
73
+ // Map to flat items preserving geometry for distance calculation
74
+ const sourceGeom = { type: "Point", coordinates: [lon, lat] };
75
+ const items = mapToFlatItemsWithGeometry(featureCollection, URBANISME_TYPES);
76
+ return items.map((item) => {
77
+ const { _rawGeometry: _, ...rest } = item;
78
+ const urbanismeItem = {
79
+ ...rest,
80
+ distance: distance(sourceGeom, item._rawGeometry),
53
81
  };
54
- return sanitizeUrbanismeItem(item);
82
+ return sanitizeUrbanismeItem(urbanismeItem);
55
83
  });
56
84
  }
57
85
  const ASSIETTES_SUP_TYPES = [
@@ -60,22 +88,42 @@ const ASSIETTES_SUP_TYPES = [
60
88
  'wfs_sup:assiette_sup_s',
61
89
  ];
62
90
  /**
63
- * Get SUP infos for a given location
91
+ * Get SUP infos for a given location.
64
92
  *
65
- * @param {number} lon
66
- * @param {number} lat
67
- * @param {(url: string) => Promise<any>} [fetcher]
68
- * @returns
93
+ * @param lon Longitude of the query point.
94
+ * @param lat Latitude of the query point.
95
+ * @returns SUP footprints relevant to the requested point.
69
96
  */
70
- export async function getAssiettesServitudes(lon, lat, fetcher) {
71
- logger.info(`getAssiettesServitudes(${lon},${lat})...`);
72
- // Using EWKT format with SRID=4326 prefix for standard lon,lat order
73
- const cql_filter = `DWITHIN(the_geom,SRID=4326;POINT(${lon} ${lat}),30,meters)`;
74
- const sourceGeom = toGeoJsonPoint(lon, lat);
75
- const features = await fetchWfsFeatures(ASSIETTES_SUP_TYPES, cql_filter, 'Urbanisme', fetcher);
76
- return features.map((feature) => ({
77
- ...mapWfsFeature(feature, ASSIETTES_SUP_TYPES),
78
- distance: distance(sourceGeom, feature.geometry),
97
+ export async function getAssiettesServitudes(lon, lat) {
98
+ logger.debug(`[gpf:urbanisme] getAssiettesServitudes(${lon},${lat})...`);
99
+ const spatialFilter = {
100
+ operator: "dwithin_point",
101
+ lon,
102
+ lat,
103
+ distance_m: 30,
104
+ };
105
+ // Resolve and compile one spatial filter per typename to avoid relying on
106
+ // cross-layer geometry property homogeneity.
107
+ const cqlFilters = await Promise.all(ASSIETTES_SUP_TYPES.map(async (typename) => {
108
+ const featureType = await getFeatureType(typename);
109
+ const geometryProperty = getGeometryProperty(featureType);
110
+ return compileDwithinSpatialFilter(geometryProperty, spatialFilter);
79
111
  }));
112
+ // Execute the multi-typename WFS query
113
+ const featureCollection = await fetchWfsMultiTypename({
114
+ typenames: ASSIETTES_SUP_TYPES,
115
+ cqlFilters,
116
+ errorLabel: 'Urbanisme',
117
+ });
118
+ // Map to flat items preserving geometry for distance calculation
119
+ const sourceGeom = { type: "Point", coordinates: [lon, lat] };
120
+ const items = mapToFlatItemsWithGeometry(featureCollection, ASSIETTES_SUP_TYPES);
121
+ return items.map((item) => {
122
+ const { _rawGeometry: _, ...rest } = item;
123
+ return {
124
+ ...rest,
125
+ distance: distance(sourceGeom, item._rawGeometry),
126
+ };
127
+ });
80
128
  }
81
129
  //# sourceMappingURL=urbanisme.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"urbanisme.js","sourceRoot":"","sources":["../../src/gpf/urbanisme.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"urbanisme.js","sourceRoot":"","sources":["../../src/gpf/urbanisme.ts"],"names":[],"mappings":"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"}