geoserver-node-client 0.0.7 → 1.2.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/README.md +80 -9
- package/dist/geoserver-rest-client.js +92 -0
- package/dist/package.json +56 -0
- package/dist/src/about.js +145 -0
- package/dist/src/datastore.js +1117 -0
- package/dist/src/imagemosaic.js +297 -0
- package/dist/src/layer.js +1263 -0
- package/dist/src/namespace.js +315 -0
- package/dist/src/reset-reload.js +160 -0
- package/dist/src/security.js +297 -0
- package/dist/src/settings.js +345 -0
- package/dist/src/style.js +597 -0
- package/dist/src/util/geoserver.js +97 -0
- package/dist/src/workspace.js +321 -0
- package/geoserver-rest-client.js +18 -52
- package/package.json +24 -6
- package/src/about.js +59 -0
- package/src/datastore.js +196 -200
- package/src/imagemosaic.js +75 -98
- package/src/layer.js +469 -328
- package/src/namespace.js +84 -83
- package/src/reset-reload.js +70 -0
- package/src/security.js +61 -84
- package/src/settings.js +76 -91
- package/src/style.js +165 -171
- package/src/util/geoserver.js +41 -0
- package/src/workspace.js +89 -81
- package/.eslintrc.json +0 -20
- package/.github/workflows/ci-geoserver-node-client.yml +0 -54
- package/.github/workflows/ci-publish-docs.yml +0 -24
- package/.github/workflows/wait-for.sh +0 -145
- package/.vscode/settings.json +0 -3
- package/DOCS_HOME.md +0 -26
- package/demo/index.js +0 -188
- package/release-it.json +0 -8
- package/test/sample_data/iceland.gpkg +0 -0
- package/test/sample_data/world.geotiff +0 -0
- package/test/test.js +0 -502
package/src/layer.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import fetch from 'node-fetch';
|
|
2
|
+
import { getGeoServerResponseText, GeoServerResponseError } from './util/geoserver.js';
|
|
3
|
+
import AboutClient from './about.js'
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Client for GeoServer layers
|
|
@@ -10,116 +12,222 @@ export default class LayerClient {
|
|
|
10
12
|
* Creates a GeoServer REST LayerClient instance.
|
|
11
13
|
*
|
|
12
14
|
* @param {String} url The URL of the GeoServer REST API endpoint
|
|
13
|
-
* @param {String}
|
|
14
|
-
* @param {String} password The password for the GeoServer REST API
|
|
15
|
+
* @param {String} auth The Basic Authentication string
|
|
15
16
|
*/
|
|
16
|
-
constructor (url,
|
|
17
|
-
this.url = url
|
|
18
|
-
this.
|
|
19
|
-
this.password = password;
|
|
17
|
+
constructor (url, auth) {
|
|
18
|
+
this.url = url;
|
|
19
|
+
this.auth = auth;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* Returns a GeoServer layer by the given
|
|
23
|
+
* Returns a GeoServer layer by the given workspace and layer name,
|
|
24
24
|
* e.g. "myWs:myLayer".
|
|
25
25
|
*
|
|
26
|
-
* @param {String}
|
|
26
|
+
* @param {String} workspace The name of the workspace, can be undefined
|
|
27
|
+
* @param {String} layerName The name of the layer to query
|
|
27
28
|
*
|
|
28
|
-
* @
|
|
29
|
+
* @throws Error if request fails
|
|
30
|
+
*
|
|
31
|
+
* @returns {Object} An object with layer information or undefined if it cannot be found
|
|
29
32
|
*/
|
|
30
|
-
async get (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
async get (workspace, layerName) {
|
|
34
|
+
let qualifiedName;
|
|
35
|
+
if (workspace) {
|
|
36
|
+
qualifiedName = `${workspace}:${layerName}`;
|
|
37
|
+
} else {
|
|
38
|
+
qualifiedName = layerName;
|
|
39
|
+
}
|
|
40
|
+
const response = await fetch(this.url + 'layers/' + qualifiedName + '.json', {
|
|
41
|
+
credentials: 'include',
|
|
42
|
+
method: 'GET',
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: this.auth
|
|
45
|
+
}
|
|
46
|
+
});
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
const grc = new AboutClient(this.url, this.auth);
|
|
50
|
+
if (await grc.exists()) {
|
|
51
|
+
// GeoServer exists, but requested item does not exist, we return empty
|
|
52
|
+
return;
|
|
43
53
|
} else {
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
// There was a general problem with GeoServer
|
|
55
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
56
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
46
57
|
}
|
|
47
|
-
} catch (error) {
|
|
48
|
-
return false;
|
|
49
58
|
}
|
|
59
|
+
return response.json();
|
|
50
60
|
}
|
|
51
61
|
|
|
52
62
|
/**
|
|
53
63
|
* Sets the attribution text and link of a layer.
|
|
54
64
|
*
|
|
55
|
-
* @param {String}
|
|
65
|
+
* @param {String} workspace The name of the workspace, can be undefined
|
|
66
|
+
* @param {String} layerName The name of the layer to query
|
|
56
67
|
* @param {String} [attributionText] The attribution text
|
|
57
68
|
* @param {String} [attributionLink] The attribution link
|
|
58
69
|
*
|
|
59
|
-
* @
|
|
70
|
+
* @throws Error if request fails
|
|
60
71
|
*/
|
|
61
|
-
async modifyAttribution (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
async modifyAttribution (workspace, layerName, attributionText, attributionLink) {
|
|
73
|
+
let qualifiedName;
|
|
74
|
+
if (workspace) {
|
|
75
|
+
qualifiedName = `${workspace}:${layerName}`;
|
|
76
|
+
} else {
|
|
77
|
+
qualifiedName = layerName;
|
|
78
|
+
}
|
|
79
|
+
// take existing layer properties as template
|
|
80
|
+
const jsonBody = await this.get(workspace, layerName);
|
|
81
|
+
|
|
82
|
+
if (!jsonBody || !jsonBody.layer || !jsonBody.layer.attribution) {
|
|
83
|
+
throw new GeoServerResponseError(
|
|
84
|
+
`layer '${workspace}:${layerName}' misses the property 'attribution'`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// set attribution text and link
|
|
89
|
+
if (attributionText) {
|
|
90
|
+
jsonBody.layer.attribution.title = attributionText;
|
|
91
|
+
}
|
|
92
|
+
if (attributionLink) {
|
|
93
|
+
jsonBody.layer.attribution.href = attributionLink;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const url = this.url + 'layers/' + qualifiedName + '.json';
|
|
97
|
+
const response = await fetch(url, {
|
|
98
|
+
credentials: 'include',
|
|
99
|
+
method: 'PUT',
|
|
100
|
+
headers: {
|
|
101
|
+
Authorization: this.auth,
|
|
102
|
+
'Content-Type': 'application/json'
|
|
103
|
+
},
|
|
104
|
+
body: JSON.stringify(jsonBody)
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
109
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Returns all layers in the GeoServer.
|
|
115
|
+
*
|
|
116
|
+
* @throws Error if request fails
|
|
117
|
+
*
|
|
118
|
+
* @returns {Object} An object with all layer information
|
|
119
|
+
*/
|
|
120
|
+
async getAll () {
|
|
121
|
+
const response = await fetch(this.url + 'layers.json', {
|
|
122
|
+
credentials: 'include',
|
|
123
|
+
method: 'GET',
|
|
124
|
+
headers: {
|
|
125
|
+
Authorization: this.auth
|
|
69
126
|
}
|
|
70
|
-
|
|
71
|
-
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (!response.ok) {
|
|
130
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
131
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
132
|
+
}
|
|
133
|
+
return response.json();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get all layers of a workspace.
|
|
138
|
+
*
|
|
139
|
+
* @param {String} workspace The workspace
|
|
140
|
+
*
|
|
141
|
+
* @throws Error if request fails
|
|
142
|
+
*
|
|
143
|
+
* @return {Object} An object with the information about the layers
|
|
144
|
+
*/
|
|
145
|
+
async getLayers (workspace) {
|
|
146
|
+
const response = await fetch(this.url + 'workspaces/' + workspace + '/layers.json', {
|
|
147
|
+
credentials: 'include',
|
|
148
|
+
method: 'GET',
|
|
149
|
+
headers: {
|
|
150
|
+
Authorization: this.auth,
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
156
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return await response.json();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Returns information about a cascaded WMS layer.
|
|
164
|
+
*
|
|
165
|
+
* @param {String} workspace The workspace
|
|
166
|
+
* @param {String} datastore The datastore
|
|
167
|
+
* @param {String} layerName The WMS layer name
|
|
168
|
+
*
|
|
169
|
+
* @throws Error if request fails
|
|
170
|
+
*
|
|
171
|
+
* @returns {Object} An object with layer information or undefined if it cannot be found
|
|
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,
|
|
72
179
|
}
|
|
180
|
+
});
|
|
73
181
|
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
headers: {
|
|
80
|
-
Authorization: 'Basic ' + auth,
|
|
81
|
-
'Content-Type': 'application/json'
|
|
82
|
-
},
|
|
83
|
-
body: JSON.stringify(jsonBody)
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
if (response.status === 200) {
|
|
87
|
-
return true;
|
|
182
|
+
if (!response.ok) {
|
|
183
|
+
const grc = new AboutClient(this.url, this.auth);
|
|
184
|
+
if (await grc.exists()) {
|
|
185
|
+
// GeoServer exists, but requested item does not exist, we return empty
|
|
186
|
+
return;
|
|
88
187
|
} else {
|
|
89
|
-
|
|
90
|
-
|
|
188
|
+
// There was a general problem with GeoServer
|
|
189
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
190
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
91
191
|
}
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.log(error);
|
|
94
|
-
return false;
|
|
95
192
|
}
|
|
193
|
+
|
|
194
|
+
return await response.json();
|
|
96
195
|
}
|
|
97
196
|
|
|
197
|
+
// TODO: automated test needed
|
|
98
198
|
/**
|
|
99
|
-
* Returns
|
|
199
|
+
* Returns information about a cascaded WMTS layer.
|
|
200
|
+
*
|
|
201
|
+
* @param {String} workspace The workspace
|
|
202
|
+
* @param {String} datastore The datastore
|
|
203
|
+
* @param {String} layerName The WMTS layer name
|
|
100
204
|
*
|
|
101
|
-
* @
|
|
205
|
+
* @throws Error if request fails
|
|
206
|
+
*
|
|
207
|
+
* @returns {Object} An object with layer information or undefined if it cannot be found
|
|
102
208
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
});
|
|
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,
|
|
215
|
+
}
|
|
216
|
+
});
|
|
113
217
|
|
|
114
|
-
|
|
115
|
-
|
|
218
|
+
if (!response.ok) {
|
|
219
|
+
const grc = new AboutClient(this.url, this.auth);
|
|
220
|
+
if (await grc.exists()) {
|
|
221
|
+
// GeoServer exists, but requested item does not exist, we return empty
|
|
222
|
+
return;
|
|
116
223
|
} else {
|
|
117
|
-
|
|
118
|
-
|
|
224
|
+
// There was a general problem with GeoServer
|
|
225
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
226
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
119
227
|
}
|
|
120
|
-
} catch (error) {
|
|
121
|
-
return false;
|
|
122
228
|
}
|
|
229
|
+
|
|
230
|
+
return await response.json();
|
|
123
231
|
}
|
|
124
232
|
|
|
125
233
|
/**
|
|
@@ -133,40 +241,33 @@ export default class LayerClient {
|
|
|
133
241
|
* @param {String} enabled Flag to enable FeatureType by default
|
|
134
242
|
* @param {String} [abstract] The abstract of the layer
|
|
135
243
|
*
|
|
136
|
-
* @
|
|
244
|
+
* @throws Error if request fails
|
|
137
245
|
*/
|
|
138
246
|
async publishFeatureTypeDefaultDataStore (workspace, nativeName, name, title, srs, enabled, abstract) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
abstract: abstract || ''
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
const auth = Buffer.from(this.user + ':' + this.password).toString('base64');
|
|
152
|
-
const response = await fetch(this.url + 'workspaces/' + workspace + '/featuretypes', {
|
|
153
|
-
credentials: 'include',
|
|
154
|
-
method: 'POST',
|
|
155
|
-
headers: {
|
|
156
|
-
Authorization: 'Basic ' + auth,
|
|
157
|
-
'Content-Type': 'application/json'
|
|
158
|
-
},
|
|
159
|
-
body: JSON.stringify(body)
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
if (response.status === 201) {
|
|
163
|
-
return true;
|
|
164
|
-
} else {
|
|
165
|
-
console.warn(await response.text());
|
|
166
|
-
return false;
|
|
247
|
+
const body = {
|
|
248
|
+
featureType: {
|
|
249
|
+
name: name,
|
|
250
|
+
nativeName: nativeName || name,
|
|
251
|
+
title: title || name,
|
|
252
|
+
srs: srs || 'EPSG:4326',
|
|
253
|
+
enabled: enabled,
|
|
254
|
+
abstract: abstract || ''
|
|
167
255
|
}
|
|
168
|
-
}
|
|
169
|
-
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const response = await fetch(this.url + 'workspaces/' + workspace + '/featuretypes', {
|
|
259
|
+
credentials: 'include',
|
|
260
|
+
method: 'POST',
|
|
261
|
+
headers: {
|
|
262
|
+
Authorization: this.auth,
|
|
263
|
+
'Content-Type': 'application/json'
|
|
264
|
+
},
|
|
265
|
+
body: JSON.stringify(body)
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
if (!response.ok) {
|
|
269
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
270
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
170
271
|
}
|
|
171
272
|
}
|
|
172
273
|
|
|
@@ -183,50 +284,78 @@ export default class LayerClient {
|
|
|
183
284
|
* @param {String} [abstract] The abstract of the layer
|
|
184
285
|
* @param {String} [nativeBoundingBox] The native BoundingBox of the FeatureType (has to be set if no data is in store at creation time)
|
|
185
286
|
*
|
|
186
|
-
* @
|
|
287
|
+
* @throws Error if request fails
|
|
187
288
|
*/
|
|
188
289
|
async publishFeatureType (workspace, dataStore, nativeName, name, title, srs, enabled, abstract, nativeBoundingBox) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
$: srs
|
|
195
|
-
}
|
|
290
|
+
// apply CRS info for native BBOX if not provided
|
|
291
|
+
if (nativeBoundingBox && !nativeBoundingBox.crs) {
|
|
292
|
+
nativeBoundingBox.crs = {
|
|
293
|
+
'@class': 'projected',
|
|
294
|
+
$: srs
|
|
196
295
|
}
|
|
296
|
+
}
|
|
197
297
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
298
|
+
const body = {
|
|
299
|
+
featureType: {
|
|
300
|
+
name: name || nativeName,
|
|
301
|
+
nativeName: nativeName,
|
|
302
|
+
title: title || name,
|
|
303
|
+
srs: srs || 'EPSG:4326',
|
|
304
|
+
enabled: enabled,
|
|
305
|
+
abstract: abstract || '',
|
|
306
|
+
nativeBoundingBox: nativeBoundingBox
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
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
|
+
});
|
|
319
|
+
|
|
320
|
+
if (!response.ok) {
|
|
321
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
322
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get detailed information about a FeatureType.
|
|
328
|
+
*
|
|
329
|
+
* @param {String} workspace The workspace of the FeatureType
|
|
330
|
+
* @param {String} datastore The datastore of the FeatureType
|
|
331
|
+
* @param {String} name The name of the FeatureType
|
|
332
|
+
*
|
|
333
|
+
* @throws Error if request fails
|
|
334
|
+
*
|
|
335
|
+
* @returns {Object} The object of the FeatureType
|
|
336
|
+
*/
|
|
337
|
+
async getFeatureType (workspace, datastore, name) {
|
|
338
|
+
const url = this.url + 'workspaces/' + workspace + '/datastores/' + datastore + '/featuretypes/' + name + '.json';
|
|
339
|
+
const response = await fetch(url, {
|
|
340
|
+
credentials: 'include',
|
|
341
|
+
method: 'GET',
|
|
342
|
+
headers: {
|
|
343
|
+
Authorization: this.auth
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
if (!response.ok) {
|
|
348
|
+
const grc = new AboutClient(this.url, this.auth);
|
|
349
|
+
if (await grc.exists()) {
|
|
350
|
+
// GeoServer exists, but requested item does not exist, we return empty
|
|
351
|
+
return;
|
|
223
352
|
} else {
|
|
224
|
-
|
|
225
|
-
|
|
353
|
+
// There was a general problem with GeoServer
|
|
354
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
355
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
226
356
|
}
|
|
227
|
-
} catch (error) {
|
|
228
|
-
return false;
|
|
229
357
|
}
|
|
358
|
+
return response.json();
|
|
230
359
|
}
|
|
231
360
|
|
|
232
361
|
/**
|
|
@@ -241,40 +370,33 @@ export default class LayerClient {
|
|
|
241
370
|
* @param {String} enabled Flag to enable WMS layer by default
|
|
242
371
|
* @param {String} [abstract] The abstract of the layer
|
|
243
372
|
*
|
|
244
|
-
* @
|
|
373
|
+
* @throws Error if request fails
|
|
245
374
|
*/
|
|
246
375
|
async publishWmsLayer (workspace, dataStore, nativeName, name, title, srs, enabled, abstract) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
abstract: abstract || ''
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
const auth = Buffer.from(this.user + ':' + this.password).toString('base64');
|
|
260
|
-
const response = await fetch(this.url + 'workspaces/' + workspace + '/wmsstores/' + dataStore + '/wmslayers', {
|
|
261
|
-
credentials: 'include',
|
|
262
|
-
method: 'POST',
|
|
263
|
-
headers: {
|
|
264
|
-
Authorization: 'Basic ' + auth,
|
|
265
|
-
'Content-Type': 'application/json'
|
|
266
|
-
},
|
|
267
|
-
body: JSON.stringify(body)
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
if (response.status === 201) {
|
|
271
|
-
return true;
|
|
272
|
-
} else {
|
|
273
|
-
console.warn(await response.text());
|
|
274
|
-
return false;
|
|
376
|
+
const body = {
|
|
377
|
+
wmsLayer: {
|
|
378
|
+
name: name || nativeName,
|
|
379
|
+
nativeName: nativeName,
|
|
380
|
+
title: title || name || nativeName,
|
|
381
|
+
srs: srs || 'EPSG:4326',
|
|
382
|
+
enabled: enabled,
|
|
383
|
+
abstract: abstract || ''
|
|
275
384
|
}
|
|
276
|
-
}
|
|
277
|
-
|
|
385
|
+
};
|
|
386
|
+
|
|
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
|
+
});
|
|
396
|
+
|
|
397
|
+
if (!response.ok) {
|
|
398
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
399
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
278
400
|
}
|
|
279
401
|
}
|
|
280
402
|
|
|
@@ -290,39 +412,33 @@ export default class LayerClient {
|
|
|
290
412
|
* @param {String} enabled Flag to enable layer by default
|
|
291
413
|
* @param {String} [abstract] The abstract of the layer
|
|
292
414
|
*
|
|
293
|
-
* @
|
|
415
|
+
* @throws Error if request fails
|
|
294
416
|
*/
|
|
295
417
|
async publishDbRaster (workspace, coverageStore, nativeName, name, title, srs, enabled, abstract) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
abstract: abstract || ''
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
const auth = Buffer.from(this.user + ':' + this.password).toString('base64');
|
|
309
|
-
const response = await fetch(this.url + 'workspaces/' + workspace + '/coveragestores/' + coverageStore + '/coverages', {
|
|
310
|
-
credentials: 'include',
|
|
311
|
-
method: 'POST',
|
|
312
|
-
headers: {
|
|
313
|
-
Authorization: 'Basic ' + auth,
|
|
314
|
-
'Content-Type': 'application/json'
|
|
315
|
-
},
|
|
316
|
-
body: JSON.stringify(body)
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
if (response.status === 201) {
|
|
320
|
-
return true;
|
|
321
|
-
} else {
|
|
322
|
-
return false;
|
|
418
|
+
const body = {
|
|
419
|
+
coverage: {
|
|
420
|
+
name: name || nativeName,
|
|
421
|
+
nativeName: nativeName,
|
|
422
|
+
title: title || name,
|
|
423
|
+
srs: srs,
|
|
424
|
+
enabled: enabled,
|
|
425
|
+
abstract: abstract || ''
|
|
323
426
|
}
|
|
324
|
-
}
|
|
325
|
-
|
|
427
|
+
};
|
|
428
|
+
|
|
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
|
+
});
|
|
438
|
+
|
|
439
|
+
if (!response.ok) {
|
|
440
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
441
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
326
442
|
}
|
|
327
443
|
}
|
|
328
444
|
|
|
@@ -334,27 +450,20 @@ export default class LayerClient {
|
|
|
334
450
|
* @param {String} name Layer to delete
|
|
335
451
|
* @param {Boolean} recurse Flag to enable recursive deletion
|
|
336
452
|
*
|
|
337
|
-
* @
|
|
453
|
+
* @throws Error if request fails
|
|
338
454
|
*/
|
|
339
455
|
async deleteFeatureType (workspace, datastore, name, recurse) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
headers: {
|
|
346
|
-
Authorization: 'Basic ' + auth
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
if (response.status === 200) {
|
|
351
|
-
return true;
|
|
352
|
-
} else {
|
|
353
|
-
console.warn(await response.text());
|
|
354
|
-
return false;
|
|
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
|
|
355
461
|
}
|
|
356
|
-
}
|
|
357
|
-
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
if (!response.ok) {
|
|
465
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
466
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
358
467
|
}
|
|
359
468
|
}
|
|
360
469
|
|
|
@@ -371,56 +480,46 @@ export default class LayerClient {
|
|
|
371
480
|
* @param {Boolean} [rawNearestMatchEnabled] Enable raw nearest match
|
|
372
481
|
* @param {String} [acceptableInterval] Acceptable interval for nearest match, e.g.'PT30M'
|
|
373
482
|
*
|
|
374
|
-
* @
|
|
483
|
+
* @throws Error if request fails
|
|
375
484
|
*/
|
|
376
485
|
async enableTimeCoverage (workspace, dataStore, name, presentation, resolution, defaultValue, nearestMatchEnabled, rawNearestMatchEnabled, acceptableInterval) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
rawNearestMatchEnabled: rawNearestMatchEnabled,
|
|
394
|
-
acceptableInterval: acceptableInterval
|
|
395
|
-
}
|
|
486
|
+
const body = {
|
|
487
|
+
coverage: {
|
|
488
|
+
metadata: {
|
|
489
|
+
entry: [
|
|
490
|
+
{
|
|
491
|
+
'@key': 'time',
|
|
492
|
+
dimensionInfo: {
|
|
493
|
+
presentation: presentation || 'DISCRETE_INTERVAL',
|
|
494
|
+
resolution: resolution,
|
|
495
|
+
units: 'ISO8601',
|
|
496
|
+
defaultValue: {
|
|
497
|
+
strategy: defaultValue
|
|
498
|
+
},
|
|
499
|
+
nearestMatchEnabled: nearestMatchEnabled,
|
|
500
|
+
rawNearestMatchEnabled: rawNearestMatchEnabled,
|
|
501
|
+
acceptableInterval: acceptableInterval
|
|
396
502
|
}
|
|
397
|
-
|
|
398
|
-
|
|
503
|
+
}
|
|
504
|
+
]
|
|
399
505
|
}
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
const auth = Buffer.from(this.user + ':' + this.password).toString('base64');
|
|
403
|
-
const url = this.url + 'workspaces/' + workspace + '/coveragestores/' + dataStore + '/coverages/' + name + '.json';
|
|
404
|
-
console.log(url);
|
|
405
|
-
const response = await fetch(url, {
|
|
406
|
-
credentials: 'include',
|
|
407
|
-
method: 'PUT',
|
|
408
|
-
headers: {
|
|
409
|
-
Authorization: 'Basic ' + auth,
|
|
410
|
-
'Content-Type': 'application/json'
|
|
411
|
-
},
|
|
412
|
-
body: JSON.stringify(body)
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
if (response.status === 200) {
|
|
416
|
-
return true;
|
|
417
|
-
} else {
|
|
418
|
-
console.warn(await response.text());
|
|
419
|
-
return false;
|
|
420
506
|
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
const url = this.url + 'workspaces/' + workspace + '/coveragestores/' + dataStore + '/coverages/' + name + '.json';
|
|
510
|
+
const response = await fetch(url, {
|
|
511
|
+
credentials: 'include',
|
|
512
|
+
method: 'PUT',
|
|
513
|
+
headers: {
|
|
514
|
+
Authorization: this.auth,
|
|
515
|
+
'Content-Type': 'application/json'
|
|
516
|
+
},
|
|
517
|
+
body: JSON.stringify(body)
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
if (!response.ok) {
|
|
521
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
522
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
424
523
|
}
|
|
425
524
|
}
|
|
426
525
|
|
|
@@ -436,57 +535,48 @@ export default class LayerClient {
|
|
|
436
535
|
* @param {String} defaultValue The default time value, e.g. 'MINIMUM' or 'MAXIMUM' or 'NEAREST' or 'FIXED'
|
|
437
536
|
* @param {Boolean} [nearestMatchEnabled] Enable nearest match
|
|
438
537
|
* @param {Boolean} [rawNearestMatchEnabled] Enable raw nearest match
|
|
439
|
-
* @param {String} [acceptableInterval] Tolerance interval for nearest mach (e.g. 'PT30M'), only has an effect if 'nearestMatchEnabled' is true
|
|
440
538
|
*
|
|
441
|
-
* @
|
|
539
|
+
* @throws Error if request fails
|
|
442
540
|
*/
|
|
443
541
|
async enableTimeFeatureType (workspace, dataStore, name, attribute, presentation, resolution, defaultValue, nearestMatchEnabled, rawNearestMatchEnabled, acceptableInterval) {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
rawNearestMatchEnabled: rawNearestMatchEnabled,
|
|
462
|
-
acceptableInterval: acceptableInterval
|
|
463
|
-
}
|
|
542
|
+
const body = {
|
|
543
|
+
featureType: {
|
|
544
|
+
metadata: {
|
|
545
|
+
entry: [
|
|
546
|
+
{
|
|
547
|
+
'@key': 'time',
|
|
548
|
+
dimensionInfo: {
|
|
549
|
+
attribute: attribute,
|
|
550
|
+
presentation: presentation,
|
|
551
|
+
resolution: resolution,
|
|
552
|
+
units: 'ISO8601',
|
|
553
|
+
defaultValue: {
|
|
554
|
+
strategy: defaultValue
|
|
555
|
+
},
|
|
556
|
+
nearestMatchEnabled: nearestMatchEnabled,
|
|
557
|
+
rawNearestMatchEnabled: rawNearestMatchEnabled,
|
|
558
|
+
acceptableInterval: acceptableInterval
|
|
464
559
|
}
|
|
465
|
-
|
|
466
|
-
|
|
560
|
+
}
|
|
561
|
+
]
|
|
467
562
|
}
|
|
468
|
-
};
|
|
469
|
-
|
|
470
|
-
const auth = Buffer.from(this.user + ':' + this.password).toString('base64');
|
|
471
|
-
const url = this.url + 'workspaces/' + workspace + '/datastores/' + dataStore + '/featuretypes/' + name + '.json';
|
|
472
|
-
const response = await fetch(url, {
|
|
473
|
-
credentials: 'include',
|
|
474
|
-
method: 'PUT',
|
|
475
|
-
headers: {
|
|
476
|
-
Authorization: 'Basic ' + auth,
|
|
477
|
-
'Content-Type': 'application/json'
|
|
478
|
-
},
|
|
479
|
-
body: JSON.stringify(body)
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
if (response.status === 200) {
|
|
483
|
-
return true;
|
|
484
|
-
} else {
|
|
485
|
-
console.warn(await response.text());
|
|
486
|
-
return false;
|
|
487
563
|
}
|
|
488
|
-
}
|
|
489
|
-
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
const url = this.url + 'workspaces/' + workspace + '/datastores/' + dataStore + '/featuretypes/' + name + '.json';
|
|
567
|
+
const response = await fetch(url, {
|
|
568
|
+
credentials: 'include',
|
|
569
|
+
method: 'PUT',
|
|
570
|
+
headers: {
|
|
571
|
+
Authorization: this.auth,
|
|
572
|
+
'Content-Type': 'application/json'
|
|
573
|
+
},
|
|
574
|
+
body: JSON.stringify(body)
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
if (!response.ok) {
|
|
578
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
579
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
490
580
|
}
|
|
491
581
|
}
|
|
492
582
|
|
|
@@ -497,28 +587,79 @@ export default class LayerClient {
|
|
|
497
587
|
* @param {String} coverageStore The coveragestore containing the coverage
|
|
498
588
|
* @param {String} name Coverage to query
|
|
499
589
|
*
|
|
500
|
-
* @
|
|
590
|
+
* @throws Error if request fails
|
|
591
|
+
*
|
|
592
|
+
* @returns {Object} An object with coverage information or undefined if it cannot be found
|
|
501
593
|
*/
|
|
502
594
|
async getCoverage (workspace, coverageStore, name) {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
}
|
|
512
|
-
});
|
|
595
|
+
const url = this.url + 'workspaces/' + workspace + '/coveragestores/' + coverageStore + '/coverages/' + name + '.json';
|
|
596
|
+
const response = await fetch(url, {
|
|
597
|
+
credentials: 'include',
|
|
598
|
+
method: 'GET',
|
|
599
|
+
headers: {
|
|
600
|
+
Authorization: this.auth
|
|
601
|
+
}
|
|
602
|
+
});
|
|
513
603
|
|
|
514
|
-
|
|
515
|
-
|
|
604
|
+
if (!response.ok) {
|
|
605
|
+
const grc = new AboutClient(this.url, this.auth);
|
|
606
|
+
if (await grc.exists()) {
|
|
607
|
+
// GeoServer exists, but requested item does not exist, we return empty
|
|
608
|
+
return;
|
|
516
609
|
} else {
|
|
517
|
-
|
|
518
|
-
|
|
610
|
+
// There was a general problem with GeoServer
|
|
611
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
612
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return response.json();
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Renames the existing bands of a coverage layer.
|
|
620
|
+
*
|
|
621
|
+
* Make sure to provide the same number of bands as existing in the layer.
|
|
622
|
+
*
|
|
623
|
+
* @param {String} workspace Workspace of layer
|
|
624
|
+
* @param {String} datastore The datastore of the layer
|
|
625
|
+
* @param {String} layername The layer name
|
|
626
|
+
* @param {String[]} bandNames An array of the new band names in correct order
|
|
627
|
+
*
|
|
628
|
+
* @throws Error if request fails
|
|
629
|
+
*/
|
|
630
|
+
async renameCoverageBands (workspace, dataStore, layername, bandNames) {
|
|
631
|
+
const body = {
|
|
632
|
+
coverage: {
|
|
633
|
+
dimensions: {
|
|
634
|
+
coverageDimension: [
|
|
635
|
+
]
|
|
636
|
+
}
|
|
519
637
|
}
|
|
520
|
-
}
|
|
521
|
-
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
// dynamically create the body
|
|
641
|
+
bandNames.forEach(bandName => {
|
|
642
|
+
body.coverage.dimensions.coverageDimension.push(
|
|
643
|
+
{
|
|
644
|
+
name: bandName
|
|
645
|
+
}
|
|
646
|
+
);
|
|
647
|
+
})
|
|
648
|
+
|
|
649
|
+
const url = this.url + 'workspaces/' + workspace + '/coveragestores/' + dataStore + '/coverages/' + layername + '.json';
|
|
650
|
+
const response = await fetch(url, {
|
|
651
|
+
credentials: 'include',
|
|
652
|
+
method: 'PUT',
|
|
653
|
+
headers: {
|
|
654
|
+
Authorization: this.auth,
|
|
655
|
+
'Content-Type': 'application/json'
|
|
656
|
+
},
|
|
657
|
+
body: JSON.stringify(body)
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
if (!response.ok) {
|
|
661
|
+
const geoServerResponse = await getGeoServerResponseText(response);
|
|
662
|
+
throw new GeoServerResponseError(null, geoServerResponse);
|
|
522
663
|
}
|
|
523
664
|
}
|
|
524
665
|
}
|