@nextgis/ngw-connector 3.0.0-alpha.4 → 3.0.0-alpha.6

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.
@@ -1,13 +1,13 @@
1
- /** Bundle of @nextgis/ngw-connector; version: 3.0.0-alpha.4; author: NextGIS */
1
+ /** Bundle of @nextgis/ngw-connector; version: 3.0.0-alpha.6; author: NextGIS */
2
2
  'use strict';
3
3
 
4
+ var utils = require('@nextgis/utils');
4
5
  var events = require('events');
5
6
  var Cache = require('@nextgis/cache');
6
- var utils = require('@nextgis/utils');
7
7
 
8
8
  var pkg = {
9
9
  name: "@nextgis/ngw-connector",
10
- version: "3.0.0-alpha.4",
10
+ version: "3.0.0-alpha.6",
11
11
  _priority: 12,
12
12
  description: "A lightweight HTTP client optimized for use with NextGIS Web API",
13
13
  main: "index.js",
@@ -16,15 +16,15 @@ var pkg = {
16
16
  jsdelivr: "lib/ngw-connector.global.prod.js",
17
17
  types: "lib/index.d.ts",
18
18
  dependencies: {
19
- "@nextgis/cache": "^3.0.0-alpha.4",
20
- "@nextgis/cancelable-promise": "^3.0.0-alpha.3",
21
- "@nextgis/utils": "^3.0.0-alpha.4",
19
+ "@nextgis/cache": "^3.0.0-alpha.5",
20
+ "@nextgis/cancelable-promise": "^3.0.0-alpha.5",
21
+ "@nextgis/utils": "^3.0.0-alpha.5",
22
22
  "@types/events": "^3.0.0",
23
23
  events: "*",
24
24
  "form-data": "^4.0.0"
25
25
  },
26
26
  devDependencies: {
27
- "@nextgis/build-tools": "^3.0.0-alpha.3"
27
+ "@nextgis/build-tools": "^3.0.0-alpha.5"
28
28
  },
29
29
  scripts: {
30
30
  clean: "rimraf ./lib",
@@ -58,403 +58,411 @@ var pkg = {
58
58
  type: "git",
59
59
  url: "git://github.com/nextgis/nextgis_frontend.git"
60
60
  },
61
+ engines: {
62
+ node: ">=18.20.4"
63
+ },
61
64
  gitHead: "edc68033f914f6c95c4125b9738bba6d36e990b4"
62
65
  };
63
66
 
64
- var __defProp$4 = Object.defineProperty;
65
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
66
- var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
67
+ const CONNECTORS = [];
68
+ function addConnector(connector) {
69
+ CONNECTORS.push(connector);
70
+ }
71
+ function findConnector(options) {
72
+ return CONNECTORS.find((x) => {
73
+ if (x.options.baseUrl === options.baseUrl) {
74
+ if (options.auth) {
75
+ if (x.options.auth) {
76
+ return utils.objectDeepEqual(x.options.auth, options.auth);
77
+ }
78
+ } else {
79
+ return true;
80
+ }
81
+ }
82
+ });
83
+ }
84
+ function removeConnector(connector) {
85
+ const index = CONNECTORS.indexOf(connector);
86
+ if (index !== -1) {
87
+ CONNECTORS.splice(index, 1);
88
+ }
89
+ }
90
+
91
+ class AbortError extends Error {
92
+ constructor(message = "AbortError") {
93
+ super(message);
94
+ this.name = "AbortError";
95
+ }
96
+ }
97
+
98
+ var __defProp$6 = Object.defineProperty;
99
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
100
+ var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
67
101
  class NgwError extends Error {
68
102
  constructor(er) {
69
103
  super();
70
- __publicField$4(this, "name", "NgwError");
71
- __publicField$4(this, "title");
72
- __publicField$4(this, "message");
73
- __publicField$4(this, "detail");
74
- __publicField$4(this, "exception");
75
- __publicField$4(this, "status_code");
76
- __publicField$4(this, "data");
77
- __publicField$4(this, "guru_meditation");
104
+ __publicField$6(this, "name", "NgwError");
105
+ __publicField$6(this, "title");
106
+ __publicField$6(this, "message");
107
+ __publicField$6(this, "detail");
108
+ __publicField$6(this, "exception");
109
+ __publicField$6(this, "status_code");
110
+ __publicField$6(this, "data");
111
+ __publicField$6(this, "guru_meditation");
78
112
  Object.assign(this, er);
79
113
  Object.setPrototypeOf(this, NgwError.prototype);
80
114
  }
81
115
  }
82
116
 
83
- var __defProp$3 = Object.defineProperty;
84
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
85
- var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
117
+ var __defProp$5 = Object.defineProperty;
118
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
119
+ var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
120
+ class InsufficientPermissionsError extends NgwError {
121
+ constructor(obj) {
122
+ super(obj);
123
+ __publicField$5(this, "name", "InsufficientPermissionsError");
124
+ __publicField$5(this, "exception", "nextgisweb.core.exception.InsufficientPermissions");
125
+ Object.setPrototypeOf(this, InsufficientPermissionsError.prototype);
126
+ }
127
+ }
128
+
129
+ var __defProp$4 = Object.defineProperty;
130
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
131
+ var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
86
132
  class ResourceNotFoundError extends NgwError {
87
133
  constructor(obj) {
88
134
  super(obj);
89
- __publicField$3(this, "name", "ResourceNotFoundError");
90
- __publicField$3(this, "exception", "nextgisweb.resource.exception.ResourceNotFound");
135
+ __publicField$4(this, "name", "ResourceNotFoundError");
136
+ __publicField$4(this, "exception", "nextgisweb.resource.exception.ResourceNotFound");
91
137
  Object.setPrototypeOf(this, ResourceNotFoundError.prototype);
92
138
  }
93
139
  }
94
140
 
95
- function isObject(val) {
96
- return Object.prototype.toString.call(val) === "[object Object]";
141
+ var __defProp$3 = Object.defineProperty;
142
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
143
+ var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
144
+ class BaseAPIError extends Error {
145
+ constructor(message) {
146
+ super(message || "Something went wrong.");
147
+ __publicField$3(this, "title");
148
+ this.name = "BaseAPIError";
149
+ this.title = "Unknown API error";
150
+ if (Error.captureStackTrace) {
151
+ Error.captureStackTrace(this, BaseAPIError);
152
+ }
153
+ }
97
154
  }
98
-
99
- function resourceCompare(res1, res2) {
100
- return utils.objectDeepEqual(res1, res2);
155
+ class NetworksResponseError extends BaseAPIError {
156
+ // prettier-ignore
157
+ constructor(message) {
158
+ super(message || "There is no response from the server or problem connecting to server.");
159
+ __publicField$3(this, "detail");
160
+ this.title = "Network error";
161
+ this.detail = "Check network connectivity and try again later.";
162
+ }
101
163
  }
102
-
103
- const exclude = ["description"];
104
- function resourceToQuery(resource, prefix = "") {
105
- prefix = prefix ? prefix + "__" : "";
106
- const query = {};
107
- for (const [key, value] of Object.entries(resource)) {
108
- if (exclude.indexOf(key) === -1) {
109
- if (isObject(value)) {
110
- if (key === "owner_user") {
111
- const children = resourceToQuery(value, key);
112
- Object.assign(query, children);
113
- } else if (key === "parent" && "id" in value) {
114
- query.parent_id = value.id;
115
- }
116
- } else if (utils.defined(value)) {
117
- query[prefix + key] = value;
118
- }
164
+ class InvalidResponseError extends BaseAPIError {
165
+ constructor(message) {
166
+ super(message || "Something went wrong.");
167
+ this.title = "Unexpected server response";
168
+ }
169
+ }
170
+ class ServerResponseError extends BaseAPIError {
171
+ constructor(data) {
172
+ super(data.message);
173
+ __publicField$3(this, "detail");
174
+ __publicField$3(this, "data");
175
+ this.title = data.title || this.title;
176
+ this.detail = data.detail || null;
177
+ this.data = data;
178
+ }
179
+ }
180
+ class LunkwillError extends Error {
181
+ // prettier-ignore
182
+ constructor(message, data = {}) {
183
+ super(message || "Unexpected error while processing long-running request.");
184
+ __publicField$3(this, "title");
185
+ __publicField$3(this, "data");
186
+ this.name = "LunkwillError";
187
+ this.title = "Long-running request error";
188
+ this.data = data;
189
+ if (Error.captureStackTrace) {
190
+ Error.captureStackTrace(this, LunkwillError);
119
191
  }
120
192
  }
121
- return query;
193
+ }
194
+ class LunkwillRequestCancelled extends LunkwillError {
195
+ constructor(data) {
196
+ super("Long-running request was cancelled.", data);
197
+ }
198
+ }
199
+ class LunkwillRequestFailed extends LunkwillError {
200
+ constructor(data) {
201
+ super(void 0, data);
202
+ }
122
203
  }
123
204
 
124
- var __defProp$2 = Object.defineProperty;
125
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
126
- var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
127
- class ResourcesControl {
128
- constructor({
129
- connector,
130
- cacheId
131
- }) {
132
- __publicField$2(this, "cache");
133
- __publicField$2(this, "connector");
134
- this.connector = connector;
135
- this.cache = new Cache({ namespace: cacheId });
205
+ function lunkwillCheckResponse(lwResp) {
206
+ const ct = lwResp.headers.get("content-type");
207
+ return ct !== void 0 && ct !== null && ct.includes("application/vnd.lunkwill.request-summary+json");
208
+ }
209
+ async function responseJson(response) {
210
+ try {
211
+ return response.json();
212
+ } catch (e) {
213
+ throw new Error();
136
214
  }
137
- // -------------------------------------------------------------------------
138
- // Resource Methods
139
- // -------------------------------------------------------------------------
140
- /**
141
- * Receive resource from NGW by id, keyname or search-object parameter.
142
- * @param resource - Resource id, keyname or search-object
143
- *
144
- * @remarks
145
- * Fetching resource would be cached to speed up next call
146
- */
147
- getOne(resource, requestOptions) {
148
- const opt = { ...requestOptions };
149
- if (typeof resource === "string") ; else if (typeof resource === "number") ; else if (isObject(resource)) {
150
- if (resource.id !== void 0) {
151
- resource.id;
152
- } else {
153
- if (resource.keyname) {
154
- resource.keyname;
155
- }
156
- if (resource.display_name) {
157
- resource.display_name;
158
- }
159
- }
215
+ }
216
+ async function lunkwillResponseUrl(lwResp) {
217
+ const lwData = await responseJson(lwResp);
218
+ let delay = lwData.delay_ms;
219
+ const retry = lwData.retry_ms !== void 0 ? lwData.retry_ms : 2e3;
220
+ const sum = `/api/lunkwill/${lwData.id}/summary`;
221
+ const res = `/api/lunkwill/${lwData.id}/response`;
222
+ const sleep = (msec) => new Promise((resolve) => setTimeout(resolve, msec));
223
+ let failed = false;
224
+ let ready = false;
225
+ while (!ready) {
226
+ await sleep(failed ? retry : delay);
227
+ failed = false;
228
+ let lwResp2;
229
+ let lwData2;
230
+ try {
231
+ lwResp2 = await fetch(sum, { credentials: "same-origin" });
232
+ lwData2 = await lwResp2.json();
233
+ } catch (e) {
234
+ failed = true;
235
+ continue;
160
236
  }
161
- if (typeof resource === "string") {
162
- return this._fetchResourceBy({ keyname: resource }, opt);
163
- } else if (typeof resource === "number") {
164
- return this._fetchResourceById(resource, opt);
165
- } else if (isObject(resource)) {
166
- return this._fetchResourceBy(resource, opt);
237
+ switch (lwData2.status) {
238
+ case void 0:
239
+ throw new LunkwillError(void 0, lwData2);
240
+ case "ready":
241
+ ready = true;
242
+ break;
243
+ case "cancelled":
244
+ throw new LunkwillRequestCancelled(lwData2);
245
+ case "failed":
246
+ throw new LunkwillRequestFailed(lwData2);
247
+ case "spooled":
248
+ case "processing":
249
+ case "buffering":
250
+ delay = lwData2.delay_ms;
251
+ break;
252
+ default:
253
+ throw new LunkwillError(void 0, lwData2);
167
254
  }
168
- return Promise.resolve(void 0);
169
255
  }
170
- getOneOrFail(resource, requestOptions) {
171
- return this.getOne(resource, requestOptions).then((res) => {
172
- if (res) {
173
- return res;
174
- }
175
- throw new ResourceNotFoundError();
176
- });
256
+ return res;
257
+ }
258
+ async function lunkwillFetch(lwRespUrl) {
259
+ try {
260
+ return await window.fetch(lwRespUrl, { credentials: "same-origin" });
261
+ } catch (e) {
262
+ throw new NetworksResponseError();
177
263
  }
178
- /**
179
- * A fast way to retrieve resource ID for any resource definition.
180
- * @param resource - Any available resource definition
181
- *
182
- * @remarks
183
- * There are situations when exactly the resource id is needed
184
- * (for example, to compose the correct request to the api)
185
- * then this method will come in handy to facilitate the extraction of the identifier
186
- * if the resource is specified through a keyname or other parameters.
187
- */
188
- getId(resource, requestOptions) {
189
- if (typeof resource === "number") {
190
- return Promise.resolve(resource);
191
- } else if (typeof resource === "string" || isObject(resource)) {
192
- return this.getOne(resource, requestOptions).then((res) => {
193
- if (res) {
194
- return res.resource.id;
264
+ }
265
+ const mediaContentTypes = [
266
+ "application/pdf",
267
+ "image/png",
268
+ "image/jpeg",
269
+ "image/tiff",
270
+ "text/csv"
271
+ ];
272
+ const mediaContentTypesRegex = new RegExp(mediaContentTypes.join("|"));
273
+ function isMediaContentType(contentType) {
274
+ return mediaContentTypesRegex.test(contentType);
275
+ }
276
+ function encodeQueryParams(value) {
277
+ const result = [];
278
+ for (const [k, v] of Object.entries(value)) {
279
+ if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
280
+ result.push(`${k}=${encodeURIComponent(v)}`);
281
+ } else if (Array.isArray(v)) {
282
+ result.push(`${k}=${v.map(encodeURIComponent).join(",")}`);
283
+ } else {
284
+ for (const [sk, sv] of Object.entries(v)) {
285
+ const ske = `${k}[${encodeURIComponent(sk)}]`;
286
+ if (typeof sv === "string" || typeof sv === "number" || typeof sv === "boolean") {
287
+ result.push(`${ske}=${encodeURIComponent(sv)}`);
288
+ } else if (Array.isArray(sv)) {
289
+ const sve = sv.map(encodeURIComponent);
290
+ result.push(`${ske}=${sve.join(",")}`);
195
291
  }
196
- });
292
+ }
197
293
  }
198
- return Promise.resolve(void 0);
199
294
  }
200
- /**
201
- * A fast way to retrieve resource ID for any resource definition.
202
- * @param resource - Any available resource definition
203
- *
204
- * @remarks
205
- * Similar with {@link NgwConnector.getResourceId | getResourceId} but rise error if resource is not exist.
206
- * To not make one more checks if the resource is definitely exists
207
- */
208
- getIdOrFail(resource, requestOptions) {
209
- return this.getId(resource, requestOptions).then((resp) => {
210
- if (resp === void 0) {
211
- throw new Error();
212
- }
213
- return resp;
214
- });
295
+ return result.join("&");
296
+ }
297
+ function generateUrl(path, query) {
298
+ let urlParams = "";
299
+ if (query !== void 0) {
300
+ urlParams = "?" + encodeQueryParams(query);
215
301
  }
216
- getMany(resource, requestOptions) {
217
- return this._resourceCacheFilter(resource).then((items) => {
218
- if (!items.length) {
219
- const query = {};
220
- if (resource.keyname) {
221
- query.keyname = resource.keyname;
222
- } else {
223
- Object.assign(query, resourceToQuery(resource));
224
- }
225
- return this.connector.get("resource.search", requestOptions, {
226
- serialization: "full",
227
- ...query
228
- }).then((resources) => {
229
- if ((requestOptions == null ? void 0 : requestOptions.cache) && resources) {
230
- for (const x of resources) {
231
- this.cache.add("resource.item", Promise.resolve(x), {
232
- id: x.resource.id
233
- });
234
- }
235
- }
236
- return resources;
237
- });
238
- }
239
- return items;
240
- });
302
+ return path + urlParams;
303
+ }
304
+ async function request(path, options, cacheEngine) {
305
+ var _a;
306
+ const defaults = {
307
+ method: "GET",
308
+ credentials: "same-origin",
309
+ headers: {}
310
+ };
311
+ const {
312
+ withCredentials,
313
+ responseType,
314
+ cacheProps,
315
+ cacheName,
316
+ lunkwill,
317
+ cache,
318
+ query,
319
+ json,
320
+ ...opt
321
+ } = {
322
+ ...defaults,
323
+ ...options
324
+ };
325
+ if (withCredentials) {
326
+ opt.credentials = "include";
241
327
  }
242
- getParent(resource, requestOptions) {
243
- return this.getOne(resource, requestOptions).then((child) => {
244
- if (child) {
245
- return this.getOne(child.resource.parent.id, requestOptions);
246
- }
247
- return Promise.resolve(void 0);
248
- });
328
+ let useLunkwill = false;
329
+ if (lunkwill !== void 0) {
330
+ lunkwill.toHeaders(opt.headers || {});
331
+ useLunkwill = true;
249
332
  }
250
- getChildrenOf(resource, requestOptions) {
251
- return this.getIdOrFail(resource).then(
252
- (parent) => this._getChildrenOf(parent, requestOptions)
253
- );
333
+ const lunkwillReturnUrl = !!opt.lunkwillReturnUrl;
334
+ delete opt.lunkwillReturnUrl;
335
+ if (json !== void 0) {
336
+ opt.body = JSON.stringify(json);
337
+ const headers = opt.headers || {};
338
+ headers["Content-Type"] = "application/json";
339
+ opt.headers = headers;
254
340
  }
255
- update(resource, data) {
256
- return this.getId(resource).then((id) => {
257
- if (id !== void 0) {
258
- return this.connector.put("resource.item", { data }, { id });
341
+ const url = generateUrl(path, query);
342
+ const makeRequest = async () => {
343
+ let response;
344
+ try {
345
+ response = await fetch(url, opt);
346
+ } catch (e) {
347
+ if (e.name === "AbortError") {
348
+ throw e;
259
349
  }
260
- });
261
- }
262
- /**
263
- * Fast way to delete resource from NGW and clean cache.
264
- * @param resource - Resource definition
265
- */
266
- delete(resource) {
267
- return this.getId(resource).then((id) => {
268
- if (id !== void 0) {
269
- return this.connector.delete("resource.item", null, { id }).then(() => {
270
- this._cleanResourceItemCache(id);
271
- return void 0;
272
- });
350
+ throw new NetworksResponseError();
351
+ }
352
+ if (useLunkwill && lunkwillCheckResponse(response)) {
353
+ const lwRespUrl = await lunkwillResponseUrl(response);
354
+ if (lunkwillReturnUrl) {
355
+ return lwRespUrl;
273
356
  }
274
- });
275
- }
276
- _getChildrenOf(parent, requestOptions, _items = []) {
277
- return this.connector.get("resource.collection", requestOptions, {
278
- parent
279
- }).then((items) => {
280
- const recursivePromises = [];
281
- for (const item of items) {
282
- if (requestOptions == null ? void 0 : requestOptions.cache) {
283
- this.cache.add("resource.item", Promise.resolve(item), {
284
- id: item.resource.id
285
- });
286
- }
287
- _items.push(item);
288
- if ((requestOptions == null ? void 0 : requestOptions.recursive) && item.resource.children) {
289
- recursivePromises.push(
290
- this._getChildrenOf(item.resource.id, requestOptions, _items)
291
- );
292
- }
293
- }
294
- if (recursivePromises.length) {
295
- return Promise.all(recursivePromises).then(() => {
296
- return _items;
297
- });
298
- }
299
- return _items;
300
- });
301
- }
302
- async _cleanResourceItemCache(id) {
303
- var _a;
304
- const all = this.cache.all();
305
- const toDelete = [];
306
- for (const c of all) {
307
- const cid = (_a = c.props) == null ? void 0 : _a.id;
308
- if (["resource.item", "resource"].includes(c.key) && cid !== void 0) {
309
- if (typeof cid === "number") {
310
- if (cid === id) {
311
- toDelete.push(c);
312
- }
313
- } else {
314
- const rid = await this.getId(cid);
315
- if (rid === id) {
316
- toDelete.push(c);
317
- }
318
- }
319
- }
320
- }
321
- for (const d of toDelete) {
322
- this.cache.delete(d);
323
- }
324
- }
325
- _fetchResourceById(id, requestOptions) {
326
- return this.connector.get("resource.item", requestOptions, { id });
327
- }
328
- _fetchResourceBy(resource, requestOptions) {
329
- return this.getMany(resource, requestOptions).then((resources) => {
330
- return resources[0];
331
- });
332
- }
333
- _resourceCacheFilter(resource) {
334
- return Promise.all(this.cache.matchAll("resource.item")).then(
335
- (resources) => {
336
- const items = [];
337
- resources.filter((x) => {
338
- if (x) {
339
- if (resource.keyname && x.resource.keyname) {
340
- return resource.keyname === x.resource.keyname;
341
- }
342
- if (utils.defined(resource.id) && utils.defined(x.resource.id)) {
343
- return resource.id === x.resource.id;
344
- }
345
- return resourceCompare(resource, x.resource);
346
- }
347
- });
348
- return items;
349
- }
350
- );
351
- }
352
- }
353
-
354
- const CONNECTORS = [];
355
- function addConnector(connector) {
356
- CONNECTORS.push(connector);
357
- }
358
- function findConnector(options) {
359
- return CONNECTORS.find((x) => {
360
- if (x.options.baseUrl === options.baseUrl) {
361
- if (options.auth) {
362
- if (x.options.auth) {
363
- return utils.objectDeepEqual(x.options.auth, options.auth);
364
- }
365
- } else {
366
- return true;
367
- }
368
- }
369
- });
370
- }
371
- function removeConnector(connector) {
372
- const index = CONNECTORS.indexOf(connector);
373
- if (index !== -1) {
374
- CONNECTORS.splice(index, 1);
375
- }
376
- }
377
-
378
- class AbortError extends Error {
379
- constructor(message = "AbortError") {
380
- super(message);
381
- this.name = "AbortError";
382
- }
383
- }
384
-
385
- var __defProp$1 = Object.defineProperty;
386
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
387
- var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
388
- class InsufficientPermissionsError extends NgwError {
389
- constructor(obj) {
390
- super(obj);
391
- __publicField$1(this, "name", "InsufficientPermissionsError");
392
- __publicField$1(this, "exception", "nextgisweb.core.exception.InsufficientPermissions");
393
- Object.setPrototypeOf(this, InsufficientPermissionsError.prototype);
357
+ response = await lunkwillFetch(lwRespUrl);
358
+ }
359
+ const respCType = response.headers.get("content-type");
360
+ const respJSON = respCType && (respCType.includes("application/json") || respCType.includes("application/vnd.lunkwill.request-summary+json"));
361
+ let body;
362
+ try {
363
+ const respMedia = respCType && isMediaContentType(respCType);
364
+ if (responseType === "blob" || respMedia) {
365
+ body = await response.blob();
366
+ } else if (respJSON) {
367
+ body = await response.json();
368
+ } else {
369
+ throw new InvalidResponseError();
370
+ }
371
+ } catch (e) {
372
+ if (e.name === "AbortError" || e instanceof InvalidResponseError) {
373
+ throw e;
374
+ }
375
+ throw new InvalidResponseError();
376
+ }
377
+ if (400 <= response.status && response.status <= 599) {
378
+ throw new ServerResponseError(body);
379
+ }
380
+ return body;
381
+ };
382
+ if (cacheEngine && cache && ((_a = opt.method) == null ? void 0 : _a.toUpperCase()) === "GET") {
383
+ const cacheOptions = cacheProps ? cacheProps : {
384
+ ...utils.objectRemoveEmpty({
385
+ withCredentials,
386
+ responseType
387
+ })
388
+ };
389
+ return cacheEngine.add(cacheName || url, makeRequest, cacheOptions, false);
394
390
  }
391
+ return makeRequest();
395
392
  }
396
393
 
397
- const templateRe = /\{ *([\w_-]+) *\}/g;
398
- function template(str, data) {
399
- return str.replace(templateRe, (s, key) => {
400
- let value = data[key];
401
- if (value === void 0) {
402
- throw new Error("No value provided for letiable " + s);
403
- } else if (typeof value === "function") {
404
- value = value(data);
394
+ function routeURL(name, baseUrl, routeData, ...rest) {
395
+ const [template, ...params] = routeData[name];
396
+ const first = rest[0];
397
+ let sub;
398
+ if (first === void 0) {
399
+ sub = [];
400
+ } else if (typeof first === "object" && first !== null) {
401
+ if (rest.length > 1) {
402
+ throw new Error("Too many arguments for route(name, object)!");
405
403
  }
406
- return value;
407
- });
408
- }
409
-
410
- async function apiRequest(opt) {
411
- const { params, name, connector, requestOptions } = opt;
412
- const apiItems = await connector.connect();
413
- let apiItem = apiItems && apiItems[name];
414
- if (apiItem) {
415
- apiItem = [...apiItem];
416
- let url = apiItem.shift();
417
- if (apiItem.length) {
418
- const replaceParams = {};
419
- for (let fry = 0; fry < apiItem.length; fry++) {
420
- const arg = apiItem[fry];
421
- replaceParams[fry] = `{${arg}}`;
422
- if (params[arg] === void 0) {
423
- throw new Error(`\`${arg}\` URL API argument is not specified`);
424
- }
425
- }
426
- if (url) {
427
- url = template(url, replaceParams);
428
- }
404
+ sub = [];
405
+ for (const [p, v] of Object.entries(first)) {
406
+ sub[params.indexOf(p)] = String(v);
429
407
  }
430
- if (params) {
431
- const paramArray = [];
432
- const paramList = params.paramList;
433
- if (Array.isArray(paramList)) {
434
- paramList.forEach(([key, value]) => {
435
- paramArray.push(`${key}=${value}`);
436
- });
437
- }
438
- for (const p in params) {
439
- if (apiItem.indexOf(p) === -1) {
440
- paramArray.push(`${p}=${params[p]}`);
441
- }
442
- }
443
- if (paramArray.length) {
444
- url = `${url}?${paramArray.join("&")}`;
408
+ } else {
409
+ sub = rest.map((v) => String(v));
410
+ }
411
+ return utils.fixUrlStr(
412
+ baseUrl + template.replace(/\{(\w+)\}/g, function(m, a) {
413
+ const idx = parseInt(a);
414
+ const value = sub[idx];
415
+ if (value === void 0) {
416
+ const msg = `Undefined parameter ${idx} in "${template}".`;
417
+ throw new Error(msg);
445
418
  }
419
+ return String(value);
420
+ })
421
+ );
422
+ }
423
+ function route(name, connector, ...rest) {
424
+ const result = {
425
+ url: async (opt) => {
426
+ var _a;
427
+ const routeData = await connector.connect();
428
+ const template = routeURL(
429
+ name,
430
+ (_a = connector.options.baseUrl) != null ? _a : "",
431
+ routeData,
432
+ ...rest
433
+ );
434
+ return generateUrl(template, opt == null ? void 0 : opt.query);
446
435
  }
447
- if (url) {
448
- return connector.makeQuery(url, params, {
449
- cacheName: name,
450
- ...requestOptions
436
+ };
437
+ const methods = ["get", "post", "put", "delete", "patch"];
438
+ for (const method of methods) {
439
+ const methodResp = async (requestOptions) => {
440
+ var _a;
441
+ const { headers: optHeaders, ...restOpt } = requestOptions || {};
442
+ const routeData = await connector.connect();
443
+ const template = routeURL(
444
+ name,
445
+ (_a = connector.options.baseUrl) != null ? _a : "",
446
+ routeData,
447
+ ...rest
448
+ );
449
+ const headers = utils.objectRemoveEmpty({
450
+ ...connector.getAuthorizationHeaders(),
451
+ ...optHeaders != null ? optHeaders : {}
451
452
  });
452
- } else {
453
- throw new Error("Request URL is not set");
454
- }
455
- } else {
456
- return void 0;
453
+ return request(
454
+ template,
455
+ {
456
+ headers,
457
+ ...restOpt,
458
+ method
459
+ },
460
+ connector.cache
461
+ );
462
+ };
463
+ result[method] = methodResp;
457
464
  }
465
+ return result;
458
466
  }
459
467
 
460
468
  function isError(error) {
@@ -464,6 +472,10 @@ function isError(error) {
464
472
  return false;
465
473
  }
466
474
 
475
+ function isObject(val) {
476
+ return Object.prototype.toString.call(val) === "[object Object]";
477
+ }
478
+
467
479
  let loadData;
468
480
  {
469
481
  const url = require("url");
@@ -585,32 +597,44 @@ let loadData;
585
597
  };
586
598
  }
587
599
 
588
- var __defProp = Object.defineProperty;
589
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
590
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
600
+ const templateRe = /\{ *([\w_-]+) *\}/g;
601
+ function template(str, data) {
602
+ return str.replace(templateRe, (s, key) => {
603
+ let value = data[key];
604
+ if (value === void 0) {
605
+ throw new Error("No value provided for letiable " + s);
606
+ } else if (typeof value === "function") {
607
+ value = value(data);
608
+ }
609
+ return value;
610
+ });
611
+ }
612
+
613
+ var __defProp$2 = Object.defineProperty;
614
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
615
+ var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
591
616
  let ID = 0;
592
617
  let REQUEST_ID = 0;
593
618
  class NgwConnector {
594
619
  constructor(options) {
595
620
  this.options = options;
596
- __publicField(this, "id", ID++);
597
- __publicField(this, "emitter", new events.EventEmitter());
598
- __publicField(this, "user");
599
- __publicField(this, "resources");
600
- __publicField(this, "cache");
601
- __publicField(this, "withCredentials");
602
- __publicField(this, "client", `NextGIS-NGW-Connector/${pkg.version}`);
603
- __publicField(this, "routeStr", "/api/component/pyramid/route");
604
- __publicField(this, "activeRequests", {});
605
- __publicField(this, "requestTransform");
621
+ __publicField$2(this, "id", ID++);
622
+ __publicField$2(this, "emitter", new events.EventEmitter());
623
+ __publicField$2(this, "user");
624
+ __publicField$2(this, "cache");
625
+ __publicField$2(this, "withCredentials");
626
+ __publicField$2(this, "client", `NextGIS-NGW-Connector/${pkg.version}`);
627
+ __publicField$2(this, "routeStr", "/api/component/pyramid/route");
628
+ __publicField$2(this, "activeRequests", {});
629
+ __publicField$2(this, "requestTransform");
606
630
  const exist = findConnector(options);
607
631
  this.cache = new Cache({ namespace: options.cacheId });
608
632
  if (exist) {
609
633
  return exist;
610
634
  } else {
611
- const { route, requestTransform, withCredentials } = this.options;
612
- if (route) {
613
- this.routeStr = route;
635
+ const { route: route2, requestTransform, withCredentials } = this.options;
636
+ if (route2) {
637
+ this.routeStr = route2;
614
638
  }
615
639
  if (requestTransform) {
616
640
  this.requestTransform = requestTransform;
@@ -618,10 +642,6 @@ class NgwConnector {
618
642
  if (withCredentials !== void 0) {
619
643
  this.withCredentials = withCredentials;
620
644
  }
621
- this.resources = new ResourcesControl({
622
- connector: this,
623
- cacheId: options.cacheId
624
- });
625
645
  addConnector(this);
626
646
  }
627
647
  }
@@ -633,7 +653,6 @@ class NgwConnector {
633
653
  */
634
654
  clearCache() {
635
655
  this.cache.clean();
636
- this.resources.cache.clean();
637
656
  }
638
657
  setRequestTransform(requestTransform) {
639
658
  this.requestTransform = requestTransform;
@@ -655,7 +674,7 @@ class NgwConnector {
655
674
  * Can be used to check connection.
656
675
  * @example
657
676
  * ```javascript
658
- * const connector = new NgwConnector({baseUrl: 'https://demo.nextgis.com'});
677
+ * const connector = new NgwConnector({ baseUrl: 'https://demo.nextgis.com' });
659
678
  * connector.connect()
660
679
  * .then(() => console.log('Ok'))
661
680
  * .catch((er) => console.log('Connection problem', er));
@@ -669,88 +688,556 @@ class NgwConnector {
669
688
  await this._login({ login, password });
670
689
  }
671
690
  }
672
- const routeUrl = `${this.routeStr}?client=${this.client}`;
673
- return await this.makeQuery(
674
- routeUrl,
675
- {},
676
- {
677
- cacheName: "route",
678
- cache: true,
679
- cacheProps: {
680
- id: this.id,
681
- auth,
682
- baseUrl: this.options.baseUrl
691
+ const routeUrl = `${this.routeStr}?client=${this.client}`;
692
+ return await this.makeQuery(
693
+ routeUrl,
694
+ {},
695
+ {
696
+ cacheName: "route",
697
+ cache: true,
698
+ cacheProps: {
699
+ id: this.id,
700
+ auth,
701
+ baseUrl: this.options.baseUrl
702
+ }
703
+ }
704
+ );
705
+ }
706
+ /**
707
+ * Quick way to change NextGIS Web user.
708
+ * @param credentials - New user credentials
709
+ */
710
+ login(credentials, options) {
711
+ this.logout();
712
+ addConnector(this);
713
+ return this._login(credentials, options);
714
+ }
715
+ /**
716
+ * Disconnecting a user. Aborting all current requests
717
+ */
718
+ logout() {
719
+ this.abort();
720
+ removeConnector(this);
721
+ this.options.auth = void 0;
722
+ this.user = void 0;
723
+ this.clearCache();
724
+ this.emitter.emit("logout");
725
+ }
726
+ async getUserInfo(credentials, options) {
727
+ if (this.user && this.user.id) {
728
+ return this.user;
729
+ }
730
+ if (credentials) {
731
+ this.options.auth = credentials;
732
+ }
733
+ const options_ = {
734
+ headers: this.getAuthorizationHeaders(credentials),
735
+ cache: true,
736
+ ...options
737
+ };
738
+ return this.makeQuery(
739
+ "/api/component/auth/current_user",
740
+ {},
741
+ options_
742
+ );
743
+ }
744
+ /**
745
+ * Obtaining the required Headers for authentication of requests in the NGW.
746
+ */
747
+ getAuthorizationHeaders(credentials) {
748
+ const client = this.makeClientId(credentials);
749
+ if (client) {
750
+ return {
751
+ Authorization: `Basic ${client}`
752
+ };
753
+ }
754
+ return {};
755
+ }
756
+ makeClientId(credentials) {
757
+ credentials = credentials || this.options.auth;
758
+ if (credentials) {
759
+ const { login, password } = credentials;
760
+ const encodedStr = [login, password].map(encodeURIComponent).join(":");
761
+ {
762
+ return Buffer.from(encodedStr).toString("base64");
763
+ }
764
+ }
765
+ }
766
+ /** Stop all api requests */
767
+ abort() {
768
+ for (const abortController of Object.values(this.activeRequests)) {
769
+ abortController.abort();
770
+ }
771
+ this.activeRequests = {};
772
+ }
773
+ getActiveApiRequests() {
774
+ return { ...this.activeRequests };
775
+ }
776
+ route(name, ...rest) {
777
+ return route(name, this, ...rest);
778
+ }
779
+ /**
780
+ * Send request to NGW.
781
+ * @param url - URL address to NGW
782
+ * @param params - Query params
783
+ * @param options - Request options
784
+ */
785
+ async makeQuery(url, params, options = {}) {
786
+ var _a;
787
+ url = (this.options.baseUrl ? this.options.baseUrl : "") + url;
788
+ if (!url) {
789
+ throw new Error("Empty `url` not allowed");
790
+ }
791
+ if (params) {
792
+ const { paramList, ...restParams } = params;
793
+ url = template(url, restParams);
794
+ }
795
+ url = encodeURI(utils.fixUrlStr(url));
796
+ options = { withCredentials: this.withCredentials, ...options };
797
+ const {
798
+ cache,
799
+ signal: externalSignal,
800
+ method = "GET",
801
+ headers,
802
+ cacheName,
803
+ cacheProps,
804
+ responseType,
805
+ withCredentials
806
+ } = options;
807
+ const internalAbortController = new AbortController();
808
+ const internalSignal = internalAbortController.signal;
809
+ if (externalSignal) {
810
+ if (externalSignal.aborted) {
811
+ throw new AbortError();
812
+ }
813
+ externalSignal.addEventListener("abort", () => {
814
+ internalAbortController.abort();
815
+ });
816
+ }
817
+ options.signal = internalSignal;
818
+ const createPromise = async () => {
819
+ const id = REQUEST_ID++;
820
+ this.activeRequests[id] = internalAbortController;
821
+ try {
822
+ return this._loadData(url, options);
823
+ } finally {
824
+ this._cleanActiveRequest(id);
825
+ }
826
+ };
827
+ if (cache && method === "GET") {
828
+ const cacheOptions = cacheProps ? cacheProps : {
829
+ ...utils.objectRemoveEmpty({
830
+ headers,
831
+ withCredentials,
832
+ responseType,
833
+ baseUrl: this.options.baseUrl,
834
+ userId: (_a = this.user) == null ? void 0 : _a.id
835
+ }),
836
+ params
837
+ };
838
+ return this.cache.add(
839
+ cacheName || url,
840
+ createPromise,
841
+ cacheOptions,
842
+ false
843
+ );
844
+ }
845
+ return createPromise();
846
+ }
847
+ _loadData(url, options) {
848
+ options.responseType = options.responseType || "json";
849
+ return new Promise((resolve, reject) => {
850
+ var _a;
851
+ if (this.user) {
852
+ options = options || {};
853
+ options.headers = {
854
+ ...this.getAuthorizationHeaders(),
855
+ ...options.headers
856
+ };
857
+ }
858
+ if (this.requestTransform) {
859
+ const [transUrl, transOptions] = this.requestTransform(url, options);
860
+ url = transUrl;
861
+ options = transOptions;
862
+ }
863
+ let runOnAbort = void 0;
864
+ loadData(url, resolve, options, reject, (handler) => {
865
+ runOnAbort = handler;
866
+ });
867
+ (_a = options.signal) == null ? void 0 : _a.addEventListener("abort", () => {
868
+ if (runOnAbort !== void 0) {
869
+ runOnAbort();
870
+ }
871
+ reject(new AbortError());
872
+ });
873
+ }).catch((httpError) => {
874
+ if (httpError.name !== "AbortError") {
875
+ {
876
+ console.warn("DEV WARN", httpError);
877
+ }
878
+ const er = this._handleHttpError(httpError);
879
+ if (er) {
880
+ throw er;
881
+ }
882
+ }
883
+ throw httpError;
884
+ });
885
+ }
886
+ async _login(credentials, options) {
887
+ try {
888
+ const data = await this.getUserInfo(credentials, options);
889
+ this.user = data;
890
+ this.emitter.emit("login", data);
891
+ return data;
892
+ } catch (er) {
893
+ this.emitter.emit("login:error", er);
894
+ throw er;
895
+ }
896
+ }
897
+ _cleanActiveRequest(requestId) {
898
+ delete this.activeRequests[requestId];
899
+ }
900
+ _handleHttpError(er) {
901
+ if (er) {
902
+ if (er instanceof NgwError) {
903
+ if (er.exception === "nextgisweb.resource.exception.ResourceNotFound") {
904
+ throw new ResourceNotFoundError(er);
905
+ } else if (er.exception === "nextgisweb.core.exception.InsufficientPermissions") {
906
+ throw new InsufficientPermissionsError(er);
907
+ }
908
+ }
909
+ }
910
+ return er;
911
+ }
912
+ }
913
+ __publicField$2(NgwConnector, "errors", {
914
+ NgwError,
915
+ ResourceNotFoundError
916
+ });
917
+
918
+ function resourceCompare(res1, res2) {
919
+ return utils.objectDeepEqual(res1, res2);
920
+ }
921
+
922
+ const exclude = ["description"];
923
+ function resourceToQuery(resource, prefix = "") {
924
+ prefix = prefix ? prefix + "__" : "";
925
+ const query = {};
926
+ for (const [key, value] of Object.entries(resource)) {
927
+ if (exclude.indexOf(key) === -1) {
928
+ if (isObject(value)) {
929
+ if (key === "owner_user") {
930
+ const children = resourceToQuery(value, key);
931
+ Object.assign(query, children);
932
+ } else if (key === "parent" && "id" in value) {
933
+ query.parent_id = value.id;
934
+ }
935
+ } else if (utils.defined(value)) {
936
+ query[prefix + key] = value;
937
+ }
938
+ }
939
+ }
940
+ return query;
941
+ }
942
+
943
+ var __defProp$1 = Object.defineProperty;
944
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
945
+ var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
946
+ class ResourcesControl {
947
+ constructor({
948
+ connector,
949
+ cacheId
950
+ }) {
951
+ __publicField$1(this, "cache");
952
+ __publicField$1(this, "connector");
953
+ this.connector = connector;
954
+ this.cache = new Cache({ namespace: cacheId });
955
+ }
956
+ // -------------------------------------------------------------------------
957
+ // Resource Methods
958
+ // -------------------------------------------------------------------------
959
+ /**
960
+ * Receive resource from NGW by id, keyname or search-object parameter.
961
+ * @param resource - Resource id, keyname or search-object
962
+ *
963
+ * @remarks
964
+ * Fetching resource would be cached to speed up next call
965
+ */
966
+ getOne(resource, requestOptions) {
967
+ const opt = { ...requestOptions };
968
+ if (typeof resource === "string") ; else if (typeof resource === "number") ; else if (isObject(resource)) {
969
+ if (resource.id !== void 0) {
970
+ resource.id;
971
+ } else {
972
+ if (resource.keyname) {
973
+ resource.keyname;
974
+ }
975
+ if (resource.display_name) {
976
+ resource.display_name;
977
+ }
978
+ }
979
+ }
980
+ if (typeof resource === "string") {
981
+ return this._fetchResourceBy({ keyname: resource }, opt);
982
+ } else if (typeof resource === "number") {
983
+ return this._fetchResourceById(resource, opt);
984
+ } else if (isObject(resource)) {
985
+ return this._fetchResourceBy(resource, opt);
986
+ }
987
+ return Promise.resolve(void 0);
988
+ }
989
+ getOneOrFail(resource, requestOptions) {
990
+ return this.getOne(resource, requestOptions).then((res) => {
991
+ if (res) {
992
+ return res;
993
+ }
994
+ throw new ResourceNotFoundError();
995
+ });
996
+ }
997
+ /**
998
+ * A fast way to retrieve resource ID for any resource definition.
999
+ * @param resource - Any available resource definition
1000
+ *
1001
+ * @remarks
1002
+ * There are situations when exactly the resource id is needed
1003
+ * (for example, to compose the correct request to the api)
1004
+ * then this method will come in handy to facilitate the extraction of the identifier
1005
+ * if the resource is specified through a keyname or other parameters.
1006
+ */
1007
+ getId(resource, requestOptions) {
1008
+ if (typeof resource === "number") {
1009
+ return Promise.resolve(resource);
1010
+ } else if (typeof resource === "string" || isObject(resource)) {
1011
+ return this.getOne(resource, requestOptions).then((res) => {
1012
+ if (res) {
1013
+ return res.resource.id;
1014
+ }
1015
+ });
1016
+ }
1017
+ return Promise.resolve(void 0);
1018
+ }
1019
+ /**
1020
+ * A fast way to retrieve resource ID for any resource definition.
1021
+ * @param resource - Any available resource definition
1022
+ *
1023
+ * @remarks
1024
+ * Similar with {@link NgwConnector.getResourceId | getResourceId} but rise error if resource is not exist.
1025
+ * To not make one more checks if the resource is definitely exists
1026
+ */
1027
+ getIdOrFail(resource, requestOptions) {
1028
+ return this.getId(resource, requestOptions).then((resp) => {
1029
+ if (resp === void 0) {
1030
+ throw new Error();
1031
+ }
1032
+ return resp;
1033
+ });
1034
+ }
1035
+ getMany(resource, requestOptions) {
1036
+ return this._resourceCacheFilter(resource).then((items) => {
1037
+ if (!items.length) {
1038
+ const query = {};
1039
+ if (resource.keyname) {
1040
+ query.keyname = resource.keyname;
1041
+ } else {
1042
+ Object.assign(query, resourceToQuery(resource));
1043
+ }
1044
+ return this.connector.get("resource.search", requestOptions, {
1045
+ serialization: "full",
1046
+ ...query
1047
+ }).then((resources) => {
1048
+ if ((requestOptions == null ? void 0 : requestOptions.cache) && resources) {
1049
+ for (const x of resources) {
1050
+ this.cache.add("resource.item", Promise.resolve(x), {
1051
+ id: x.resource.id
1052
+ });
1053
+ }
1054
+ }
1055
+ return resources;
1056
+ });
1057
+ }
1058
+ return items;
1059
+ });
1060
+ }
1061
+ getParent(resource, requestOptions) {
1062
+ return this.getOne(resource, requestOptions).then((child) => {
1063
+ if (child) {
1064
+ return this.getOne(child.resource.parent.id, requestOptions);
1065
+ }
1066
+ return Promise.resolve(void 0);
1067
+ });
1068
+ }
1069
+ getChildrenOf(resource, requestOptions) {
1070
+ return this.getIdOrFail(resource).then(
1071
+ (parent) => this._getChildrenOf(parent, requestOptions)
1072
+ );
1073
+ }
1074
+ update(resource, data) {
1075
+ return this.getId(resource).then((id) => {
1076
+ if (id !== void 0) {
1077
+ return this.connector.put("resource.item", { data }, { id });
1078
+ }
1079
+ });
1080
+ }
1081
+ /**
1082
+ * Fast way to delete resource from NGW and clean cache.
1083
+ * @param resource - Resource definition
1084
+ */
1085
+ delete(resource) {
1086
+ return this.getId(resource).then((id) => {
1087
+ if (id !== void 0) {
1088
+ return this.connector.delete("resource.item", null, { id }).then(() => {
1089
+ this._cleanResourceItemCache(id);
1090
+ return void 0;
1091
+ });
1092
+ }
1093
+ });
1094
+ }
1095
+ _getChildrenOf(parent, requestOptions, _items = []) {
1096
+ return this.connector.get("resource.collection", requestOptions, {
1097
+ parent
1098
+ }).then((items) => {
1099
+ const recursivePromises = [];
1100
+ for (const item of items) {
1101
+ if (requestOptions == null ? void 0 : requestOptions.cache) {
1102
+ this.cache.add("resource.item", Promise.resolve(item), {
1103
+ id: item.resource.id
1104
+ });
1105
+ }
1106
+ _items.push(item);
1107
+ if ((requestOptions == null ? void 0 : requestOptions.recursive) && item.resource.children) {
1108
+ recursivePromises.push(
1109
+ this._getChildrenOf(item.resource.id, requestOptions, _items)
1110
+ );
1111
+ }
1112
+ }
1113
+ if (recursivePromises.length) {
1114
+ return Promise.all(recursivePromises).then(() => {
1115
+ return _items;
1116
+ });
1117
+ }
1118
+ return _items;
1119
+ });
1120
+ }
1121
+ async _cleanResourceItemCache(id) {
1122
+ var _a;
1123
+ const all = this.cache.all();
1124
+ const toDelete = [];
1125
+ for (const c of all) {
1126
+ const cid = (_a = c.props) == null ? void 0 : _a.id;
1127
+ if (["resource.item", "resource"].includes(c.key) && cid !== void 0) {
1128
+ if (typeof cid === "number") {
1129
+ if (cid === id) {
1130
+ toDelete.push(c);
1131
+ }
1132
+ } else {
1133
+ const rid = await this.getId(cid);
1134
+ if (rid === id) {
1135
+ toDelete.push(c);
1136
+ }
1137
+ }
1138
+ }
1139
+ }
1140
+ for (const d of toDelete) {
1141
+ this.cache.delete(d);
1142
+ }
1143
+ }
1144
+ _fetchResourceById(id, requestOptions) {
1145
+ return this.connector.get("resource.item", requestOptions, { id });
1146
+ }
1147
+ _fetchResourceBy(resource, requestOptions) {
1148
+ return this.getMany(resource, requestOptions).then((resources) => {
1149
+ return resources[0];
1150
+ });
1151
+ }
1152
+ _resourceCacheFilter(resource) {
1153
+ return Promise.all(this.cache.matchAll("resource.item")).then(
1154
+ (resources) => {
1155
+ const items = [];
1156
+ resources.filter((x) => {
1157
+ if (x) {
1158
+ if (resource.keyname && x.resource.keyname) {
1159
+ return resource.keyname === x.resource.keyname;
1160
+ }
1161
+ if (utils.defined(resource.id) && utils.defined(x.resource.id)) {
1162
+ return resource.id === x.resource.id;
1163
+ }
1164
+ return resourceCompare(resource, x.resource);
1165
+ }
1166
+ });
1167
+ return items;
1168
+ }
1169
+ );
1170
+ }
1171
+ }
1172
+
1173
+ async function apiRequest(opt) {
1174
+ const { params, name, connector, requestOptions } = opt;
1175
+ const apiItems = await connector.connect();
1176
+ let apiItem = apiItems && apiItems[name];
1177
+ if (apiItem) {
1178
+ apiItem = [...apiItem];
1179
+ let url = apiItem.shift();
1180
+ if (apiItem.length) {
1181
+ const replaceParams = {};
1182
+ for (let fry = 0; fry < apiItem.length; fry++) {
1183
+ const arg = apiItem[fry];
1184
+ replaceParams[fry] = `{${arg}}`;
1185
+ if (params[arg] === void 0) {
1186
+ throw new Error(`\`${arg}\` URL API argument is not specified`);
1187
+ }
1188
+ }
1189
+ if (url) {
1190
+ url = template(url, replaceParams);
1191
+ }
1192
+ }
1193
+ if (params) {
1194
+ const paramArray = [];
1195
+ const paramList = params.paramList;
1196
+ if (Array.isArray(paramList)) {
1197
+ paramList.forEach(([key, value]) => {
1198
+ paramArray.push(`${key}=${value}`);
1199
+ });
1200
+ }
1201
+ for (const p in params) {
1202
+ if (apiItem.indexOf(p) === -1) {
1203
+ paramArray.push(`${p}=${params[p]}`);
683
1204
  }
684
1205
  }
685
- );
686
- }
687
- /**
688
- * Quick way to change NextGIS Web user.
689
- * @param credentials - New user credentials
690
- */
691
- login(credentials, options) {
692
- this.logout();
693
- addConnector(this);
694
- return this._login(credentials, options);
695
- }
696
- /**
697
- * Disconnecting a user. Aborting all current requests
698
- */
699
- logout() {
700
- this.abort();
701
- removeConnector(this);
702
- this.options.auth = void 0;
703
- this.user = void 0;
704
- this.clearCache();
705
- this.emitter.emit("logout");
706
- }
707
- async getUserInfo(credentials, options) {
708
- if (this.user && this.user.id) {
709
- return this.user;
1206
+ if (paramArray.length) {
1207
+ url = `${url}?${paramArray.join("&")}`;
1208
+ }
710
1209
  }
711
- if (credentials) {
712
- this.options.auth = credentials;
1210
+ if (url) {
1211
+ return connector.makeQuery(url, params, {
1212
+ cacheName: name,
1213
+ ...requestOptions
1214
+ });
1215
+ } else {
1216
+ throw new Error("Request URL is not set");
713
1217
  }
714
- const options_ = {
715
- headers: this.getAuthorizationHeaders(credentials),
716
- ...options
717
- };
718
- return this.makeQuery(
719
- "/api/component/auth/current_user",
720
- {},
721
- options_
722
- );
1218
+ } else {
1219
+ return void 0;
1220
+ }
1221
+ }
1222
+
1223
+ var __defProp = Object.defineProperty;
1224
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1225
+ var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
1226
+ class NgwConnectorExtended extends NgwConnector {
1227
+ constructor(options) {
1228
+ super(options);
1229
+ __publicField(this, "resources");
1230
+ this.resources = new ResourcesControl({
1231
+ connector: this,
1232
+ cacheId: options.cacheId
1233
+ });
723
1234
  }
724
1235
  /**
725
- * Obtaining the required Headers for authentication of requests in the NGW.
1236
+ * Clear the cache.
726
1237
  */
727
- getAuthorizationHeaders(credentials) {
728
- const client = this.makeClientId(credentials);
729
- if (client) {
730
- return {
731
- Authorization: `Basic ${client}`
732
- };
733
- }
734
- }
735
- makeClientId(credentials) {
736
- credentials = credentials || this.options.auth;
737
- if (credentials) {
738
- const { login, password } = credentials;
739
- const encodedStr = [login, password].map(encodeURIComponent).join(":");
740
- {
741
- return Buffer.from(encodedStr).toString("base64");
742
- }
743
- }
744
- }
745
- /** Stop all api requests */
746
- abort() {
747
- for (const abortController of Object.values(this.activeRequests)) {
748
- abortController.abort();
749
- }
750
- this.activeRequests = {};
751
- }
752
- getActiveApiRequests() {
753
- return { ...this.activeRequests };
1238
+ clearCache() {
1239
+ super.clearCache();
1240
+ this.resources.cache.clean();
754
1241
  }
755
1242
  /**
756
1243
  * Send request to NGW api router.
@@ -869,74 +1356,6 @@ class NgwConnector {
869
1356
  options
870
1357
  );
871
1358
  }
872
- /**
873
- * Send request to NGW.
874
- * @param url - URL address to NGW
875
- * @param params - Query params
876
- * @param options - Request options
877
- */
878
- async makeQuery(url, params, options = {}) {
879
- var _a;
880
- url = (this.options.baseUrl ? this.options.baseUrl : "") + url;
881
- if (!url) {
882
- throw new Error("Empty `url` not allowed");
883
- }
884
- if (params) {
885
- const { paramList, ...restParams } = params;
886
- url = template(url, restParams);
887
- }
888
- url = encodeURI(utils.fixUrlStr(url));
889
- options = { withCredentials: this.withCredentials, ...options };
890
- const {
891
- cache,
892
- signal: externalSignal,
893
- method = "GET",
894
- headers,
895
- cacheName,
896
- cacheProps,
897
- responseType,
898
- withCredentials
899
- } = options;
900
- const internalAbortController = new AbortController();
901
- const internalSignal = internalAbortController.signal;
902
- if (externalSignal) {
903
- if (externalSignal.aborted) {
904
- throw new AbortError();
905
- }
906
- externalSignal.addEventListener("abort", () => {
907
- internalAbortController.abort();
908
- });
909
- }
910
- options.signal = internalSignal;
911
- const createPromise = async () => {
912
- const id = REQUEST_ID++;
913
- this.activeRequests[id] = internalAbortController;
914
- try {
915
- return this._loadData(url, options);
916
- } finally {
917
- this._cleanActiveRequest(id);
918
- }
919
- };
920
- if (cache && method === "GET") {
921
- const cacheOptions = cacheProps ? cacheProps : {
922
- ...utils.objectRemoveEmpty({
923
- headers,
924
- withCredentials,
925
- responseType,
926
- baseUrl: this.options.baseUrl,
927
- userId: (_a = this.user) == null ? void 0 : _a.id
928
- }),
929
- params
930
- };
931
- return this.cache.add(
932
- cacheName || url,
933
- createPromise,
934
- cacheOptions,
935
- false
936
- );
937
- }
938
- return createPromise();
939
- }
940
1359
  // -------------------------------------------------------------------------
941
1360
  // Resource Methods
942
1361
  // -------------------------------------------------------------------------
@@ -1012,79 +1431,7 @@ class NgwConnector {
1012
1431
  deleteResource(resource) {
1013
1432
  return this.resources.delete(resource);
1014
1433
  }
1015
- /**
1016
- * @internal
1017
- */
1018
- _loadData(url, options) {
1019
- options.responseType = options.responseType || "json";
1020
- return new Promise((resolve, reject) => {
1021
- var _a;
1022
- if (this.user) {
1023
- options = options || {};
1024
- options.headers = {
1025
- ...this.getAuthorizationHeaders(),
1026
- ...options.headers
1027
- };
1028
- }
1029
- if (this.requestTransform) {
1030
- const [transUrl, transOptions] = this.requestTransform(url, options);
1031
- url = transUrl;
1032
- options = transOptions;
1033
- }
1034
- let runOnAbort = void 0;
1035
- loadData(url, resolve, options, reject, (handler) => {
1036
- runOnAbort = handler;
1037
- });
1038
- (_a = options.signal) == null ? void 0 : _a.addEventListener("abort", () => {
1039
- if (runOnAbort !== void 0) {
1040
- runOnAbort();
1041
- }
1042
- reject(new AbortError());
1043
- });
1044
- }).catch((httpError) => {
1045
- if (httpError.name !== "AbortError") {
1046
- {
1047
- console.warn("DEV WARN", httpError);
1048
- }
1049
- const er = this._handleHttpError(httpError);
1050
- if (er) {
1051
- throw er;
1052
- }
1053
- }
1054
- throw httpError;
1055
- });
1056
- }
1057
- async _login(credentials, options) {
1058
- try {
1059
- const data = await this.getUserInfo(credentials, options);
1060
- this.user = data;
1061
- this.emitter.emit("login", data);
1062
- return data;
1063
- } catch (er) {
1064
- this.emitter.emit("login:error", er);
1065
- throw er;
1066
- }
1067
- }
1068
- _cleanActiveRequest(requestId) {
1069
- delete this.activeRequests[requestId];
1070
- }
1071
- _handleHttpError(er) {
1072
- if (er) {
1073
- if (er instanceof NgwError) {
1074
- if (er.exception === "nextgisweb.resource.exception.ResourceNotFound") {
1075
- throw new ResourceNotFoundError(er);
1076
- } else if (er.exception === "nextgisweb.core.exception.InsufficientPermissions") {
1077
- throw new InsufficientPermissionsError(er);
1078
- }
1079
- }
1080
- }
1081
- return er;
1082
- }
1083
1434
  }
1084
- __publicField(NgwConnector, "errors", {
1085
- NgwError,
1086
- ResourceNotFoundError
1087
- });
1088
1435
 
1089
- module.exports = NgwConnector;
1436
+ module.exports = NgwConnectorExtended;
1090
1437
  //# sourceMappingURL=ngw-connector.cjs.js.map