@ignfab/geocontext 0.9.0 → 0.9.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.
Files changed (62) hide show
  1. package/README.md +51 -22
  2. package/dist/gpf/adminexpress.d.ts +2 -1
  3. package/dist/gpf/adminexpress.js +7 -3
  4. package/dist/gpf/adminexpress.js.map +1 -1
  5. package/dist/gpf/altitude.d.ts +2 -1
  6. package/dist/gpf/altitude.js +13 -19
  7. package/dist/gpf/altitude.js.map +1 -1
  8. package/dist/gpf/geocode.d.ts +3 -1
  9. package/dist/gpf/geocode.js +19 -8
  10. package/dist/gpf/geocode.js.map +1 -1
  11. package/dist/gpf/parcellaire-express.d.ts +2 -1
  12. package/dist/gpf/parcellaire-express.js +8 -4
  13. package/dist/gpf/parcellaire-express.js.map +1 -1
  14. package/dist/gpf/urbanisme.d.ts +4 -2
  15. package/dist/gpf/urbanisme.js +32 -5
  16. package/dist/gpf/urbanisme.js.map +1 -1
  17. package/dist/gpf/wfs.d.ts +5 -3
  18. package/dist/gpf/wfs.js +59 -19
  19. package/dist/gpf/wfs.js.map +1 -1
  20. package/dist/index.js +1 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/logger.js.map +1 -1
  23. package/dist/resources/WfsCqlFilterResource.d.ts +10 -0
  24. package/dist/resources/WfsCqlFilterResource.js +21 -0
  25. package/dist/resources/WfsCqlFilterResource.js.map +1 -0
  26. package/dist/resources/readMarkdownResource.d.ts +1 -0
  27. package/dist/resources/readMarkdownResource.js +21 -0
  28. package/dist/resources/readMarkdownResource.js.map +1 -0
  29. package/dist/tools/AdminexpressTool.d.ts +58 -15
  30. package/dist/tools/AdminexpressTool.js +33 -13
  31. package/dist/tools/AdminexpressTool.js.map +1 -1
  32. package/dist/tools/AltitudeTool.d.ts +64 -16
  33. package/dist/tools/AltitudeTool.js +30 -12
  34. package/dist/tools/AltitudeTool.js.map +1 -1
  35. package/dist/tools/AssietteSupTool.d.ts +64 -16
  36. package/dist/tools/AssietteSupTool.js +34 -13
  37. package/dist/tools/AssietteSupTool.js.map +1 -1
  38. package/dist/tools/CadastreTool.d.ts +68 -15
  39. package/dist/tools/CadastreTool.js +35 -13
  40. package/dist/tools/CadastreTool.js.map +1 -1
  41. package/dist/tools/GeocodeTool.d.ts +73 -10
  42. package/dist/tools/GeocodeTool.js +35 -9
  43. package/dist/tools/GeocodeTool.js.map +1 -1
  44. package/dist/tools/GpfWfsDescribeTypeTool.d.ts +115 -12
  45. package/dist/tools/GpfWfsDescribeTypeTool.js +39 -13
  46. package/dist/tools/GpfWfsDescribeTypeTool.js.map +1 -1
  47. package/dist/tools/GpfWfsGetFeaturesTool.d.ts +65 -28
  48. package/dist/tools/GpfWfsGetFeaturesTool.js +117 -47
  49. package/dist/tools/GpfWfsGetFeaturesTool.js.map +1 -1
  50. package/dist/tools/GpfWfsListTypesTool.d.ts +18 -6
  51. package/dist/tools/GpfWfsListTypesTool.js +16 -8
  52. package/dist/tools/GpfWfsListTypesTool.js.map +1 -1
  53. package/dist/tools/GpfWfsSearchTypesTool.d.ts +61 -14
  54. package/dist/tools/GpfWfsSearchTypesTool.js +38 -17
  55. package/dist/tools/GpfWfsSearchTypesTool.js.map +1 -1
  56. package/dist/tools/UrbanismeTool.d.ts +63 -15
  57. package/dist/tools/UrbanismeTool.js +42 -13
  58. package/dist/tools/UrbanismeTool.js.map +1 -1
  59. package/dist/tools/toolAnnotations.d.ts +6 -0
  60. package/dist/tools/toolAnnotations.js +7 -0
  61. package/dist/tools/toolAnnotations.js.map +1 -0
  62. package/package.json +5 -5
package/README.md CHANGED
@@ -14,7 +14,7 @@ L'idée est ici d'**expérimenter la conception d'un MCP rendant les données et
14
14
 
15
15
  ## Mises en garde
16
16
 
17
- - Ce développement est un POC en incubation avec IgnFab (archivage en cours de [mborne/geocontext](https://github.com/mborne/geocontext))
17
+ - Ce développement est un POC en incubation au sein d'ignfab (archivage en cours de [mborne/geocontext](https://github.com/mborne/geocontext))
18
18
  - S'il s'avère utile de l'industrialiser, le dépôt sera migré sous responsabilité IGN et l'outil sera renommé (ex : `IGNF/mcp-gpf-server`)
19
19
  - Plusieurs problèmes et améliorations possibles ont été identifiés et sont en cours de mitigation/résolution (c.f. [issues](https://github.com/ignfab/geocontext/issues?q=is%3Aissue%20state%3Aopen%20label%3Ametadata)).
20
20
  - Cet outil n'est pas magique (voir [Fonctionnalités](#fonctionnalités) pour avoir une idée de ses capacités)
@@ -42,14 +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
- 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 :
53
58
 
54
59
  ```json
55
60
  {
@@ -74,6 +79,8 @@ npm run build
74
79
 
75
80
  ### Utilisation de la version locale
76
81
 
82
+ #### Avec un client MCP compatible JSON
83
+
77
84
  ```json
78
85
  {
79
86
  "mcpServers": {
@@ -85,6 +92,27 @@ npm run build
85
92
  }
86
93
  ```
87
94
 
95
+ #### Avec Codex CLI / VS Code
96
+
97
+ Avec Codex CLI ou l'extension Codex pour VS Code, la configuration se fait dans `~/.codex/config.toml` :
98
+
99
+ ```toml
100
+ [mcp_servers.geocontext]
101
+ command = "node"
102
+ args = ["/chemin/absolu/vers/geocontext/dist/index.js"]
103
+
104
+ # Définition d'un corporate proxy si nécessaire
105
+ [mcp_servers.geocontext.env]
106
+ HTTPS_PROXY = "http://proxy.domain.fr:3128"
107
+ HTTP_PROXY = "http://proxy.domain.fr:3128"
108
+ NO_PROXY = "localhost,127.0.0.1"
109
+ http_proxy = "http://proxy.domain.fr:3128"
110
+ https_proxy = "http://proxy.domain.fr:3128"
111
+ no_proxy = "localhost,127.0.0.1"
112
+ ```
113
+
114
+ Après mise à jour de `~/.codex/config.toml`, relancer la session Codex CLI ou recharger VS Code si l'extension Codex est déjà ouverte.
115
+
88
116
  ### Debug de la version locale
89
117
 
90
118
  ```bash
@@ -95,18 +123,19 @@ npx -y @modelcontextprotocol/inspector node dist/index.js
95
123
 
96
124
  Pour une utilisation avancée :
97
125
 
98
- | Nom | Description | Valeur par défaut |
99
- | ---------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------- |
100
- | `TRANSPORT_TYPE` | [Transport](https://mcp-framework.com/docs/Transports/transports-overview) permet de choisir entre "stdio" et "http" | "stdio" |
101
- | `GPF_WFS_SEARCH_OPTIONS` | Chaîne JSON optionnelle pour ajuster la recherche `gpf_wfs_search_types` (`fuzzy`, `boost.namespace`, `boost.name`, `boost.title`, `boost.description`, `boost.properties`). | 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` |
102
131
 
103
132
  Exemple :
104
133
 
105
134
  ```bash
106
- export GPF_WFS_SEARCH_OPTIONS='{"fuzzy":0.05,"boost":{"title":4,"name":5}}'
135
+ export GPF_WFS_MINISEARCH_OPTIONS='{"fields":["title","identifierTokens"],"combineWith":"OR","fuzzy":0.05,"boost":{"title":4,"name":5}}'
107
136
  ```
108
137
 
109
- Si `GPF_WFS_SEARCH_OPTIONS` est absent ou vide, les options par défaut restent celles de `@ignfab/gpf-schema-store`.
138
+ Si `GPF_WFS_MINISEARCH_OPTIONS` est absent ou vide, les options par défaut restent celles de `@ignfab/gpf-schema-store`, y compris le comportement par défaut `OR` de MiniSearch pour `combineWith`.
110
139
 
111
140
  Remarque :
112
141
 
@@ -148,18 +177,18 @@ L'idée est ici de répondre à des précises en traitant côté serveur les app
148
177
 
149
178
  ### Explorer les données vecteurs
150
179
 
151
- #### Explorer les tables
152
-
153
- * [gpf_wfs_list_types()](src/tools/GpfWfsListTypesTool.ts) pour **lister les tables connues du catalogue de schémas embarqué** - **déprécié (trop de résultats)**
154
- * [gpf_wfs_search_types(keywords,max_results=10)](src/tools/GpfWfsSearchTypesTool.ts) pour **rechercher des tables dans le catalogue de schémas embarqué**. La recherche est textuelle et configurable via `GPF_WFS_SEARCH_OPTIONS`.
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`.
155
184
 
156
185
  > - Quels sont les millésimes ADMINEXPRESS disponibles sur la Géoplateforme?
157
186
  > - Quelle est la table de la BDTOPO correspondant aux bâtiments?
158
187
  > - Dans quelle table de la BDTOPO peut-on trouver les ponts?
159
188
 
160
- #### Explorer la structure des tables
161
-
162
- * [gpf_wfs_describe_type(typename)](src/tools/GpfWfsDescribeTypeTool.ts) pour récupérer le **schéma détaillé d'une table** depuis le catalogue embarqué (`id`, `namespace`, `name`, `title`, `description`, `properties`)
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`
163
192
 
164
193
  > - Quelles sont les informations disponibles pour les communes avec ADMINEXPRESS-COG.LATEST?
165
194
  > - Compare le modèle des communes entre ADMINEXPRESS-COG:2024 et ADMINEXPRESS-COG.LATEST
@@ -3,9 +3,10 @@
3
3
  *
4
4
  * @param {number} lon
5
5
  * @param {number} lat
6
+ * @param {(url: string) => Promise<any>} [fetcher]
6
7
  * @returns {object[]}
7
8
  */
8
- export function getAdminUnits(lon: number, lat: number): object[];
9
+ export function getAdminUnits(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): object[];
9
10
  /**
10
11
  * ADMINEXPRESS-COG.LATEST:{type}
11
12
  *
@@ -1,6 +1,6 @@
1
+ import _ from 'lodash';
1
2
  import { fetchJSON } from '../helpers/http.js';
2
3
  import logger from '../logger.js';
3
- import _ from 'lodash';
4
4
  /**
5
5
  * ADMINEXPRESS-COG.LATEST:{type}
6
6
  *
@@ -21,9 +21,10 @@ export const ADMINEXPRESS_TYPES = [
21
21
  *
22
22
  * @param {number} lon
23
23
  * @param {number} lat
24
+ * @param {(url: string) => Promise<any>} [fetcher]
24
25
  * @returns {object[]}
25
26
  */
26
- export async function getAdminUnits(lon, lat) {
27
+ export async function getAdminUnits(lon, lat, fetcher = fetchJSON) {
27
28
  logger.info(`[adminexpress] getAdminUnits(${lon},${lat})...`);
28
29
  // note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
29
30
  const cql_filter = `INTERSECTS(geometrie,Point(${lat} ${lon}))`;
@@ -35,7 +36,10 @@ export async function getAdminUnits(lon, lat) {
35
36
  outputFormat: 'application/json',
36
37
  cql_filter: cql_filter
37
38
  }).toString();
38
- const featureCollection = await fetchJSON(url);
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
+ }
39
43
  return featureCollection.features.map((feature) => {
40
44
  // parse type from id (ex: "commune.3837")
41
45
  const type = feature.id.split('.')[0];
@@ -1 +1 @@
1
- {"version":3,"file":"adminexpress.js","sourceRoot":"","sources":["../../src/gpf/adminexpress.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB;;;;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;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAG,EAAE,GAAG;IACxC,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,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/C,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,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"}
@@ -5,9 +5,10 @@
5
5
  *
6
6
  * @param {number} lon
7
7
  * @param {number} lat
8
+ * @param {(url: string) => Promise<any>} [fetcher]
8
9
  * @returns
9
10
  */
10
- export function getAltitudeByLocation(lon: number, lat: number): Promise<{
11
+ export function getAltitudeByLocation(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<{
11
12
  lon: number;
12
13
  lat: number;
13
14
  altitude: any;
@@ -1,5 +1,5 @@
1
- import logger from "../logger.js";
2
1
  import { fetchJSON } from "../helpers/http.js";
2
+ import logger from "../logger.js";
3
3
  export const ALTITUDE_SOURCE = "Géoplateforme (altimétrie)";
4
4
  /**
5
5
  * Get altitude for a given location.
@@ -8,28 +8,22 @@ 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]
11
12
  * @returns
12
13
  */
13
- export async function getAltitudeByLocation(lon, lat) {
14
+ export async function getAltitudeByLocation(lon, lat, fetcher = fetchJSON) {
14
15
  logger.info(`getAltitudeByLocation(${lon},${lat})...`);
15
16
  const url = `https://data.geopf.fr/altimetrie/1.0/calcul/alti/rest/elevation.json?lon=${lon}&lat=${lat}&resource=ign_rge_alti_wld`;
16
- try {
17
- const json = await fetchJSON(url);
18
- const elevation = json.elevations[0];
19
- return {
20
- lon: lon,
21
- lat: lat,
22
- altitude: elevation.z,
23
- accuracy: elevation.acc,
24
- };
25
- }
26
- catch (e) {
27
- return {
28
- lon: lon,
29
- lat: lat,
30
- altitude: null,
31
- accuracy: 'No data',
32
- };
17
+ const json = await fetcher(url);
18
+ const elevation = json?.elevations?.[0];
19
+ if (!elevation) {
20
+ throw new Error("Le service d'altitude n'a renvoyé aucune donnée d'altitude");
33
21
  }
22
+ return {
23
+ lon: lon,
24
+ lat: lat,
25
+ altitude: elevation.z,
26
+ accuracy: elevation.acc,
27
+ };
34
28
  }
35
29
  //# sourceMappingURL=altitude.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"altitude.js","sourceRoot":"","sources":["../../src/gpf/altitude.js"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,MAAM,eAAe,GAAG,4BAA4B,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAG,EAAE,GAAG;IAChD,MAAM,CAAC,IAAI,CAAC,yBAAyB,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IAEvD,MAAM,GAAG,GAAG,4EAA4E,GAAG,QAAQ,GAAG,4BAA4B,CAAC;IACnI,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAE;QACtC,OAAO;YACH,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG;YACR,QAAQ,EAAE,SAAS,CAAC,CAAC;YACrB,QAAQ,EAAE,SAAS,CAAC,GAAG;SAC1B,CAAC;IACN,CAAC;IAAA,OAAM,CAAC,EAAC,CAAC;QACN,OAAO;YACH,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,SAAS;SACtB,CAAC;IACN,CAAC;AAGL,CAAC"}
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"}
@@ -4,7 +4,9 @@
4
4
  * @see https://geoservices.ign.fr/documentation/services/services-geoplateforme/autocompletion
5
5
  *
6
6
  * @param {string} text
7
+ * @param {number} [maximumResponses=3]
8
+ * @param {(url: string) => Promise<any>} [fetcher]
7
9
  * @returns
8
10
  */
9
- export function geocode(text: string): Promise<any>;
11
+ export function geocode(text: string, maximumResponses?: number, fetcher?: (url: string) => Promise<any>): Promise<any>;
10
12
  export const GEOCODE_SOURCE: "G\u00E9oplateforme (service d'autocompl\u00E9tion)";
@@ -1,26 +1,37 @@
1
- import logger from "../logger.js";
2
1
  import { fetchJSON } from "../helpers/http.js";
2
+ import logger from "../logger.js";
3
3
  export const GEOCODE_SOURCE = "Géoplateforme (service d'autocomplétion)";
4
+ // https://data.geopf.fr/geocodage/completion/openapi does not provide all the necessary information yet
4
5
  /**
5
6
  * Get coordinates for a given location
6
7
  *
7
8
  * @see https://geoservices.ign.fr/documentation/services/services-geoplateforme/autocompletion
8
9
  *
9
10
  * @param {string} text
11
+ * @param {number} [maximumResponses=3]
12
+ * @param {(url: string) => Promise<any>} [fetcher]
10
13
  * @returns
11
14
  */
12
- export async function geocode(text) {
13
- logger.info(`geocode(${JSON.stringify(text)})...`);
15
+ export async function geocode(text, maximumResponses = 3, fetcher = fetchJSON) {
16
+ const normalizedText = typeof text === "string" ? text.trim() : "";
17
+ if (!normalizedText) {
18
+ return [];
19
+ }
20
+ logger.info(`geocode(${JSON.stringify(normalizedText)}, ${maximumResponses})...`);
14
21
  const url = 'https://data.geopf.fr/geocodage/completion/?' + new URLSearchParams({
15
- text: text,
16
- maximumResponses: 3
22
+ text: normalizedText,
23
+ maximumResponses: String(maximumResponses)
17
24
  }).toString();
18
- const json = await fetchJSON(url);
19
- return json.results.map((item) => {
25
+ const json = await fetcher(url);
26
+ const results = Array.isArray(json?.results) ? json.results : [];
27
+ return results.map((item) => {
20
28
  return {
21
29
  lon: item.x,
22
30
  lat: item.y,
23
- fulltext: item.fulltext
31
+ fulltext: item.fulltext,
32
+ kind: item.kind,
33
+ city: item.city,
34
+ zipcode: item.zipcode
24
35
  };
25
36
  });
26
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"geocode.js","sourceRoot":"","sources":["../../src/gpf/geocode.js"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,CAAC,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAEzE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAI;IAC9B,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEnD,MAAM,GAAG,GAAG,8CAA8C,GAAG,IAAI,eAAe,CAAC;QAC/E,IAAI,EAAE,IAAI;QACV,gBAAgB,EAAE,CAAC;KACpB,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAC,EAAE;QAAC,OAAO;YACtC,GAAG,EAAE,IAAI,CAAC,CAAC;YACX,GAAG,EAAE,IAAI,CAAC,CAAC;YACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAA;IAAA,CAAC,CAAC,CAAC;AACR,CAAC"}
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"}
@@ -5,8 +5,9 @@
5
5
  *
6
6
  * @param {number} lon
7
7
  * @param {number} lat
8
+ * @param {(url: string) => Promise<any>} [fetcher]
8
9
  * @returns
9
10
  */
10
- export function getParcellaireExpress(lon: number, lat: number): Promise<array<object>>;
11
+ export function getParcellaireExpress(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<array<object>>;
11
12
  export const PARCELLAIRE_EXPRESS_SOURCE: "G\u00E9oplateforme (WFS, CADASTRALPARCELS.PARCELLAIRE_EXPRESS)";
12
13
  export const PARCELLAIRE_EXPRESS_TYPES: string[];
@@ -1,7 +1,7 @@
1
- import logger from '../logger.js';
2
- import distance from '../helpers/distance.js';
3
1
  import _ from 'lodash';
2
+ import distance from '../helpers/distance.js';
4
3
  import { fetchJSON } from '../helpers/http.js';
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
7
7
  export const PARCELLAIRE_EXPRESS_SOURCE = "Géoplateforme (WFS, CADASTRALPARCELS.PARCELLAIRE_EXPRESS)";
@@ -39,9 +39,10 @@ function filterByDistance(items) {
39
39
  *
40
40
  * @param {number} lon
41
41
  * @param {number} lat
42
+ * @param {(url: string) => Promise<any>} [fetcher]
42
43
  * @returns
43
44
  */
44
- export async function getParcellaireExpress(lon, lat) {
45
+ export async function getParcellaireExpress(lon, lat, fetcher = fetchJSON) {
45
46
  logger.info(`getParcellaireExpress(${lon},${lat}) ...`);
46
47
  // note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
47
48
  const cql_filter = `DWITHIN(geom,Point(${lat} ${lon}),10,meters)`;
@@ -57,7 +58,10 @@ export async function getParcellaireExpress(lon, lat) {
57
58
  outputFormat: 'application/json',
58
59
  cql_filter: cql_filter
59
60
  }).toString();
60
- const featureCollection = await fetchJSON(url);
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
+ }
61
65
  return filterByDistance(featureCollection.features.map((feature) => {
62
66
  // parse type from id (ex: "commune.3837")
63
67
  const type = feature.id.split('.')[0];
@@ -1 +1 @@
1
- {"version":3,"file":"parcellaire-express.js","sourceRoot":"","sources":["../../src/gpf/parcellaire-express.js"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAE9C,OAAO,CAAC,MAAM,QAAQ,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,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;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAG,EAAE,GAAG;IAChD,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,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/C,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,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"}
@@ -3,16 +3,18 @@
3
3
  *
4
4
  * @param {number} lon
5
5
  * @param {number} lat
6
+ * @param {(url: string) => Promise<any>} [fetcher]
6
7
  * @returns
7
8
  */
8
- export function getUrbanisme(lon: number, lat: number): Promise<any>;
9
+ export function getUrbanisme(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<any>;
9
10
  /**
10
11
  * Get SUP infos for a given location
11
12
  *
12
13
  * @param {number} lon
13
14
  * @param {number} lat
15
+ * @param {(url: string) => Promise<any>} [fetcher]
14
16
  * @returns
15
17
  */
16
- export function getAssiettesServitudes(lon: number, lat: number): Promise<any>;
18
+ export function getAssiettesServitudes(lon: number, lat: number, fetcher?: (url: string) => Promise<any>): Promise<any>;
17
19
  export const URBANISME_TYPES: string[];
18
20
  export const URBANISME_SOURCE: "G\u00E9oplateforme - (WFS G\u00E9oportail de l'Urbanisme)";
@@ -15,14 +15,33 @@ 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
+ const URBANISME_EXCLUDED_PROPERTIES = new Set([
20
+ 'gpu_status',
21
+ 'urlfic'
22
+ ]);
23
+ function sanitizeUrbanismeItem(item) {
24
+ const sanitized = {};
25
+ for (const [key, value] of Object.entries(item)) {
26
+ if (URBANISME_EXCLUDED_PROPERTIES.has(key)) {
27
+ continue;
28
+ }
29
+ if (value === null || value === '') {
30
+ continue;
31
+ }
32
+ sanitized[key] = value;
33
+ }
34
+ return sanitized;
35
+ }
18
36
  /**
19
37
  * Get urbanism infos for a given location
20
38
  *
21
39
  * @param {number} lon
22
40
  * @param {number} lat
41
+ * @param {(url: string) => Promise<any>} [fetcher]
23
42
  * @returns
24
43
  */
25
- export async function getUrbanisme(lon, lat) {
44
+ export async function getUrbanisme(lon, lat, fetcher = fetchJSON) {
26
45
  logger.info(`getUrbanisme(${lon},${lat})...`);
27
46
  // note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
28
47
  const cql_filter = `DWITHIN(the_geom,Point(${lat} ${lon}),30,meters)`;
@@ -38,17 +57,21 @@ export async function getUrbanisme(lon, lat) {
38
57
  outputFormat: 'application/json',
39
58
  cql_filter: cql_filter
40
59
  }).toString();
41
- const featureCollection = await fetchJSON(url);
60
+ const featureCollection = await fetcher(url);
61
+ if (!Array.isArray(featureCollection?.features)) {
62
+ throw new Error(URBANISME_INVALID_COLLECTION_ERROR);
63
+ }
42
64
  return featureCollection.features.map((feature) => {
43
65
  // parse type from id (ex: "commune.3837")
44
66
  const type = feature.id.split('.')[0];
45
67
  // ignore geometry and extend properties
46
- return Object.assign({
68
+ const item = Object.assign({
47
69
  type: type,
48
70
  id: feature.id,
49
71
  bbox: feature.bbox,
50
72
  distance: (distance(sourceGeom, feature.geometry) * 1000.0)
51
73
  }, feature.properties);
74
+ return sanitizeUrbanismeItem(item);
52
75
  });
53
76
  }
54
77
  const ASSIETTES_SUP_TYPES = [
@@ -61,9 +84,10 @@ const ASSIETTES_SUP_TYPES = [
61
84
  *
62
85
  * @param {number} lon
63
86
  * @param {number} lat
87
+ * @param {(url: string) => Promise<any>} [fetcher]
64
88
  * @returns
65
89
  */
66
- export async function getAssiettesServitudes(lon, lat) {
90
+ export async function getAssiettesServitudes(lon, lat, fetcher = fetchJSON) {
67
91
  logger.info(`getAssiettesServitudes(${lon},${lat})...`);
68
92
  // note that EPSG:4326 means lat,lon order for GeoServer -> flipped coordinates...
69
93
  const cql_filter = `DWITHIN(the_geom,Point(${lat} ${lon}),30,meters)`;
@@ -79,7 +103,10 @@ export async function getAssiettesServitudes(lon, lat) {
79
103
  outputFormat: 'application/json',
80
104
  cql_filter: cql_filter
81
105
  }).toString();
82
- const featureCollection = await fetchJSON(url);
106
+ const featureCollection = await fetcher(url);
107
+ if (!Array.isArray(featureCollection?.features)) {
108
+ throw new Error(URBANISME_INVALID_COLLECTION_ERROR);
109
+ }
83
110
  return featureCollection.features.map((feature) => {
84
111
  // parse type from id (ex: "commune.3837")
85
112
  const type = feature.id.split('.')[0];
@@ -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,17 +1,19 @@
1
- import { Collection, MiniSearchCollectionSearchEngineOptions } from '@ignfab/gpf-schema-store';
1
+ import { Collection, MiniSearchCollectionSearchOptions } from '@ignfab/gpf-schema-store';
2
2
  export declare const GPF_WFS_URL = "https://data.geopf.fr/wfs";
3
+ type MiniSearchOptions = MiniSearchCollectionSearchOptions;
3
4
  export declare class FeatureTypeNotFoundError extends Error {
4
5
  constructor(name: string);
5
6
  }
6
- export declare function loadSearchOptionsFromEnv(): MiniSearchCollectionSearchEngineOptions | undefined;
7
+ export declare function loadMiniSearchOptionsFromEnv(): MiniSearchOptions | undefined;
7
8
  export declare class WfsClient {
8
9
  baseUrl: string;
9
10
  private readonly catalog;
10
11
  constructor(baseUrl?: string, options?: {
11
- search?: MiniSearchCollectionSearchEngineOptions;
12
+ miniSearch?: MiniSearchOptions;
12
13
  });
13
14
  getFeatureTypes(): Promise<Collection[]>;
14
15
  searchFeatureTypes(query: string, maxResults?: number): Promise<Collection[]>;
15
16
  getFeatureType(name: string): Promise<Collection>;
16
17
  }
17
18
  export declare const wfsClient: WfsClient;
19
+ export {};