@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.
- package/README.md +349 -259
- package/dist/gpf/adminexpress.d.ts +17 -8
- package/dist/gpf/adminexpress.js +40 -17
- package/dist/gpf/adminexpress.js.map +1 -1
- package/dist/gpf/altitude.d.ts +21 -9
- package/dist/gpf/altitude.js +5 -5
- package/dist/gpf/altitude.js.map +1 -1
- package/dist/gpf/geocode.d.ts +25 -4
- package/dist/gpf/geocode.js +5 -5
- package/dist/gpf/geocode.js.map +1 -1
- package/dist/gpf/parcellaire-express.d.ts +19 -9
- package/dist/gpf/parcellaire-express.js +59 -26
- package/dist/gpf/parcellaire-express.js.map +1 -1
- package/dist/gpf/urbanisme.d.ts +24 -16
- package/dist/gpf/urbanisme.js +81 -33
- package/dist/gpf/urbanisme.js.map +1 -1
- package/dist/gpf/{wfs.js → wfs-schema-catalog.js} +1 -1
- package/dist/gpf/wfs-schema-catalog.js.map +1 -0
- package/dist/helpers/RateLimiter.d.ts +44 -0
- package/dist/helpers/RateLimiter.js +52 -0
- package/dist/helpers/RateLimiter.js.map +1 -0
- package/dist/helpers/distance.d.ts +2 -1
- package/dist/helpers/distance.js +2 -1
- package/dist/helpers/distance.js.map +1 -1
- package/dist/helpers/errors/toolError.d.ts +30 -0
- package/dist/helpers/errors/toolError.js +193 -0
- package/dist/helpers/errors/toolError.js.map +1 -0
- package/dist/helpers/errors/zodErrorMapFr.d.ts +20 -0
- package/dist/helpers/errors/zodErrorMapFr.js +191 -0
- package/dist/helpers/errors/zodErrorMapFr.js.map +1 -0
- package/dist/helpers/http.d.ts +67 -7
- package/dist/helpers/http.js +458 -84
- package/dist/helpers/http.js.map +1 -1
- package/dist/helpers/jsonSchema.d.ts +20 -2
- package/dist/helpers/jsonSchema.js +12 -0
- package/dist/helpers/jsonSchema.js.map +1 -1
- package/dist/helpers/schemas.d.ts +4 -4
- package/dist/helpers/wfs_engine/attributeFilter.d.ts +51 -0
- package/dist/helpers/wfs_engine/attributeFilter.js +258 -0
- package/dist/helpers/wfs_engine/attributeFilter.js.map +1 -0
- package/dist/helpers/wfs_engine/byId.d.ts +76 -0
- package/dist/helpers/wfs_engine/byId.js +106 -0
- package/dist/helpers/wfs_engine/byId.js.map +1 -0
- package/dist/helpers/wfs_engine/execution.d.ts +72 -0
- package/dist/helpers/wfs_engine/execution.js +95 -0
- package/dist/helpers/wfs_engine/execution.js.map +1 -0
- package/dist/helpers/wfs_engine/features.d.ts +64 -0
- package/dist/helpers/wfs_engine/features.js +138 -0
- package/dist/helpers/wfs_engine/features.js.map +1 -0
- package/dist/helpers/wfs_engine/geometry.d.ts +16 -0
- package/dist/helpers/wfs_engine/geometry.js +44 -0
- package/dist/helpers/wfs_engine/geometry.js.map +1 -0
- package/dist/helpers/wfs_engine/properties.d.ts +51 -0
- package/dist/helpers/wfs_engine/properties.js +128 -0
- package/dist/helpers/wfs_engine/properties.js.map +1 -0
- package/dist/helpers/wfs_engine/queryPreparation.d.ts +32 -0
- package/dist/helpers/wfs_engine/queryPreparation.js +149 -0
- package/dist/helpers/wfs_engine/queryPreparation.js.map +1 -0
- package/dist/helpers/wfs_engine/request.d.ts +94 -0
- package/dist/helpers/wfs_engine/request.js +197 -0
- package/dist/helpers/wfs_engine/request.js.map +1 -0
- package/dist/helpers/wfs_engine/response.d.ts +80 -0
- package/dist/helpers/wfs_engine/response.js +135 -0
- package/dist/helpers/wfs_engine/response.js.map +1 -0
- package/dist/helpers/wfs_engine/schema.d.ts +209 -0
- package/dist/helpers/{wfs_internal → wfs_engine}/schema.js +50 -10
- package/dist/helpers/wfs_engine/schema.js.map +1 -0
- package/dist/helpers/wfs_engine/spatialCql.d.ts +46 -0
- package/dist/helpers/wfs_engine/spatialCql.js +54 -0
- package/dist/helpers/wfs_engine/spatialCql.js.map +1 -0
- package/dist/helpers/wfs_engine/spatialFilter.d.ts +14 -0
- package/dist/helpers/wfs_engine/spatialFilter.js +131 -0
- package/dist/helpers/wfs_engine/spatialFilter.js.map +1 -0
- package/dist/index.js +65 -23
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +4 -1
- package/dist/logger.js.map +1 -1
- package/dist/tools/AdminexpressTool.d.ts +42 -33
- package/dist/tools/AdminexpressTool.js +19 -3
- package/dist/tools/AdminexpressTool.js.map +1 -1
- package/dist/tools/AltitudeTool.d.ts +35 -44
- package/dist/tools/AltitudeTool.js +19 -8
- package/dist/tools/AltitudeTool.js.map +1 -1
- package/dist/tools/AssietteSupTool.d.ts +51 -34
- package/dist/tools/AssietteSupTool.js +18 -2
- package/dist/tools/AssietteSupTool.js.map +1 -1
- package/dist/tools/BaseTool.d.ts +17 -0
- package/dist/tools/BaseTool.js +41 -0
- package/dist/tools/BaseTool.js.map +1 -0
- package/dist/tools/CadastreTool.d.ts +53 -33
- package/dist/tools/CadastreTool.js +18 -2
- package/dist/tools/CadastreTool.js.map +1 -1
- package/dist/tools/GeocodeTool.d.ts +53 -37
- package/dist/tools/GeocodeTool.js +17 -2
- package/dist/tools/GeocodeTool.js.map +1 -1
- package/dist/tools/GpfWfsDescribeTypeTool.d.ts +66 -94
- package/dist/tools/GpfWfsDescribeTypeTool.js +26 -15
- package/dist/tools/GpfWfsDescribeTypeTool.js.map +1 -1
- package/dist/tools/GpfWfsGetFeatureByIdTool.d.ts +89 -0
- package/dist/tools/GpfWfsGetFeatureByIdTool.js +99 -0
- package/dist/tools/GpfWfsGetFeatureByIdTool.js.map +1 -0
- package/dist/tools/GpfWfsGetFeaturesTool.d.ts +89 -123
- package/dist/tools/GpfWfsGetFeaturesTool.js +31 -144
- package/dist/tools/GpfWfsGetFeaturesTool.js.map +1 -1
- package/dist/tools/GpfWfsSearchTypesTool.d.ts +41 -32
- package/dist/tools/GpfWfsSearchTypesTool.js +18 -3
- package/dist/tools/GpfWfsSearchTypesTool.js.map +1 -1
- package/dist/tools/UrbanismeTool.d.ts +42 -33
- package/dist/tools/UrbanismeTool.js +18 -2
- package/dist/tools/UrbanismeTool.js.map +1 -1
- package/package.json +51 -24
- package/dist/gpf/wfs.js.map +0 -1
- package/dist/helpers/wfs.d.ts +0 -27
- package/dist/helpers/wfs.js +0 -55
- package/dist/helpers/wfs.js.map +0 -1
- package/dist/helpers/wfs_internal/compile.d.ts +0 -46
- package/dist/helpers/wfs_internal/compile.js +0 -595
- package/dist/helpers/wfs_internal/compile.js.map +0 -1
- package/dist/helpers/wfs_internal/request.d.ts +0 -38
- package/dist/helpers/wfs_internal/request.js +0 -92
- package/dist/helpers/wfs_internal/request.js.map +0 -1
- package/dist/helpers/wfs_internal/response.d.ts +0 -21
- package/dist/helpers/wfs_internal/response.js +0 -29
- package/dist/helpers/wfs_internal/response.js.map +0 -1
- package/dist/helpers/wfs_internal/schema.d.ts +0 -167
- package/dist/helpers/wfs_internal/schema.js.map +0 -1
- /package/dist/gpf/{wfs.d.ts → wfs-schema-catalog.d.ts} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-level WFS execution helpers for the structured WFS engine.
|
|
3
|
+
*
|
|
4
|
+
* This module centralizes:
|
|
5
|
+
* - feature type lookup from the embedded catalog
|
|
6
|
+
* - execution of compiled WFS requests
|
|
7
|
+
* - extraction of response-level metadata such as total hit counts
|
|
8
|
+
*/
|
|
9
|
+
import type { CompiledRequest } from "./request.js";
|
|
10
|
+
export type WfsFeatureResponse = {
|
|
11
|
+
type?: "Feature";
|
|
12
|
+
id?: string;
|
|
13
|
+
geometry?: unknown;
|
|
14
|
+
geometry_name?: string;
|
|
15
|
+
properties?: Record<string, unknown>;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
};
|
|
18
|
+
export type WfsFeatureCollectionResponse = Record<string, unknown> & {
|
|
19
|
+
features?: WfsFeatureResponse[];
|
|
20
|
+
totalFeatures?: number;
|
|
21
|
+
numberMatched?: number | "unknown";
|
|
22
|
+
numberReturned?: number;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Loads a WFS feature type description from the embedded catalog.
|
|
26
|
+
*
|
|
27
|
+
* @param typename Exact WFS typename to load from the embedded schema store.
|
|
28
|
+
* @returns The matching feature type description.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getFeatureType(typename: string): Promise<Collection>;
|
|
31
|
+
/**
|
|
32
|
+
* Executes a compiled WFS request as POST and returns the JSON FeatureCollection.
|
|
33
|
+
*
|
|
34
|
+
* @param request Compiled request split into query-string parameters and POST body.
|
|
35
|
+
* @returns The parsed JSON response returned by the WFS endpoint.
|
|
36
|
+
*/
|
|
37
|
+
export declare function fetchFeatureCollection(request: CompiledRequest): Promise<WfsFeatureCollectionResponse>;
|
|
38
|
+
/**
|
|
39
|
+
* Extracts a result count from a WFS response using `numberMatched`.
|
|
40
|
+
* Explicitly rejects responses that do not provide a usable WFS 2 total.
|
|
41
|
+
*
|
|
42
|
+
* @param featureCollection Parsed WFS response object.
|
|
43
|
+
* @returns The total number of matching features.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getMatchedFeatureCount(featureCollection: WfsFeatureCollectionResponse): number;
|
|
46
|
+
/**
|
|
47
|
+
* Input parameters for multi-typename WFS execution.
|
|
48
|
+
*/
|
|
49
|
+
export type MultiTypenameExecutionInput = {
|
|
50
|
+
/** Fully qualified WFS type names to query. */
|
|
51
|
+
typenames: string[];
|
|
52
|
+
/** Pre-compiled CQL filter string, when one shared filter is intentionally reused for all typenames. */
|
|
53
|
+
cqlFilter?: string;
|
|
54
|
+
/** Pre-compiled CQL filters aligned with `typenames` (same length, same order). */
|
|
55
|
+
cqlFilters?: string[];
|
|
56
|
+
/** Service label used in error messages. */
|
|
57
|
+
errorLabel: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Executes a WFS GetFeature request targeting multiple typenames.
|
|
61
|
+
*
|
|
62
|
+
* Uses the WFS 2.0.0 multi-typename format expected by GeoServer:
|
|
63
|
+
* - `typeNames=(type1)(type2)...`
|
|
64
|
+
* - `cql_filter=filter1;filter2;...` (one filter per typename, same order)
|
|
65
|
+
*
|
|
66
|
+
* This helper is used by domain-oriented modules (`src/gpf/*`) that
|
|
67
|
+
* query several WFS layers at once with a pre-compiled CQL filter.
|
|
68
|
+
*
|
|
69
|
+
* @param input Multi-typename execution parameters.
|
|
70
|
+
* @returns The parsed JSON FeatureCollection returned by the WFS endpoint.
|
|
71
|
+
*/
|
|
72
|
+
export declare function fetchWfsMultiTypename(input: MultiTypenameExecutionInput): Promise<WfsFeatureCollectionResponse>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-level WFS execution helpers for the structured WFS engine.
|
|
3
|
+
*
|
|
4
|
+
* This module centralizes:
|
|
5
|
+
* - feature type lookup from the embedded catalog
|
|
6
|
+
* - execution of compiled WFS requests
|
|
7
|
+
* - extraction of response-level metadata such as total hit counts
|
|
8
|
+
*/
|
|
9
|
+
import { buildMultiTypenameRequest } from "./request.js";
|
|
10
|
+
import { wfsClient } from "../../gpf/wfs-schema-catalog.js";
|
|
11
|
+
import { fetchJSONPost } from "../http.js";
|
|
12
|
+
import { createRateLimiter } from "../RateLimiter.js";
|
|
13
|
+
/**
|
|
14
|
+
* Default rate limit for WFS requests, in requests per second.
|
|
15
|
+
* https://cartes.gouv.fr/aide/fr/guides-utilisateur/utiliser-les-services-de-la-geoplateforme/limites-d-usage/#valeur-de-la-limite-d-usage-pour-chaque-api-concernee
|
|
16
|
+
*
|
|
17
|
+
* TODO in #33 : move/call fetchFeatureCollection and fetchWfsMultiTypename in WfsClient to allow rateLimiter as a property?
|
|
18
|
+
*/
|
|
19
|
+
const gpfWfsRateLimit = parseInt(process.env.GPF_WFS_RATE_LIMIT || "30", 10);
|
|
20
|
+
const gpfWfsRateLimiter = createRateLimiter("GPF_WFS", gpfWfsRateLimit, 1);
|
|
21
|
+
// --- Catalog Lookup ---
|
|
22
|
+
/**
|
|
23
|
+
* Loads a WFS feature type description from the embedded catalog.
|
|
24
|
+
*
|
|
25
|
+
* @param typename Exact WFS typename to load from the embedded schema store.
|
|
26
|
+
* @returns The matching feature type description.
|
|
27
|
+
*/
|
|
28
|
+
export async function getFeatureType(typename) {
|
|
29
|
+
return wfsClient.getFeatureType(typename);
|
|
30
|
+
}
|
|
31
|
+
// --- Request Execution ---
|
|
32
|
+
/**
|
|
33
|
+
* Executes a compiled WFS request as POST and returns the JSON FeatureCollection.
|
|
34
|
+
*
|
|
35
|
+
* @param request Compiled request split into query-string parameters and POST body.
|
|
36
|
+
* @returns The parsed JSON response returned by the WFS endpoint.
|
|
37
|
+
*/
|
|
38
|
+
export async function fetchFeatureCollection(request) {
|
|
39
|
+
// Enforce a global rate limit on all WFS requests to the GPF.
|
|
40
|
+
await gpfWfsRateLimiter.limit();
|
|
41
|
+
const url = `${request.url}?${new URLSearchParams(request.query).toString()}`;
|
|
42
|
+
return fetchJSONPost(url, request.body, {
|
|
43
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
44
|
+
"Accept": "application/json",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// --- Response Metadata ---
|
|
48
|
+
/**
|
|
49
|
+
* Extracts a result count from a WFS response using `numberMatched`.
|
|
50
|
+
* Explicitly rejects responses that do not provide a usable WFS 2 total.
|
|
51
|
+
*
|
|
52
|
+
* @param featureCollection Parsed WFS response object.
|
|
53
|
+
* @returns The total number of matching features.
|
|
54
|
+
*/
|
|
55
|
+
export function getMatchedFeatureCount(featureCollection) {
|
|
56
|
+
if (typeof featureCollection.numberMatched === "number") {
|
|
57
|
+
return featureCollection.numberMatched;
|
|
58
|
+
}
|
|
59
|
+
if (featureCollection.numberMatched === "unknown") {
|
|
60
|
+
throw new Error("Le service WFS a renvoyé un comptage indéterminé (numberMatched=\"unknown\").");
|
|
61
|
+
}
|
|
62
|
+
throw new Error("Le service WFS n'a pas retourné de comptage exploitable dans `numberMatched`.");
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Executes a WFS GetFeature request targeting multiple typenames.
|
|
66
|
+
*
|
|
67
|
+
* Uses the WFS 2.0.0 multi-typename format expected by GeoServer:
|
|
68
|
+
* - `typeNames=(type1)(type2)...`
|
|
69
|
+
* - `cql_filter=filter1;filter2;...` (one filter per typename, same order)
|
|
70
|
+
*
|
|
71
|
+
* This helper is used by domain-oriented modules (`src/gpf/*`) that
|
|
72
|
+
* query several WFS layers at once with a pre-compiled CQL filter.
|
|
73
|
+
*
|
|
74
|
+
* @param input Multi-typename execution parameters.
|
|
75
|
+
* @returns The parsed JSON FeatureCollection returned by the WFS endpoint.
|
|
76
|
+
*/
|
|
77
|
+
export async function fetchWfsMultiTypename(input) {
|
|
78
|
+
// Enforce a global rate limit on all WFS requests to the GPF.
|
|
79
|
+
await gpfWfsRateLimiter.limit();
|
|
80
|
+
const request = buildMultiTypenameRequest({
|
|
81
|
+
typenames: input.typenames,
|
|
82
|
+
cqlFilter: input.cqlFilter,
|
|
83
|
+
cqlFilters: input.cqlFilters,
|
|
84
|
+
});
|
|
85
|
+
const url = `${request.url}?${new URLSearchParams(request.query).toString()}`;
|
|
86
|
+
const featureCollection = await fetchJSONPost(url, request.body, {
|
|
87
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
88
|
+
"Accept": "application/json",
|
|
89
|
+
});
|
|
90
|
+
if (!Array.isArray(featureCollection?.features)) {
|
|
91
|
+
throw new Error(`Le service ${input.errorLabel} n'a pas retourné de collection d'objets exploitable`);
|
|
92
|
+
}
|
|
93
|
+
return featureCollection;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../../../src/helpers/wfs_engine/execution.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;AAC7E,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;AAqB3E,yBAAyB;AAEzB;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACnD,OAAO,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED,4BAA4B;AAE5B;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAwB;IACnE,8DAA8D;IAC9D,MAAM,iBAAiB,CAAC,KAAK,EAAE,CAAC;IAEhC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC9E,OAAO,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE;QACtC,cAAc,EAAE,mCAAmC;QACnD,QAAQ,EAAE,kBAAkB;KAC7B,CAA0C,CAAC;AAC9C,CAAC;AAED,4BAA4B;AAE5B;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,iBAA+C;IACpF,IAAI,OAAO,iBAAiB,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;QACxD,OAAO,iBAAiB,CAAC,aAAa,CAAC;IACzC,CAAC;IACD,IAAI,iBAAiB,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;IACnG,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;AACnG,CAAC;AAkBD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAkC;IAElC,8DAA8D;IAC9D,MAAM,iBAAiB,CAAC,KAAK,EAAE,CAAC;IAEhC,MAAM,OAAO,GAAG,yBAAyB,CAAC;QACxC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC9E,MAAM,iBAAiB,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE;QAC/D,cAAc,EAAE,mCAAmC;QACnD,QAAQ,EAAE,kBAAkB;KAC7B,CAAiC,CAAC;IAEnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CACb,cAAc,KAAK,CAAC,UAAU,sDAAsD,CACrF,CAAC;IACJ,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared execution helpers for structured WFS feature search.
|
|
3
|
+
*
|
|
4
|
+
* This module owns the WFS-side execution flow for `gpf_wfs_get_features`:
|
|
5
|
+
* request preparation, optional reference-geometry lookup, query execution,
|
|
6
|
+
* hit counting, and FeatureCollection post-processing.
|
|
7
|
+
*/
|
|
8
|
+
import { type CompiledQuery, type ResolvedFeatureGeometryRef } from "./queryPreparation.js";
|
|
9
|
+
import { type CompiledRequest } from "./request.js";
|
|
10
|
+
import type { GpfWfsGetFeaturesInput } from "./schema.js";
|
|
11
|
+
/**
|
|
12
|
+
* Prepared request context returned once the `get_features` input has been
|
|
13
|
+
* validated, compiled, and assembled into a live WFS request.
|
|
14
|
+
*/
|
|
15
|
+
export type PreparedGetFeaturesRequest = {
|
|
16
|
+
compiled: CompiledQuery;
|
|
17
|
+
request: CompiledRequest;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Rejects `intersects_feature` requests that target the same typename.
|
|
21
|
+
*
|
|
22
|
+
* In that configuration the predicate may legitimately match multiple
|
|
23
|
+
* features, so callers must switch to the by-id tool instead.
|
|
24
|
+
*
|
|
25
|
+
* @param input Normalized tool input.
|
|
26
|
+
*/
|
|
27
|
+
export declare function ensureIntersectsFeatureTargetsOtherTypename(input: GpfWfsGetFeaturesInput): void;
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the geometry of a reference feature when `intersects_feature` is used,
|
|
30
|
+
* then converts it to EWKT for CQL compilation.
|
|
31
|
+
*
|
|
32
|
+
* @param input Normalized tool input.
|
|
33
|
+
* @returns The resolved reference geometry, or `undefined` when no reference feature is needed.
|
|
34
|
+
*/
|
|
35
|
+
export declare function resolveIntersectsFeatureGeometry(input: GpfWfsGetFeaturesInput): Promise<ResolvedFeatureGeometryRef | undefined>;
|
|
36
|
+
/**
|
|
37
|
+
* Prepares the main WFS request for `gpf_wfs_get_features`.
|
|
38
|
+
*
|
|
39
|
+
* This includes upfront validation of unsupported same-typename
|
|
40
|
+
* `intersects_feature` requests, feature type lookup, optional
|
|
41
|
+
* reference-geometry resolution, query compilation, and request assembly.
|
|
42
|
+
*
|
|
43
|
+
* @param input Normalized tool input.
|
|
44
|
+
* @returns The compiled query fragments and final WFS request.
|
|
45
|
+
*/
|
|
46
|
+
export declare function prepareGetFeaturesRequest(input: GpfWfsGetFeaturesInput): Promise<PreparedGetFeaturesRequest>;
|
|
47
|
+
/**
|
|
48
|
+
* Executes the structured WFS search flow for `result_type="results"` and `hits`.
|
|
49
|
+
*
|
|
50
|
+
* This function prepares the request, executes it against the live WFS, then
|
|
51
|
+
* either extracts a hit count or attaches `feature_ref` metadata to the result
|
|
52
|
+
* FeatureCollection.
|
|
53
|
+
*
|
|
54
|
+
* @param input Normalized tool input.
|
|
55
|
+
* @returns Either a hit-count payload or a transformed FeatureCollection.
|
|
56
|
+
*/
|
|
57
|
+
export declare function executeGetFeatures(input: GpfWfsGetFeaturesInput): Promise<Record<string, unknown> & {
|
|
58
|
+
features?: (Record<string, unknown> & {
|
|
59
|
+
feature_ref?: {
|
|
60
|
+
typename: string | null;
|
|
61
|
+
feature_id: string;
|
|
62
|
+
};
|
|
63
|
+
})[];
|
|
64
|
+
}>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared execution helpers for structured WFS feature search.
|
|
3
|
+
*
|
|
4
|
+
* This module owns the WFS-side execution flow for `gpf_wfs_get_features`:
|
|
5
|
+
* request preparation, optional reference-geometry lookup, query execution,
|
|
6
|
+
* hit counting, and FeatureCollection post-processing.
|
|
7
|
+
*/
|
|
8
|
+
import { ServiceResponseError } from "../http.js";
|
|
9
|
+
import logger from "../../logger.js";
|
|
10
|
+
import { fetchFeatureById, requireSingleFeatureById } from "./byId.js";
|
|
11
|
+
import { compileQueryParts, geometryToEwkt, getGeometryProperty, getSpatialFilter, } from "./queryPreparation.js";
|
|
12
|
+
import { fetchFeatureCollection, getFeatureType, getMatchedFeatureCount, } from "./execution.js";
|
|
13
|
+
import { buildMainRequest, } from "./request.js";
|
|
14
|
+
import { attachFeatureRefs } from "./response.js";
|
|
15
|
+
// --- Validation ---
|
|
16
|
+
/**
|
|
17
|
+
* Rejects `intersects_feature` requests that target the same typename.
|
|
18
|
+
*
|
|
19
|
+
* In that configuration the predicate may legitimately match multiple
|
|
20
|
+
* features, so callers must switch to the by-id tool instead.
|
|
21
|
+
*
|
|
22
|
+
* @param input Normalized tool input.
|
|
23
|
+
*/
|
|
24
|
+
export function ensureIntersectsFeatureTargetsOtherTypename(input) {
|
|
25
|
+
if (input.spatial_operator === "intersects_feature" &&
|
|
26
|
+
input.intersects_feature_typename !== undefined &&
|
|
27
|
+
input.typename === input.intersects_feature_typename) {
|
|
28
|
+
throw new Error("Le filtre `intersects_feature` sur le même `typename` retourne potentiellement plusieurs objets. " +
|
|
29
|
+
"Utiliser `gpf_wfs_get_feature_by_id` avec `{ typename, feature_id: intersects_feature_id }` pour cibler exactement un objet.");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Checks whether a raw value exposes the minimal geometry shape required by
|
|
34
|
+
* `geometryToEwkt`.
|
|
35
|
+
*
|
|
36
|
+
* @param value Unknown feature geometry value.
|
|
37
|
+
* @returns `true` when the value looks like a GeoJSON geometry object.
|
|
38
|
+
*/
|
|
39
|
+
function isGeometryLike(value) {
|
|
40
|
+
return (typeof value === "object" &&
|
|
41
|
+
value !== null &&
|
|
42
|
+
"type" in value &&
|
|
43
|
+
typeof value.type === "string" &&
|
|
44
|
+
"coordinates" in value);
|
|
45
|
+
}
|
|
46
|
+
// --- Reference Geometry ---
|
|
47
|
+
/**
|
|
48
|
+
* Resolves the geometry of a reference feature when `intersects_feature` is used,
|
|
49
|
+
* then converts it to EWKT for CQL compilation.
|
|
50
|
+
*
|
|
51
|
+
* @param input Normalized tool input.
|
|
52
|
+
* @returns The resolved reference geometry, or `undefined` when no reference feature is needed.
|
|
53
|
+
*/
|
|
54
|
+
export async function resolveIntersectsFeatureGeometry(input) {
|
|
55
|
+
const spatialFilter = getSpatialFilter(input);
|
|
56
|
+
if (!spatialFilter || spatialFilter.operator !== "intersects_feature") {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const referenceFeatureType = await getFeatureType(spatialFilter.typename);
|
|
60
|
+
const referenceGeometryProperty = getGeometryProperty(referenceFeatureType);
|
|
61
|
+
const featureCollection = await fetchFeatureById({
|
|
62
|
+
typename: spatialFilter.typename,
|
|
63
|
+
feature_id: spatialFilter.feature_id,
|
|
64
|
+
propertyName: referenceGeometryProperty.name,
|
|
65
|
+
});
|
|
66
|
+
const referenceFeature = requireSingleFeatureById(featureCollection, {
|
|
67
|
+
typename: spatialFilter.typename,
|
|
68
|
+
feature_id: spatialFilter.feature_id,
|
|
69
|
+
});
|
|
70
|
+
if (!isGeometryLike(referenceFeature?.geometry)) {
|
|
71
|
+
throw new Error(`Le feature de référence '${spatialFilter.feature_id}' n'a pas de géométrie exploitable.`);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
geometry_ewkt: geometryToEwkt(referenceFeature.geometry),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// --- Request Preparation ---
|
|
78
|
+
/**
|
|
79
|
+
* Prepares the main WFS request for `gpf_wfs_get_features`.
|
|
80
|
+
*
|
|
81
|
+
* This includes upfront validation of unsupported same-typename
|
|
82
|
+
* `intersects_feature` requests, feature type lookup, optional
|
|
83
|
+
* reference-geometry resolution, query compilation, and request assembly.
|
|
84
|
+
*
|
|
85
|
+
* @param input Normalized tool input.
|
|
86
|
+
* @returns The compiled query fragments and final WFS request.
|
|
87
|
+
*/
|
|
88
|
+
export async function prepareGetFeaturesRequest(input) {
|
|
89
|
+
// TODO: Assess if this guard does not prevent legitimate use cases.
|
|
90
|
+
ensureIntersectsFeatureTargetsOtherTypename(input);
|
|
91
|
+
// Get the feature type definition from the embedded catalog to access
|
|
92
|
+
// property definitions and the geometry column name.
|
|
93
|
+
const featureType = await getFeatureType(input.typename);
|
|
94
|
+
// Resolve the reference geometry for `intersects_feature`, when needed by
|
|
95
|
+
// the selected spatial filter.
|
|
96
|
+
const resolvedGeometryRef = await resolveIntersectsFeatureGeometry(input);
|
|
97
|
+
// Compile query fragments from the normalized input, feature type, and
|
|
98
|
+
// optional resolved reference geometry.
|
|
99
|
+
const compiled = compileQueryParts(input, featureType, resolvedGeometryRef);
|
|
100
|
+
// Assemble the final WFS request from the compiled fragments.
|
|
101
|
+
const request = buildMainRequest(input, compiled);
|
|
102
|
+
return { compiled, request };
|
|
103
|
+
}
|
|
104
|
+
// --- Execution ---
|
|
105
|
+
/**
|
|
106
|
+
* Executes the structured WFS search flow for `result_type="results"` and `hits`.
|
|
107
|
+
*
|
|
108
|
+
* This function prepares the request, executes it against the live WFS, then
|
|
109
|
+
* either extracts a hit count or attaches `feature_ref` metadata to the result
|
|
110
|
+
* FeatureCollection.
|
|
111
|
+
*
|
|
112
|
+
* @param input Normalized tool input.
|
|
113
|
+
* @returns Either a hit-count payload or a transformed FeatureCollection.
|
|
114
|
+
*/
|
|
115
|
+
export async function executeGetFeatures(input) {
|
|
116
|
+
const { compiled, request } = await prepareGetFeaturesRequest(input);
|
|
117
|
+
let featureCollection;
|
|
118
|
+
try {
|
|
119
|
+
logger.debug(`[gpf_wfs_get_features] POST ${request.url}?${new URLSearchParams(request.query).toString()}`);
|
|
120
|
+
featureCollection = await fetchFeatureCollection(request);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (error instanceof ServiceResponseError &&
|
|
124
|
+
error.serviceCode === "InvalidParameterValue" &&
|
|
125
|
+
error.serviceDetail === `Illegal property name: ${compiled.geometryProperty.name}`) {
|
|
126
|
+
throw new Error(`Le champ géométrique '${compiled.geometryProperty.name}' issu du catalogue embarqué est rejeté par le WFS live pour '${input.typename}'. Le catalogue embarqué est probablement désynchronisé. Détail : ${error.message}`);
|
|
127
|
+
}
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
if (input.result_type === "hits") {
|
|
131
|
+
return {
|
|
132
|
+
result_type: "hits",
|
|
133
|
+
totalFeatures: getMatchedFeatureCount(featureCollection),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return attachFeatureRefs(featureCollection, input.typename);
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.js","sourceRoot":"","sources":["../../../src/helpers/wfs_engine/features.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeoJSON geometry serialization helpers for the structured WFS engine.
|
|
3
|
+
*
|
|
4
|
+
* This module converts GeoJSON-like geometries to EWKT so they can be reused
|
|
5
|
+
* in spatial CQL predicates such as `intersects_feature`.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Serializes a GeoJSON-like geometry object into EWKT for CQL spatial predicates.
|
|
9
|
+
*
|
|
10
|
+
* @param geometry Geometry object exposing a GeoJSON `type` and `coordinates`.
|
|
11
|
+
* @returns The EWKT representation of the geometry.
|
|
12
|
+
*/
|
|
13
|
+
export declare function geometryToEwkt(geometry: {
|
|
14
|
+
type: string;
|
|
15
|
+
coordinates: unknown;
|
|
16
|
+
}): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeoJSON geometry serialization helpers for the structured WFS engine.
|
|
3
|
+
*
|
|
4
|
+
* This module converts GeoJSON-like geometries to EWKT so they can be reused
|
|
5
|
+
* in spatial CQL predicates such as `intersects_feature`.
|
|
6
|
+
*/
|
|
7
|
+
// --- Coordinate Serialization ---
|
|
8
|
+
/**
|
|
9
|
+
* Serializes a single coordinate pair into a WKT position.
|
|
10
|
+
*
|
|
11
|
+
* @param position Coordinate pair expressed as `[lon, lat]`.
|
|
12
|
+
* @returns A WKT position string.
|
|
13
|
+
*/
|
|
14
|
+
function positionToWkt(position) {
|
|
15
|
+
return `${position[0]} ${position[1]}`;
|
|
16
|
+
}
|
|
17
|
+
// --- Geometry Serialization ---
|
|
18
|
+
/**
|
|
19
|
+
* Serializes a GeoJSON-like geometry object into EWKT for CQL spatial predicates.
|
|
20
|
+
*
|
|
21
|
+
* @param geometry Geometry object exposing a GeoJSON `type` and `coordinates`.
|
|
22
|
+
* @returns The EWKT representation of the geometry.
|
|
23
|
+
*/
|
|
24
|
+
export function geometryToEwkt(geometry) {
|
|
25
|
+
switch (geometry.type) {
|
|
26
|
+
case "Point":
|
|
27
|
+
return `SRID=4326;POINT(${positionToWkt(geometry.coordinates)})`;
|
|
28
|
+
case "MultiPoint":
|
|
29
|
+
return `SRID=4326;MULTIPOINT(${geometry.coordinates
|
|
30
|
+
.map((position) => `(${positionToWkt(position)})`)
|
|
31
|
+
.join(",")})`;
|
|
32
|
+
case "LineString":
|
|
33
|
+
return `SRID=4326;LINESTRING(${geometry.coordinates.map(positionToWkt).join(",")})`;
|
|
34
|
+
case "MultiLineString":
|
|
35
|
+
return `SRID=4326;MULTILINESTRING(${geometry.coordinates.map((line) => `(${line.map(positionToWkt).join(",")})`).join(",")})`;
|
|
36
|
+
case "Polygon":
|
|
37
|
+
return `SRID=4326;POLYGON(${geometry.coordinates.map((ring) => `(${ring.map(positionToWkt).join(",")})`).join(",")})`;
|
|
38
|
+
case "MultiPolygon":
|
|
39
|
+
return `SRID=4326;MULTIPOLYGON(${geometry.coordinates.map((polygon) => `(${polygon.map((ring) => `(${ring.map(positionToWkt).join(",")})`).join(",")})`).join(",")})`;
|
|
40
|
+
default:
|
|
41
|
+
throw new Error(`Le type de géométrie '${geometry.type}' n'est pas supporté pour \`intersects_feature\`.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../../src/helpers/wfs_engine/geometry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mCAAmC;AAEnC;;;;;GAKG;AACH,SAAS,aAAa,CAAC,QAA0B;IAC/C,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC;AAED,iCAAiC;AAEjC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgD;IAC7E,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,OAAO;YACV,OAAO,mBAAmB,aAAa,CAAC,QAAQ,CAAC,WAA+B,CAAC,GAAG,CAAC;QACvF,KAAK,YAAY;YACf,OAAO,wBAAyB,QAAQ,CAAC,WAAkC;iBACxE,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC;iBACjD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAClB,KAAK,YAAY;YACf,OAAO,wBAAyB,QAAQ,CAAC,WAAkC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAC9G,KAAK,iBAAiB;YACpB,OAAO,6BAA8B,QAAQ,CAAC,WAAoC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAC1J,KAAK,SAAS;YACZ,OAAO,qBAAsB,QAAQ,CAAC,WAAoC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAClJ,KAAK,cAAc;YACjB,OAAO,0BAA2B,QAAQ,CAAC,WAAsC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACpM;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,IAAI,mDAAmD,CAAC,CAAC;IAC/G,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property resolution and validation helpers for the structured WFS query compiler.
|
|
3
|
+
*
|
|
4
|
+
* This module centralizes:
|
|
5
|
+
* - geometry property lookup
|
|
6
|
+
* - property existence checks
|
|
7
|
+
* - non-geometry validation for select/order/filter compilation
|
|
8
|
+
*/
|
|
9
|
+
import type { Collection, CollectionProperty } from "@ignfab/gpf-schema-store";
|
|
10
|
+
import type { GpfWfsGetFeaturesInput } from "./schema.js";
|
|
11
|
+
/**
|
|
12
|
+
* Resolves the single geometry property expected by the query compiler.
|
|
13
|
+
*
|
|
14
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
15
|
+
* @returns The unique geometry property for the feature type.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getGeometryProperty(featureType: Collection): any;
|
|
18
|
+
/**
|
|
19
|
+
* Resolves a property by exact name and ensures it is not the geometry column
|
|
20
|
+
* of the feature type.
|
|
21
|
+
*
|
|
22
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
23
|
+
* @param geometryProperty Geometry property already resolved for the feature type.
|
|
24
|
+
* @param propertyName Exact property name requested by the caller.
|
|
25
|
+
* @param message Error message template used when the property is geometric.
|
|
26
|
+
* @returns The matching non-geometric property metadata.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveNonGeometryProperty(featureType: Collection, geometryProperty: CollectionProperty, propertyName: string, message: string): any;
|
|
29
|
+
/**
|
|
30
|
+
* Validates a selected property name and returns the exact property name to expose.
|
|
31
|
+
*
|
|
32
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
33
|
+
* @param geometryProperty Geometry property already resolved for the feature type.
|
|
34
|
+
* @param propertyName Raw selected property name.
|
|
35
|
+
* @returns The validated non-geometric property name.
|
|
36
|
+
*/
|
|
37
|
+
export declare function validateSelectProperty(featureType: Collection, geometryProperty: CollectionProperty, propertyName: string): any;
|
|
38
|
+
/**
|
|
39
|
+
* Builds the list of property names to return according to `select` and `result_type`.
|
|
40
|
+
*
|
|
41
|
+
* Note that:
|
|
42
|
+
* - when `select` is omitted and `result_type` is `results`, every non-geometric property is returned
|
|
43
|
+
* - when `select` is provided, each property is validated against the embedded catalog
|
|
44
|
+
* - when `result_type` is `request`, the geometry column is appended to the requested selection
|
|
45
|
+
*
|
|
46
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
47
|
+
* @param geometryProperty Geometry property already resolved for the feature type.
|
|
48
|
+
* @param input Normalized tool input.
|
|
49
|
+
* @returns The list of property names to expose in the WFS `propertyName` parameter.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildSelectList(featureType: Collection, geometryProperty: CollectionProperty, input: GpfWfsGetFeaturesInput): any;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property resolution and validation helpers for the structured WFS query compiler.
|
|
3
|
+
*
|
|
4
|
+
* This module centralizes:
|
|
5
|
+
* - geometry property lookup
|
|
6
|
+
* - property existence checks
|
|
7
|
+
* - non-geometry validation for select/order/filter compilation
|
|
8
|
+
*/
|
|
9
|
+
// --- Property Listing ---
|
|
10
|
+
/**
|
|
11
|
+
* Lists available property names for a feature type, mainly for error reporting.
|
|
12
|
+
*
|
|
13
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
14
|
+
* @returns A comma-separated list of property names.
|
|
15
|
+
*/
|
|
16
|
+
function getPropertyList(featureType) {
|
|
17
|
+
return featureType.properties.map((property) => property.name).join(", ");
|
|
18
|
+
}
|
|
19
|
+
// --- Geometry Resolution ---
|
|
20
|
+
/**
|
|
21
|
+
* Returns every geometry-like property exposed by a feature type.
|
|
22
|
+
*
|
|
23
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
24
|
+
* @returns The list of properties carrying a `defaultCrs`.
|
|
25
|
+
*/
|
|
26
|
+
function getGeometryProperties(featureType) {
|
|
27
|
+
return featureType.properties.filter((property) => property.defaultCrs);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolves the single geometry property expected by the query compiler.
|
|
31
|
+
*
|
|
32
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
33
|
+
* @returns The unique geometry property for the feature type.
|
|
34
|
+
*/
|
|
35
|
+
export function getGeometryProperty(featureType) {
|
|
36
|
+
const geometryProperties = getGeometryProperties(featureType);
|
|
37
|
+
if (geometryProperties.length === 0) {
|
|
38
|
+
throw new Error(`Le type '${featureType.id}' n'expose aucune propriété géométrique exploitable dans le catalogue embarqué.`);
|
|
39
|
+
}
|
|
40
|
+
if (geometryProperties.length > 1) {
|
|
41
|
+
throw new Error(`Le type '${featureType.id}' expose plusieurs propriétés géométriques dans le catalogue embarqué : ${geometryProperties.map((property) => property.name).join(", ")}.`);
|
|
42
|
+
}
|
|
43
|
+
return geometryProperties[0];
|
|
44
|
+
}
|
|
45
|
+
// --- Generic Property Resolution ---
|
|
46
|
+
/**
|
|
47
|
+
* Loads a property by exact name and throws a descriptive error when it does not exist.
|
|
48
|
+
*
|
|
49
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
50
|
+
* @param propertyName Exact property name requested by the caller.
|
|
51
|
+
* @returns The matching property metadata.
|
|
52
|
+
*/
|
|
53
|
+
function getPropertyOrThrow(featureType, propertyName) {
|
|
54
|
+
const property = featureType.properties.find((candidate) => candidate.name === propertyName);
|
|
55
|
+
if (!property) {
|
|
56
|
+
throw new Error(`La propriété '${propertyName}' n'existe pas pour '${featureType.id}'. ` +
|
|
57
|
+
`Appelle \`gpf_wfs_describe_type\` pour obtenir la liste des propriétés disponibles.`);
|
|
58
|
+
}
|
|
59
|
+
return property;
|
|
60
|
+
}
|
|
61
|
+
// --- Non-Geometry Validation ---
|
|
62
|
+
/**
|
|
63
|
+
* Resolves a property by exact name and ensures it is not the geometry column
|
|
64
|
+
* of the feature type.
|
|
65
|
+
*
|
|
66
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
67
|
+
* @param geometryProperty Geometry property already resolved for the feature type.
|
|
68
|
+
* @param propertyName Exact property name requested by the caller.
|
|
69
|
+
* @param message Error message template used when the property is geometric.
|
|
70
|
+
* @returns The matching non-geometric property metadata.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveNonGeometryProperty(featureType, geometryProperty, propertyName, message) {
|
|
73
|
+
const property = getPropertyOrThrow(featureType, propertyName);
|
|
74
|
+
if (property.name === geometryProperty.name || property.defaultCrs) {
|
|
75
|
+
throw new Error(message.replace("{property}", property.name));
|
|
76
|
+
}
|
|
77
|
+
return property;
|
|
78
|
+
}
|
|
79
|
+
// --- Select Validation ---
|
|
80
|
+
/**
|
|
81
|
+
* Validates a selected property name and returns the exact property name to expose.
|
|
82
|
+
*
|
|
83
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
84
|
+
* @param geometryProperty Geometry property already resolved for the feature type.
|
|
85
|
+
* @param propertyName Raw selected property name.
|
|
86
|
+
* @returns The validated non-geometric property name.
|
|
87
|
+
*/
|
|
88
|
+
export function validateSelectProperty(featureType, geometryProperty, propertyName) {
|
|
89
|
+
return resolveNonGeometryProperty(featureType, geometryProperty, propertyName, "La propriété '{property}' est géométrique. `select` accepte uniquement des propriétés non géométriques.").name;
|
|
90
|
+
}
|
|
91
|
+
// --- Property Selection ---
|
|
92
|
+
/**
|
|
93
|
+
* Builds the list of property names to return according to `select` and `result_type`.
|
|
94
|
+
*
|
|
95
|
+
* Note that:
|
|
96
|
+
* - when `select` is omitted and `result_type` is `results`, every non-geometric property is returned
|
|
97
|
+
* - when `select` is provided, each property is validated against the embedded catalog
|
|
98
|
+
* - when `result_type` is `request`, the geometry column is appended to the requested selection
|
|
99
|
+
*
|
|
100
|
+
* @param featureType Feature type definition loaded from the embedded catalog.
|
|
101
|
+
* @param geometryProperty Geometry property already resolved for the feature type.
|
|
102
|
+
* @param input Normalized tool input.
|
|
103
|
+
* @returns The list of property names to expose in the WFS `propertyName` parameter.
|
|
104
|
+
*/
|
|
105
|
+
export function buildSelectList(featureType, geometryProperty, input) {
|
|
106
|
+
// If `select` is specified, only the requested properties are returned
|
|
107
|
+
// after validation against the embedded catalog.
|
|
108
|
+
if (input.select && input.select.length > 0) {
|
|
109
|
+
const selectedProperties = input.select.map((propertyName) => validateSelectProperty(featureType, geometryProperty, propertyName));
|
|
110
|
+
// For `result_type="request"`, also include the geometry column so the
|
|
111
|
+
// compiled request stays directly usable for mapping/debugging.
|
|
112
|
+
if (input.result_type === "request") {
|
|
113
|
+
return [...selectedProperties, geometryProperty.name];
|
|
114
|
+
}
|
|
115
|
+
return selectedProperties;
|
|
116
|
+
}
|
|
117
|
+
// If `select` is omitted and `result_type="results"`, return every
|
|
118
|
+
// non-geometric property from the feature type.
|
|
119
|
+
if (input.result_type === "results") {
|
|
120
|
+
return featureType.properties
|
|
121
|
+
.filter((property) => !property.defaultCrs)
|
|
122
|
+
.map((property) => property.name);
|
|
123
|
+
}
|
|
124
|
+
// If `select` is omitted and `result_type` is `hits` or `request`,
|
|
125
|
+
// do not send any `propertyName` selection.
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=properties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"properties.js","sourceRoot":"","sources":["../../../src/helpers/wfs_engine/properties.ts"],"names":[],"mappings":"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"}
|