bruce-models 5.9.7 → 5.9.9

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.
Files changed (40) hide show
  1. package/dist/bruce-models.es5.js +144 -103
  2. package/dist/bruce-models.es5.js.map +1 -1
  3. package/dist/bruce-models.umd.js +144 -103
  4. package/dist/bruce-models.umd.js.map +1 -1
  5. package/dist/lib/api/api.js.map +1 -1
  6. package/dist/lib/assembly/assembly.js +16 -3
  7. package/dist/lib/assembly/assembly.js.map +1 -1
  8. package/dist/lib/bruce-models.js +1 -1
  9. package/dist/lib/calculator/calculator.js +25 -13
  10. package/dist/lib/calculator/calculator.js.map +1 -1
  11. package/dist/lib/common/bruce-event.js +8 -3
  12. package/dist/lib/common/bruce-event.js.map +1 -1
  13. package/dist/lib/common/bruce-variable.js +31 -38
  14. package/dist/lib/common/bruce-variable.js.map +1 -1
  15. package/dist/lib/common/cache.js +2 -3
  16. package/dist/lib/common/cache.js.map +1 -1
  17. package/dist/lib/common/delay-queue.js +6 -2
  18. package/dist/lib/common/delay-queue.js.map +1 -1
  19. package/dist/lib/common/geometry.js +17 -13
  20. package/dist/lib/common/geometry.js.map +1 -1
  21. package/dist/lib/common/lru-cache.js +7 -1
  22. package/dist/lib/common/lru-cache.js.map +1 -1
  23. package/dist/lib/common/utc.js +15 -7
  24. package/dist/lib/common/utc.js.map +1 -1
  25. package/dist/lib/entity/entity-attribute.js +4 -1
  26. package/dist/lib/entity/entity-attribute.js.map +1 -1
  27. package/dist/lib/entity/entity.js +1 -1
  28. package/dist/lib/entity/entity.js.map +1 -1
  29. package/dist/lib/util/math-utils.js +7 -7
  30. package/dist/lib/util/math-utils.js.map +1 -1
  31. package/dist/lib/util/path-utils.js +6 -5
  32. package/dist/lib/util/path-utils.js.map +1 -1
  33. package/dist/types/api/api.d.ts +2 -2
  34. package/dist/types/assembly/assembly.d.ts +8 -2
  35. package/dist/types/bruce-models.d.ts +1 -1
  36. package/dist/types/calculator/calculator.d.ts +1 -1
  37. package/dist/types/common/bruce-variable.d.ts +1 -0
  38. package/dist/types/common/delay-queue.d.ts +2 -1
  39. package/dist/types/util/math-utils.d.ts +1 -1
  40. package/package.json +1 -1
@@ -150,8 +150,6 @@ var Api;
150
150
  Api.PrepReqParams = PrepReqParams;
151
151
  })(Api || (Api = {}));
152
152
 
153
- // 1 minute.
154
- const DEFAULT_DURATION = 60 * 1000;
155
153
  class CacheControl {
156
154
  constructor(id) {
157
155
  this.memory = new Map();
@@ -172,7 +170,7 @@ class CacheControl {
172
170
  }
173
171
  let { id, data, duration } = params;
174
172
  if (!duration || duration < 0) {
175
- duration = DEFAULT_DURATION;
173
+ duration = Api.DEFAULT_CACHE_DURATION;
176
174
  }
177
175
  id = String(id);
178
176
  const expires = Date.now() + duration;
@@ -1653,6 +1651,10 @@ class BruceEvent {
1653
1651
  Unsubscribe(id) {
1654
1652
  let index = this.callbacks.findIndex(x => x._id == id);
1655
1653
  if (index > -1) {
1654
+ // Null the callback function to prevent it from being called.
1655
+ // This stops a trigger from calling it if it's currently looping.
1656
+ this.callbacks[index].callback = null;
1657
+ // Remove the callback from the list.
1656
1658
  this.callbacks.splice(index, 1);
1657
1659
  }
1658
1660
  }
@@ -1662,9 +1664,10 @@ class BruceEvent {
1662
1664
  * @param data
1663
1665
  */
1664
1666
  Trigger(data) {
1665
- let callbacks = this.callbacks;
1666
- for (let i = 0; i < callbacks.length; i++) {
1667
- let callback = callbacks[i];
1667
+ // We copy in case the callback modifies the list.
1668
+ const callbacksCopy = [...this.callbacks];
1669
+ for (let i = 0; i < callbacksCopy.length; i++) {
1670
+ const callback = callbacksCopy[i];
1668
1671
  if (callback.callback) {
1669
1672
  callback.callback(data);
1670
1673
  }
@@ -1882,8 +1885,11 @@ var Assembly;
1882
1885
  if (!api) {
1883
1886
  api = ENVIRONMENT.Api().GetBruceApi();
1884
1887
  }
1885
- yield api.DELETE(`v3/assembly/${assemblyId}`, Api.PrepReqParams(reqParams));
1888
+ const res = yield api.DELETE(`v3/assembly/${assemblyId}`, Api.PrepReqParams(reqParams));
1886
1889
  api.Cache.RemoveByStartsWith(Api.ECacheKey.Assembly + Api.ECacheKey.Id + assemblyId);
1890
+ return {
1891
+ action: res
1892
+ };
1887
1893
  });
1888
1894
  }
1889
1895
  Assembly.Delete = Delete;
@@ -1893,7 +1899,7 @@ var Assembly;
1893
1899
  */
1894
1900
  function DeleteList(params) {
1895
1901
  return __awaiter(this, void 0, void 0, function* () {
1896
- let { api, req: reqParams } = params;
1902
+ let { api, req: reqParams, assemblyIds } = params;
1897
1903
  if (!api) {
1898
1904
  api = ENVIRONMENT.Api().GetBruceApi();
1899
1905
  }
@@ -1902,9 +1908,19 @@ var Assembly;
1902
1908
  if (params.invalidRootIds) {
1903
1909
  urlParams.append("InvalidRootEntityID", "true");
1904
1910
  }
1911
+ // Cannot be used with invalidRootIds.
1912
+ // So if both are supplied, invalidRootIds will take precedence.
1913
+ else if (params.assemblyIds) {
1914
+ for (let i = 0; i < assemblyIds.length; i++) {
1915
+ urlParams.append("ID", String(assemblyIds[i]));
1916
+ }
1917
+ }
1905
1918
  url += "?" + urlParams.toString();
1906
- yield api.DELETE(url, Api.PrepReqParams(reqParams));
1919
+ const res = yield api.DELETE(url, Api.PrepReqParams(reqParams));
1907
1920
  api.Cache.RemoveByStartsWith(Api.ECacheKey.Assembly);
1921
+ return {
1922
+ action: res
1923
+ };
1908
1924
  });
1909
1925
  }
1910
1926
  Assembly.DeleteList = DeleteList;
@@ -2579,7 +2595,10 @@ var EntityAttribute;
2579
2595
  }
2580
2596
  const key = path[0];
2581
2597
  const item = items.find((i) => i.Key === key);
2582
- if (!item || !item.Structure || !path.length) {
2598
+ if (!item) {
2599
+ return null;
2600
+ }
2601
+ if (path.length === 1) {
2583
2602
  return item;
2584
2603
  }
2585
2604
  return GetAttribute(item.Structure, path.slice(1));
@@ -3170,13 +3189,14 @@ var PathUtils;
3170
3189
  }
3171
3190
  const broken = str.split(".");
3172
3191
  for (let i = 0; i < broken.length; i++) {
3173
- let piece = broken[0];
3174
- if (piece.charAt(0) == "\"") {
3175
- piece = broken[0] = piece.substring(1);
3192
+ let piece = broken[i];
3193
+ if (piece.startsWith("\"")) {
3194
+ piece = piece.substring(1);
3176
3195
  }
3177
- if (piece.charAt(piece.length - 1) == "\"") {
3178
- broken[0] = piece.substring(0, piece.length - 1);
3196
+ if (piece.endsWith("\"")) {
3197
+ piece = piece.substring(0, piece.length - 1);
3179
3198
  }
3199
+ broken[i] = piece;
3180
3200
  }
3181
3201
  return broken;
3182
3202
  }
@@ -3841,7 +3861,7 @@ var Entity;
3841
3861
  function GetValue(params) {
3842
3862
  var _a;
3843
3863
  let { entity: data, path, handleLegacy: checkAgainstLegacy } = params;
3844
- if (checkAgainstLegacy == null) {
3864
+ if (checkAgainstLegacy == null || checkAgainstLegacy == undefined) {
3845
3865
  checkAgainstLegacy = true;
3846
3866
  }
3847
3867
  if (!path || !path.length) {
@@ -4386,25 +4406,6 @@ var Entity;
4386
4406
  Entity.GetHistoricContainsKey = GetHistoricContainsKey;
4387
4407
  })(Entity || (Entity = {}));
4388
4408
 
4389
- /**
4390
- * Gets the first Bruce variable in a string.
4391
- * @param str
4392
- * @returns
4393
- */
4394
- function getVariable(str) {
4395
- const start = str.indexOf("${");
4396
- if (start > -1) {
4397
- const end = str.indexOf("}");
4398
- if (end > -1) {
4399
- if (start < end) {
4400
- const path = str.substring(start + 2, end);
4401
- const txt = str.substring(start, end + 1);
4402
- return { path: path, text: txt };
4403
- }
4404
- }
4405
- }
4406
- return null;
4407
- }
4408
4409
  /**
4409
4410
  * Utilities for parsing "Bruce variables", typically within strings.
4410
4411
  *
@@ -4421,28 +4422,40 @@ var BruceVariable;
4421
4422
  * @returns
4422
4423
  */
4423
4424
  function SwapValues(params) {
4424
- let { str, entity: data, legacyParse } = params;
4425
- if (!legacyParse) {
4426
- legacyParse = false;
4427
- }
4428
- while (true) {
4429
- const variable = getVariable(str);
4430
- if (variable) {
4431
- const path = legacyParse ? PathUtils.ParseLegacy(variable.path) : PathUtils.Parse(variable.path);
4432
- let value = "";
4433
- if (path.length > 0) {
4434
- value = Entity.GetValue({
4435
- entity: data,
4436
- path: path
4437
- });
4438
- }
4439
- str = str.replace(variable.text, value);
4425
+ const { str, entity: data, legacyParse, retainType } = params;
4426
+ // If the input is just a path, return the value of the path.
4427
+ // We only do this for 'retainType=true' because all existing code expects a string result.
4428
+ if (retainType && str.startsWith("${") && str.endsWith("}")) {
4429
+ let pathStr = str.slice(2, -1);
4430
+ pathStr = pathStr.trim();
4431
+ const path = legacyParse ? PathUtils.ParseLegacy(pathStr) : PathUtils.Parse(pathStr);
4432
+ return Entity.GetValue({
4433
+ entity: data,
4434
+ path: path
4435
+ });
4436
+ }
4437
+ // Regex that will match all Bruce variables.
4438
+ // It looks for ${...} and captures the content inside the brackets.
4439
+ const variableRegex = /\${([^}]*)}/g;
4440
+ return str.replace(variableRegex, (match, pathStr) => {
4441
+ // If the path is empty or just whitespace, return empty string
4442
+ if (!pathStr || pathStr.trim().length === 0) {
4443
+ return "";
4440
4444
  }
4441
- else {
4442
- break;
4445
+ pathStr = pathStr.trim();
4446
+ const path = legacyParse ? PathUtils.ParseLegacy(pathStr) : PathUtils.Parse(pathStr);
4447
+ if (!path.length) {
4448
+ return "";
4443
4449
  }
4444
- }
4445
- return str;
4450
+ const value = Entity.GetValue({
4451
+ entity: data,
4452
+ path: path
4453
+ });
4454
+ if (value == null || value == undefined) {
4455
+ return "";
4456
+ }
4457
+ return String(value);
4458
+ });
4446
4459
  }
4447
4460
  BruceVariable.SwapValues = SwapValues;
4448
4461
  })(BruceVariable || (BruceVariable = {}));
@@ -4526,6 +4539,11 @@ var Calculator;
4526
4539
  */
4527
4540
  function Calculate(params) {
4528
4541
  let { fields, tags, data, defaultValue, type } = params;
4542
+ // If params doesn't include a defaultValue, use null.
4543
+ // Though passing in undefined is valid!
4544
+ if ("defaultValue" in params == false) {
4545
+ defaultValue = null;
4546
+ }
4529
4547
  if (fields == null) {
4530
4548
  return defaultValue;
4531
4549
  }
@@ -4576,11 +4594,6 @@ var Calculator;
4576
4594
  let value = null;
4577
4595
  for (let i = 0; i < fieldsArr.length; i++) {
4578
4596
  let field = fieldsArr[i];
4579
- if (field) {
4580
- // Dereference.
4581
- // We do this because we'll be modifying the field to fix bad data.
4582
- field = JSON.parse(JSON.stringify(field));
4583
- }
4584
4597
  // Bad data has it set to 'color' but expects the input to be a number.
4585
4598
  if (type == "number" && field.type == EValueType.Color) {
4586
4599
  field.type = EValueType.Input;
@@ -4937,20 +4950,26 @@ var Calculator;
4937
4950
  try {
4938
4951
  value = BruceVariable.SwapValues({
4939
4952
  str: value,
4940
- entity: entity
4953
+ entity: entity,
4954
+ retainType: true
4941
4955
  });
4942
- const isJsEval = value.startsWith("JS:");
4943
- const MATH_REGEX = /(\d+\.?\d*|\.\d+)([+\-*/])(\d+\.?\d*|\.\d+)/;
4944
- const isMathEval = isJsEval || MATH_REGEX.test(value);
4945
- if (isJsEval || isMathEval) {
4946
- if (isJsEval) {
4947
- value = value.replace("JS:", "");
4948
- value = value.trim();
4956
+ if (value == null || value == undefined) {
4957
+ return null;
4958
+ }
4959
+ if (typeof value === "string") {
4960
+ const isJsEval = value.startsWith("JS:");
4961
+ const MATH_REGEX = /(\d+\.?\d*|\.\d+)([+\-*/])(\d+\.?\d*|\.\d+)/;
4962
+ const isMathEval = isJsEval || MATH_REGEX.test(value);
4963
+ if (isJsEval || isMathEval) {
4964
+ if (isJsEval) {
4965
+ value = value.replace("JS:", "");
4966
+ value = value.trim();
4967
+ }
4968
+ // https://rollupjs.org/guide/en/#avoiding-eval
4969
+ // This stops eval warning.
4970
+ const eval2 = eval;
4971
+ return eval2(value);
4949
4972
  }
4950
- // https://rollupjs.org/guide/en/#avoiding-eval
4951
- // This stops eval warning.
4952
- const eval2 = eval;
4953
- return eval2(value);
4954
4973
  }
4955
4974
  }
4956
4975
  catch (exception) {
@@ -5009,13 +5028,7 @@ var Geometry;
5009
5028
  if (!points.length) {
5010
5029
  throw ("points is empty.");
5011
5030
  }
5012
- let carto = points[0];
5013
- let lineString = `${carto.longitude},${carto.latitude}` + (carto.altitude != null ? `,${carto.altitude}` : "");
5014
- for (let i = 1; i < points.length; i++) {
5015
- carto = points[i];
5016
- lineString += ` ${carto.longitude},${carto.latitude}` + (carto.altitude != null ? `,${carto.altitude}` : "");
5017
- }
5018
- return lineString;
5031
+ return points.map(carto => `${carto.longitude},${carto.latitude}` + (carto.altitude != null ? `,${carto.altitude}` : "")).join(' ');
5019
5032
  }
5020
5033
  Geometry.LineStrFromPoints = LineStrFromPoints;
5021
5034
  /**
@@ -5107,6 +5120,9 @@ var Geometry;
5107
5120
  }
5108
5121
  return newGeometry;
5109
5122
  }
5123
+ else if (!geometry) {
5124
+ return {};
5125
+ }
5110
5126
  return geometry;
5111
5127
  }
5112
5128
  Geometry.ParseGeometry = ParseGeometry;
@@ -5123,19 +5139,26 @@ var Geometry;
5123
5139
  const collection = [];
5124
5140
  // Returns if two coordinates are equal.
5125
5141
  const areCoordinatesEqual = (coord1, coord2) => {
5126
- return coord1[0] === coord2[0] && coord1[1] === coord2[1] && coord1[2] === coord2[2];
5142
+ return coord1[0] === coord2[0] && coord1[1] === coord2[1] &&
5143
+ (noAltitude || coord1[2] === coord2[2]);
5127
5144
  };
5128
5145
  // Removes consecutive duplicate coordinates.
5129
5146
  const removeConsecutiveDuplicates = (coordinates) => {
5130
- return coordinates.filter((coord, index) => {
5131
- return index === 0 || !areCoordinatesEqual(coord, coordinates[index - 1]);
5132
- });
5147
+ if (coordinates.length <= 1)
5148
+ return coordinates;
5149
+ const result = [coordinates[0]];
5150
+ for (let i = 1; i < coordinates.length; i++) {
5151
+ if (!areCoordinatesEqual(coordinates[i], coordinates[i - 1])) {
5152
+ result.push(coordinates[i]);
5153
+ }
5154
+ }
5155
+ return result;
5133
5156
  };
5134
5157
  // Ensures that the polygon is closed.
5135
5158
  const closePolygonCoordinates = (coordinates) => {
5136
5159
  return coordinates.map(ring => {
5137
- if (!areCoordinatesEqual(ring[0], ring[ring.length - 1])) {
5138
- ring.push(ring[0]);
5160
+ if (ring.length > 0 && !areCoordinatesEqual(ring[0], ring[ring.length - 1])) {
5161
+ return [...ring, ring[0]];
5139
5162
  }
5140
5163
  return ring;
5141
5164
  });
@@ -5729,13 +5752,14 @@ var Carto;
5729
5752
  * If you have a method that may be called often, but you don't want it to run often, use this.
5730
5753
  */
5731
5754
  class DelayQueue {
5732
- constructor(callback, delay = 200) {
5755
+ constructor(callback, delay = 200, startDelayed = false) {
5733
5756
  // Millisecond delay.
5734
5757
  this.delay = 200;
5735
5758
  // Date-time stamp for the last callback call.
5736
5759
  this.lastCallTime = null;
5737
5760
  this.callback = callback;
5738
5761
  this.delay = delay;
5762
+ this.startDelayed = startDelayed;
5739
5763
  }
5740
5764
  /**
5741
5765
  * Request a call on the callback.
@@ -5743,7 +5767,10 @@ class DelayQueue {
5743
5767
  */
5744
5768
  Call(force = false) {
5745
5769
  if (this.lastCallTime == null) {
5746
- force = true;
5770
+ this.lastCallTime = new Date().getTime();
5771
+ if (this.startDelayed) {
5772
+ force = false;
5773
+ }
5747
5774
  }
5748
5775
  if (force) {
5749
5776
  let endDate = new Date().getTime();
@@ -5848,28 +5875,36 @@ var UTC;
5848
5875
  * @param utc
5849
5876
  */
5850
5877
  function GetPassedTime(utc) {
5851
- const passedSeconds = GetPassedSeconds(utc);
5878
+ let tense = "ago";
5879
+ let passedSeconds = GetPassedSeconds(utc);
5880
+ if (passedSeconds < 0) {
5881
+ // Account for the time difference between the client and the server.
5882
+ if (passedSeconds < -(15 * 60)) {
5883
+ return "recently";
5884
+ }
5885
+ tense = "from now";
5886
+ }
5852
5887
  if (passedSeconds < 60) {
5853
- return `${passedSeconds} second${passedSeconds > 1 ? "s" : ""} ago`;
5888
+ return `${passedSeconds} second${passedSeconds > 1 ? "s" : ""} ${tense}`;
5854
5889
  }
5855
5890
  const passedMinutes = Math.floor(passedSeconds / 60);
5856
5891
  if (passedMinutes < 60) {
5857
- return `${passedMinutes} minute${passedMinutes > 1 ? "s" : ""} ago`;
5892
+ return `${passedMinutes} minute${passedMinutes > 1 ? "s" : ""} ${tense}`;
5858
5893
  }
5859
5894
  const passedHours = Math.floor(passedMinutes / 60);
5860
5895
  if (passedHours < 24) {
5861
- return `${passedHours} hour${passedHours > 1 ? "s" : ""} ago`;
5896
+ return `${passedHours} hour${passedHours > 1 ? "s" : ""} ${tense}`;
5862
5897
  }
5863
5898
  const passedDays = Math.floor(passedHours / 24);
5864
5899
  if (passedDays < 30) {
5865
- return `${passedDays} day${passedDays > 1 ? "s" : ""} ago`;
5900
+ return `${passedDays} day${passedDays > 1 ? "s" : ""} ${tense}`;
5866
5901
  }
5867
5902
  const passedMonths = Math.floor(passedDays / 30);
5868
5903
  if (passedMonths < 12) {
5869
- return `${passedMonths} month${passedMonths > 1 ? "s" : ""} ago`;
5904
+ return `${passedMonths} month${passedMonths > 1 ? "s" : ""} ${tense}`;
5870
5905
  }
5871
5906
  const passedYears = Math.floor(passedMonths / 12);
5872
- return `${passedYears} year${passedYears > 1 ? "s" : ""} ago`;
5907
+ return `${passedYears} year${passedYears > 1 ? "s" : ""} ${tense}`;
5873
5908
  }
5874
5909
  UTC.GetPassedTime = GetPassedTime;
5875
5910
  /**
@@ -5950,7 +5985,13 @@ class LRUCache {
5950
5985
  * @param value
5951
5986
  */
5952
5987
  Set(key, value) {
5953
- if (this.cache.size >= this.capacity) {
5988
+ if (this.capacity <= 0) {
5989
+ // Empty cache.
5990
+ // Means we were configured to not cache anything.
5991
+ this.cache.clear();
5992
+ return;
5993
+ }
5994
+ else if (this.cache.size >= this.capacity) {
5954
5995
  const leastRecentlyUsedKey = this.cache.keys().next().value;
5955
5996
  this.cache.delete(leastRecentlyUsedKey);
5956
5997
  }
@@ -7721,15 +7762,15 @@ var MathUtils;
7721
7762
  * @returns
7722
7763
  */
7723
7764
  function Round(num, decimals = 0) {
7724
- if (decimals <= 0) {
7725
- return Math.round(num);
7765
+ const n = typeof num === 'string' ? parseFloat(num) : num;
7766
+ if (isNaN(n)) {
7767
+ return 0;
7726
7768
  }
7727
- let tmp = "1";
7728
- for (let i = 0; i < decimals; i++) {
7729
- tmp += "0";
7769
+ if (decimals <= 0) {
7770
+ return Math.round(n);
7730
7771
  }
7731
- const d = parseFloat(tmp);
7732
- return Math.round((num + Number.EPSILON) * d) / d;
7772
+ const multiplier = Math.pow(10, decimals);
7773
+ return Math.round((n + Number.EPSILON) * multiplier) / multiplier;
7733
7774
  }
7734
7775
  MathUtils.Round = Round;
7735
7776
  /**
@@ -15649,7 +15690,7 @@ var Scenario;
15649
15690
  })(Scenario || (Scenario = {}));
15650
15691
 
15651
15692
  // This is updated with the package.json version on build.
15652
- const VERSION = "5.9.7";
15693
+ const VERSION = "5.9.9";
15653
15694
 
15654
15695
  export { VERSION, Assembly, AnnDocument, CustomForm, AbstractApi, Api, BruceApi, GlobalApi, GuardianApi, ApiGetters, Calculator, Bounds, BruceEvent, CacheControl, Camera, Cartes, Carto, Color, DelayQueue, Geometry, UTC, BruceVariable, LRUCache, GeoJson, EntityAttachmentType, EntityAttachment, EntityComment, EntityLink, EntityLod, EntityLodCategory, EntityRelationType, EntityRelation, EntitySource, EntityTag, EntityType, Entity, EntityCoords, EntityAttribute, EntityHistoricData, EntityTableView, Comment, ClientFile, ProgramKey, ZoomControl, MenuItem, ProjectViewBookmark, ProjectView, ProjectViewLegacyTile, ProjectViewTile, ProjectViewLegacy, ProjectViewLegacyBookmark, ProjectViewBookmarkGroup, PendingAction, MessageBroker, HostingLocation, Style, Tileset, Permission, Session, UserGroup, User, Account, AccountInvite, AccountFeatures, AccountLimits, AccountTemplate, AccountType, EncryptUtils, MathUtils, ObjectUtils, PathUtils, UrlUtils, DataLab, DataLabGroup, ImportAssembly, ImportCad, ImportCsv, ImportJson, ImportGeoJson, ImportKml, ImportedFile, ExportBrz, ExportUsd, Markup, Uploader, Plugin, ENVIRONMENT, DataSource, Scenario };
15655
15696
  //# sourceMappingURL=bruce-models.es5.js.map