geoserver-node-client 1.4.7 → 1.5.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.
package/src/layer.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import fetch from 'node-fetch';
2
2
  import { getGeoServerResponseText, GeoServerResponseError } from './util/geoserver.js';
3
- import AboutClient from './about.js'
3
+ import AboutClient from './about.js';
4
4
 
5
5
  /**
6
6
  * Client for GeoServer layers
@@ -14,7 +14,7 @@ export default class LayerClient {
14
14
  * @param {String} url The URL of the GeoServer REST API endpoint
15
15
  * @param {String} auth The Basic Authentication string
16
16
  */
17
- constructor (url, auth) {
17
+ constructor(url, auth) {
18
18
  this.url = url;
19
19
  this.auth = auth;
20
20
  }
@@ -30,7 +30,7 @@ export default class LayerClient {
30
30
  *
31
31
  * @returns {Object} An object with layer information or undefined if it cannot be found
32
32
  */
33
- async get (workspace, layerName) {
33
+ async get(workspace, layerName) {
34
34
  let qualifiedName;
35
35
  if (workspace) {
36
36
  qualifiedName = `${workspace}:${layerName}`;
@@ -69,7 +69,7 @@ export default class LayerClient {
69
69
  *
70
70
  * @throws Error if request fails
71
71
  */
72
- async modifyAttribution (workspace, layerName, attributionText, attributionLink) {
72
+ async modifyAttribution(workspace, layerName, attributionText, attributionLink) {
73
73
  let qualifiedName;
74
74
  if (workspace) {
75
75
  qualifiedName = `${workspace}:${layerName}`;
@@ -117,7 +117,7 @@ export default class LayerClient {
117
117
  *
118
118
  * @returns {Object} An object with all layer information
119
119
  */
120
- async getAll () {
120
+ async getAll() {
121
121
  const response = await fetch(this.url + 'layers.json', {
122
122
  credentials: 'include',
123
123
  method: 'GET',
@@ -142,12 +142,12 @@ export default class LayerClient {
142
142
  *
143
143
  * @return {Object} An object with the information about the layers
144
144
  */
145
- async getLayers (workspace) {
145
+ async getLayers(workspace) {
146
146
  const response = await fetch(this.url + 'workspaces/' + workspace + '/layers.json', {
147
147
  credentials: 'include',
148
148
  method: 'GET',
149
149
  headers: {
150
- Authorization: this.auth,
150
+ Authorization: this.auth
151
151
  }
152
152
  });
153
153
 
@@ -170,14 +170,24 @@ export default class LayerClient {
170
170
  *
171
171
  * @returns {Object} An object with layer information or undefined if it cannot be found
172
172
  */
173
- async getWmsLayer (workspace, datastore, layerName) {
174
- const response = await fetch(this.url + 'workspaces/' + workspace + '/wmsstores/' + datastore + '/wmslayers/' + layerName + '.json', {
175
- credentials: 'include',
176
- method: 'GET',
177
- headers: {
178
- Authorization: this.auth,
173
+ async getWmsLayer(workspace, datastore, layerName) {
174
+ const response = await fetch(
175
+ this.url +
176
+ 'workspaces/' +
177
+ workspace +
178
+ '/wmsstores/' +
179
+ datastore +
180
+ '/wmslayers/' +
181
+ layerName +
182
+ '.json',
183
+ {
184
+ credentials: 'include',
185
+ method: 'GET',
186
+ headers: {
187
+ Authorization: this.auth
188
+ }
179
189
  }
180
- });
190
+ );
181
191
 
182
192
  if (!response.ok) {
183
193
  const grc = new AboutClient(this.url, this.auth);
@@ -206,14 +216,24 @@ export default class LayerClient {
206
216
  *
207
217
  * @returns {Object} An object with layer information or undefined if it cannot be found
208
218
  */
209
- async getWmtsLayer (workspace, datastore, layerName) {
210
- const response = await fetch(this.url + 'workspaces/' + workspace + '/wmtsstores/' + datastore + '/layers/' + layerName + '.json', {
211
- credentials: 'include',
212
- method: 'GET',
213
- headers: {
214
- Authorization: this.auth,
219
+ async getWmtsLayer(workspace, datastore, layerName) {
220
+ const response = await fetch(
221
+ this.url +
222
+ 'workspaces/' +
223
+ workspace +
224
+ '/wmtsstores/' +
225
+ datastore +
226
+ '/layers/' +
227
+ layerName +
228
+ '.json',
229
+ {
230
+ credentials: 'include',
231
+ method: 'GET',
232
+ headers: {
233
+ Authorization: this.auth
234
+ }
215
235
  }
216
- });
236
+ );
217
237
 
218
238
  if (!response.ok) {
219
239
  const grc = new AboutClient(this.url, this.auth);
@@ -243,7 +263,15 @@ export default class LayerClient {
243
263
  *
244
264
  * @throws Error if request fails
245
265
  */
246
- async publishFeatureTypeDefaultDataStore (workspace, nativeName, name, title, srs, enabled, abstract) {
266
+ async publishFeatureTypeDefaultDataStore(
267
+ workspace,
268
+ nativeName,
269
+ name,
270
+ title,
271
+ srs,
272
+ enabled,
273
+ abstract
274
+ ) {
247
275
  const body = {
248
276
  featureType: {
249
277
  name: name,
@@ -286,13 +314,23 @@ export default class LayerClient {
286
314
  *
287
315
  * @throws Error if request fails
288
316
  */
289
- async publishFeatureType (workspace, dataStore, nativeName, name, title, srs, enabled, abstract, nativeBoundingBox) {
317
+ async publishFeatureType(
318
+ workspace,
319
+ dataStore,
320
+ nativeName,
321
+ name,
322
+ title,
323
+ srs,
324
+ enabled,
325
+ abstract,
326
+ nativeBoundingBox
327
+ ) {
290
328
  // apply CRS info for native BBOX if not provided
291
329
  if (nativeBoundingBox && !nativeBoundingBox.crs) {
292
330
  nativeBoundingBox.crs = {
293
331
  '@class': 'projected',
294
332
  $: srs
295
- }
333
+ };
296
334
  }
297
335
 
298
336
  const body = {
@@ -307,15 +345,18 @@ export default class LayerClient {
307
345
  }
308
346
  };
309
347
 
310
- const response = await fetch(this.url + 'workspaces/' + workspace + '/datastores/' + dataStore + '/featuretypes', {
311
- credentials: 'include',
312
- method: 'POST',
313
- headers: {
314
- Authorization: this.auth,
315
- 'Content-Type': 'application/json'
316
- },
317
- body: JSON.stringify(body)
318
- });
348
+ const response = await fetch(
349
+ this.url + 'workspaces/' + workspace + '/datastores/' + dataStore + '/featuretypes',
350
+ {
351
+ credentials: 'include',
352
+ method: 'POST',
353
+ headers: {
354
+ Authorization: this.auth,
355
+ 'Content-Type': 'application/json'
356
+ },
357
+ body: JSON.stringify(body)
358
+ }
359
+ );
319
360
 
320
361
  if (!response.ok) {
321
362
  const geoServerResponse = await getGeoServerResponseText(response);
@@ -334,8 +375,16 @@ export default class LayerClient {
334
375
  *
335
376
  * @returns {Object} The object of the FeatureType
336
377
  */
337
- async getFeatureType (workspace, datastore, name) {
338
- const url = this.url + 'workspaces/' + workspace + '/datastores/' + datastore + '/featuretypes/' + name + '.json';
378
+ async getFeatureType(workspace, datastore, name) {
379
+ const url =
380
+ this.url +
381
+ 'workspaces/' +
382
+ workspace +
383
+ '/datastores/' +
384
+ datastore +
385
+ '/featuretypes/' +
386
+ name +
387
+ '.json';
339
388
  const response = await fetch(url, {
340
389
  credentials: 'include',
341
390
  method: 'GET',
@@ -358,6 +407,42 @@ export default class LayerClient {
358
407
  return response.json();
359
408
  }
360
409
 
410
+ /**
411
+ * Get detailed information about a FeatureType.
412
+ *
413
+ * @param {String} workspace The workspace of the FeatureType
414
+ * @param {String} name The name of the FeatureType
415
+ *
416
+ * @throws GeoServerResponseError if request fails or layer does not exist or lacks the right properties.
417
+ *
418
+ * @returns {Object} The object of the FeatureType
419
+ */
420
+ async getFeatureTypeFromLayer(workspace, layer) {
421
+ const layerObj = await this.get(workspace, layer);
422
+
423
+ if (!layerObj || !layerObj.layer || !layerObj.layer.resource || !layerObj.layer.resource.href) {
424
+ throw new GeoServerResponseError(
425
+ `Layer '${workspace}:${layer}' does not exist or lacks the layer.resource.href property.`
426
+ );
427
+ }
428
+
429
+ const url = layerObj?.layer?.resource?.href;
430
+
431
+ const response = await fetch(url, {
432
+ credentials: 'include',
433
+ method: 'GET',
434
+ headers: {
435
+ Authorization: this.auth
436
+ }
437
+ });
438
+
439
+ if (!response.ok) {
440
+ const geoServerResponse = await getGeoServerResponseText(response);
441
+ throw new GeoServerResponseError(null, geoServerResponse);
442
+ }
443
+ return response.json();
444
+ }
445
+
361
446
  /**
362
447
  * Publishes a WMS layer.
363
448
  *
@@ -372,7 +457,7 @@ export default class LayerClient {
372
457
  *
373
458
  * @throws Error if request fails
374
459
  */
375
- async publishWmsLayer (workspace, dataStore, nativeName, name, title, srs, enabled, abstract) {
460
+ async publishWmsLayer(workspace, dataStore, nativeName, name, title, srs, enabled, abstract) {
376
461
  const body = {
377
462
  wmsLayer: {
378
463
  name: name || nativeName,
@@ -384,15 +469,18 @@ export default class LayerClient {
384
469
  }
385
470
  };
386
471
 
387
- const response = await fetch(this.url + 'workspaces/' + workspace + '/wmsstores/' + dataStore + '/wmslayers', {
388
- credentials: 'include',
389
- method: 'POST',
390
- headers: {
391
- Authorization: this.auth,
392
- 'Content-Type': 'application/json'
393
- },
394
- body: JSON.stringify(body)
395
- });
472
+ const response = await fetch(
473
+ this.url + 'workspaces/' + workspace + '/wmsstores/' + dataStore + '/wmslayers',
474
+ {
475
+ credentials: 'include',
476
+ method: 'POST',
477
+ headers: {
478
+ Authorization: this.auth,
479
+ 'Content-Type': 'application/json'
480
+ },
481
+ body: JSON.stringify(body)
482
+ }
483
+ );
396
484
 
397
485
  if (!response.ok) {
398
486
  const geoServerResponse = await getGeoServerResponseText(response);
@@ -414,7 +502,7 @@ export default class LayerClient {
414
502
  *
415
503
  * @throws Error if request fails
416
504
  */
417
- async publishDbRaster (workspace, coverageStore, nativeName, name, title, srs, enabled, abstract) {
505
+ async publishDbRaster(workspace, coverageStore, nativeName, name, title, srs, enabled, abstract) {
418
506
  const body = {
419
507
  coverage: {
420
508
  name: name || nativeName,
@@ -426,15 +514,18 @@ export default class LayerClient {
426
514
  }
427
515
  };
428
516
 
429
- const response = await fetch(this.url + 'workspaces/' + workspace + '/coveragestores/' + coverageStore + '/coverages', {
430
- credentials: 'include',
431
- method: 'POST',
432
- headers: {
433
- Authorization: this.auth,
434
- 'Content-Type': 'application/json'
435
- },
436
- body: JSON.stringify(body)
437
- });
517
+ const response = await fetch(
518
+ this.url + 'workspaces/' + workspace + '/coveragestores/' + coverageStore + '/coverages',
519
+ {
520
+ credentials: 'include',
521
+ method: 'POST',
522
+ headers: {
523
+ Authorization: this.auth,
524
+ 'Content-Type': 'application/json'
525
+ },
526
+ body: JSON.stringify(body)
527
+ }
528
+ );
438
529
 
439
530
  if (!response.ok) {
440
531
  const geoServerResponse = await getGeoServerResponseText(response);
@@ -452,14 +543,25 @@ export default class LayerClient {
452
543
  *
453
544
  * @throws Error if request fails
454
545
  */
455
- async deleteFeatureType (workspace, datastore, name, recurse) {
456
- const response = await fetch(this.url + 'workspaces/' + workspace + '/datastores/' + datastore + '/featuretypes/' + name + '?recurse=' + recurse, {
457
- credentials: 'include',
458
- method: 'DELETE',
459
- headers: {
460
- Authorization: this.auth
546
+ async deleteFeatureType(workspace, datastore, name, recurse) {
547
+ const response = await fetch(
548
+ this.url +
549
+ 'workspaces/' +
550
+ workspace +
551
+ '/datastores/' +
552
+ datastore +
553
+ '/featuretypes/' +
554
+ name +
555
+ '?recurse=' +
556
+ recurse,
557
+ {
558
+ credentials: 'include',
559
+ method: 'DELETE',
560
+ headers: {
561
+ Authorization: this.auth
562
+ }
461
563
  }
462
- });
564
+ );
463
565
 
464
566
  if (!response.ok) {
465
567
  const geoServerResponse = await getGeoServerResponseText(response);
@@ -482,7 +584,17 @@ export default class LayerClient {
482
584
  *
483
585
  * @throws Error if request fails
484
586
  */
485
- async enableTimeCoverage (workspace, dataStore, name, presentation, resolution, defaultValue, nearestMatchEnabled, rawNearestMatchEnabled, acceptableInterval) {
587
+ async enableTimeCoverage(
588
+ workspace,
589
+ dataStore,
590
+ name,
591
+ presentation,
592
+ resolution,
593
+ defaultValue,
594
+ nearestMatchEnabled,
595
+ rawNearestMatchEnabled,
596
+ acceptableInterval
597
+ ) {
486
598
  const body = {
487
599
  coverage: {
488
600
  metadata: {
@@ -507,7 +619,15 @@ export default class LayerClient {
507
619
  }
508
620
  };
509
621
 
510
- const url = this.url + 'workspaces/' + workspace + '/coveragestores/' + dataStore + '/coverages/' + name + '.json';
622
+ const url =
623
+ this.url +
624
+ 'workspaces/' +
625
+ workspace +
626
+ '/coveragestores/' +
627
+ dataStore +
628
+ '/coverages/' +
629
+ name +
630
+ '.json';
511
631
  const response = await fetch(url, {
512
632
  credentials: 'include',
513
633
  method: 'PUT',
@@ -539,7 +659,18 @@ export default class LayerClient {
539
659
  *
540
660
  * @throws Error if request fails
541
661
  */
542
- async enableTimeFeatureType (workspace, dataStore, name, attribute, presentation, resolution, defaultValue, nearestMatchEnabled, rawNearestMatchEnabled, acceptableInterval) {
662
+ async enableTimeFeatureType(
663
+ workspace,
664
+ dataStore,
665
+ name,
666
+ attribute,
667
+ presentation,
668
+ resolution,
669
+ defaultValue,
670
+ nearestMatchEnabled,
671
+ rawNearestMatchEnabled,
672
+ acceptableInterval
673
+ ) {
543
674
  const body = {
544
675
  featureType: {
545
676
  metadata: {
@@ -564,7 +695,15 @@ export default class LayerClient {
564
695
  }
565
696
  };
566
697
 
567
- const url = this.url + 'workspaces/' + workspace + '/datastores/' + dataStore + '/featuretypes/' + name + '.json';
698
+ const url =
699
+ this.url +
700
+ 'workspaces/' +
701
+ workspace +
702
+ '/datastores/' +
703
+ dataStore +
704
+ '/featuretypes/' +
705
+ name +
706
+ '.json';
568
707
  const response = await fetch(url, {
569
708
  credentials: 'include',
570
709
  method: 'PUT',
@@ -592,8 +731,16 @@ export default class LayerClient {
592
731
  *
593
732
  * @returns {Object} An object with coverage information or undefined if it cannot be found
594
733
  */
595
- async getCoverage (workspace, coverageStore, name) {
596
- const url = this.url + 'workspaces/' + workspace + '/coveragestores/' + coverageStore + '/coverages/' + name + '.json';
734
+ async getCoverage(workspace, coverageStore, name) {
735
+ const url =
736
+ this.url +
737
+ 'workspaces/' +
738
+ workspace +
739
+ '/coveragestores/' +
740
+ coverageStore +
741
+ '/coverages/' +
742
+ name +
743
+ '.json';
597
744
  const response = await fetch(url, {
598
745
  credentials: 'include',
599
746
  method: 'GET',
@@ -616,6 +763,40 @@ export default class LayerClient {
616
763
  return response.json();
617
764
  }
618
765
 
766
+ /**
767
+ * Returns a dedicated coverage object.
768
+ *
769
+ * @param {String} workspace Workspace containing the coverage
770
+ * @param {String} name Coverage to query
771
+ *
772
+ * @throws Error if request fails
773
+ *
774
+ * @returns {Object} An object with coverage information or undefined if it cannot be found
775
+ */
776
+ async getCoverageFromLayer(workspace, name) {
777
+ const url = this.url + '/workspaces/' + workspace + '/coverages/' + name + '.json';
778
+ const response = await fetch(url, {
779
+ credentials: 'include',
780
+ method: 'GET',
781
+ headers: {
782
+ Authorization: this.auth
783
+ }
784
+ });
785
+
786
+ if (!response.ok) {
787
+ const grc = new AboutClient(this.url, this.auth);
788
+ if (await grc.exists()) {
789
+ // GeoServer exists, but requested item does not exist, we return empty
790
+ return;
791
+ } else {
792
+ // There was a general problem with GeoServer
793
+ const geoServerResponse = await getGeoServerResponseText(response);
794
+ throw new GeoServerResponseError(null, geoServerResponse);
795
+ }
796
+ }
797
+ return response.json();
798
+ }
799
+
619
800
  /**
620
801
  * Renames the existing bands of a coverage layer.
621
802
  *
@@ -628,26 +809,31 @@ export default class LayerClient {
628
809
  *
629
810
  * @throws Error if request fails
630
811
  */
631
- async renameCoverageBands (workspace, dataStore, layername, bandNames) {
812
+ async renameCoverageBands(workspace, dataStore, layername, bandNames) {
632
813
  const body = {
633
814
  coverage: {
634
815
  dimensions: {
635
- coverageDimension: [
636
- ]
816
+ coverageDimension: []
637
817
  }
638
818
  }
639
819
  };
640
820
 
641
821
  // dynamically create the body
642
- bandNames.forEach(bandName => {
643
- body.coverage.dimensions.coverageDimension.push(
644
- {
645
- name: bandName
646
- }
647
- );
648
- })
822
+ bandNames.forEach((bandName) => {
823
+ body.coverage.dimensions.coverageDimension.push({
824
+ name: bandName
825
+ });
826
+ });
649
827
 
650
- const url = this.url + 'workspaces/' + workspace + '/coveragestores/' + dataStore + '/coverages/' + layername + '.json';
828
+ const url =
829
+ this.url +
830
+ 'workspaces/' +
831
+ workspace +
832
+ '/coveragestores/' +
833
+ dataStore +
834
+ '/coverages/' +
835
+ layername +
836
+ '.json';
651
837
  const response = await fetch(url, {
652
838
  credentials: 'include',
653
839
  method: 'PUT',
@@ -663,4 +849,100 @@ export default class LayerClient {
663
849
  throw new GeoServerResponseError(null, geoServerResponse);
664
850
  }
665
851
  }
852
+
853
+ /**
854
+ * Returns the data store of a layer.
855
+ *
856
+ * @param {String} workspace The workspace of the layer
857
+ * @param {String} layer The name of the layer
858
+ *
859
+ * @throws GeoServerResponseError if request fails or layer does not exist or lacks a data store.
860
+ *
861
+ * @returns {Object} The data store object
862
+ */
863
+ async getDataStore(workspace, layer) {
864
+ const featureTypeObj = await this.getFeatureTypeFromLayer(workspace, layer);
865
+
866
+ if (
867
+ !featureTypeObj ||
868
+ !featureTypeObj.featureType ||
869
+ !featureTypeObj.featureType.store ||
870
+ !featureTypeObj.featureType.store.name
871
+ ) {
872
+ throw new GeoServerResponseError(
873
+ `Layer '${workspace}:${layer}' lacks a feature type or the feature type lacks a data store.`
874
+ );
875
+ }
876
+
877
+ const url = featureTypeObj?.featureType?.store?.href;
878
+
879
+ const response = await fetch(url, {
880
+ credentials: 'include',
881
+ method: 'GET',
882
+ headers: {
883
+ Authorization: this.auth
884
+ }
885
+ });
886
+
887
+ if (!response.ok) {
888
+ const grc = new AboutClient(this.url, this.auth);
889
+ if (await grc.exists()) {
890
+ // GeoServer exists, but requested item does not exist, we return empty
891
+ return;
892
+ } else {
893
+ // There was a general problem with GeoServer
894
+ const geoServerResponse = await getGeoServerResponseText(response);
895
+ throw new GeoServerResponseError(null, geoServerResponse);
896
+ }
897
+ }
898
+ return response.json();
899
+ }
900
+
901
+ /**
902
+ * Returns the coverage store of a layer.
903
+ *
904
+ * @param {String} workspace The workspace of the layer
905
+ * @param {String} layer The name of the layer
906
+ *
907
+ * @throws GeoServerResponseError if request fails or layer does not exist or lacks a coverage store.
908
+ *
909
+ * @returns {Object} The coverage store object
910
+ */
911
+ async getCoverageStore(workspace, layer) {
912
+ const coverageObj = await this.getCoverageFromLayer(workspace, layer);
913
+
914
+ if (
915
+ !coverageObj ||
916
+ !coverageObj.coverage ||
917
+ !coverageObj.coverage.store ||
918
+ !coverageObj.coverage.store.name
919
+ ) {
920
+ throw new GeoServerResponseError(
921
+ `Layer '${workspace}:${layer}' lacks a coverage or the coverage lacks a coverage store.`
922
+ );
923
+ }
924
+
925
+ const url = coverageObj?.coverage?.store?.href;
926
+
927
+ const response = await fetch(url, {
928
+ credentials: 'include',
929
+ method: 'GET',
930
+ headers: {
931
+ Authorization: this.auth
932
+ }
933
+ });
934
+
935
+ if (!response.ok) {
936
+ const grc = new AboutClient(this.url, this.auth);
937
+ if (await grc.exists()) {
938
+ // GeoServer exists, but requested item does not exist, we return empty
939
+ return;
940
+ } else {
941
+ // There was a general problem with GeoServer
942
+ const geoServerResponse = await getGeoServerResponseText(response);
943
+ throw new GeoServerResponseError(null, geoServerResponse);
944
+ }
945
+ }
946
+ return response.json();
947
+ }
666
948
  }