ogcopenapis 0.0.12 → 1.0.0

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 (60) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +310 -72
  3. package/lib/OgcOpenApiCrsTools.d.ts +10 -9
  4. package/lib/OgcOpenApiCrsTools.d.ts.map +1 -0
  5. package/lib/OgcOpenApiCrsTools.js +40 -39
  6. package/lib/OgcOpenApiCrsTools.js.map +1 -0
  7. package/lib/OgcOpenApiFeatureStore.d.ts +94 -93
  8. package/lib/OgcOpenApiFeatureStore.d.ts.map +1 -0
  9. package/lib/OgcOpenApiFeatureStore.js +200 -244
  10. package/lib/OgcOpenApiFeatureStore.js.map +1 -0
  11. package/lib/OgcOpenApiFetchTools.d.ts +37 -30
  12. package/lib/OgcOpenApiFetchTools.d.ts.map +1 -0
  13. package/lib/OgcOpenApiFetchTools.js +68 -50
  14. package/lib/OgcOpenApiFetchTools.js.map +1 -0
  15. package/lib/OgcOpenApiGetCapabilities.d.ts +209 -112
  16. package/lib/OgcOpenApiGetCapabilities.d.ts.map +1 -0
  17. package/lib/OgcOpenApiGetCapabilities.js +424 -277
  18. package/lib/OgcOpenApiGetCapabilities.js.map +1 -0
  19. package/lib/OgcOpenApiMapsModel.d.ts +41 -36
  20. package/lib/OgcOpenApiMapsModel.d.ts.map +1 -0
  21. package/lib/OgcOpenApiMapsModel.js +88 -75
  22. package/lib/OgcOpenApiMapsModel.js.map +1 -0
  23. package/lib/OgcOpenApiMvtTools.d.ts +12 -0
  24. package/lib/OgcOpenApiMvtTools.d.ts.map +1 -0
  25. package/lib/OgcOpenApiMvtTools.js +100 -0
  26. package/lib/OgcOpenApiMvtTools.js.map +1 -0
  27. package/lib/OgcOpenApiStyleTools.d.ts +51 -0
  28. package/lib/OgcOpenApiStyleTools.d.ts.map +1 -0
  29. package/lib/OgcOpenApiStyleTools.js +155 -0
  30. package/lib/OgcOpenApiStyleTools.js.map +1 -0
  31. package/lib/OgcOpenApiTileMatrixTools.d.ts +41 -0
  32. package/lib/OgcOpenApiTileMatrixTools.d.ts.map +1 -0
  33. package/lib/OgcOpenApiTileMatrixTools.js +88 -0
  34. package/lib/OgcOpenApiTileMatrixTools.js.map +1 -0
  35. package/lib/OgcOpenApiTilesModel.d.ts +56 -31
  36. package/lib/OgcOpenApiTilesModel.d.ts.map +1 -0
  37. package/lib/OgcOpenApiTilesModel.js +167 -128
  38. package/lib/OgcOpenApiTilesModel.js.map +1 -0
  39. package/lib/OgcOpenApiVectorTilesModel.d.ts +39 -0
  40. package/lib/OgcOpenApiVectorTilesModel.d.ts.map +1 -0
  41. package/lib/OgcOpenApiVectorTilesModel.js +122 -0
  42. package/lib/OgcOpenApiVectorTilesModel.js.map +1 -0
  43. package/lib/OgcOpenApiWmtsTools.d.ts +30 -0
  44. package/lib/OgcOpenApiWmtsTools.d.ts.map +1 -0
  45. package/lib/OgcOpenApiWmtsTools.js +89 -0
  46. package/lib/OgcOpenApiWmtsTools.js.map +1 -0
  47. package/package.json +56 -27
  48. package/src/OgcOpenApiCrsTools.ts +40 -0
  49. package/src/OgcOpenApiFeatureStore.ts +296 -0
  50. package/src/OgcOpenApiFetchTools.ts +84 -0
  51. package/src/OgcOpenApiGetCapabilities.ts +641 -0
  52. package/src/OgcOpenApiMapsModel.ts +128 -0
  53. package/src/OgcOpenApiMvtTools.ts +104 -0
  54. package/src/OgcOpenApiStyleTools.ts +187 -0
  55. package/src/OgcOpenApiTileMatrixTools.ts +111 -0
  56. package/src/OgcOpenApiTilesModel.ts +214 -0
  57. package/src/OgcOpenApiVectorTilesModel.ts +141 -0
  58. package/src/OgcOpenApiWmtsTools.ts +114 -0
  59. package/lib/OgcOpenApiGetCollectionTiles.d.ts +0 -7
  60. package/lib/OgcOpenApiGetCollectionTiles.js +0 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OgcOpenApiWmtsTools.js","sourceRoot":"","sources":["../src/OgcOpenApiWmtsTools.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,39 +1,68 @@
1
1
  {
2
2
  "name": "ogcopenapis",
3
- "version": "0.0.12",
4
- "description": "Implements OGC OPEN API Features/Maps/Tiles capabilities and models for LuciadRIA",
3
+ "version": "1.0.0",
4
+ "description": "OGC API Features, Maps, Tiles and Styles for LuciadRIA",
5
+ "type": "module",
6
+ "exports": {
7
+ "./lib/*": {
8
+ "types": "./lib/*.d.ts",
9
+ "import": "./lib/*.js"
10
+ },
11
+ "./*": {
12
+ "types": "./lib/*.d.ts",
13
+ "import": "./lib/*.js"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
5
17
  "files": [
6
- "lib/"
18
+ "lib/",
19
+ "src/",
20
+ "!src/**/*.test.ts",
21
+ "!src/fixtures/"
7
22
  ],
23
+ "sideEffects": false,
8
24
  "scripts": {
9
- "test": "jest",
10
- "transpile": "tsc -p tsconfig.json",
11
- "copyjs": "copyfiles -u 1 \"src/**/*.js\" ./lib",
12
- "copycss": "copyfiles -u 1 \"src/**/*.css\" ./lib",
13
- "copyscss": "copyfiles -u 1 \"src/**/*.scss\" ./lib",
14
- "copysvg": "copyfiles -u 1 \"src/**/*.svg\" ./lib",
15
- "copyfonts": "copyfiles -u 1 \"src/fonts/**\" ./lib",
16
- "build": "npm run transpile && npm run copyjs && npm run copycss && npm run copyscss && npm run copysvg && npm run copyfonts"
25
+ "clean": "node -e \"require('node:fs').rmSync('lib', {recursive: true, force: true})\"",
26
+ "build:lib": "tsc -p tsconfig.build.json",
27
+ "build": "npm run clean && npm run build:lib",
28
+ "test": "vitest run",
29
+ "test:live": "vitest run --config vitest.live.config.ts",
30
+ "test:record": "vitest run --config vitest.record.config.ts",
31
+ "test:browser": "vitest run --config vitest.browser.config.ts",
32
+ "test:package": "npm run build && node test/package/checkPackage.mjs",
33
+ "prepublishOnly": "npm run test && npm run test:package",
34
+ "demo": "vite demo",
35
+ "demo:build": "vite build demo"
17
36
  },
18
- "keywords": [],
19
- "author": "",
20
- "license": "ISC",
21
- "devDependencies": {
22
- "@babel/preset-env": "^7.20.2",
23
- "@babel/preset-typescript": "^7.18.6",
24
- "@jest/globals": "^29.3.1",
25
- "copyfiles": "^2.3.0",
26
- "isomorphic-fetch": "^3.0.0",
27
- "jest": "^29.3.1",
28
- "jest-canvas-mock": "^2.4.0",
29
- "jest-environment-jsdom": "^29.3.1",
30
- "typescript": "^4.6.3"
37
+ "keywords": [
38
+ "ogc",
39
+ "ogc-api",
40
+ "features",
41
+ "maps",
42
+ "tiles",
43
+ "vector-tiles",
44
+ "styles",
45
+ "luciadria"
46
+ ],
47
+ "author": "felipecarrillo100",
48
+ "license": "MIT",
49
+ "peerDependencies": {
50
+ "@luciad/ria": ">=2026.1.0"
31
51
  },
32
- "dependencies": {
33
- "@luciad/ria": ">=2020.0"
52
+ "devDependencies": {
53
+ "@arethetypeswrong/cli": "0.18.5",
54
+ "@luciad/ria": "2026.1.1",
55
+ "@types/node": "^18.11.18",
56
+ "jsdom": "^25.0.1",
57
+ "playwright-core": "1.63.0",
58
+ "publint": "0.3.25",
59
+ "typescript": "5.9.3",
60
+ "vite": "^5.4.21",
61
+ "vitest": "^3.2.4",
62
+ "vitest-canvas-mock": "^1.2.0"
34
63
  },
35
64
  "repository": {
36
65
  "type": "git",
37
- "url": "git+https://github.com/felipecarrillo100/ogcopenapis"
66
+ "url": "git+https://github.com/felipecarrillo100/ogcopenapis.git"
38
67
  }
39
68
  }
@@ -0,0 +1,40 @@
1
+ class OgcOpenApiCrsTools {
2
+ /**
3
+ *
4
+ * @param uriOrName
5
+ * @private
6
+ */
7
+ public static getReferenceName(uriOrNameI: string) {
8
+ let uriOrName;
9
+ if (typeof uriOrNameI === "undefined") {
10
+ uriOrName = "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
11
+ } else {
12
+ uriOrName = uriOrNameI.replace(/[<>]/g, '');
13
+ }
14
+
15
+ if (!uriOrName.startsWith('http')) {
16
+ return uriOrName;
17
+ }
18
+ const prefix = 'http://www.opengis.net/def/crs/';
19
+ if (uriOrName.startsWith(prefix)) {
20
+ const cleanCRS = uriOrName.substr(prefix.length);
21
+ const parts = cleanCRS.split('/');
22
+ if (parts.length === 3) {
23
+ const name = parts[0];
24
+ const version = parts[1];
25
+ const code = parts[2];
26
+ switch (name) {
27
+ case 'EPSG':
28
+ return name + ':' + code;
29
+ break;
30
+ case 'OGC':
31
+ return 'CRS' + ':' + code.substr('CRS'.length);
32
+ break;
33
+ }
34
+ }
35
+ }
36
+ return uriOrName;
37
+ }
38
+ }
39
+
40
+ export { OgcOpenApiCrsTools}
@@ -0,0 +1,296 @@
1
+ import {type QueryOptions, Store, type StoreOperationName} from '@luciad/ria/model/store/Store.js';
2
+ import type {Cursor} from '@luciad/ria/model/Cursor.js';
3
+ import {Feature} from '@luciad/ria/model/feature/Feature.js';
4
+ import {Bounds} from '@luciad/ria/shape/Bounds.js';
5
+ import {Codec, type CodecDecodeOptions} from '@luciad/ria/model/codec/Codec.js';
6
+ import {createBounds} from '@luciad/ria/shape/ShapeFactory.js';
7
+ import {CoordinateReference} from '@luciad/ria/reference/CoordinateReference.js';
8
+ import {getReference} from "@luciad/ria/reference/ReferenceProvider.js";
9
+ import {createTransformation} from "@luciad/ria/transformation/TransformationFactory.js";
10
+ import {OgcOpenApiCrsTools} from "./OgcOpenApiCrsTools.js";
11
+ import {GeoJsonCodec} from "@luciad/ria/model/codec/GeoJsonCodec.js";
12
+ import {GMLCodec} from "@luciad/ria/model/codec/GMLCodec.js";
13
+ import type {ProxifyFunction} from "./OgcOpenApiGetCapabilities.js";
14
+ import {OgcOpenApiFetchTools} from "./OgcOpenApiFetchTools.js";
15
+
16
+ export interface OgcOpenApiFeatureStoreConstructorOptions {
17
+ swapAxes?: string[];
18
+ dataUrl: string;
19
+ featureUrl?: string;
20
+ outputFormat: string;
21
+ useCrs84Bounds?: boolean;
22
+ codec: Codec;
23
+ credentials?: boolean;
24
+ requestHeaders?: { [key: string]: string };
25
+ extent?: { spatial: { bbox: any[] } };
26
+ crs: string;
27
+ proxify?: ProxifyFunction
28
+ }
29
+
30
+ export interface OgcOpenApiFeatureStoreQueryOptions {
31
+ f?:string;
32
+ limit?: number;
33
+ offset?: number;
34
+ bbox?: number[];
35
+ "bbox-crs"? : string;
36
+ datetime?: string;
37
+ filter?: string;
38
+ "filter-crs"?: string;
39
+ "filter-lang"?: string;
40
+ crs?: string | any;
41
+ skipGeometry?: boolean;
42
+ properties?: string[];
43
+ sortby?: string[];
44
+ ident?: string;
45
+ name?: string;
46
+ q?: string[];
47
+ maxAllowableOffset?: number;
48
+ level?: string;
49
+ sector?: string;
50
+ milCode?: string;
51
+ localType?: string;
52
+ upperLimitDesc?: number;
53
+ upperLimitValue?: number;
54
+ upperLimitUnit?: string;
55
+ upperLimitCode?: string;
56
+ lowerLimitDesc?: string;
57
+ lowerLimitValue?: number;
58
+ lowerLimitUnit?: string;
59
+ lowerLimitCode?: string;
60
+ onshore?:boolean;
61
+ exclusion?: boolean;
62
+ wkhrCode?: string;
63
+ wkhrRemark?: string;
64
+ }
65
+
66
+ interface OgcOpenApiFeaturesCodecDecodeOptions extends CodecDecodeOptions {
67
+ contentCrs?: string;
68
+ contentLength?: number;
69
+ }
70
+
71
+ export class OgcOpenApiFeatureStore extends Store {
72
+ private dataUrl: string;
73
+ private codec: Codec;
74
+ private baseUrl: string;
75
+ private dataFormat: string | undefined;
76
+ private customCrs: string | undefined;
77
+ private dataBounds: Bounds;
78
+ private requestHeaders: { [key: string]: string };
79
+ private reference: CoordinateReference;
80
+ private outputFormat: string;
81
+ private useCrs84Bounds: boolean;
82
+ private featureUrl: string;
83
+ private proxy: ProxifyFunction;
84
+ private credentials: boolean;
85
+ private serverOptions: { proxy: (url: string, fetchOptions) => { fetchOptions: any; url: string }; hostname: string; complete: (url: string) => string };
86
+ private swapAxes: string[] | undefined;
87
+
88
+ constructor(options: OgcOpenApiFeatureStoreConstructorOptions) {
89
+ super();
90
+ // console.log(options);
91
+ this.swapAxes = options.swapAxes;
92
+ this.useCrs84Bounds = typeof options.useCrs84Bounds !== "undefined" ? options.useCrs84Bounds : false;
93
+ this.dataUrl = options.dataUrl;
94
+ this.outputFormat = options.outputFormat;
95
+ const predictedFeatureUrl = this.dataUrl.replace(/\.[^/.]+$/, "");
96
+
97
+ this.featureUrl = options.featureUrl ? OgcOpenApiFeatureStore.cleanUrl(options.featureUrl, true) : OgcOpenApiFeatureStore.cleanUrl(predictedFeatureUrl, true);
98
+
99
+ this.baseUrl = OgcOpenApiFeatureStore.cleanUrl(this.dataUrl);
100
+ this.dataFormat = OgcOpenApiFeatureStore.dataFormatInQuery(this.dataUrl);
101
+ this.customCrs = options.crs === "http://www.opengis.net/def/crs/OGC/1.3/CRS84" ? undefined : options.crs;
102
+ this.codec = options.codec;
103
+ this.requestHeaders = options.requestHeaders ? options.requestHeaders : {};
104
+ const referenceName = OgcOpenApiCrsTools.getReferenceName(options.crs)
105
+ this.reference = getReference(referenceName);
106
+ this.proxy = options.proxify;
107
+ this.credentials = options.credentials;
108
+
109
+ this.serverOptions = OgcOpenApiFetchTools.createFetchOptions({originalUrl: this.dataUrl, proxify: options.proxify});
110
+
111
+ if (
112
+ options.extent &&
113
+ options.extent.spatial &&
114
+ options.extent.spatial.bbox &&
115
+ options.extent.spatial.bbox.length > 0
116
+ ) {
117
+ const bbox = options.extent.spatial.bbox[0];
118
+ const WGS84 = getReference("CRS:84");
119
+ const tmpBounds = createBounds(WGS84, [
120
+ bbox[0],
121
+ bbox[2] - bbox[0],
122
+ bbox[1],
123
+ bbox[3] - bbox[1],
124
+ ]);
125
+ this.dataBounds = OgcOpenApiFeatureStore.targetBounds(tmpBounds, this.reference);
126
+ }
127
+ }
128
+
129
+ // Store defines bounds as a getter, the extent is kept in dataBounds
130
+ get bounds(): Bounds {
131
+ return this.dataBounds;
132
+ }
133
+
134
+ isOperationSupported(methodName: StoreOperationName): boolean {
135
+ return methodName === "get" || methodName === "spatialQuery";
136
+ }
137
+
138
+ get(id: number | string, optionsInput?: any): Promise<Feature> {
139
+ const options = optionsInput ? { ...optionsInput } : {};
140
+ options.query = (options.query ? options.query : {}) as OgcOpenApiFeatureStoreQueryOptions;
141
+ options.query.f = options.query.f ? options.query.f : this.dataFormat;
142
+ options.query.crs = options.query.crs ? options.query.crs : this.customCrs;
143
+ let request = this.featureUrl + id;
144
+ const simpleQuery = [];
145
+ if (options.query.f) simpleQuery.push("f");
146
+ if (options.query.crs) simpleQuery.push("crs");
147
+ if (simpleQuery.length > 0) {
148
+ const queryString = simpleQuery.map( k => ""+k+"="+options.query[k]).join("&");
149
+ request += "?" + queryString;
150
+ }
151
+ return this.fetchFeatures(request, options.abortSignal).then(cursor => cursor && cursor.hasNext() ? cursor.next() : null);
152
+ }
153
+
154
+ query(receivedQuery?: OgcOpenApiFeatureStoreQueryOptions, options?: QueryOptions): Cursor | Promise<Cursor> {
155
+ const query = receivedQuery ? { ...receivedQuery } : {};
156
+ query.f = query.f ? query.f : this.dataFormat;
157
+ query.crs = query.crs ? query.crs : this.customCrs;
158
+ query.limit = query.limit ? query.limit : undefined;
159
+ let request = this.baseUrl;
160
+
161
+ const allKeys = Object.keys(query);
162
+ if (allKeys.length>0) {
163
+ const filteredKeys = allKeys.filter(e => (typeof query[e] !== "undefined" && query[e] !== null));
164
+ const indexOfFormat = filteredKeys.indexOf("f");
165
+ if (indexOfFormat > -1) {
166
+ filteredKeys.splice(indexOfFormat, 1);
167
+ filteredKeys.unshift("f");
168
+ }
169
+ const queryString = filteredKeys.map( k => ""+k+"="+query[k]).join("&");
170
+ request += "?" + queryString;
171
+ }
172
+ return this.fetchFeatures(request, options?.abortSignal);
173
+ }
174
+
175
+ // Fetches and decodes features. The promise always settles: it rejects with the reason when the request,
176
+ // the response or the decoding fails, and when LuciadRIA aborts the request through abortSignal.
177
+ private fetchFeatures(request: string, abortSignal?: AbortSignal): Promise<Cursor> {
178
+ // Mod starta
179
+ const itemsAccept =
180
+ typeof this.requestHeaders.accept !== 'undefined'
181
+ ? this.requestHeaders.accept.split(';')
182
+ : typeof this.requestHeaders.Accept !== 'undefined'
183
+ ? this.requestHeaders.Accept.split(';')
184
+ : [];
185
+ itemsAccept.push(this.outputFormat);
186
+ const accept = itemsAccept.join(';');
187
+ // Mod end
188
+ const headers = { ...this.requestHeaders, Accept: accept };
189
+ return OgcOpenApiFetchTools.fetch(request, {
190
+ method: 'GET',
191
+ credentials: this.credentials ? "same-origin": "omit",
192
+ headers,
193
+ signal: abortSignal,
194
+ }, this.serverOptions).then((response) => {
195
+ if (response.status !== 200) {
196
+ throw new Error("Invalid response: " + response.status + " for " + request);
197
+ }
198
+ return response.text().then((content) => {
199
+ let contentType = response.headers.get('Content-Type');
200
+ const contentCrs = response.headers.get('content-crs') ? response.headers.get('content-crs') : this.customCrs;
201
+ const contentLengthStr = response.headers.get('Content-Length');
202
+ const contentLength = Number(contentLengthStr);
203
+ contentType = contentType ? contentType : 'text/plain';
204
+ // GeoJsonCodec reads the CRS84 URI, GML is given the URN
205
+ content = content
206
+ .split('srsName="http://www.opengis.net/def/crs/OGC/1.3/CRS84"')
207
+ .join('srsName="urn:ogc:def:crs:OGC:1.3:CRS84"');
208
+ const codecOptions: OgcOpenApiFeaturesCodecDecodeOptions = {
209
+ content, contentType, contentCrs, contentLength
210
+ };
211
+ if (this.codec instanceof GeoJsonCodec || this.codec instanceof GMLCodec) {
212
+ return this.codec.decode({...codecOptions, reference: getReference(OgcOpenApiCrsTools.getReferenceName(contentCrs))});
213
+ }
214
+ return this.codec.decode(codecOptions);
215
+ });
216
+ });
217
+ }
218
+
219
+ spatialQuery(
220
+ bounds?: Bounds,
221
+ receivedQuery?: OgcOpenApiFeatureStoreQueryOptions,
222
+ options?: QueryOptions
223
+ ): Promise<Cursor> | Cursor {
224
+ const query = (receivedQuery ? { ...receivedQuery } : {}) as OgcOpenApiFeatureStoreQueryOptions;
225
+ delete query.bbox;
226
+ query.limit = query.limit ? query.limit : undefined;
227
+ if (bounds) {
228
+ if (this.useCrs84Bounds) {
229
+ const crs84Bounds = OgcOpenApiFeatureStore.getCRS84BoundingBox(bounds);
230
+ query.bbox = query.bbox
231
+ ? query.bbox
232
+ : [
233
+ crs84Bounds.x,
234
+ crs84Bounds.y,
235
+ crs84Bounds.x + crs84Bounds.width,
236
+ crs84Bounds.y + crs84Bounds.height,
237
+ ];
238
+ } else {
239
+ query.bbox = query.bbox
240
+ ? query.bbox
241
+ : [
242
+ bounds.x,
243
+ bounds.y,
244
+ bounds.x + bounds.width,
245
+ bounds.y + bounds.height,
246
+ ];
247
+ if (this.customCrs) {
248
+ query["bbox-crs"] = this.customCrs;
249
+ }
250
+ const referenceName = OgcOpenApiCrsTools.getReferenceName(this.customCrs);
251
+ if (this.swapAxes && this.swapAxes.findIndex(f=>f===referenceName)>-1) {
252
+ query.bbox = [query.bbox[1], query.bbox[0],query.bbox[3], query.bbox[2]]
253
+ }
254
+ }
255
+ }
256
+ return this.query(query, options);
257
+ }
258
+
259
+ private static getCRS84BoundingBox(shape: Bounds) {
260
+ const WGS84 = getReference("CRS:84");
261
+ const bounds = shape.bounds;
262
+ const toWgs84 = createTransformation(bounds.reference, WGS84);
263
+ return toWgs84.transformBounds(bounds);
264
+ }
265
+
266
+ private static targetBounds(bounds: Bounds, targetReferenceBounds: CoordinateReference) {
267
+ const WGS84 = getReference("CRS:84");
268
+ const toTargetReference = createTransformation(WGS84, targetReferenceBounds);
269
+ return toTargetReference.transformBounds(bounds);
270
+ }
271
+
272
+ private static cleanUrl(dataUrl: string, addSlash=false) {
273
+ const parts = dataUrl.split('?');
274
+ return parts[0].endsWith('/') ? parts[0] : (addSlash ? parts[0] + '/' : parts[0]);
275
+ }
276
+
277
+ private static dataFormatInQuery(dataUrl: string) {
278
+ let format;
279
+ const parts = dataUrl.split('?');
280
+ if (parts.length > 1) {
281
+ const query = parts[1];
282
+ const qs = query.split('&');
283
+ for (const q of qs) {
284
+ if (q.startsWith('f=')) {
285
+ format = q.slice(2);
286
+ return format;
287
+ }
288
+ }
289
+ }
290
+ return format;
291
+ }
292
+ }
293
+
294
+ export type {
295
+ OgcOpenApiFeaturesCodecDecodeOptions
296
+ }
@@ -0,0 +1,84 @@
1
+ import type {ProxifyFunction} from "./OgcOpenApiGetCapabilities.js";
2
+
3
+ interface ExtFetchOptions {
4
+ originalUrl: string;
5
+ complete?: (url: string) => string;
6
+ proxify?: ProxifyFunction
7
+ }
8
+ export interface FetchServerOptions {
9
+ proxy: (url: string, fetchOptions) => { fetchOptions: any; url: string };
10
+ hostname: string;
11
+ complete: (url: string) => string
12
+ }
13
+
14
+ // Stand-ins for the braces of URL templates while resolving, URL keeps them as they are
15
+ const OPEN_BRACE = "__OGC_OPEN_BRACE__";
16
+ const CLOSE_BRACE = "__OGC_CLOSE_BRACE__";
17
+
18
+ class OgcOpenApiFetchTools {
19
+
20
+ public static createFetchOptions(options: ExtFetchOptions) {
21
+ const hostname = this.getHostURL(options.originalUrl);
22
+ return {
23
+ hostname: hostname,
24
+ complete: typeof options.complete === "function" ? options.complete : (url: string) => {
25
+ return this.addHostURL(url, hostname)
26
+ },
27
+ proxy: typeof options.proxify === "function" ? options.proxify : (url: string, fetchOptions) => ({
28
+ url: url,
29
+ fetchOptions: fetchOptions
30
+ })
31
+ }
32
+ }
33
+
34
+ public static fetch(input: string, options: RequestInit, serverOptions: FetchServerOptions) {
35
+ const fullUrl = serverOptions.complete(input);
36
+ const result = serverOptions.proxy(fullUrl, options)
37
+ return fetch(result.url, result.fetchOptions);
38
+ }
39
+
40
+ /**
41
+ * A link of a document, resolved against the URL of that document (RFC 3986): ./x, ../x, x, /x and //host/x.
42
+ * Absolute links are kept as they are. Without an absolute document URL, as behind a relative proxy path, the link
43
+ * is completed with the host of the server.
44
+ */
45
+ public static resolveUrl(href: string, documentUrl: string, serverOptions: FetchServerOptions) {
46
+ if (typeof href !== "string" || /^[a-z][a-z0-9+.-]*:/i.test(href)) return href;
47
+ if (!/^https?:\/\//i.test(documentUrl)) return serverOptions.complete(href);
48
+ // URL encodes { and } in paths, which tile URL templates use: {tileMatrix}/{tileRow}/{tileCol}
49
+ const resolved = new URL(href.replace(/\{/g, OPEN_BRACE).replace(/}/g, CLOSE_BRACE), documentUrl).href;
50
+ return resolved.split(OPEN_BRACE).join("{").split(CLOSE_BRACE).join("}");
51
+ }
52
+
53
+ public static addHostURL(url: string, HostUrl?: string) {
54
+ if (typeof url === "undefined") return url;
55
+ const hostUrl = HostUrl ? HostUrl : "";
56
+ if (url.startsWith("http://") || url.startsWith("https://")) {
57
+ return url;
58
+ } else {
59
+ if (url.startsWith("/")) return hostUrl + url;
60
+ if (url.startsWith("./")) return hostUrl + url.substring(1);
61
+ }
62
+ return hostUrl + "/" + url;
63
+ }
64
+
65
+ public static cleanUrl(inputUrl:string) {
66
+ return inputUrl.split("?")[0].replace(/\/?$/, '/');
67
+ }
68
+
69
+ public static cleanUrlToAsset(inputUrl:string) {
70
+ return inputUrl.split("?")[0].replace(/\/?$/, '');
71
+ }
72
+
73
+ public static getHostURL(fullUrl: string) {
74
+ if (!fullUrl.startsWith("http")) return "";
75
+ const pathArray = fullUrl.split( '/' );
76
+ const protocol = pathArray[0];
77
+ const host = pathArray[2];
78
+ return protocol + '//' + host;
79
+ }
80
+ }
81
+
82
+ export {
83
+ OgcOpenApiFetchTools
84
+ }