@ignfab/geocontext 0.9.3 → 0.9.5

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 (75) hide show
  1. package/README.md +46 -28
  2. package/dist/gpf/adminexpress.js +7 -27
  3. package/dist/gpf/adminexpress.js.map +1 -1
  4. package/dist/gpf/parcellaire-express.js +13 -33
  5. package/dist/gpf/parcellaire-express.js.map +1 -1
  6. package/dist/gpf/urbanisme.d.ts +4 -2
  7. package/dist/gpf/urbanisme.js +20 -61
  8. package/dist/gpf/urbanisme.js.map +1 -1
  9. package/dist/gpf/wfs.d.ts +2 -2
  10. package/dist/gpf/wfs.js +17 -71
  11. package/dist/gpf/wfs.js.map +1 -1
  12. package/dist/helpers/distance.d.ts +4 -2
  13. package/dist/helpers/distance.js +20 -5
  14. package/dist/helpers/distance.js.map +1 -1
  15. package/dist/helpers/http.d.ts +4 -0
  16. package/dist/helpers/http.js +103 -1
  17. package/dist/helpers/http.js.map +1 -1
  18. package/dist/helpers/jsonSchema.d.ts +3 -0
  19. package/dist/helpers/jsonSchema.js +8 -0
  20. package/dist/helpers/jsonSchema.js.map +1 -0
  21. package/dist/helpers/schemas.d.ts +13 -0
  22. package/dist/helpers/schemas.js +18 -0
  23. package/dist/helpers/schemas.js.map +1 -0
  24. package/dist/helpers/wfs.d.ts +27 -0
  25. package/dist/helpers/wfs.js +55 -0
  26. package/dist/helpers/wfs.js.map +1 -0
  27. package/dist/helpers/wfs_internal/compile.d.ts +46 -0
  28. package/dist/helpers/wfs_internal/compile.js +595 -0
  29. package/dist/helpers/wfs_internal/compile.js.map +1 -0
  30. package/dist/helpers/wfs_internal/request.d.ts +38 -0
  31. package/dist/helpers/wfs_internal/request.js +92 -0
  32. package/dist/helpers/wfs_internal/request.js.map +1 -0
  33. package/dist/helpers/wfs_internal/response.d.ts +21 -0
  34. package/dist/helpers/wfs_internal/response.js +29 -0
  35. package/dist/helpers/wfs_internal/response.js.map +1 -0
  36. package/dist/helpers/wfs_internal/schema.d.ts +167 -0
  37. package/dist/helpers/wfs_internal/schema.js +81 -0
  38. package/dist/helpers/wfs_internal/schema.js.map +1 -0
  39. package/dist/index.js +47 -25
  40. package/dist/index.js.map +1 -1
  41. package/dist/tools/AdminexpressTool.d.ts +52 -2
  42. package/dist/tools/AdminexpressTool.js +11 -14
  43. package/dist/tools/AdminexpressTool.js.map +1 -1
  44. package/dist/tools/AltitudeTool.d.ts +2 -2
  45. package/dist/tools/AltitudeTool.js +4 -13
  46. package/dist/tools/AltitudeTool.js.map +1 -1
  47. package/dist/tools/AssietteSupTool.d.ts +55 -3
  48. package/dist/tools/AssietteSupTool.js +12 -15
  49. package/dist/tools/AssietteSupTool.js.map +1 -1
  50. package/dist/tools/CadastreTool.d.ts +52 -2
  51. package/dist/tools/CadastreTool.js +13 -15
  52. package/dist/tools/CadastreTool.js.map +1 -1
  53. package/dist/tools/GeocodeTool.d.ts +2 -2
  54. package/dist/tools/GeocodeTool.js +6 -4
  55. package/dist/tools/GeocodeTool.js.map +1 -1
  56. package/dist/tools/GpfWfsDescribeTypeTool.d.ts +16 -16
  57. package/dist/tools/GpfWfsDescribeTypeTool.js +4 -3
  58. package/dist/tools/GpfWfsDescribeTypeTool.js.map +1 -1
  59. package/dist/tools/GpfWfsGetFeaturesTool.d.ts +170 -44
  60. package/dist/tools/GpfWfsGetFeaturesTool.js +161 -114
  61. package/dist/tools/GpfWfsGetFeaturesTool.js.map +1 -1
  62. package/dist/tools/GpfWfsSearchTypesTool.d.ts +8 -2
  63. package/dist/tools/GpfWfsSearchTypesTool.js +12 -9
  64. package/dist/tools/GpfWfsSearchTypesTool.js.map +1 -1
  65. package/dist/tools/UrbanismeTool.d.ts +53 -3
  66. package/dist/tools/UrbanismeTool.js +9 -15
  67. package/dist/tools/UrbanismeTool.js.map +1 -1
  68. package/package.json +8 -7
  69. package/dist/resources/WfsCqlFilterResource.d.ts +0 -10
  70. package/dist/resources/WfsCqlFilterResource.js +0 -23
  71. package/dist/resources/WfsCqlFilterResource.js.map +0 -1
  72. package/dist/resources/content/wfs-cql-filter.md +0 -215
  73. package/dist/tools/GpfWfsListTypesTool.d.ts +0 -22
  74. package/dist/tools/GpfWfsListTypesTool.js +0 -26
  75. package/dist/tools/GpfWfsListTypesTool.js.map +0 -1
package/README.md CHANGED
@@ -42,19 +42,19 @@ Par exemple, avec "Cursor Settings / MCP / Add server" :
42
42
  }
43
43
  ```
44
44
 
45
- ### Utilisation avec Docker
46
-
47
- ```bash
48
- docker compose build
49
- docker compose up -d
50
- ```
51
-
52
- Remarque :
53
-
54
- - le `docker-compose.yaml` fournit `HTTP_HOST=0.0.0.0` pour rendre le serveur HTTP joignable depuis l'hôte ;
55
- - sans ce paramètre, `mcp-framework` écoute par défaut sur `127.0.0.1` en mode HTTP, ce qui n'est pas adapté à une exécution en conteneur.
56
-
57
- Ensuite :
45
+ ### Utilisation avec Docker
46
+
47
+ ```bash
48
+ docker compose build
49
+ docker compose up -d
50
+ ```
51
+
52
+ Remarque :
53
+
54
+ - le `docker-compose.yaml` fournit `HTTP_HOST=0.0.0.0` pour rendre le serveur HTTP joignable depuis l'hôte ;
55
+ - sans ce paramètre, `mcp-framework` écoute par défaut sur `127.0.0.1` en mode HTTP, ce qui n'est pas adapté à une exécution en conteneur.
56
+
57
+ Ensuite :
58
58
 
59
59
  ```json
60
60
  {
@@ -123,11 +123,13 @@ npx -y @modelcontextprotocol/inspector node dist/index.js
123
123
 
124
124
  Pour une utilisation avancée :
125
125
 
126
- | Nom | Description | Valeur par défaut |
127
- | ---------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------- |
128
- | `TRANSPORT_TYPE` | [Transport](https://mcp-framework.com/docs/Transports/transports-overview) permet de choisir entre "stdio" et "http" | "stdio" |
129
- | `HTTP_HOST` | Adresse d'écoute en mode HTTP. Utile avec Docker pour exposer le service via `0.0.0.0`. | défaut `mcp-framework` (`127.0.0.1`) |
130
- | `GPF_WFS_MINISEARCH_OPTIONS` | Chaîne JSON optionnelle pour ajuster les options MiniSearch utilisées par `gpf_wfs_search_types` (`fields`, `combineWith`, `fuzzy`, `boost.namespace`, `boost.name`, `boost.title`, `boost.description`, `boost.properties`, `boost.enums`, `boost.identifierTokens`). | options par défaut de `@ignfab/gpf-schema-store` |
126
+ | Nom | Description | Valeur par défaut |
127
+ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
128
+ | `TRANSPORT_TYPE` | [Transport](https://mcp-framework.com/docs/Transports/transports-overview) permet de choisir entre "stdio" et "http" | "stdio" |
129
+ | `HTTP_HOST` | Adresse d'écoute en mode HTTP. Utile avec Docker pour exposer le service via `0.0.0.0`. | défaut `mcp-framework` (`127.0.0.1`) |
130
+ | `GPF_WFS_MINISEARCH_OPTIONS` | Chaîne JSON optionnelle pour ajuster les options MiniSearch utilisées par `gpf_wfs_search_types` (`fields`, `combineWith`, `fuzzy`, `boost.namespace`, `boost.name`, `boost.title`, `boost.description`, `boost.properties`, `boost.enums`, `boost.identifierTokens`). | options par défaut de `@ignfab/gpf-schema-store` |
131
+ | `LOG_FORMAT` | Le format d'écriture des logs : "json" ou "simple". | "simple" |
132
+ | `LOG_LEVEL` | Le niveau d'écriture des logs : ["error", "info", ou "debug"](https://github.com/winstonjs/winston#logging-levels) | "debug" |
131
133
 
132
134
  Exemple :
133
135
 
@@ -139,7 +141,7 @@ Si `GPF_WFS_MINISEARCH_OPTIONS` est absent ou vide, les options par défaut rest
139
141
 
140
142
  Remarque :
141
143
 
142
- - Les outils `gpf_wfs_list_types`, `gpf_wfs_search_types` et `gpf_wfs_describe_type` s'appuient sur un catalogue de schémas embarqué fourni par `@ignfab/gpf-schema-store`.
144
+ - Les outils `gpf_wfs_search_types` et `gpf_wfs_describe_type` s'appuient sur un catalogue de schémas embarqué fourni par `@ignfab/gpf-schema-store`.
143
145
  - L'outil `gpf_wfs_get_features` interroge toujours le service WFS de la Géoplateforme en direct.
144
146
  - Le catalogue embarqué améliore la description des featureTypes mais il peut être légèrement décalé par rapport à l'état courant du WFS.
145
147
 
@@ -175,27 +177,43 @@ L'idée est ici de répondre à des précises en traitant côté serveur les app
175
177
 
176
178
  * [assiette_sup(lon,lat)](src/tools/AssietteSupTool.ts) permet de **récupérer les Servitude d'Utilité Publiques (SUP)**
177
179
 
180
+ Les tools WFS orientés "objet" (`adminexpress`, `cadastre`, `urbanisme`, `assiette_sup`) exposent un `feature_ref { typename, feature_id }` quand l'objet source est réutilisable tel quel dans un appel ultérieur à `gpf_wfs_get_features`, notamment avec `spatial_operator="intersects_feature"`.
181
+
178
182
  ### Explorer les données vecteurs
179
183
 
180
- #### Explorer les tables
181
-
182
- * [gpf_wfs_list_types()](src/tools/GpfWfsListTypesTool.ts) pour **lister de façon exhaustive les types WFS connus du catalogue de schémas embarqué**. Cet outil est surtout utile pour un inventaire complet ou une exploration globale du catalogue ; pour trouver rapidement un type pertinent, préférer `gpf_wfs_search_types`.
183
- * [gpf_wfs_search_types(keywords,max_results=10)](src/tools/GpfWfsSearchTypesTool.ts) pour **rechercher un type WFS pertinent à partir de mots-clés et obtenir un `typename` valide**. La recherche est textuelle et configurable via `GPF_WFS_MINISEARCH_OPTIONS`.
184
+ #### Explorer les tables
185
+
186
+ * [gpf_wfs_search_types(keywords,max_results=10)](src/tools/GpfWfsSearchTypesTool.ts) pour **rechercher un type WFS pertinent à partir de mots-clés et obtenir un `typename` valide**. La recherche est textuelle et configurable via `GPF_WFS_MINISEARCH_OPTIONS`.
184
187
 
185
188
  > - Quels sont les millésimes ADMINEXPRESS disponibles sur la Géoplateforme?
186
189
  > - Quelle est la table de la BDTOPO correspondant aux bâtiments?
187
190
  > - Dans quelle table de la BDTOPO peut-on trouver les ponts?
188
191
 
189
- #### Explorer la structure des tables
190
-
191
- * [gpf_wfs_describe_type(typename)](src/tools/GpfWfsDescribeTypeTool.ts) pour récupérer le **schéma détaillé d'un type WFS** depuis le catalogue embarqué (`id`, `namespace`, `name`, `title`, `description`, `properties`), en particulier avant d'appeler `gpf_wfs_get_features`
192
+ #### Explorer la structure des tables
193
+
194
+ * [gpf_wfs_describe_type(typename)](src/tools/GpfWfsDescribeTypeTool.ts) pour récupérer le **schéma détaillé d'un type WFS** depuis le catalogue embarqué (`id`, `namespace`, `name`, `title`, `description`, `properties`), en particulier avant d'appeler `gpf_wfs_get_features`
192
195
 
193
196
  > - Quelles sont les informations disponibles pour les communes avec ADMINEXPRESS-COG.LATEST?
194
197
  > - Compare le modèle des communes entre ADMINEXPRESS-COG:2024 et ADMINEXPRESS-COG.LATEST
195
198
 
196
199
  #### Explorer les données des tables
197
200
 
198
- * [gpf_wfs_get_features(typename,...)](src/tools/GpfWfsGetFeaturesTool.ts) pour **récupérer les données d'une table** depuis le service WFS de la Géoplateforme ([GetFeature](https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetFeature&typename=ADMINEXPRESS-COG.LATEST:commune&outputFormat=application/json&count=1))
201
+ * [gpf_wfs_get_features(typename,...)](src/tools/GpfWfsGetFeaturesTool.ts) pour **récupérer les données d'une table** depuis le service WFS de la Géoplateforme sans écrire de CQL à la main.
202
+
203
+ Le tool accepte un contrat structuré :
204
+
205
+ - `select` pour choisir les propriétés à renvoyer
206
+ - `where` pour filtrer les objets
207
+ - `order_by` pour trier les résultats
208
+ - `spatial_operator` et ses paramètres dédiés pour le spatial en `lon/lat`
209
+ - `result_type="request"` pour récupérer la requête compilée en `POST`, ainsi qu'une `get_url` dérivée quand elle reste raisonnablement portable en GET
210
+
211
+ Exemples :
212
+
213
+ - `where=[{ property: "code_insee", operator: "eq", value: "25000" }]`
214
+ - `spatial_operator="bbox"` avec `bbox_west`, `bbox_south`, `bbox_east`, `bbox_north`
215
+ - `spatial_operator="dwithin_point"` avec `dwithin_lon`, `dwithin_lat`, `dwithin_distance_m`
216
+ - `spatial_operator="intersects_feature"` avec `intersects_feature_typename` et `intersects_feature_id` issus d'une `feature_ref`
199
217
 
200
218
  > - Quelles sont les 5 communes les plus peuplées du Doubs (25)?
201
219
  > - Combien y-a-t'il de bâtiments à moins de 5 km de la tour Eiffel?
@@ -229,10 +247,10 @@ N'hésitez pas :
229
247
  mcp add tool gpf_wmts_layers
230
248
  ```
231
249
 
232
- * [@camptocamp/ogc-client](https://camptocamp.github.io/ogc-client/#/) pour la **lecture des réponses XML des services WFS, WMTS,...**
233
250
  * [@ignfab/gpf-schema-store](https://www.npmjs.com/package/@ignfab/gpf-schema-store) pour le **catalogue de schémas embarqué** utilisé par les outils d'exploration WFS.
234
251
  * [MiniSearch](https://github.com/lucaong/minisearch) pour la **recherche par mot clé** utilisée dans `@ignfab/gpf-schema-store`.
235
252
  * [jsts](https://bjornharrtell.github.io/jsts/) pour les **traitements géométriques** (ex : tri des réponses par distance au point recherché).
253
+ * [turfjs/distance](https://turfjs.org/docs/api/distance) pour les **calculs de distance** avec la [formule de Haversine](https://en.wikipedia.org/wiki/Haversine_formula).
236
254
 
237
255
  ## Licence
238
256
 
@@ -1,5 +1,4 @@
1
- import _ from 'lodash';
2
- import { fetchJSON } from '../helpers/http.js';
1
+ import { fetchWfsFeatures, mapWfsFeature } from '../helpers/wfs.js';
3
2
  import logger from '../logger.js';
4
3
  /**
5
4
  * ADMINEXPRESS-COG.LATEST:{type}
@@ -24,31 +23,12 @@ export const ADMINEXPRESS_TYPES = [
24
23
  * @param {(url: string) => Promise<any>} [fetcher]
25
24
  * @returns {object[]}
26
25
  */
27
- export async function getAdminUnits(lon, lat, fetcher = fetchJSON) {
26
+ export async function getAdminUnits(lon, lat, fetcher) {
28
27
  logger.info(`[adminexpress] getAdminUnits(${lon},${lat})...`);
29
- // note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
30
- const cql_filter = `INTERSECTS(geometrie,Point(${lat} ${lon}))`;
31
- // TODO : avoid useless geometry retrieval at WFS level
32
- const url = 'https://data.geopf.fr/wfs?' + new URLSearchParams({
33
- service: 'WFS',
34
- request: 'GetFeature',
35
- typeName: ADMINEXPRESS_TYPES.map((type) => { return `ADMINEXPRESS-COG.LATEST:${type}`; }).join(','),
36
- outputFormat: 'application/json',
37
- cql_filter: cql_filter
38
- }).toString();
39
- const featureCollection = await fetcher(url);
40
- if (!Array.isArray(featureCollection?.features)) {
41
- throw new Error("Le service ADMINEXPRESS n'a pas retourné de collection d'objets exploitable");
42
- }
43
- return featureCollection.features.map((feature) => {
44
- // parse type from id (ex: "commune.3837")
45
- const type = feature.id.split('.')[0];
46
- // ignore geometry and extend properties
47
- return Object.assign({
48
- type: type,
49
- id: feature.id,
50
- bbox: feature.bbox
51
- }, feature.properties);
52
- });
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));
53
33
  }
54
34
  //# sourceMappingURL=adminexpress.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adminexpress.js","sourceRoot":"","sources":["../../src/gpf/adminexpress.js"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,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,GAAG,SAAS;IAC7D,MAAM,CAAC,IAAI,CAAC,gCAAgC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAE9D,kFAAkF;IAClF,MAAM,UAAU,GAAG,8BAA8B,GAAG,IAAI,GAAG,IAAI,CAAC;IAEhE,uDAAuD;IACvD,MAAM,GAAG,GAAG,4BAA4B,GAAG,IAAI,eAAe,CAAC;QAC3D,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,2BAA2B,IAAI,EAAE,CAAA,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAClG,YAAY,EAAE,kBAAkB;QAChC,UAAU,EAAE,UAAU;KACzB,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACnG,CAAC;IACD,OAAO,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9C,0CAA0C;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,wCAAwC;QACxC,OAAO,MAAM,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI;SACrB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACP,CAAC"}
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,6 +1,6 @@
1
1
  import _ from 'lodash';
2
2
  import distance from '../helpers/distance.js';
3
- import { fetchJSON } from '../helpers/http.js';
3
+ import { fetchWfsFeatures, mapWfsFeature, toGeoJsonPoint } from '../helpers/wfs.js';
4
4
  import logger from '../logger.js';
5
5
  // CADASTRALPARCELS.PARCELLAIRE_EXPRESS:
6
6
  // https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
@@ -24,7 +24,7 @@ function filterByDistance(items) {
24
24
  const result = [];
25
25
  let lastType = null;
26
26
  for (const item of sortedItems) {
27
- if (lastType == item.type) {
27
+ if (lastType === item.type) {
28
28
  continue;
29
29
  }
30
30
  result.push(item);
@@ -42,37 +42,17 @@ function filterByDistance(items) {
42
42
  * @param {(url: string) => Promise<any>} [fetcher]
43
43
  * @returns
44
44
  */
45
- export async function getParcellaireExpress(lon, lat, fetcher = fetchJSON) {
45
+ export async function getParcellaireExpress(lon, lat, fetcher) {
46
46
  logger.info(`getParcellaireExpress(${lon},${lat}) ...`);
47
- // note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
48
- const cql_filter = `DWITHIN(geom,Point(${lat} ${lon}),10,meters)`;
49
- const sourceGeom = {
50
- "type": "Point",
51
- "coordinates": [lon, lat]
52
- };
53
- // TODO : avoid useless geometry retrieval at WFS level
54
- const url = 'https://data.geopf.fr/wfs?' + new URLSearchParams({
55
- service: 'WFS',
56
- request: 'GetFeature',
57
- typeName: PARCELLAIRE_EXPRESS_TYPES.map((type) => { return `CADASTRALPARCELS.PARCELLAIRE_EXPRESS:${type}`; }).join(','),
58
- outputFormat: 'application/json',
59
- cql_filter: cql_filter
60
- }).toString();
61
- const featureCollection = await fetcher(url);
62
- if (!Array.isArray(featureCollection?.features)) {
63
- throw new Error("Le service PARCELLAIRE_EXPRESS n'a pas retourné de collection d'objets exploitable");
64
- }
65
- return filterByDistance(featureCollection.features.map((feature) => {
66
- // parse type from id (ex: "commune.3837")
67
- const type = feature.id.split('.')[0];
68
- // ignore geometry and extend properties
69
- return Object.assign({
70
- type: type,
71
- id: feature.id,
72
- bbox: feature.bbox,
73
- distance: distance(sourceGeom, feature.geometry),
74
- source: PARCELLAIRE_EXPRESS_SOURCE,
75
- }, feature.properties);
76
- }));
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
+ })));
77
57
  }
78
58
  //# 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,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,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,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACzB,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,GAAG,SAAS;IACrE,MAAM,CAAC,IAAI,CAAC,yBAAyB,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC;IACxD,kFAAkF;IAClF,MAAM,UAAU,GAAG,sBAAsB,GAAG,IAAI,GAAG,cAAc,CAAC;IAElE,MAAM,UAAU,GAAG;QACf,MAAM,EAAE,OAAO;QACf,aAAa,EAAE,CAAC,GAAG,EAAC,GAAG,CAAC;KAC3B,CAAC;IAEF,uDAAuD;IACvD,MAAM,GAAG,GAAG,4BAA4B,GAAG,IAAI,eAAe,CAAC;QAC3D,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,wCAAwC,IAAI,EAAE,CAAA,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACtH,YAAY,EAAE,kBAAkB;QAChC,UAAU,EAAE,UAAU;KACzB,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAC;IAC1G,CAAC;IACD,OAAO,gBAAgB,CAAC,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC/D,0CAA0C;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,wCAAwC;QACxC,OAAO,MAAM,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,IAAI;YACV,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,QAAQ,CACd,UAAU,EACV,OAAO,CAAC,QAAQ,CACnB;YACD,MAAM,EAAE,0BAA0B;SACrC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC,CAAC;AACR,CAAC"}
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"}
@@ -6,7 +6,7 @@
6
6
  * @param {(url: string) => Promise<any>} [fetcher]
7
7
  * @returns
8
8
  */
9
- export function getUrbanisme(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<any>;
9
+ export function getUrbanisme(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<{}[]>;
10
10
  /**
11
11
  * Get SUP infos for a given location
12
12
  *
@@ -15,6 +15,8 @@ export function getUrbanisme(lon: number, lat: number, fetcher?: (url: string) =
15
15
  * @param {(url: string) => Promise<any>} [fetcher]
16
16
  * @returns
17
17
  */
18
- export function getAssiettesServitudes(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<any>;
18
+ export function getAssiettesServitudes(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<{
19
+ distance: number;
20
+ }[]>;
19
21
  export const URBANISME_TYPES: string[];
20
22
  export const URBANISME_SOURCE: "G\u00E9oplateforme - (WFS G\u00E9oportail de l'Urbanisme)";
@@ -1,5 +1,5 @@
1
1
  import distance from "../helpers/distance.js";
2
- import { fetchJSON } from "../helpers/http.js";
2
+ import { fetchWfsFeatures, mapWfsFeature, toGeoJsonPoint } from "../helpers/wfs.js";
3
3
  import logger from "../logger.js";
4
4
  // https://data.geopf.fr/wfs/ows?service=WFS&version=2.0.0&request=GetCapabilities
5
5
  export const URBANISME_TYPES = [
@@ -15,7 +15,6 @@ export const URBANISME_TYPES = [
15
15
  'wfs_du:prescription_surf'
16
16
  ];
17
17
  export const URBANISME_SOURCE = "Géoplateforme - (WFS Géoportail de l'Urbanisme)";
18
- const URBANISME_INVALID_COLLECTION_ERROR = "Le service Urbanisme n'a pas retourné de collection d'objets exploitable";
19
18
  const URBANISME_EXCLUDED_PROPERTIES = new Set([
20
19
  'gpu_status',
21
20
  'urlfic'
@@ -41,36 +40,17 @@ function sanitizeUrbanismeItem(item) {
41
40
  * @param {(url: string) => Promise<any>} [fetcher]
42
41
  * @returns
43
42
  */
44
- export async function getUrbanisme(lon, lat, fetcher = fetchJSON) {
43
+ export async function getUrbanisme(lon, lat, fetcher) {
45
44
  logger.info(`getUrbanisme(${lon},${lat})...`);
46
- // note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
47
- const cql_filter = `DWITHIN(the_geom,Point(${lat} ${lon}),30,meters)`;
48
- const sourceGeom = {
49
- "type": "Point",
50
- "coordinates": [lon, lat]
51
- };
52
- // TODO : avoid useless geometry retrieval at WFS level
53
- const url = 'https://data.geopf.fr/wfs?' + new URLSearchParams({
54
- service: 'WFS',
55
- request: 'GetFeature',
56
- typeName: URBANISME_TYPES.join(','),
57
- outputFormat: 'application/json',
58
- cql_filter: cql_filter
59
- }).toString();
60
- const featureCollection = await fetcher(url);
61
- if (!Array.isArray(featureCollection?.features)) {
62
- throw new Error(URBANISME_INVALID_COLLECTION_ERROR);
63
- }
64
- return featureCollection.features.map((feature) => {
65
- // parse type from id (ex: "commune.3837")
66
- const type = feature.id.split('.')[0];
67
- // ignore geometry and extend properties
68
- const item = Object.assign({
69
- type: type,
70
- id: feature.id,
71
- bbox: feature.bbox,
72
- distance: (distance(sourceGeom, feature.geometry) * 1000.0)
73
- }, feature.properties);
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),
53
+ };
74
54
  return sanitizeUrbanismeItem(item);
75
55
  });
76
56
  }
@@ -87,36 +67,15 @@ const ASSIETTES_SUP_TYPES = [
87
67
  * @param {(url: string) => Promise<any>} [fetcher]
88
68
  * @returns
89
69
  */
90
- export async function getAssiettesServitudes(lon, lat, fetcher = fetchJSON) {
70
+ export async function getAssiettesServitudes(lon, lat, fetcher) {
91
71
  logger.info(`getAssiettesServitudes(${lon},${lat})...`);
92
- // note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
93
- const cql_filter = `DWITHIN(the_geom,Point(${lat} ${lon}),30,meters)`;
94
- const sourceGeom = {
95
- "type": "Point",
96
- "coordinates": [lon, lat]
97
- };
98
- // TODO : avoid useless geometry retrieval at WFS level
99
- const url = 'https://data.geopf.fr/wfs?' + new URLSearchParams({
100
- service: 'WFS',
101
- request: 'GetFeature',
102
- typeName: ASSIETTES_SUP_TYPES.join(','),
103
- outputFormat: 'application/json',
104
- cql_filter: cql_filter
105
- }).toString();
106
- const featureCollection = await fetcher(url);
107
- if (!Array.isArray(featureCollection?.features)) {
108
- throw new Error(URBANISME_INVALID_COLLECTION_ERROR);
109
- }
110
- return featureCollection.features.map((feature) => {
111
- // parse type from id (ex: "commune.3837")
112
- const type = feature.id.split('.')[0];
113
- // ignore geometry and extend properties
114
- return Object.assign({
115
- type: type,
116
- id: feature.id,
117
- bbox: feature.bbox,
118
- distance: (distance(sourceGeom, feature.geometry) * 1000.0)
119
- }, feature.properties);
120
- });
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),
79
+ }));
121
80
  }
122
81
  //# 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.js"],"names":[],"mappings":"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"}
package/dist/gpf/wfs.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Collection, MiniSearchCollectionSearchOptions } from '@ignfab/gpf-schema-store';
1
+ import { Collection, CollectionSearchResult, MiniSearchCollectionSearchOptions } from '@ignfab/gpf-schema-store';
2
2
  export declare const GPF_WFS_URL = "https://data.geopf.fr/wfs";
3
3
  type MiniSearchOptions = MiniSearchCollectionSearchOptions;
4
4
  export declare class FeatureTypeNotFoundError extends Error {
@@ -12,7 +12,7 @@ export declare class WfsClient {
12
12
  miniSearch?: MiniSearchOptions;
13
13
  });
14
14
  getFeatureTypes(): Promise<Collection[]>;
15
- searchFeatureTypes(query: string, maxResults?: number): Promise<Collection[]>;
15
+ searchFeatureTypesWithScores(query: string, maxResults?: number): Promise<CollectionSearchResult[]>;
16
16
  getFeatureType(name: string): Promise<Collection>;
17
17
  }
18
18
  export declare const wfsClient: WfsClient;
package/dist/gpf/wfs.js CHANGED
@@ -1,11 +1,10 @@
1
1
  // --- Imports ---
2
2
  import { getCollectionCatalog, MiniSearchCollectionSearchEngine, } from '@ignfab/gpf-schema-store';
3
+ import { z } from 'zod';
3
4
  // --- Constants ---
4
5
  export const GPF_WFS_URL = "https://data.geopf.fr/wfs";
5
6
  // Environment variable used to inject MiniSearch options at runtime (JSON string).
6
7
  const GPF_WFS_MINISEARCH_OPTIONS_ENV = "GPF_WFS_MINISEARCH_OPTIONS";
7
- // Keys accepted at the top level of the search options object.
8
- const TOP_LEVEL_MINISEARCH_OPTION_KEYS = ["fields", "combineWith", "fuzzy", "boost"];
9
8
  // Shared keys used by both `fields` and `boost` in MiniSearchCollectionSearchOptions.
10
9
  const MINISEARCH_INDEXED_OPTION_KEYS = [
11
10
  "namespace",
@@ -16,9 +15,7 @@ const MINISEARCH_INDEXED_OPTION_KEYS = [
16
15
  "enums",
17
16
  "identifierTokens",
18
17
  ];
19
- const MINISEARCH_FIELD_OPTION_KEYS = MINISEARCH_INDEXED_OPTION_KEYS;
20
18
  const MINISEARCH_COMBINE_WITH_VALUES = ["AND", "OR"];
21
- const MINISEARCH_BOOST_OPTION_KEYS = MINISEARCH_INDEXED_OPTION_KEYS;
22
19
  // --- Errors ---
23
20
  export class FeatureTypeNotFoundError extends Error {
24
21
  constructor(name) {
@@ -27,78 +24,27 @@ export class FeatureTypeNotFoundError extends Error {
27
24
  }
28
25
  }
29
26
  // --- Helpers ---
30
- function isPlainObject(value) {
31
- return typeof value === "object" && value !== null && !Array.isArray(value);
32
- }
33
- function isFiniteNumber(value) {
34
- return typeof value === "number" && Number.isFinite(value);
35
- }
36
27
  function invalidSearchOptionsError(reason) {
37
28
  return new Error(`Invalid ${GPF_WFS_MINISEARCH_OPTIONS_ENV}: ${reason}`);
38
29
  }
39
- // --- Search options parsing ---
30
+ // --- Search options schema ---
31
+ const miniSearchOptionsSchema = z.object({
32
+ fields: z.array(z.enum(MINISEARCH_INDEXED_OPTION_KEYS)).optional(),
33
+ combineWith: z.enum(MINISEARCH_COMBINE_WITH_VALUES).optional(),
34
+ fuzzy: z.number().finite().optional(),
35
+ boost: z.record(z.enum(MINISEARCH_INDEXED_OPTION_KEYS), z.number().finite()).optional(),
36
+ }).strict();
40
37
  // Parses and validates a plain-object value into MiniSearchCollectionSearchOptions.
41
38
  // Throws a descriptive error if the value has unexpected keys or wrong value types.
42
39
  function parseMiniSearchOptions(value) {
43
- if (!isPlainObject(value)) {
44
- throw invalidSearchOptionsError("expected a JSON object");
45
- }
46
- for (const key of Object.keys(value)) {
47
- if (!TOP_LEVEL_MINISEARCH_OPTION_KEYS.includes(key)) {
48
- throw invalidSearchOptionsError(`unexpected key '${key}'`);
49
- }
50
- }
51
- const options = {};
52
- if (value.fields !== undefined) {
53
- if (!Array.isArray(value.fields)) {
54
- throw invalidSearchOptionsError("expected 'fields' to be an array");
55
- }
56
- const fields = [];
57
- for (const field of value.fields) {
58
- if (typeof field !== "string") {
59
- throw invalidSearchOptionsError("expected every 'fields' item to be a string");
60
- }
61
- if (!MINISEARCH_FIELD_OPTION_KEYS.includes(field)) {
62
- throw invalidSearchOptionsError(`unexpected value 'fields.${field}'`);
63
- }
64
- fields.push(field);
65
- }
66
- options.fields = fields;
67
- }
68
- if (value.combineWith !== undefined) {
69
- if (typeof value.combineWith !== "string") {
70
- throw invalidSearchOptionsError("expected 'combineWith' to be a string");
71
- }
72
- const combineWith = value.combineWith;
73
- if (!MINISEARCH_COMBINE_WITH_VALUES.includes(combineWith)) {
74
- throw invalidSearchOptionsError("expected 'combineWith' to be 'AND' or 'OR'");
75
- }
76
- options.combineWith = combineWith;
77
- }
78
- if (value.fuzzy !== undefined) {
79
- if (!isFiniteNumber(value.fuzzy)) {
80
- throw invalidSearchOptionsError("expected 'fuzzy' to be a finite number");
81
- }
82
- options.fuzzy = value.fuzzy;
83
- }
84
- if (value.boost !== undefined) {
85
- if (!isPlainObject(value.boost)) {
86
- throw invalidSearchOptionsError("expected 'boost' to be an object");
87
- }
88
- const boost = {};
89
- for (const key of Object.keys(value.boost)) {
90
- if (!MINISEARCH_BOOST_OPTION_KEYS.includes(key)) {
91
- throw invalidSearchOptionsError(`unexpected key 'boost.${key}'`);
92
- }
93
- const rawScore = value.boost[key];
94
- if (!isFiniteNumber(rawScore)) {
95
- throw invalidSearchOptionsError(`expected 'boost.${key}' to be a finite number`);
96
- }
97
- boost[key] = rawScore;
98
- }
99
- options.boost = boost;
40
+ const result = miniSearchOptionsSchema.safeParse(value);
41
+ if (!result.success) {
42
+ const issue = result.error.issues[0];
43
+ const path = issue.path.length > 0 ? issue.path.join('.') : undefined;
44
+ const detail = path ? `${path}: ${issue.message}` : issue.message;
45
+ throw invalidSearchOptionsError(detail);
100
46
  }
101
- return options;
47
+ return result.data;
102
48
  }
103
49
  function createMiniSearchEngineOptions(miniSearch) {
104
50
  if (!miniSearch) {
@@ -139,8 +85,8 @@ export class WfsClient {
139
85
  async getFeatureTypes() {
140
86
  return this.catalog.list();
141
87
  }
142
- async searchFeatureTypes(query, maxResults = 20) {
143
- return this.catalog.search(query, {
88
+ async searchFeatureTypesWithScores(query, maxResults = 20) {
89
+ return this.catalog.searchWithScores(query, {
144
90
  limit: maxResults,
145
91
  });
146
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"wfs.js","sourceRoot":"","sources":["../../src/gpf/wfs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wfs.js","sourceRoot":"","sources":["../../src/gpf/wfs.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  /**
2
- * Compute approximative distance in km between gA and gB.
2
+ * Compute approximative distance in meters between gA and gB.
3
3
  *
4
- * @param {object} gA GeoJSON Point
4
+ * TODO: replace the lon/lat planar nearest-point step with a geodesic geometry distance.
5
+ *
6
+ * @param {object} gA GeoJSON Geometry
5
7
  * @param {object} gB GeoJSON Geometry
6
8
  */
7
9
  export default function distance(gA: object, gB: object): number;
@@ -1,17 +1,32 @@
1
1
  import GeoJSONReader from 'jsts/org/locationtech/jts/io/GeoJSONReader.js';
2
2
  import { DistanceOp } from 'jsts/org/locationtech/jts/operation/distance.js';
3
+ import turfDistance from '@turf/distance';
4
+ import { point as turfPoint } from '@turf/helpers';
3
5
  /**
4
- * Compute approximative distance in km between gA and gB.
6
+ * Compute approximative distance in meters between gA and gB.
5
7
  *
6
- * @param {object} gA GeoJSON Point
8
+ * TODO: replace the lon/lat planar nearest-point step with a geodesic geometry distance.
9
+ *
10
+ * @param {object} gA GeoJSON Geometry
7
11
  * @param {object} gB GeoJSON Geometry
8
12
  */
9
13
  export default function distance(gA, gB) {
10
14
  const geojsonReader = new GeoJSONReader();
11
15
  const a = geojsonReader.read(gA);
12
16
  const b = geojsonReader.read(gB);
13
- // converts to kilometers assuming earth is a sphere
14
- const distanceInDegree = DistanceOp.distance(a, b);
15
- return 6480.0 * (distanceInDegree * 2.0 * Math.PI / 360.0);
17
+ /*
18
+ * Get the 2 nearest points between a and b
19
+ *
20
+ * Note that it will project according to longitude and latitude axis,
21
+ * so it is not really accurate, but it is a good approximation
22
+ */
23
+ const nearestPoints = DistanceOp.nearestPoints(a, b);
24
+ if (nearestPoints.length !== 2) {
25
+ throw new Error('DistanceOp.nearestPoints should return 2 points');
26
+ }
27
+ /*
28
+ * haversine distance between the 2 nearest points (see https://turfjs.org/docs/api/distance)
29
+ */
30
+ return turfDistance(turfPoint([nearestPoints[0].x, nearestPoints[0].y]), turfPoint([nearestPoints[1].x, nearestPoints[1].y]), { units: 'meters' });
16
31
  }
17
32
  //# sourceMappingURL=distance.js.map