@nextgis/geocoder 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/geocoder; version: 1.8.4; author: NextGIS */
1
+ /** Bundle of @nextgis/geocoder; version: 1.11.0; author: NextGIS */
2
2
  class CancelError extends Error {
3
3
  constructor() {
4
4
  super();
@@ -356,6 +356,23 @@ var CancelablePromise = CancelablePromise$1;
356
356
  */
357
357
  function defined(val) {
358
358
  return val !== undefined && val !== null;
359
+ }
360
+ /**
361
+ * from https://github.com/CesiumGS/cesium/blob/master/Source/Core/defined.js
362
+ *
363
+ * @param val - The object.
364
+ * @returns Returns true if the object is defined and not empty string, returns false otherwise.
365
+ *
366
+ * @example
367
+ * ```javascript
368
+ * full('foo') // true
369
+ * full('') // false
370
+ * full(undefined) // false
371
+ * full(0) // true
372
+ * ```
373
+ */
374
+ function full(val) {
375
+ return typeof val === 'string' ? !!val : defined(val);
359
376
  }
360
377
 
361
378
  /**
@@ -962,13 +979,45 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
962
979
  }
963
980
  }
964
981
 
982
+ /**
983
+ * @example
984
+ * ```javascript
985
+ * const cache1 = new Cache();
986
+ * cache1.add('foo', 'value');
987
+ *
988
+ * const cache2 = new Cache();
989
+ * cache2.match('foo'); // value
990
+ *
991
+ * const cache3 = new Cache({ namespace: 'foo' });
992
+ * cache3.match('foo'); // undefined
993
+ * ```
994
+ *
995
+ * @example
996
+ * ```javascript
997
+ * let COUNTER = 0;
998
+ * const createPromise = () => new Promise((res) => {
999
+ * COUNTER++
1000
+ * setTimeout(() => res('Ok'), 300)
1001
+ * });
1002
+ *
1003
+ * const cache = new Cache();
1004
+ * for (let i = 0; i < 10; i++) {
1005
+ * cache.add('foo', createPromise).then((data) => {
1006
+ * console.log(data); // 'Ok'
1007
+ * });
1008
+ * }
1009
+ * console.log(COUNTER); // 1
1010
+ * ```
1011
+ */
965
1012
  class Cache$1 {
966
- constructor() {
1013
+ constructor(options = {}) {
1014
+ var _a;
967
1015
  this.cache = [];
968
- if (Cache$1.instance) {
969
- return Cache$1.instance;
1016
+ const namespace = (_a = options.namespace) !== null && _a !== void 0 ? _a : 'default';
1017
+ if (Cache$1.instance[namespace]) {
1018
+ return Cache$1.instance[namespace];
970
1019
  }
971
- Cache$1.instance = this;
1020
+ Cache$1.instance[namespace] = this;
972
1021
  return this;
973
1022
  }
974
1023
  clean() {
@@ -977,8 +1026,33 @@ class Cache$1 {
977
1026
  all() {
978
1027
  return this.cache;
979
1028
  }
980
- add(key, valueToSet, options) {
981
- const exist = this._find(key, options);
1029
+ /**
1030
+ * Caching only a non-empty value.
1031
+ *
1032
+ * Useful for get or create strategy
1033
+ * @example
1034
+ * ```javascript
1035
+ * const cache = new Cache();
1036
+ * const getItemFunc = () => fetch(url).then((data) => {
1037
+ * return data.json(); // undefined
1038
+ * });
1039
+ * const item = await cache.addFull('foo', getItemFunc);
1040
+ * if (!item) {
1041
+ * await createItem(); // 'New item'
1042
+ * }
1043
+ *
1044
+ * // somewhere else in the code
1045
+ * const item = await cache.addFull('foo', getItemFunc).then((resp) => {
1046
+ * console.log(resp); // 'New item'
1047
+ * })
1048
+ *
1049
+ * ```
1050
+ */
1051
+ addFull(key, valueToSet, props) {
1052
+ return this.add(key, valueToSet, props, true);
1053
+ }
1054
+ add(key, valueToSet, props, onlyFull) {
1055
+ const exist = this._find(key, props);
982
1056
  if (!exist) {
983
1057
  let value;
984
1058
  if (valueToSet instanceof Function) {
@@ -987,18 +1061,31 @@ class Cache$1 {
987
1061
  else {
988
1062
  value = valueToSet;
989
1063
  }
990
- const options_ = options && JSON.parse(JSON.stringify(objectRemoveEmpty(options)));
1064
+ const props_ = props && JSON.parse(JSON.stringify(objectRemoveEmpty(props)));
991
1065
  const cacheItem = {
992
1066
  key,
993
1067
  value,
994
- options: options_,
1068
+ props: props_,
1069
+ // TODO: remove backward compatibility use only props
1070
+ options: props_,
995
1071
  };
1072
+ if (onlyFull && !full(value)) {
1073
+ return value;
1074
+ }
996
1075
  this.cache.push(cacheItem);
997
1076
  if (value instanceof Promise) {
998
1077
  value.catch((er) => {
999
- this.delete(key, options);
1078
+ this.delete(key, props);
1000
1079
  throw er;
1001
1080
  });
1081
+ if (onlyFull) {
1082
+ value.then((x) => {
1083
+ if (!full(x)) {
1084
+ this.delete(key, props);
1085
+ }
1086
+ return x;
1087
+ });
1088
+ }
1002
1089
  return value;
1003
1090
  }
1004
1091
  return value;
@@ -1007,40 +1094,49 @@ class Cache$1 {
1007
1094
  return exist.value;
1008
1095
  }
1009
1096
  }
1010
- match(key, options) {
1011
- const cacheRecord = this._find(key, options);
1097
+ match(key, props) {
1098
+ const cacheRecord = this._find(key, props);
1012
1099
  if (cacheRecord) {
1013
1100
  return cacheRecord.value;
1014
1101
  }
1015
1102
  }
1016
- matchAll(key, options) {
1103
+ matchAll(key, props) {
1017
1104
  if (key) {
1018
1105
  return this.cache
1019
- .filter((x) => this._filter(x, key, options))
1106
+ .filter((x) => this._filter(x, key, props))
1020
1107
  .map((x) => x.value);
1021
1108
  }
1022
1109
  return this.cache.map((x) => x.value);
1023
1110
  }
1024
- delete(key, options) {
1025
- const exist = this.cache.filter((x) => this._filter(x, key, options));
1111
+ delete(keyOrItem, props) {
1112
+ let exist = [];
1113
+ if (typeof keyOrItem === 'string') {
1114
+ exist = this.cache.filter((x) => this._filter(x, keyOrItem, props));
1115
+ }
1116
+ else {
1117
+ exist.push(keyOrItem);
1118
+ }
1026
1119
  for (const e of exist) {
1027
1120
  const index = this.cache.indexOf(e);
1028
1121
  this.cache.splice(index, 1);
1029
1122
  }
1030
1123
  }
1031
- _find(key, options) {
1032
- return this.cache.find((x) => this._filter(x, key, options));
1124
+ _find(key, props) {
1125
+ return this.cache.find((x) => this._filter(x, key, props));
1033
1126
  }
1034
- _filter(item, key, options) {
1127
+ _filter(item, key, props) {
1035
1128
  if (item.key === key) {
1036
- if (options) {
1037
- return objectDeepEqual(item.options || {}, objectRemoveEmpty(options));
1129
+ if (props) {
1130
+ // TODO: remove backward compatibility
1131
+ const itemProps = item.props || item.options;
1132
+ return objectDeepEqual(itemProps || {}, objectRemoveEmpty(props));
1038
1133
  }
1039
1134
  return true;
1040
1135
  }
1041
1136
  return false;
1042
1137
  }
1043
- }
1138
+ }
1139
+ Cache$1.instance = {};
1044
1140
 
1045
1141
  /**
1046
1142
  * Caching for asynchronous functions
@@ -1075,6 +1171,10 @@ class NetworkError extends Error {
1075
1171
  }
1076
1172
  }
1077
1173
 
1174
+ function isObject(val) {
1175
+ return Object.prototype.toString.call(val) === '[object Object]';
1176
+ }
1177
+
1078
1178
  let loadData;
1079
1179
  // @ts-ignore
1080
1180
  {
@@ -1108,7 +1208,7 @@ let loadData;
1108
1208
  }
1109
1209
  };
1110
1210
  xhr.onload = () => {
1111
- if ([401, 403, 404, 500].indexOf(xhr.status) !== -1) {
1211
+ if ([401, 403, 404, 422, 500].indexOf(xhr.status) !== -1) {
1112
1212
  error(new NgwError(getResponseText()));
1113
1213
  }
1114
1214
  processingResponse();
@@ -1163,7 +1263,7 @@ let loadData;
1163
1263
  data = new FormData();
1164
1264
  data.append('file', options.file);
1165
1265
  if (options.data) {
1166
- for (const d in data) {
1266
+ for (const d in options.data) {
1167
1267
  data.append(d, data[d]);
1168
1268
  }
1169
1269
  }
@@ -1249,28 +1349,36 @@ function removeConnector(connector) {
1249
1349
  }
1250
1350
  }
1251
1351
 
1252
- function isObject(val) {
1253
- return Object.prototype.toString.call(val) === '[object Object]';
1254
- }
1255
-
1352
+ const exclude = ['description'];
1256
1353
  /**
1354
+ * @remarks
1355
+ * https://docs.nextgis.ru/docs_ngweb_dev/doc/developer/resource.html#search-resources
1356
+ *
1257
1357
  * ```
1258
- * { keyname, parent: { id }} > { keyname, parent__id }
1358
+ * { keyname, owner_user: { id }} > { keyname, owner_user__id }
1259
1359
  * ```
1360
+ *
1260
1361
  * @param resource - Any property from NGW resource item
1261
1362
  */
1262
1363
  function resourceToQuery(resource, prefix = '') {
1263
1364
  prefix = prefix ? prefix + '__' : '';
1264
1365
  const query = {};
1265
- Object.entries(resource).forEach(([key, value]) => {
1266
- if (isObject(value)) {
1267
- const children = resourceToQuery(value, key);
1268
- Object.assign(query, children);
1269
- }
1270
- else if (defined(value)) {
1271
- query[prefix + key] = value;
1366
+ for (const [key, value] of Object.entries(resource)) {
1367
+ if (exclude.indexOf(key) === -1) {
1368
+ if (isObject(value)) {
1369
+ if (key === 'owner_user') {
1370
+ const children = resourceToQuery(value, key);
1371
+ Object.assign(query, children);
1372
+ }
1373
+ else if (key === 'parent' && 'id' in value) {
1374
+ query.parent_id = value.id;
1375
+ }
1376
+ }
1377
+ else if (defined(value)) {
1378
+ query[prefix + key] = value;
1379
+ }
1272
1380
  }
1273
- });
1381
+ }
1274
1382
  return query;
1275
1383
  }
1276
1384
 
@@ -1295,22 +1403,33 @@ class ResourcesControl {
1295
1403
  */
1296
1404
  getOne(resource, requestOptions) {
1297
1405
  const cache = new Cache();
1406
+ const forCache = {};
1407
+ const opt = { ...requestOptions, cache: false };
1408
+ if (typeof resource === 'string') {
1409
+ forCache.keyname = resource;
1410
+ }
1411
+ else if (typeof resource === 'number') {
1412
+ forCache.id = resource;
1413
+ }
1414
+ else if (isObject(resource)) {
1415
+ forCache.id = resource.id;
1416
+ }
1298
1417
  const makeRequest = () => {
1299
1418
  if (typeof resource === 'string') {
1300
- return this._fetchResourceBy({ keyname: resource }, requestOptions);
1419
+ return this._fetchResourceBy({ keyname: resource }, opt);
1301
1420
  }
1302
1421
  else if (typeof resource === 'number') {
1303
- return this._fetchResourceById(resource, requestOptions);
1422
+ return this._fetchResourceById(resource, opt);
1304
1423
  }
1305
1424
  else if (isObject(resource)) {
1306
- return this._fetchResourceBy(resource, requestOptions);
1425
+ return this._fetchResourceBy(resource, opt);
1307
1426
  }
1308
1427
  return CancelablePromise.resolve(undefined);
1309
1428
  };
1310
- return cache.add('resource', makeRequest, { resource });
1429
+ return cache.addFull('resource', makeRequest, forCache);
1311
1430
  }
1312
- getOneOrFail(resource) {
1313
- return this.getOne(resource).then((res) => {
1431
+ getOneOrFail(resource, requestOptions) {
1432
+ return this.getOne(resource, requestOptions).then((res) => {
1314
1433
  if (res) {
1315
1434
  return res;
1316
1435
  }
@@ -1327,12 +1446,12 @@ class ResourcesControl {
1327
1446
  * then this method will come in handy to facilitate the extraction of the identifier
1328
1447
  * if the resource is specified through a keyname or other parameters.
1329
1448
  */
1330
- getId(resource) {
1449
+ getId(resource, requestOptions) {
1331
1450
  if (typeof resource === 'number') {
1332
1451
  return CancelablePromise.resolve(resource);
1333
1452
  }
1334
1453
  else if (typeof resource === 'string' || isObject(resource)) {
1335
- return this.getOne(resource).then((res) => {
1454
+ return this.getOne(resource, requestOptions).then((res) => {
1336
1455
  if (res) {
1337
1456
  return res.resource.id;
1338
1457
  }
@@ -1348,8 +1467,8 @@ class ResourcesControl {
1348
1467
  * Similar with {@link NgwConnector.getResourceId | getResourceId} but rise error if resource is not exist.
1349
1468
  * To not make one more checks if the resource is definitely exists
1350
1469
  */
1351
- getIdOrFail(resource) {
1352
- return this.getId(resource).then((resp) => {
1470
+ getIdOrFail(resource, requestOptions) {
1471
+ return this.getId(resource, requestOptions).then((resp) => {
1353
1472
  if (resp === undefined) {
1354
1473
  throw new Error();
1355
1474
  }
@@ -1373,11 +1492,11 @@ class ResourcesControl {
1373
1492
  })
1374
1493
  .then((resources) => {
1375
1494
  if (resources) {
1376
- resources.forEach((x) => {
1495
+ for (const x of resources) {
1377
1496
  this.cache.add('resource.item', CancelablePromise.resolve(x), {
1378
1497
  id: x.resource.id,
1379
1498
  });
1380
- });
1499
+ }
1381
1500
  }
1382
1501
  return resources;
1383
1502
  });
@@ -1385,18 +1504,18 @@ class ResourcesControl {
1385
1504
  return items;
1386
1505
  });
1387
1506
  }
1388
- getParent(resource) {
1389
- return this.connector.getResource(resource).then((child) => {
1507
+ getParent(resource, requestOptions) {
1508
+ return this.getOne(resource, requestOptions).then((child) => {
1390
1509
  if (child) {
1391
- return this.connector.getResource(child.resource.parent.id);
1510
+ return this.getOne(child.resource.parent.id, requestOptions);
1392
1511
  }
1393
1512
  return CancelablePromise.resolve(undefined);
1394
1513
  });
1395
1514
  }
1396
- getChildrenOf(resource) {
1515
+ getChildrenOf(resource, requestOptions) {
1397
1516
  return this.getId(resource).then((parent) => {
1398
1517
  return this.connector
1399
- .get('resource.collection', { cache: true }, {
1518
+ .get('resource.collection', { cache: true, ...requestOptions }, {
1400
1519
  parent,
1401
1520
  })
1402
1521
  .then((items) => {
@@ -1424,12 +1543,35 @@ class ResourcesControl {
1424
1543
  return this.getId(resource).then((id) => {
1425
1544
  if (id !== undefined) {
1426
1545
  return this.connector.delete('resource.item', null, { id }).then(() => {
1427
- this.cache.delete('resource.item', { id });
1546
+ this._cleanResourceItemCache(id);
1428
1547
  return undefined;
1429
1548
  });
1430
1549
  }
1431
1550
  });
1432
1551
  }
1552
+ async _cleanResourceItemCache(id) {
1553
+ const all = this.cache.all();
1554
+ const toDelete = [];
1555
+ for (const c of all) {
1556
+ const cid = c.options && c.options.id;
1557
+ if (['resource.item', 'resource'].includes(c.key) && cid !== undefined) {
1558
+ if (typeof cid === 'number') {
1559
+ if (cid === id) {
1560
+ toDelete.push(c);
1561
+ }
1562
+ }
1563
+ else {
1564
+ const rid = await this.getId(cid);
1565
+ if (rid === id) {
1566
+ toDelete.push(c);
1567
+ }
1568
+ }
1569
+ }
1570
+ }
1571
+ for (const d of toDelete) {
1572
+ this.cache.delete(d);
1573
+ }
1574
+ }
1433
1575
  _fetchResourceById(id, requestOptions) {
1434
1576
  const promise = () => this.connector.get('resource.item', requestOptions, { id });
1435
1577
  return this.cache
@@ -1633,7 +1775,7 @@ class NgwConnector$1 {
1633
1775
  headers: this.getAuthorizationHeaders(credentials),
1634
1776
  // withCredentials: true
1635
1777
  };
1636
- // Do not use request('auth.current_user') to avoid circular-references
1778
+ // Do not use apiRequest('auth.current_user') to avoid circular-references
1637
1779
  return this.makeQuery('/api/component/auth/current_user', {}, options)
1638
1780
  .then((data) => {
1639
1781
  this.user = data;
@@ -1791,7 +1933,7 @@ class NgwConnector$1 {
1791
1933
  }
1792
1934
  // remove double slash
1793
1935
  url = fixUrlStr(url);
1794
- return this._loadData(url, options);
1936
+ return this._loadData(encodeURI(url), options);
1795
1937
  }
1796
1938
  else {
1797
1939
  throw new Error('Empty `url` not allowed');
@@ -1803,14 +1945,14 @@ class NgwConnector$1 {
1803
1945
  /**
1804
1946
  * {@inheritDoc ResourcesControl.getOne}
1805
1947
  */
1806
- getResource(resource) {
1807
- return this.resources.getOne(resource);
1948
+ getResource(resource, requestOptions) {
1949
+ return this.resources.getOne(resource, requestOptions);
1808
1950
  }
1809
1951
  /**
1810
1952
  * {@inheritDoc ResourcesControl.getOneOrFail}
1811
1953
  */
1812
- getResourceOrFail(resource) {
1813
- return this.resources.getOneOrFail(resource);
1954
+ getResourceOrFail(resource, requestOptions) {
1955
+ return this.resources.getOneOrFail(resource, requestOptions);
1814
1956
  }
1815
1957
  /**
1816
1958
  * @deprecated - use {@link NgwConnector.getResource}
@@ -1833,32 +1975,32 @@ class NgwConnector$1 {
1833
1975
  /**
1834
1976
  * {@inheritDoc ResourcesControl.getId}
1835
1977
  */
1836
- getResourceId(resource) {
1837
- return this.resources.getId(resource);
1978
+ getResourceId(resource, requestOptions) {
1979
+ return this.resources.getId(resource, requestOptions);
1838
1980
  }
1839
1981
  /**
1840
1982
  * {@inheritDoc ResourcesControl.getIdOrFail}
1841
1983
  */
1842
- getResourceIdOrFail(resource) {
1843
- return this.resources.getIdOrFail(resource);
1984
+ getResourceIdOrFail(resource, requestOptions) {
1985
+ return this.resources.getIdOrFail(resource, requestOptions);
1844
1986
  }
1845
1987
  /**
1846
1988
  * {@inheritDoc ResourcesControl.getMany}
1847
1989
  */
1848
- getResourcesBy(resource) {
1849
- return this.resources.getMany(resource);
1990
+ getResourcesBy(resource, requestOptions) {
1991
+ return this.resources.getMany(resource, requestOptions);
1850
1992
  }
1851
1993
  /**
1852
1994
  * {@inheritDoc ResourcesControl.getParent}
1853
1995
  */
1854
- getResourceParent(resource) {
1855
- return this.resources.getParent(resource);
1996
+ getResourceParent(resource, requestOptions) {
1997
+ return this.resources.getParent(resource, requestOptions);
1856
1998
  }
1857
1999
  /**
1858
2000
  * {@inheritDoc ResourcesControl.getChildrenOf}
1859
2001
  */
1860
- getResourceChildren(resource) {
1861
- return this.resources.getChildrenOf(resource);
2002
+ getResourceChildren(resource, requestOptions) {
2003
+ return this.resources.getChildrenOf(resource, requestOptions);
1862
2004
  }
1863
2005
  /**
1864
2006
  * {@inheritDoc ResourcesControl.update}
@@ -1892,7 +2034,7 @@ class NgwConnector$1 {
1892
2034
  else {
1893
2035
  // @ts-ignore
1894
2036
  {
1895
- console.warn(httpError);
2037
+ console.warn('DEV WARN', httpError);
1896
2038
  }
1897
2039
  const er = this._handleHttpError(httpError);
1898
2040
  if (er) {
@@ -1963,7 +2105,7 @@ class NgwProvider extends BaseProvider {
1963
2105
  });
1964
2106
  this.requests.push(request);
1965
2107
  request.catch((er) => {
1966
- console.log(er);
2108
+ console.warn(er);
1967
2109
  });
1968
2110
  const resp = await request;
1969
2111
  const entries = [];