@nextgis/ngw-connector 1.8.4 → 1.11.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.
@@ -1,4 +1,4 @@
1
- /** Bundle of @nextgis/ngw-connector; version: 1.8.4; author: NextGIS */
1
+ /** Bundle of @nextgis/ngw-connector; version: 1.11.0; author: NextGIS */
2
2
  'use strict';
3
3
 
4
4
  var events = require('events');
@@ -23,12 +23,17 @@ class NgwError extends Error {
23
23
  }
24
24
  }
25
25
 
26
+ function isObject(val) {
27
+ return Object.prototype.toString.call(val) === '[object Object]';
28
+ }
29
+
26
30
  let loadData;
27
31
  // @ts-ignore
28
32
  {
29
33
  const url = require('url');
30
34
  const http = require('http');
31
35
  const https = require('https');
36
+ const FormData = require('form-data');
32
37
  const adapterFor = (inputUrl) => {
33
38
  const adapters = {
34
39
  'http:': http,
@@ -38,21 +43,41 @@ let loadData;
38
43
  return adapters[protocol];
39
44
  };
40
45
  loadData = (url, callback, options = {}, error, onCancel) => {
46
+ const { file, headers, method, data, responseType } = options;
41
47
  const request = new Promise((resolve, reject) => {
42
48
  const adapter = adapterFor(url);
43
49
  if (adapter) {
44
50
  const requestOpt = {
45
- headers: options.headers || {},
46
- method: options.method,
51
+ headers: headers || {},
52
+ method,
47
53
  };
48
- const body = typeof options.data === 'string'
49
- ? options.data
50
- : JSON.stringify(options.data);
54
+ const body = typeof data === 'string' ? data : JSON.stringify(data);
51
55
  // https://stackoverflow.com/questions/35589109/node-http-delete-request-no-longer-works-after-upgrading-from-0-10-40
52
- if (body !== undefined && options.method !== 'POST') {
56
+ let form;
57
+ let uploadedFile = file;
58
+ if (file) {
59
+ const fileMeta = {};
60
+ if (isObject(file) && 'file' in file && 'filename' in file) {
61
+ const { file: file_, ...fileMeta_ } = file;
62
+ Object.assign(fileMeta, fileMeta_);
63
+ uploadedFile = file_;
64
+ }
65
+ form = new FormData();
66
+ form.append('file', uploadedFile, fileMeta);
67
+ if (data) {
68
+ for (const d in data) {
69
+ form.append(d, data[d]);
70
+ }
71
+ }
72
+ Object.assign(requestOpt.headers, {
73
+ // 'content-length': form.getLengthSync(),
74
+ ...form.getHeaders(),
75
+ });
76
+ }
77
+ if (body !== undefined && method !== 'POST') {
53
78
  Object.assign(requestOpt.headers, {
54
- 'Content-Type': 'application/json',
55
- 'Content-Length': Buffer.byteLength(body),
79
+ 'content-type': 'application/json',
80
+ 'content-length': Buffer.byteLength(body),
56
81
  });
57
82
  }
58
83
  const req = adapter.request(url, requestOpt, (resp) => {
@@ -62,24 +87,32 @@ let loadData;
62
87
  });
63
88
  resp.on('end', () => {
64
89
  if (data) {
65
- let json;
66
- try {
67
- json = JSON.parse(data);
68
- if (json && json.status_code && json.status_code) {
69
- reject(json.message);
70
- }
71
- }
72
- catch (er) {
73
- reject(er);
74
- // throw new Error(er);
90
+ if (responseType === 'blob') {
91
+ resolve(data);
75
92
  }
76
- if (json !== undefined) {
77
- resolve(json);
93
+ else {
94
+ let json;
95
+ try {
96
+ json = JSON.parse(data);
97
+ if (json && json.status_code && json.status_code) {
98
+ reject(json.message);
99
+ }
100
+ }
101
+ catch (er) {
102
+ reject(er);
103
+ // throw new Error(er);
104
+ }
105
+ if (json !== undefined) {
106
+ resolve(json);
107
+ }
78
108
  }
79
109
  }
80
110
  reject('no data');
81
111
  });
82
112
  });
113
+ if (form) {
114
+ form.pipe(req);
115
+ }
83
116
  req.on('error', (err) => {
84
117
  reject(err);
85
118
  });
@@ -178,28 +211,36 @@ function removeConnector(connector) {
178
211
  }
179
212
  }
180
213
 
181
- function isObject(val) {
182
- return Object.prototype.toString.call(val) === '[object Object]';
183
- }
184
-
214
+ const exclude = ['description'];
185
215
  /**
216
+ * @remarks
217
+ * https://docs.nextgis.ru/docs_ngweb_dev/doc/developer/resource.html#search-resources
218
+ *
186
219
  * ```
187
- * { keyname, parent: { id }} > { keyname, parent__id }
220
+ * { keyname, owner_user: { id }} > { keyname, owner_user__id }
188
221
  * ```
222
+ *
189
223
  * @param resource - Any property from NGW resource item
190
224
  */
191
225
  function resourceToQuery(resource, prefix = '') {
192
226
  prefix = prefix ? prefix + '__' : '';
193
227
  const query = {};
194
- Object.entries(resource).forEach(([key, value]) => {
195
- if (isObject(value)) {
196
- const children = resourceToQuery(value, key);
197
- Object.assign(query, children);
198
- }
199
- else if (utils.defined(value)) {
200
- query[prefix + key] = value;
228
+ for (const [key, value] of Object.entries(resource)) {
229
+ if (exclude.indexOf(key) === -1) {
230
+ if (isObject(value)) {
231
+ if (key === 'owner_user') {
232
+ const children = resourceToQuery(value, key);
233
+ Object.assign(query, children);
234
+ }
235
+ else if (key === 'parent' && 'id' in value) {
236
+ query.parent_id = value.id;
237
+ }
238
+ }
239
+ else if (utils.defined(value)) {
240
+ query[prefix + key] = value;
241
+ }
201
242
  }
202
- });
243
+ }
203
244
  return query;
204
245
  }
205
246
 
@@ -224,22 +265,33 @@ class ResourcesControl {
224
265
  */
225
266
  getOne(resource, requestOptions) {
226
267
  const cache = new Cache__default();
268
+ const forCache = {};
269
+ const opt = { ...requestOptions, cache: false };
270
+ if (typeof resource === 'string') {
271
+ forCache.keyname = resource;
272
+ }
273
+ else if (typeof resource === 'number') {
274
+ forCache.id = resource;
275
+ }
276
+ else if (isObject(resource)) {
277
+ forCache.id = resource.id;
278
+ }
227
279
  const makeRequest = () => {
228
280
  if (typeof resource === 'string') {
229
- return this._fetchResourceBy({ keyname: resource }, requestOptions);
281
+ return this._fetchResourceBy({ keyname: resource }, opt);
230
282
  }
231
283
  else if (typeof resource === 'number') {
232
- return this._fetchResourceById(resource, requestOptions);
284
+ return this._fetchResourceById(resource, opt);
233
285
  }
234
286
  else if (isObject(resource)) {
235
- return this._fetchResourceBy(resource, requestOptions);
287
+ return this._fetchResourceBy(resource, opt);
236
288
  }
237
289
  return CancelablePromise__default.resolve(undefined);
238
290
  };
239
- return cache.add('resource', makeRequest, { resource });
291
+ return cache.addFull('resource', makeRequest, forCache);
240
292
  }
241
- getOneOrFail(resource) {
242
- return this.getOne(resource).then((res) => {
293
+ getOneOrFail(resource, requestOptions) {
294
+ return this.getOne(resource, requestOptions).then((res) => {
243
295
  if (res) {
244
296
  return res;
245
297
  }
@@ -256,12 +308,12 @@ class ResourcesControl {
256
308
  * then this method will come in handy to facilitate the extraction of the identifier
257
309
  * if the resource is specified through a keyname or other parameters.
258
310
  */
259
- getId(resource) {
311
+ getId(resource, requestOptions) {
260
312
  if (typeof resource === 'number') {
261
313
  return CancelablePromise__default.resolve(resource);
262
314
  }
263
315
  else if (typeof resource === 'string' || isObject(resource)) {
264
- return this.getOne(resource).then((res) => {
316
+ return this.getOne(resource, requestOptions).then((res) => {
265
317
  if (res) {
266
318
  return res.resource.id;
267
319
  }
@@ -277,8 +329,8 @@ class ResourcesControl {
277
329
  * Similar with {@link NgwConnector.getResourceId | getResourceId} but rise error if resource is not exist.
278
330
  * To not make one more checks if the resource is definitely exists
279
331
  */
280
- getIdOrFail(resource) {
281
- return this.getId(resource).then((resp) => {
332
+ getIdOrFail(resource, requestOptions) {
333
+ return this.getId(resource, requestOptions).then((resp) => {
282
334
  if (resp === undefined) {
283
335
  throw new Error();
284
336
  }
@@ -302,11 +354,11 @@ class ResourcesControl {
302
354
  })
303
355
  .then((resources) => {
304
356
  if (resources) {
305
- resources.forEach((x) => {
357
+ for (const x of resources) {
306
358
  this.cache.add('resource.item', CancelablePromise__default.resolve(x), {
307
359
  id: x.resource.id,
308
360
  });
309
- });
361
+ }
310
362
  }
311
363
  return resources;
312
364
  });
@@ -314,18 +366,18 @@ class ResourcesControl {
314
366
  return items;
315
367
  });
316
368
  }
317
- getParent(resource) {
318
- return this.connector.getResource(resource).then((child) => {
369
+ getParent(resource, requestOptions) {
370
+ return this.getOne(resource, requestOptions).then((child) => {
319
371
  if (child) {
320
- return this.connector.getResource(child.resource.parent.id);
372
+ return this.getOne(child.resource.parent.id, requestOptions);
321
373
  }
322
374
  return CancelablePromise__default.resolve(undefined);
323
375
  });
324
376
  }
325
- getChildrenOf(resource) {
377
+ getChildrenOf(resource, requestOptions) {
326
378
  return this.getId(resource).then((parent) => {
327
379
  return this.connector
328
- .get('resource.collection', { cache: true }, {
380
+ .get('resource.collection', { cache: true, ...requestOptions }, {
329
381
  parent,
330
382
  })
331
383
  .then((items) => {
@@ -353,12 +405,35 @@ class ResourcesControl {
353
405
  return this.getId(resource).then((id) => {
354
406
  if (id !== undefined) {
355
407
  return this.connector.delete('resource.item', null, { id }).then(() => {
356
- this.cache.delete('resource.item', { id });
408
+ this._cleanResourceItemCache(id);
357
409
  return undefined;
358
410
  });
359
411
  }
360
412
  });
361
413
  }
414
+ async _cleanResourceItemCache(id) {
415
+ const all = this.cache.all();
416
+ const toDelete = [];
417
+ for (const c of all) {
418
+ const cid = c.options && c.options.id;
419
+ if (['resource.item', 'resource'].includes(c.key) && cid !== undefined) {
420
+ if (typeof cid === 'number') {
421
+ if (cid === id) {
422
+ toDelete.push(c);
423
+ }
424
+ }
425
+ else {
426
+ const rid = await this.getId(cid);
427
+ if (rid === id) {
428
+ toDelete.push(c);
429
+ }
430
+ }
431
+ }
432
+ }
433
+ for (const d of toDelete) {
434
+ this.cache.delete(d);
435
+ }
436
+ }
362
437
  _fetchResourceById(id, requestOptions) {
363
438
  const promise = () => this.connector.get('resource.item', requestOptions, { id });
364
439
  return this.cache
@@ -562,7 +637,7 @@ class NgwConnector$1 {
562
637
  headers: this.getAuthorizationHeaders(credentials),
563
638
  // withCredentials: true
564
639
  };
565
- // Do not use request('auth.current_user') to avoid circular-references
640
+ // Do not use apiRequest('auth.current_user') to avoid circular-references
566
641
  return this.makeQuery('/api/component/auth/current_user', {}, options)
567
642
  .then((data) => {
568
643
  this.user = data;
@@ -720,7 +795,7 @@ class NgwConnector$1 {
720
795
  }
721
796
  // remove double slash
722
797
  url = utils.fixUrlStr(url);
723
- return this._loadData(url, options);
798
+ return this._loadData(encodeURI(url), options);
724
799
  }
725
800
  else {
726
801
  throw new Error('Empty `url` not allowed');
@@ -732,14 +807,14 @@ class NgwConnector$1 {
732
807
  /**
733
808
  * {@inheritDoc ResourcesControl.getOne}
734
809
  */
735
- getResource(resource) {
736
- return this.resources.getOne(resource);
810
+ getResource(resource, requestOptions) {
811
+ return this.resources.getOne(resource, requestOptions);
737
812
  }
738
813
  /**
739
814
  * {@inheritDoc ResourcesControl.getOneOrFail}
740
815
  */
741
- getResourceOrFail(resource) {
742
- return this.resources.getOneOrFail(resource);
816
+ getResourceOrFail(resource, requestOptions) {
817
+ return this.resources.getOneOrFail(resource, requestOptions);
743
818
  }
744
819
  /**
745
820
  * @deprecated - use {@link NgwConnector.getResource}
@@ -762,32 +837,32 @@ class NgwConnector$1 {
762
837
  /**
763
838
  * {@inheritDoc ResourcesControl.getId}
764
839
  */
765
- getResourceId(resource) {
766
- return this.resources.getId(resource);
840
+ getResourceId(resource, requestOptions) {
841
+ return this.resources.getId(resource, requestOptions);
767
842
  }
768
843
  /**
769
844
  * {@inheritDoc ResourcesControl.getIdOrFail}
770
845
  */
771
- getResourceIdOrFail(resource) {
772
- return this.resources.getIdOrFail(resource);
846
+ getResourceIdOrFail(resource, requestOptions) {
847
+ return this.resources.getIdOrFail(resource, requestOptions);
773
848
  }
774
849
  /**
775
850
  * {@inheritDoc ResourcesControl.getMany}
776
851
  */
777
- getResourcesBy(resource) {
778
- return this.resources.getMany(resource);
852
+ getResourcesBy(resource, requestOptions) {
853
+ return this.resources.getMany(resource, requestOptions);
779
854
  }
780
855
  /**
781
856
  * {@inheritDoc ResourcesControl.getParent}
782
857
  */
783
- getResourceParent(resource) {
784
- return this.resources.getParent(resource);
858
+ getResourceParent(resource, requestOptions) {
859
+ return this.resources.getParent(resource, requestOptions);
785
860
  }
786
861
  /**
787
862
  * {@inheritDoc ResourcesControl.getChildrenOf}
788
863
  */
789
- getResourceChildren(resource) {
790
- return this.resources.getChildrenOf(resource);
864
+ getResourceChildren(resource, requestOptions) {
865
+ return this.resources.getChildrenOf(resource, requestOptions);
791
866
  }
792
867
  /**
793
868
  * {@inheritDoc ResourcesControl.update}
@@ -821,7 +896,7 @@ class NgwConnector$1 {
821
896
  else {
822
897
  // @ts-ignore
823
898
  {
824
- console.warn(httpError);
899
+ console.warn('DEV WARN', httpError);
825
900
  }
826
901
  const er = this._handleHttpError(httpError);
827
902
  if (er) {