@aemforms/af-core 0.22.20 → 0.22.23

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 (54) hide show
  1. package/LICENSE +18 -4
  2. package/README.md +14 -5
  3. package/lib/cjs/index.cjs +267 -1876
  4. package/lib/esm/BaseNode-dc59ab07.js +478 -0
  5. package/lib/esm/BaseNode.js +26 -454
  6. package/lib/esm/Checkbox.js +37 -1
  7. package/lib/esm/CheckboxGroup.js +38 -1
  8. package/lib/esm/Container.js +30 -9
  9. package/lib/esm/DateField.js +38 -2
  10. package/lib/esm/Field.d.ts +2 -2
  11. package/lib/esm/Field.js +62 -26
  12. package/lib/esm/Fieldset.js +36 -3
  13. package/lib/esm/FileObject.js +23 -1
  14. package/lib/esm/FileUpload.js +34 -1
  15. package/lib/esm/Form.d.ts +1 -1
  16. package/lib/esm/Form.js +40 -8
  17. package/lib/esm/FormInstance.js +53 -5
  18. package/lib/esm/FormMetaData.js +26 -1
  19. package/lib/esm/InstanceManager.js +35 -8
  20. package/lib/esm/Node.js +25 -1
  21. package/lib/esm/Scriptable.js +29 -2
  22. package/lib/esm/controller/EventQueue.js +23 -1
  23. package/lib/esm/controller/Events.d.ts +1 -1
  24. package/lib/esm/controller/Events.js +41 -19
  25. package/lib/esm/controller/Logger.d.ts +2 -2
  26. package/lib/esm/controller/Logger.js +23 -1
  27. package/lib/esm/data/DataGroup.js +24 -1
  28. package/lib/esm/data/DataValue.js +23 -1
  29. package/lib/esm/data/EmptyDataValue.js +23 -1
  30. package/lib/esm/index.js +55 -21
  31. package/lib/esm/rules/FunctionRuntime.d.ts +3 -3
  32. package/lib/esm/rules/FunctionRuntime.js +31 -6
  33. package/lib/esm/rules/RuleEngine.js +30 -1
  34. package/lib/esm/types/Json.d.ts +16 -16
  35. package/lib/esm/types/Json.js +24 -2
  36. package/lib/esm/types/Model.d.ts +4 -4
  37. package/lib/esm/types/Model.js +23 -1
  38. package/lib/esm/types/index.js +22 -2
  39. package/lib/esm/utils/DataRefParser.d.ts +2 -2
  40. package/lib/esm/utils/DataRefParser.js +31 -6
  41. package/lib/esm/utils/Fetch.d.ts +1 -1
  42. package/lib/esm/utils/Fetch.js +24 -2
  43. package/lib/esm/utils/FormCreationUtils.js +40 -2
  44. package/lib/esm/utils/FormUtils.js +33 -8
  45. package/lib/esm/utils/JsonUtils.js +34 -11
  46. package/lib/esm/utils/LogUtils.js +23 -1
  47. package/lib/esm/utils/SchemaUtils.js +24 -2
  48. package/lib/esm/utils/TranslationUtils.d.ts +1 -1
  49. package/lib/esm/utils/TranslationUtils.js +32 -9
  50. package/lib/esm/utils/ValidationUtils.d.ts +4 -4
  51. package/lib/esm/utils/ValidationUtils.js +30 -4
  52. package/package.json +4 -3
  53. package/lib/browser/afb-events.js +0 -151
  54. package/lib/browser/afb-runtime.js +0 -3620
package/lib/cjs/index.cjs CHANGED
@@ -1,168 +1,24 @@
1
- 'use strict';
2
-
3
- const translationProps = ['description', 'placeholder', 'enum', 'enumNames', 'label.value', 'constraintMessages.accept',
4
- 'constraintMessages.enum', 'constraintMessages.exclusiveMinimum', 'constraintMessages.exclusiveMaximum', 'constraintMessages.format', 'constraintMessages.maxFileSize', 'constraintMessages.maxLength',
5
- 'constraintMessages.maximum', 'constraintMessages.maxItems', 'constraintMessages.minLength', 'constraintMessages.minimum', 'constraintMessages.minItems', 'constraintMessages.pattern', 'constraintMessages.required',
6
- 'constraintMessages.step', 'constraintMessages.type', 'constraintMessages.validationExpression'];
7
- const constraintProps = ['accept', 'enum', 'exclusiveMinimum', 'exclusiveMaximum',
8
- 'format', 'maxFileSize', 'maxLength', 'maximum', 'maxItems',
9
- 'minLength', 'minimum', 'minItems', 'pattern', 'required', 'step', 'validationExpression', 'enumNames'];
10
-
11
- class ValidationError {
12
- fieldName;
13
- errorMessages;
14
- constructor(fieldName = '', errorMessages = []) {
15
- this.errorMessages = errorMessages;
16
- this.fieldName = fieldName;
17
- }
18
- }
19
-
20
- const objToMap = (o) => new Map(Object.entries(o));
21
- const stringViewTypes = objToMap({ 'date': 'date-input', 'data-url': 'file-input', 'binary': 'file-input' });
22
- const typeToViewTypes = objToMap({
23
- 'number': 'number-input',
24
- 'boolean': 'checkbox',
25
- 'object': 'panel',
26
- 'array': 'panel',
27
- 'file': 'file-input',
28
- 'file[]': 'file-input'
29
- });
30
- const arrayTypes = ['string[]', 'boolean[]', 'number[]', 'array'];
31
- const defaultFieldTypes = (schema) => {
32
- const type = schema.type || 'string';
33
- if ('enum' in schema) {
34
- const enums = schema.enum;
35
- if (enums.length > 2 || arrayTypes.indexOf(type) > -1) {
36
- return 'drop-down';
37
- }
38
- else {
39
- return 'checkbox';
40
- }
41
- }
42
- if (type === 'string' || type === 'string[]') {
43
- return stringViewTypes.get(schema.format) || 'text-input';
44
- }
45
- return typeToViewTypes.get(type) || 'text-input';
46
- };
47
- const fieldSchema = (input) => {
48
- if ('items' in input) {
49
- const fieldset = input;
50
- const items = fieldset.items;
51
- if (fieldset.type === 'array') {
52
- return {
53
- type: 'array',
54
- items: fieldSchema(items[0]),
55
- minItems: fieldset?.minItems,
56
- maxItems: fieldset?.maxItems
57
- };
58
- }
59
- else {
60
- const iter = items.filter(x => x.name != null);
61
- return {
62
- type: 'object',
63
- properties: Object.fromEntries(iter.map(item => [item.name, fieldSchema(item)])),
64
- required: iter.filter(x => x.required).map(x => x.name)
65
- };
66
- }
67
- }
68
- else {
69
- const field = input;
70
- const schemaProps = ['type', 'maxLength', 'minLength', 'minimum', 'maximum', 'format', 'pattern', 'step', 'enum'];
71
- const schema = schemaProps.reduce((acc, prop) => {
72
- const p = prop;
73
- if (prop in field && field[p] != undefined) {
74
- acc[prop] = field[p];
75
- }
76
- return acc;
77
- }, {});
78
- if (field.dataRef === 'none' || Object.keys(schema).length == 0) {
79
- return undefined;
80
- }
81
- return {
82
- title: field.label?.value,
83
- description: field.description,
84
- ...schema
85
- };
86
- }
87
- };
88
- const exportDataSchema = (form) => {
89
- return fieldSchema(form);
90
- };
1
+ /*************************************************************************
2
+ * ADOBE CONFIDENTIAL
3
+ * ___________________
4
+ *
5
+ * Copyright 2022 Adobe
6
+ * All Rights Reserved.
7
+ *
8
+ * NOTICE: All information contained herein is, and remains
9
+ * the property of Adobe and its suppliers, if any. The intellectual
10
+ * and technical concepts contained herein are proprietary to Adobe
11
+ * and its suppliers and are protected by all applicable intellectual
12
+ * property laws, including trade secret and copyright laws.
13
+ * Dissemination of this information or reproduction of this material
14
+ * is strictly forbidden unless prior written permission is obtained
15
+ * from Adobe.
16
+
17
+ * Adobe permits you to use and modify this file solely in accordance with
18
+ * the terms of the Adobe license agreement accompanying it.
19
+ *************************************************************************/
91
20
 
92
- const getProperty = (data, key, def) => {
93
- if (key in data) {
94
- return data[key];
95
- }
96
- else if (!key.startsWith(':')) {
97
- const prefixedKey = `:${key}`;
98
- if (prefixedKey in data) {
99
- return data[prefixedKey];
100
- }
101
- }
102
- return def;
103
- };
104
- const isFile = function (item) {
105
- return (item?.type === 'file' || item?.type === 'file[]') ||
106
- ((item?.type === 'string' || item?.type === 'string[]') &&
107
- (item?.format === 'binary' || item?.format === 'data-url'));
108
- };
109
- const checkIfConstraintsArePresent = function (item) {
110
- return constraintProps.some(cp => item[cp] !== undefined);
111
- };
112
- const isCheckbox = function (item) {
113
- const fieldType = item?.fieldType || defaultFieldTypes(item);
114
- return fieldType === 'checkbox';
115
- };
116
- const isCheckboxGroup = function (item) {
117
- const fieldType = item?.fieldType || defaultFieldTypes(item);
118
- return fieldType === 'checkbox-group';
119
- };
120
- const isDateField = function (item) {
121
- const fieldType = item?.fieldType || defaultFieldTypes(item);
122
- return (fieldType === 'text-input' && item?.format === 'date') || fieldType === 'date-input';
123
- };
124
- function deepClone(obj, idGenerator) {
125
- let result;
126
- if (obj instanceof Array) {
127
- result = [];
128
- result = obj.map(x => deepClone(x, idGenerator));
129
- }
130
- else if (typeof obj === 'object' && obj !== null) {
131
- result = {};
132
- Object.entries(obj).forEach(([key, value]) => {
133
- result[key] = deepClone(value, idGenerator);
134
- });
135
- }
136
- else {
137
- result = obj;
138
- }
139
- if (idGenerator && result && result.id) {
140
- result.id = idGenerator();
141
- }
142
- return result;
143
- }
144
- function checkIfKeyAdded(currentObj, prevObj, objKey) {
145
- if (currentObj != null && prevObj != null) {
146
- const newPrvObj = { ...prevObj };
147
- newPrvObj[objKey] = currentObj[objKey];
148
- const newJsonStr = jsonString(currentObj).replace(jsonString(newPrvObj), '');
149
- return newJsonStr === '';
150
- }
151
- else {
152
- return false;
153
- }
154
- }
155
- const jsonString = (obj) => {
156
- return JSON.stringify(obj, null, 2);
157
- };
158
- const isRepeatable = (obj) => {
159
- return ((obj.repeatable &&
160
- ((obj.minOccur === undefined && obj.maxOccur === undefined) ||
161
- (obj.minOccur !== undefined && obj.maxOccur !== undefined && obj.maxOccur !== 0) ||
162
- (obj.minOccur !== undefined && obj.maxOccur !== undefined && obj.minOccur !== 0 && obj.maxOccur !== 0) ||
163
- (obj.minOccur !== undefined && obj.minOccur >= 0) ||
164
- (obj.maxOccur !== undefined && obj.maxOccur !== 0))) || false);
165
- };
21
+ 'use strict';
166
22
 
167
23
  class ActionImpl {
168
24
  _metadata;
@@ -687,12 +543,12 @@ const resolveData = (data, input, create) => {
687
543
  return result;
688
544
  };
689
545
 
690
- var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
546
+ function __decorate(decorators, target, key, desc) {
691
547
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
692
548
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
693
549
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
694
550
  return c > 3 && r && Object.defineProperty(target, key, r), r;
695
- };
551
+ }
696
552
  const editableProperties = [
697
553
  'value',
698
554
  'label',
@@ -1123,22 +979,177 @@ class BaseNode {
1123
979
  }
1124
980
  }
1125
981
  }
1126
- __decorate$3([
982
+ __decorate([
1127
983
  dependencyTracked()
1128
984
  ], BaseNode.prototype, "index", null);
1129
- __decorate$3([
985
+ __decorate([
1130
986
  dependencyTracked()
1131
987
  ], BaseNode.prototype, "description", null);
1132
- __decorate$3([
988
+ __decorate([
1133
989
  dependencyTracked()
1134
990
  ], BaseNode.prototype, "visible", null);
1135
- __decorate$3([
991
+ __decorate([
1136
992
  dependencyTracked()
1137
993
  ], BaseNode.prototype, "label", null);
1138
- __decorate$3([
994
+ __decorate([
1139
995
  dependencyTracked()
1140
996
  ], BaseNode.prototype, "properties", null);
1141
997
 
998
+ const translationProps = ['description', 'placeholder', 'enum', 'enumNames', 'label.value', 'constraintMessages.accept',
999
+ 'constraintMessages.enum', 'constraintMessages.exclusiveMinimum', 'constraintMessages.exclusiveMaximum', 'constraintMessages.format', 'constraintMessages.maxFileSize', 'constraintMessages.maxLength',
1000
+ 'constraintMessages.maximum', 'constraintMessages.maxItems', 'constraintMessages.minLength', 'constraintMessages.minimum', 'constraintMessages.minItems', 'constraintMessages.pattern', 'constraintMessages.required',
1001
+ 'constraintMessages.step', 'constraintMessages.type', 'constraintMessages.validationExpression'];
1002
+ const constraintProps = ['accept', 'enum', 'exclusiveMinimum', 'exclusiveMaximum',
1003
+ 'format', 'maxFileSize', 'maxLength', 'maximum', 'maxItems',
1004
+ 'minLength', 'minimum', 'minItems', 'pattern', 'required', 'step', 'validationExpression', 'enumNames'];
1005
+
1006
+ const objToMap = (o) => new Map(Object.entries(o));
1007
+ const stringViewTypes = objToMap({ 'date': 'date-input', 'data-url': 'file-input', 'binary': 'file-input' });
1008
+ const typeToViewTypes = objToMap({
1009
+ 'number': 'number-input',
1010
+ 'boolean': 'checkbox',
1011
+ 'object': 'panel',
1012
+ 'array': 'panel',
1013
+ 'file': 'file-input',
1014
+ 'file[]': 'file-input'
1015
+ });
1016
+ const arrayTypes = ['string[]', 'boolean[]', 'number[]', 'array'];
1017
+ const defaultFieldTypes = (schema) => {
1018
+ const type = schema.type || 'string';
1019
+ if ('enum' in schema) {
1020
+ const enums = schema.enum;
1021
+ if (enums.length > 2 || arrayTypes.indexOf(type) > -1) {
1022
+ return 'drop-down';
1023
+ }
1024
+ else {
1025
+ return 'checkbox';
1026
+ }
1027
+ }
1028
+ if (type === 'string' || type === 'string[]') {
1029
+ return stringViewTypes.get(schema.format) || 'text-input';
1030
+ }
1031
+ return typeToViewTypes.get(type) || 'text-input';
1032
+ };
1033
+ const fieldSchema = (input) => {
1034
+ if ('items' in input) {
1035
+ const fieldset = input;
1036
+ const items = fieldset.items;
1037
+ if (fieldset.type === 'array') {
1038
+ return {
1039
+ type: 'array',
1040
+ items: fieldSchema(items[0]),
1041
+ minItems: fieldset?.minItems,
1042
+ maxItems: fieldset?.maxItems
1043
+ };
1044
+ }
1045
+ else {
1046
+ const iter = items.filter(x => x.name != null);
1047
+ return {
1048
+ type: 'object',
1049
+ properties: Object.fromEntries(iter.map(item => [item.name, fieldSchema(item)])),
1050
+ required: iter.filter(x => x.required).map(x => x.name)
1051
+ };
1052
+ }
1053
+ }
1054
+ else {
1055
+ const field = input;
1056
+ const schemaProps = ['type', 'maxLength', 'minLength', 'minimum', 'maximum', 'format', 'pattern', 'step', 'enum'];
1057
+ const schema = schemaProps.reduce((acc, prop) => {
1058
+ const p = prop;
1059
+ if (prop in field && field[p] != undefined) {
1060
+ acc[prop] = field[p];
1061
+ }
1062
+ return acc;
1063
+ }, {});
1064
+ if (field.dataRef === 'none' || Object.keys(schema).length == 0) {
1065
+ return undefined;
1066
+ }
1067
+ return {
1068
+ title: field.label?.value,
1069
+ description: field.description,
1070
+ ...schema
1071
+ };
1072
+ }
1073
+ };
1074
+ const exportDataSchema = (form) => {
1075
+ return fieldSchema(form);
1076
+ };
1077
+
1078
+ const getProperty = (data, key, def) => {
1079
+ if (key in data) {
1080
+ return data[key];
1081
+ }
1082
+ else if (!key.startsWith(':')) {
1083
+ const prefixedKey = `:${key}`;
1084
+ if (prefixedKey in data) {
1085
+ return data[prefixedKey];
1086
+ }
1087
+ }
1088
+ return def;
1089
+ };
1090
+ const isFile = function (item) {
1091
+ return (item?.type === 'file' || item?.type === 'file[]') ||
1092
+ ((item?.type === 'string' || item?.type === 'string[]') &&
1093
+ (item?.format === 'binary' || item?.format === 'data-url'));
1094
+ };
1095
+ const checkIfConstraintsArePresent = function (item) {
1096
+ return constraintProps.some(cp => item[cp] !== undefined);
1097
+ };
1098
+ const isCheckbox = function (item) {
1099
+ const fieldType = item?.fieldType || defaultFieldTypes(item);
1100
+ return fieldType === 'checkbox';
1101
+ };
1102
+ const isCheckboxGroup = function (item) {
1103
+ const fieldType = item?.fieldType || defaultFieldTypes(item);
1104
+ return fieldType === 'checkbox-group';
1105
+ };
1106
+ const isDateField = function (item) {
1107
+ const fieldType = item?.fieldType || defaultFieldTypes(item);
1108
+ return (fieldType === 'text-input' && item?.format === 'date') || fieldType === 'date-input';
1109
+ };
1110
+ function deepClone(obj, idGenerator) {
1111
+ let result;
1112
+ if (obj instanceof Array) {
1113
+ result = [];
1114
+ result = obj.map(x => deepClone(x, idGenerator));
1115
+ }
1116
+ else if (typeof obj === 'object' && obj !== null) {
1117
+ result = {};
1118
+ Object.entries(obj).forEach(([key, value]) => {
1119
+ result[key] = deepClone(value, idGenerator);
1120
+ });
1121
+ }
1122
+ else {
1123
+ result = obj;
1124
+ }
1125
+ if (idGenerator && result && result.id) {
1126
+ result.id = idGenerator();
1127
+ }
1128
+ return result;
1129
+ }
1130
+ function checkIfKeyAdded(currentObj, prevObj, objKey) {
1131
+ if (currentObj != null && prevObj != null) {
1132
+ const newPrvObj = { ...prevObj };
1133
+ newPrvObj[objKey] = currentObj[objKey];
1134
+ const newJsonStr = jsonString(currentObj).replace(jsonString(newPrvObj), '');
1135
+ return newJsonStr === '';
1136
+ }
1137
+ else {
1138
+ return false;
1139
+ }
1140
+ }
1141
+ const jsonString = (obj) => {
1142
+ return JSON.stringify(obj, null, 2);
1143
+ };
1144
+ const isRepeatable = (obj) => {
1145
+ return ((obj.repeatable &&
1146
+ ((obj.minOccur === undefined && obj.maxOccur === undefined) ||
1147
+ (obj.minOccur !== undefined && obj.maxOccur !== undefined && obj.maxOccur !== 0) ||
1148
+ (obj.minOccur !== undefined && obj.maxOccur !== undefined && obj.minOccur !== 0 && obj.maxOccur !== 0) ||
1149
+ (obj.minOccur !== undefined && obj.minOccur >= 0) ||
1150
+ (obj.maxOccur !== undefined && obj.maxOccur !== 0))) || false);
1151
+ };
1152
+
1142
1153
  class Scriptable extends BaseNode {
1143
1154
  _events = {};
1144
1155
  _rules = {};
@@ -1301,12 +1312,6 @@ class Scriptable extends BaseNode {
1301
1312
  }
1302
1313
  }
1303
1314
 
1304
- var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
1305
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1306
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1307
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1308
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1309
- };
1310
1315
  class Container extends Scriptable {
1311
1316
  _children = [];
1312
1317
  _childrenReference;
@@ -1576,13 +1581,13 @@ class Container extends Scriptable {
1576
1581
  }
1577
1582
  }
1578
1583
  }
1579
- __decorate$2([
1584
+ __decorate([
1580
1585
  dependencyTracked()
1581
1586
  ], Container.prototype, "maxItems", null);
1582
- __decorate$2([
1587
+ __decorate([
1583
1588
  dependencyTracked()
1584
1589
  ], Container.prototype, "minItems", null);
1585
- __decorate$2([
1590
+ __decorate([
1586
1591
  dependencyTracked()
1587
1592
  ], Container.prototype, "activeChild", null);
1588
1593
 
@@ -2448,17 +2453,16 @@ class Form extends Container {
2448
2453
  super.dispatch(action);
2449
2454
  }
2450
2455
  }
2451
- executeAction(action) {
2452
- if ((action.type !== 'submit') || this._invalidFields.length === 0) {
2453
- super.executeAction(action);
2454
- }
2455
- }
2456
2456
  submit(action, context) {
2457
2457
  if (this.validate().length === 0) {
2458
2458
  const payload = action?.payload || {};
2459
2459
  submit(context, payload?.success, payload?.error, payload?.submit_as, payload?.data);
2460
2460
  }
2461
2461
  }
2462
+ reset() {
2463
+ super.reset();
2464
+ this._invalidFields = [];
2465
+ }
2462
2466
  getElement(id) {
2463
2467
  if (id == this.id) {
2464
2468
  return this;
@@ -2485,7 +2489,6 @@ class Form extends Container {
2485
2489
  }
2486
2490
  }
2487
2491
 
2488
- // Type constants used to define functions.
2489
2492
  var dataTypes = {
2490
2493
  TYPE_NUMBER: 0,
2491
2494
  TYPE_ANY: 1,
@@ -2557,11 +2560,9 @@ const {
2557
2560
  TYPE_CLASS: TYPE_CLASS$1,
2558
2561
  TYPE_ARRAY_ARRAY,
2559
2562
  } = dataTypes;
2560
-
2561
2563
  const {
2562
2564
  TOK_EXPREF: TOK_EXPREF$3,
2563
2565
  } = tokenDefinitions;
2564
-
2565
2566
  const TYPE_NAME_TABLE = {
2566
2567
  [TYPE_NUMBER]: 'number',
2567
2568
  [TYPE_ANY$1]: 'any',
@@ -2576,13 +2577,10 @@ const TYPE_NAME_TABLE = {
2576
2577
  [TYPE_CLASS$1]: 'class',
2577
2578
  [TYPE_ARRAY_ARRAY]: 'Array<array>',
2578
2579
  };
2579
-
2580
2580
  function getTypeName(inputObj, useValueOf = true) {
2581
2581
  if (inputObj === null) return TYPE_NULL;
2582
2582
  let obj = inputObj;
2583
2583
  if (useValueOf) {
2584
- // check for the case where there's a child named 'valueOf' that's not a function
2585
- // if so, then it's an object...
2586
2584
  if (typeof inputObj.valueOf === 'function') obj = inputObj.valueOf.call(inputObj);
2587
2585
  else return TYPE_OBJECT;
2588
2586
  }
@@ -2598,8 +2596,6 @@ function getTypeName(inputObj, useValueOf = true) {
2598
2596
  case '[object Null]':
2599
2597
  return TYPE_NULL;
2600
2598
  case '[object Object]':
2601
- // Check if it's an expref. If it has, it's been
2602
- // tagged with a jmespathType attr of 'Expref';
2603
2599
  if (obj.jmespathType === TOK_EXPREF$3) {
2604
2600
  return TYPE_EXPREF;
2605
2601
  }
@@ -2608,23 +2604,17 @@ function getTypeName(inputObj, useValueOf = true) {
2608
2604
  return TYPE_OBJECT;
2609
2605
  }
2610
2606
  }
2611
-
2612
2607
  function getTypeNames(inputObj) {
2613
- // return the types with and without using valueOf
2614
- // needed for the cases where we really need an object passed to a function -- not it's value
2615
2608
  const type1 = getTypeName(inputObj);
2616
2609
  const type2 = getTypeName(inputObj, false);
2617
2610
  return [type1, type2];
2618
2611
  }
2619
-
2620
2612
  function matchType(actuals, expectedList, argValue, context, toNumber, toString) {
2621
2613
  const actual = actuals[0];
2622
2614
  if (expectedList.findIndex(
2623
2615
  type => type === TYPE_ANY$1 || actual === type,
2624
2616
  ) !== -1
2625
2617
  ) return argValue;
2626
- // Can't coerce Objects to any other type,
2627
- // and cannot coerce anything to a Class
2628
2618
  let wrongType = false;
2629
2619
  if (actual === TYPE_OBJECT || (expectedList.length === 1 && expectedList[0] === TYPE_CLASS$1)) {
2630
2620
  wrongType = true;
@@ -2644,11 +2634,9 @@ function matchType(actuals, expectedList, argValue, context, toNumber, toString)
2644
2634
  if (wrongType) {
2645
2635
  throw new Error(`TypeError: ${context} expected argument to be type ${TYPE_NAME_TABLE[expectedList[0]]} but received type ${TYPE_NAME_TABLE[actual]} instead.`);
2646
2636
  }
2647
- // no exact match in the list of possible types, see if we can coerce an array type
2648
2637
  let expected = -1;
2649
2638
  if (actual === TYPE_ARRAY$1) {
2650
2639
  if (expectedList.includes(TYPE_ARRAY_STRING$1) && expectedList.includes(TYPE_ARRAY_NUMBER)) {
2651
- // choose the array type based on the first element
2652
2640
  if (argValue.length > 0 && typeof argValue[0] === 'string') expected = TYPE_ARRAY_STRING$1;
2653
2641
  else expected = TYPE_ARRAY_NUMBER;
2654
2642
  }
@@ -2658,7 +2646,6 @@ function matchType(actuals, expectedList, argValue, context, toNumber, toString)
2658
2646
  e => [TYPE_ARRAY_STRING$1, TYPE_ARRAY_NUMBER, TYPE_ARRAY$1].includes(e),
2659
2647
  );
2660
2648
  }
2661
- // no match, just take the first type
2662
2649
  if (expected === -1) [expected] = expectedList;
2663
2650
  if (expected === TYPE_ANY$1) return argValue;
2664
2651
  if (expected === TYPE_ARRAY_STRING$1
@@ -2668,12 +2655,8 @@ function matchType(actuals, expectedList, argValue, context, toNumber, toString)
2668
2655
  if (actual === TYPE_ARRAY_NUMBER || actual === TYPE_ARRAY_STRING$1) return argValue;
2669
2656
  return argValue === null ? [] : [argValue];
2670
2657
  }
2671
- // The expected type can either just be array,
2672
- // or it can require a specific subtype (array of numbers).
2673
2658
  const subtype = expected === TYPE_ARRAY_NUMBER ? TYPE_NUMBER : TYPE_STRING$1;
2674
2659
  if (actual === TYPE_ARRAY$1) {
2675
- // Otherwise we need to check subtypes.
2676
- // We're going to modify the array, so take a copy
2677
2660
  const returnArray = argValue.slice();
2678
2661
  for (let i = 0; i < returnArray.length; i += 1) {
2679
2662
  const indexType = getTypeNames(returnArray[i]);
@@ -2694,7 +2677,6 @@ function matchType(actuals, expectedList, argValue, context, toNumber, toString)
2694
2677
  } else {
2695
2678
  if (expected === TYPE_NUMBER) {
2696
2679
  if ([TYPE_STRING$1, TYPE_BOOLEAN, TYPE_NULL].includes(actual)) return toNumber(argValue);
2697
- /* TYPE_ARRAY, TYPE_EXPREF, TYPE_OBJECT, TYPE_ARRAY, TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING */
2698
2680
  return 0;
2699
2681
  }
2700
2682
  if (expected === TYPE_STRING$1) {
@@ -2717,42 +2699,31 @@ function isArray(obj) {
2717
2699
  }
2718
2700
  return false;
2719
2701
  }
2720
-
2721
2702
  function isObject(obj) {
2722
2703
  if (obj !== null) {
2723
2704
  return Object.prototype.toString.call(obj) === '[object Object]';
2724
2705
  }
2725
2706
  return false;
2726
2707
  }
2727
-
2728
2708
  function getValueOf(a) {
2729
2709
  if (a === null || a === undefined) return a;
2730
2710
  if (isArray(a)) {
2731
2711
  return a.map(i => getValueOf(i));
2732
2712
  }
2733
- // if we have a child named 'valueOf' then we're an object,
2734
- // and just return the object.
2735
2713
  if (typeof (a.valueOf) !== 'function') return a;
2736
2714
  return a.valueOf();
2737
2715
  }
2738
-
2739
2716
  function strictDeepEqual(lhs, rhs) {
2740
2717
  const first = getValueOf(lhs);
2741
2718
  const second = getValueOf(rhs);
2742
- // Check the scalar case first.
2743
2719
  if (first === second) {
2744
2720
  return true;
2745
2721
  }
2746
-
2747
- // Check if they are the same type.
2748
2722
  const firstType = Object.prototype.toString.call(first);
2749
2723
  if (firstType !== Object.prototype.toString.call(second)) {
2750
2724
  return false;
2751
2725
  }
2752
- // We know that first and second have the same type so we can just check the
2753
- // first type from now on.
2754
2726
  if (isArray(first) === true) {
2755
- // Short circuit if they're not the same length;
2756
2727
  if (first.length !== second.length) {
2757
2728
  return false;
2758
2729
  }
@@ -2764,9 +2735,7 @@ function strictDeepEqual(lhs, rhs) {
2764
2735
  return true;
2765
2736
  }
2766
2737
  if (isObject(first) === true) {
2767
- // An object is equal if it has the same key/value pairs.
2768
2738
  const keysSeen = {};
2769
- // eslint-disable-next-line no-restricted-syntax
2770
2739
  for (const key in first) {
2771
2740
  if (hasOwnProperty.call(first, key)) {
2772
2741
  if (strictDeepEqual(first[key], second[key]) === false) {
@@ -2775,9 +2744,6 @@ function strictDeepEqual(lhs, rhs) {
2775
2744
  keysSeen[key] = true;
2776
2745
  }
2777
2746
  }
2778
- // Now check that there aren't any keys in second that weren't
2779
- // in first.
2780
- // eslint-disable-next-line no-restricted-syntax
2781
2747
  for (const key2 in second) {
2782
2748
  if (hasOwnProperty.call(second, key2)) {
2783
2749
  if (keysSeen[key2] !== true) {
@@ -2803,42 +2769,22 @@ const {
2803
2769
  TOK_NE: TOK_NE$2,
2804
2770
  TOK_FLATTEN: TOK_FLATTEN$2,
2805
2771
  } = tokenDefinitions;
2806
-
2807
2772
  const {
2808
2773
  TYPE_STRING,
2809
2774
  TYPE_ARRAY_STRING,
2810
2775
  TYPE_ARRAY,
2811
2776
  } = dataTypes;
2812
-
2813
2777
  function isFalse(value) {
2814
- // From the spec:
2815
- // A false value corresponds to the following values:
2816
- // Empty list
2817
- // Empty object
2818
- // Empty string
2819
- // False boolean
2820
- // null value
2821
- // (new) use JS truthy evaluation. This changes the spec behavior.
2822
- // Where in the past a zero (0) would be True, it's now false
2823
-
2824
- // First check the scalar values.
2825
2778
  if (value === null) return true;
2826
- // in case it's an object with a valueOf defined
2827
2779
  const obj = getValueOf(value);
2828
2780
  if (obj === '' || obj === false || obj === null) {
2829
2781
  return true;
2830
2782
  }
2831
2783
  if (isArray(obj) && obj.length === 0) {
2832
- // Check for an empty array.
2833
2784
  return true;
2834
2785
  }
2835
2786
  if (isObject(obj)) {
2836
- // Check for an empty object.
2837
- // eslint-disable-next-line no-restricted-syntax
2838
2787
  for (const key in obj) {
2839
- // If there are any keys, then
2840
- // the object is not empty so the object
2841
- // is not false.
2842
2788
  if (Object.prototype.hasOwnProperty.call(obj, key)) {
2843
2789
  return false;
2844
2790
  }
@@ -2847,11 +2793,9 @@ function isFalse(value) {
2847
2793
  }
2848
2794
  return !obj;
2849
2795
  }
2850
-
2851
2796
  function objValues(obj) {
2852
2797
  return Object.values(obj);
2853
2798
  }
2854
-
2855
2799
  class TreeInterpreter {
2856
2800
  constructor(runtime, globals, toNumber, toString, debug, language) {
2857
2801
  this.runtime = runtime;
@@ -2861,27 +2805,20 @@ class TreeInterpreter {
2861
2805
  this.debug = debug;
2862
2806
  this.language = language;
2863
2807
  }
2864
-
2865
2808
  search(node, value) {
2866
2809
  return this.visit(node, value);
2867
2810
  }
2868
-
2869
2811
  visit(n, v) {
2870
2812
  const visitFunctions = {
2871
2813
  Field: (node, value) => {
2872
- // we used to check isObject(value) here -- but it is possible for an array-based
2873
- // object to have properties. So we'll allow the child check on objects and arrays.
2874
2814
  if (value !== null && (isObject(value) || isArray(value))) {
2875
2815
  let field = value[node.name];
2876
- // fields can be objects with overridden methods. e.g. valueOf
2877
- // so don't resolve to a function...
2878
2816
  if (typeof field === 'function') field = undefined;
2879
2817
  if (field === undefined) {
2880
2818
  try {
2881
2819
  this.debug.push(`Failed to find: '${node.name}'`);
2882
2820
  const available = Object.keys(value).map(a => `'${a}'`).toString();
2883
2821
  if (available.length) this.debug.push(`Available fields: ${available}`);
2884
- // eslint-disable-next-line no-empty
2885
2822
  } catch (e) {}
2886
2823
  return null;
2887
2824
  }
@@ -2889,7 +2826,6 @@ class TreeInterpreter {
2889
2826
  }
2890
2827
  return null;
2891
2828
  },
2892
-
2893
2829
  Subexpression: (node, value) => {
2894
2830
  let result = this.visit(node.children[0], value);
2895
2831
  for (let i = 1; i < node.children.length; i += 1) {
@@ -2898,12 +2834,10 @@ class TreeInterpreter {
2898
2834
  }
2899
2835
  return result;
2900
2836
  },
2901
-
2902
2837
  IndexExpression: (node, value) => {
2903
2838
  const left = this.visit(node.children[0], value);
2904
2839
  return this.visit(node.children[1], left);
2905
2840
  },
2906
-
2907
2841
  Index: (node, value) => {
2908
2842
  if (isArray(value)) {
2909
2843
  let index = this.toNumber(this.visit(node.value, value));
@@ -2929,7 +2863,6 @@ class TreeInterpreter {
2929
2863
  this.debug.push(`left side of index expression ${value} is not an array or object.`);
2930
2864
  return null;
2931
2865
  },
2932
-
2933
2866
  Slice: (node, value) => {
2934
2867
  if (!isArray(value)) return null;
2935
2868
  const sliceParams = node.children.slice(0).map(
@@ -2949,9 +2882,7 @@ class TreeInterpreter {
2949
2882
  }
2950
2883
  return result;
2951
2884
  },
2952
-
2953
2885
  Projection: (node, value) => {
2954
- // Evaluate left child.
2955
2886
  const base = this.visit(node.children[0], value);
2956
2887
  if (!isArray(base)) return null;
2957
2888
  const collected = [];
@@ -2963,9 +2894,7 @@ class TreeInterpreter {
2963
2894
  });
2964
2895
  return collected;
2965
2896
  },
2966
-
2967
2897
  ValueProjection: (node, value) => {
2968
- // Evaluate left child.
2969
2898
  const projection = this.visit(node.children[0], value);
2970
2899
  if (!isObject(getValueOf(projection))) return null;
2971
2900
  const collected = [];
@@ -2976,7 +2905,6 @@ class TreeInterpreter {
2976
2905
  });
2977
2906
  return collected;
2978
2907
  },
2979
-
2980
2908
  FilterProjection: (node, value) => {
2981
2909
  const base = this.visit(node.children[0], value);
2982
2910
  if (!isArray(base)) return null;
@@ -2984,7 +2912,6 @@ class TreeInterpreter {
2984
2912
  const matched = this.visit(node.children[2], b);
2985
2913
  return !isFalse(matched);
2986
2914
  });
2987
-
2988
2915
  const finalResults = [];
2989
2916
  filtered.forEach(f => {
2990
2917
  const current = this.visit(node.children[1], f);
@@ -2992,11 +2919,9 @@ class TreeInterpreter {
2992
2919
  });
2993
2920
  return finalResults;
2994
2921
  },
2995
-
2996
2922
  Comparator: (node, value) => {
2997
2923
  const first = this.visit(node.children[0], value);
2998
2924
  const second = this.visit(node.children[1], value);
2999
-
3000
2925
  if (node.name === TOK_EQ$2) return strictDeepEqual(first, second);
3001
2926
  if (node.name === TOK_NE$2) return !strictDeepEqual(first, second);
3002
2927
  if (node.name === TOK_GT$2) return first > second;
@@ -3005,7 +2930,6 @@ class TreeInterpreter {
3005
2930
  if (node.name === TOK_LTE$2) return first <= second;
3006
2931
  throw new Error(`Unknown comparator: ${node.name}`);
3007
2932
  },
3008
-
3009
2933
  [TOK_FLATTEN$2]: (node, value) => {
3010
2934
  const original = this.visit(node.children[0], value);
3011
2935
  if (!isArray(original)) return null;
@@ -3019,14 +2943,11 @@ class TreeInterpreter {
3019
2943
  });
3020
2944
  return merged;
3021
2945
  },
3022
-
3023
2946
  Identity: (_node, value) => value,
3024
-
3025
2947
  MultiSelectList: (node, value) => {
3026
2948
  if (value === null) return null;
3027
2949
  return node.children.map(child => this.visit(child, value));
3028
2950
  },
3029
-
3030
2951
  MultiSelectHash: (node, value) => {
3031
2952
  if (value === null) return null;
3032
2953
  const collected = {};
@@ -3035,26 +2956,21 @@ class TreeInterpreter {
3035
2956
  });
3036
2957
  return collected;
3037
2958
  },
3038
-
3039
2959
  OrExpression: (node, value) => {
3040
2960
  let matched = this.visit(node.children[0], value);
3041
2961
  if (isFalse(matched)) matched = this.visit(node.children[1], value);
3042
2962
  return matched;
3043
2963
  },
3044
-
3045
2964
  AndExpression: (node, value) => {
3046
2965
  const first = this.visit(node.children[0], value);
3047
-
3048
2966
  if (isFalse(first) === true) return first;
3049
2967
  return this.visit(node.children[1], value);
3050
2968
  },
3051
-
3052
2969
  AddExpression: (node, value) => {
3053
2970
  const first = this.visit(node.children[0], value);
3054
2971
  const second = this.visit(node.children[1], value);
3055
2972
  return this.applyOperator(first, second, '+');
3056
2973
  },
3057
-
3058
2974
  ConcatenateExpression: (node, value) => {
3059
2975
  let first = this.visit(node.children[0], value);
3060
2976
  let second = this.visit(node.children[1], value);
@@ -3062,7 +2978,6 @@ class TreeInterpreter {
3062
2978
  second = matchType(getTypeNames(second), [TYPE_STRING, TYPE_ARRAY_STRING], second, 'concatenate', this.toNumber, this.toString);
3063
2979
  return this.applyOperator(first, second, '&');
3064
2980
  },
3065
-
3066
2981
  UnionExpression: (node, value) => {
3067
2982
  let first = this.visit(node.children[0], value);
3068
2983
  let second = this.visit(node.children[1], value);
@@ -3070,72 +2985,52 @@ class TreeInterpreter {
3070
2985
  second = matchType(getTypeNames(second), [TYPE_ARRAY], second, 'union', this.toNumber, this.toString);
3071
2986
  return first.concat(second);
3072
2987
  },
3073
-
3074
2988
  SubtractExpression: (node, value) => {
3075
2989
  const first = this.visit(node.children[0], value);
3076
2990
  const second = this.visit(node.children[1], value);
3077
2991
  return this.applyOperator(first, second, '-');
3078
2992
  },
3079
-
3080
2993
  MultiplyExpression: (node, value) => {
3081
2994
  const first = this.visit(node.children[0], value);
3082
2995
  const second = this.visit(node.children[1], value);
3083
2996
  return this.applyOperator(first, second, '*');
3084
2997
  },
3085
-
3086
2998
  DivideExpression: (node, value) => {
3087
2999
  const first = this.visit(node.children[0], value);
3088
3000
  const second = this.visit(node.children[1], value);
3089
3001
  return this.applyOperator(first, second, '/');
3090
3002
  },
3091
-
3092
3003
  PowerExpression: (node, value) => {
3093
3004
  const first = this.visit(node.children[0], value);
3094
3005
  const second = this.visit(node.children[1], value);
3095
3006
  return this.applyOperator(first, second, '^');
3096
3007
  },
3097
-
3098
3008
  NotExpression: (node, value) => {
3099
3009
  const first = this.visit(node.children[0], value);
3100
3010
  return isFalse(first);
3101
3011
  },
3102
-
3103
3012
  UnaryMinusExpression: (node, value) => {
3104
3013
  const first = this.visit(node.children[0], value);
3105
3014
  return first * -1;
3106
3015
  },
3107
-
3108
3016
  Literal: node => node.value,
3109
-
3110
3017
  Number: node => node.value,
3111
-
3112
3018
  [TOK_PIPE$2]: (node, value) => {
3113
3019
  const left = this.visit(node.children[0], value);
3114
3020
  return this.visit(node.children[1], left);
3115
3021
  },
3116
-
3117
3022
  [TOK_CURRENT$2]: (_node, value) => value,
3118
-
3119
3023
  [TOK_GLOBAL$2]: node => {
3120
3024
  const result = this.globals[node.name];
3121
3025
  return result === undefined ? null : result;
3122
3026
  },
3123
-
3124
3027
  Function: (node, value) => {
3125
- // Special case for if()
3126
- // we need to make sure the results are called only after the condition is evaluated
3127
- // Otherwise we end up with both results invoked -- which could include side effects
3128
- // For "if", the last parameter to callFunction is false (bResolved) to indicate there's
3129
- // no point in validating the argument type.
3130
3028
  if (node.name === 'if') return this.runtime.callFunction(node.name, node.children, value, this, false);
3131
3029
  const resolvedArgs = node.children.map(child => this.visit(child, value));
3132
3030
  return this.runtime.callFunction(node.name, resolvedArgs, value, this);
3133
3031
  },
3134
-
3135
3032
  ExpressionReference: node => {
3136
3033
  const [refNode] = node.children;
3137
- // Tag the node with a specific attribute so the type
3138
- // checker verify the type.
3139
3034
  refNode.jmespathType = TOK_EXPREF$2;
3140
3035
  return refNode;
3141
3036
  },
@@ -3144,8 +3039,6 @@ class TreeInterpreter {
3144
3039
  if (!fn) throw new Error(`Unknown/missing node type ${(n && n.type) || ''}`);
3145
3040
  return fn(n, v);
3146
3041
  }
3147
-
3148
- // eslint-disable-next-line class-methods-use-this
3149
3042
  computeSliceParams(arrayLength, sliceParams) {
3150
3043
  function capSliceRange(arrayLen, actual, stp) {
3151
3044
  let actualValue = actual;
@@ -3159,7 +3052,6 @@ class TreeInterpreter {
3159
3052
  }
3160
3053
  return actualValue;
3161
3054
  }
3162
-
3163
3055
  let [start, stop, step] = sliceParams;
3164
3056
  if (step === null) {
3165
3057
  step = 1;
@@ -3169,13 +3061,11 @@ class TreeInterpreter {
3169
3061
  throw error;
3170
3062
  }
3171
3063
  const stepValueNegative = step < 0;
3172
-
3173
3064
  if (start === null) {
3174
3065
  start = stepValueNegative ? arrayLength - 1 : 0;
3175
3066
  } else {
3176
3067
  start = capSliceRange(arrayLength, start, step);
3177
3068
  }
3178
-
3179
3069
  if (stop === null) {
3180
3070
  stop = stepValueNegative ? -1 : arrayLength;
3181
3071
  } else {
@@ -3183,10 +3073,8 @@ class TreeInterpreter {
3183
3073
  }
3184
3074
  return [start, stop, step];
3185
3075
  }
3186
-
3187
3076
  applyOperator(first, second, operator) {
3188
3077
  if (isArray(first) && isArray(second)) {
3189
- // balance the size of the arrays
3190
3078
  const shorter = first.length < second.length ? first : second;
3191
3079
  const diff = Math.abs(first.length - second.length);
3192
3080
  shorter.length += diff;
@@ -3197,10 +3085,8 @@ class TreeInterpreter {
3197
3085
  }
3198
3086
  return result;
3199
3087
  }
3200
-
3201
3088
  if (isArray(first)) return first.map(a => this.applyOperator(a, second, operator));
3202
3089
  if (isArray(second)) return second.map(a => this.applyOperator(first, a, operator));
3203
-
3204
3090
  if (operator === '*') return this.toNumber(first) * this.toNumber(second);
3205
3091
  if (operator === '&') return first + second;
3206
3092
  if (operator === '+') {
@@ -3218,8 +3104,6 @@ class TreeInterpreter {
3218
3104
  }
3219
3105
  }
3220
3106
 
3221
- /* eslint-disable no-underscore-dangle */
3222
-
3223
3107
  const {
3224
3108
  TOK_UNQUOTEDIDENTIFIER: TOK_UNQUOTEDIDENTIFIER$1,
3225
3109
  TOK_QUOTEDIDENTIFIER: TOK_QUOTEDIDENTIFIER$1,
@@ -3259,16 +3143,8 @@ const {
3259
3143
  TOK_LPAREN: TOK_LPAREN$1,
3260
3144
  TOK_LITERAL: TOK_LITERAL$1,
3261
3145
  } = tokenDefinitions;
3262
-
3263
- // The "&", "[", "<", ">" tokens
3264
- // are not in basicToken because
3265
- // there are two token variants
3266
- // ("&&", "[?", "<=", ">="). This is specially handled
3267
- // below.
3268
-
3269
3146
  const basicTokens = {
3270
3147
  '.': TOK_DOT$1,
3271
- // "*": TOK_STAR,
3272
3148
  ',': TOK_COMMA$1,
3273
3149
  ':': TOK_COLON$1,
3274
3150
  '{': TOK_LBRACE$1,
@@ -3278,7 +3154,6 @@ const basicTokens = {
3278
3154
  ')': TOK_RPAREN$1,
3279
3155
  '@': TOK_CURRENT$1,
3280
3156
  };
3281
-
3282
3157
  const globalStartToken = '$';
3283
3158
  const operatorStartToken = {
3284
3159
  '<': true,
@@ -3286,42 +3161,34 @@ const operatorStartToken = {
3286
3161
  '=': true,
3287
3162
  '!': true,
3288
3163
  };
3289
-
3290
3164
  const skipChars = {
3291
3165
  ' ': true,
3292
3166
  '\t': true,
3293
3167
  '\n': true,
3294
3168
  };
3295
-
3296
3169
  function isNum(ch) {
3297
3170
  return (ch >= '0' && ch <= '9') || (ch === '.');
3298
3171
  }
3299
-
3300
3172
  function isAlphaNum(ch) {
3301
3173
  return (ch >= 'a' && ch <= 'z')
3302
3174
  || (ch >= 'A' && ch <= 'Z')
3303
3175
  || (ch >= '0' && ch <= '9')
3304
3176
  || ch === '_';
3305
3177
  }
3306
-
3307
3178
  function isIdentifier(stream, pos) {
3308
3179
  const ch = stream[pos];
3309
- // $ is special -- it's allowed to be part of an identifier if it's the first character
3310
3180
  if (ch === '$') {
3311
3181
  return stream.length > pos && isAlphaNum(stream[pos + 1]);
3312
3182
  }
3313
- // return whether character 'isAlpha'
3314
3183
  return (ch >= 'a' && ch <= 'z')
3315
3184
  || (ch >= 'A' && ch <= 'Z')
3316
3185
  || ch === '_';
3317
3186
  }
3318
-
3319
3187
  class Lexer {
3320
3188
  constructor(allowedGlobalNames = [], debug = []) {
3321
3189
  this._allowedGlobalNames = allowedGlobalNames;
3322
3190
  this.debug = debug;
3323
3191
  }
3324
-
3325
3192
  tokenize(stream) {
3326
3193
  const tokens = [];
3327
3194
  this._current = 0;
@@ -3330,7 +3197,6 @@ class Lexer {
3330
3197
  let token;
3331
3198
  while (this._current < stream.length) {
3332
3199
  const prev = tokens.length ? tokens.slice(-1)[0].type : null;
3333
-
3334
3200
  if (this._isGlobal(prev, stream, this._current)) {
3335
3201
  tokens.push(this._consumeGlobal(stream));
3336
3202
  } else if (isIdentifier(stream, this._current)) {
@@ -3355,8 +3221,6 @@ class Lexer {
3355
3221
  token = this._consumeNumber(stream);
3356
3222
  tokens.push(token);
3357
3223
  } else if (stream[this._current] === '[') {
3358
- // No need to increment this._current. This happens
3359
- // in _consumeLBracket
3360
3224
  token = this._consumeLBracket(stream);
3361
3225
  tokens.push(token);
3362
3226
  } else if (stream[this._current] === '"') {
@@ -3386,7 +3250,6 @@ class Lexer {
3386
3250
  } else if (operatorStartToken[stream[this._current]] !== undefined) {
3387
3251
  tokens.push(this._consumeOperator(stream));
3388
3252
  } else if (skipChars[stream[this._current]] !== undefined) {
3389
- // Ignore whitespace.
3390
3253
  this._current += 1;
3391
3254
  } else if (stream[this._current] === '&') {
3392
3255
  start = this._current;
@@ -3395,9 +3258,6 @@ class Lexer {
3395
3258
  this._current += 1;
3396
3259
  tokens.push({ type: TOK_AND$1, value: '&&', start });
3397
3260
  } else if (prev === TOK_COMMA$1 || prev === TOK_LPAREN$1) {
3398
- // based on previous token we'll know if this & is a JMESPath expression-type
3399
- // or if it's a concatenation operator
3400
- // if we're a function arg then it's an expression-type
3401
3261
  tokens.push({ type: TOK_EXPREF$1, value: '&', start });
3402
3262
  } else {
3403
3263
  tokens.push({ type: TOK_CONCATENATE$1, value: '&', start });
@@ -3417,8 +3277,6 @@ class Lexer {
3417
3277
  } else if (stream[this._current] === '*') {
3418
3278
  start = this._current;
3419
3279
  this._current += 1;
3420
- // based on previous token we'll know if this asterix is a star -- not a multiply
3421
- // might be better to list the prev tokens that are valid for multiply?
3422
3280
  const prevToken = tokens.length && tokens.slice(-1)[0].type;
3423
3281
  if (tokens.length === 0 || [
3424
3282
  TOK_LBRACKET$1,
@@ -3458,7 +3316,6 @@ class Lexer {
3458
3316
  }
3459
3317
  return tokens;
3460
3318
  }
3461
-
3462
3319
  _consumeUnquotedIdentifier(stream) {
3463
3320
  const start = this._current;
3464
3321
  this._current += 1;
@@ -3467,14 +3324,12 @@ class Lexer {
3467
3324
  }
3468
3325
  return stream.slice(start, this._current);
3469
3326
  }
3470
-
3471
3327
  _consumeQuotedIdentifier(stream) {
3472
3328
  const start = this._current;
3473
3329
  this._current += 1;
3474
3330
  const maxLength = stream.length;
3475
3331
  let foundNonAlpha = !isIdentifier(stream, start + 1);
3476
3332
  while (stream[this._current] !== '"' && this._current < maxLength) {
3477
- // You can escape a double quote and you can escape an escape.
3478
3333
  let current = this._current;
3479
3334
  if (!isAlphaNum(stream[current])) foundNonAlpha = true;
3480
3335
  if (stream[current] === '\\' && (stream[current + 1] === '\\'
@@ -3487,26 +3342,19 @@ class Lexer {
3487
3342
  }
3488
3343
  this._current += 1;
3489
3344
  const val = stream.slice(start, this._current);
3490
- // Check for unnecessary double quotes.
3491
- // json-formula uses double quotes to escape characters that don't belong in names names.
3492
- // e.g. "purchase-order".address
3493
- // If we find a double-quoted entity with spaces or all legal characters, issue a warning
3494
3345
  try {
3495
3346
  if (!foundNonAlpha || val.includes(' ')) {
3496
3347
  this.debug.push(`Suspicious quotes: ${val}`);
3497
3348
  this.debug.push(`Did you intend a literal? '${val.replace(/"/g, '')}'?`);
3498
3349
  }
3499
- // eslint-disable-next-line no-empty
3500
3350
  } catch (e) {}
3501
3351
  return JSON.parse(val);
3502
3352
  }
3503
-
3504
3353
  _consumeRawStringLiteral(stream) {
3505
3354
  const start = this._current;
3506
3355
  this._current += 1;
3507
3356
  const maxLength = stream.length;
3508
3357
  while (stream[this._current] !== "'" && this._current < maxLength) {
3509
- // You can escape a single quote and you can escape an escape.
3510
3358
  let current = this._current;
3511
3359
  if (stream[current] === '\\' && (stream[current + 1] === '\\'
3512
3360
  || stream[current + 1] === "'")) {
@@ -3520,7 +3368,6 @@ class Lexer {
3520
3368
  const literal = stream.slice(start + 1, this._current - 1);
3521
3369
  return literal.replaceAll("\\'", "'");
3522
3370
  }
3523
-
3524
3371
  _consumeNumber(stream) {
3525
3372
  const start = this._current;
3526
3373
  this._current += 1;
@@ -3537,13 +3384,11 @@ class Lexer {
3537
3384
  }
3538
3385
  return { type: TOK_NUMBER$1, value, start };
3539
3386
  }
3540
-
3541
3387
  _consumeUnaryMinus() {
3542
3388
  const start = this._current;
3543
3389
  this._current += 1;
3544
3390
  return { type: TOK_UNARY_MINUS$1, value: '-', start };
3545
3391
  }
3546
-
3547
3392
  _consumeLBracket(stream) {
3548
3393
  const start = this._current;
3549
3394
  this._current += 1;
@@ -3557,28 +3402,22 @@ class Lexer {
3557
3402
  }
3558
3403
  return { type: TOK_LBRACKET$1, value: '[', start };
3559
3404
  }
3560
-
3561
3405
  _isGlobal(prev, stream, pos) {
3562
- // global tokens occur only at the start of an expression
3563
3406
  if (prev !== null && prev === TOK_DOT$1) return false;
3564
3407
  const ch = stream[pos];
3565
3408
  if (ch !== globalStartToken) return false;
3566
- // $ is special -- it's allowed to be part of an identifier if it's the first character
3567
3409
  let i = pos + 1;
3568
3410
  while (i < stream.length && isAlphaNum(stream[i])) i += 1;
3569
3411
  const global = stream.slice(pos, i);
3570
3412
  return this._allowedGlobalNames.includes(global);
3571
3413
  }
3572
-
3573
3414
  _consumeGlobal(stream) {
3574
3415
  const start = this._current;
3575
3416
  this._current += 1;
3576
3417
  while (this._current < stream.length && isAlphaNum(stream[this._current])) this._current += 1;
3577
3418
  const global = stream.slice(start, this._current);
3578
-
3579
3419
  return { type: TOK_GLOBAL$1, name: global, start };
3580
3420
  }
3581
-
3582
3421
  _consumeOperator(stream) {
3583
3422
  const start = this._current;
3584
3423
  const startingChar = stream[start];
@@ -3604,20 +3443,17 @@ class Lexer {
3604
3443
  }
3605
3444
  return { type: TOK_GT$1, value: '>', start };
3606
3445
  }
3607
- // startingChar is '='
3608
3446
  if (stream[this._current] === '=') {
3609
3447
  this._current += 1;
3610
3448
  return { type: TOK_EQ$1, value: '==', start };
3611
3449
  }
3612
3450
  return { type: TOK_EQ$1, value: '=', start };
3613
3451
  }
3614
-
3615
3452
  _consumeLiteral(stream) {
3616
3453
  function _looksLikeJSON(str) {
3617
3454
  if (str === '') return false;
3618
3455
  if ('[{"'.includes(str[0])) return true;
3619
3456
  if (['true', 'false', 'null'].includes(str)) return true;
3620
-
3621
3457
  if ('-0123456789'.includes(str[0])) {
3622
3458
  try {
3623
3459
  JSON.parse(str);
@@ -3629,7 +3465,6 @@ class Lexer {
3629
3465
  return false;
3630
3466
  }
3631
3467
  }
3632
-
3633
3468
  this._current += 1;
3634
3469
  const start = this._current;
3635
3470
  const maxLength = stream.length;
@@ -3637,14 +3472,12 @@ class Lexer {
3637
3472
  let inQuotes = false;
3638
3473
  while ((inQuotes || stream[this._current] !== '`') && this._current < maxLength) {
3639
3474
  let current = this._current;
3640
- // bypass escaped double quotes when we're inside quotes
3641
3475
  if (inQuotes && stream[current] === '\\' && stream[current + 1] === '"') current += 2;
3642
3476
  else {
3643
3477
  if (stream[current] === '"') inQuotes = !inQuotes;
3644
3478
  if (inQuotes && stream[current + 1] === '`') current += 2;
3645
3479
  else if (stream[current] === '\\' && (stream[current + 1] === '\\'
3646
3480
  || stream[current + 1] === '`')) {
3647
- // You can escape a literal char or you can escape the escape.
3648
3481
  current += 2;
3649
3482
  } else {
3650
3483
  current += 1;
@@ -3657,16 +3490,13 @@ class Lexer {
3657
3490
  if (_looksLikeJSON(literalString)) {
3658
3491
  literal = JSON.parse(literalString);
3659
3492
  } else {
3660
- // Try to JSON parse it as "<literal>"
3661
3493
  literal = JSON.parse(`"${literalString}"`);
3662
3494
  }
3663
- // +1 gets us to the ending "`", +1 to move on to the next char.
3664
3495
  this._current += 1;
3665
3496
  return literal;
3666
3497
  }
3667
3498
  }
3668
3499
 
3669
- /* eslint-disable no-underscore-dangle */
3670
3500
  const {
3671
3501
  TOK_LITERAL,
3672
3502
  TOK_COLON,
@@ -3708,7 +3538,6 @@ const {
3708
3538
  TOK_LBRACKET,
3709
3539
  TOK_LPAREN,
3710
3540
  } = tokenDefinitions;
3711
-
3712
3541
  const bindingPower = {
3713
3542
  [TOK_EOF]: 0,
3714
3543
  [TOK_UNQUOTEDIDENTIFIER]: 0,
@@ -3748,12 +3577,10 @@ const bindingPower = {
3748
3577
  [TOK_LBRACKET]: 55,
3749
3578
  [TOK_LPAREN]: 60,
3750
3579
  };
3751
-
3752
3580
  class Parser {
3753
3581
  constructor(allowedGlobalNames = []) {
3754
3582
  this._allowedGlobalNames = allowedGlobalNames;
3755
3583
  }
3756
-
3757
3584
  parse(expression, debug) {
3758
3585
  this._loadTokens(expression, debug);
3759
3586
  this.index = 0;
@@ -3768,14 +3595,12 @@ class Parser {
3768
3595
  }
3769
3596
  return ast;
3770
3597
  }
3771
-
3772
3598
  _loadTokens(expression, debug) {
3773
3599
  const lexer = new Lexer(this._allowedGlobalNames, debug);
3774
3600
  const tokens = lexer.tokenize(expression);
3775
3601
  tokens.push({ type: TOK_EOF, value: '', start: expression.length });
3776
3602
  this.tokens = tokens;
3777
3603
  }
3778
-
3779
3604
  expression(rbp) {
3780
3605
  const leftToken = this._lookaheadToken(0);
3781
3606
  this._advance();
@@ -3788,28 +3613,21 @@ class Parser {
3788
3613
  }
3789
3614
  return left;
3790
3615
  }
3791
-
3792
3616
  _lookahead(number) {
3793
3617
  return this.tokens[this.index + number].type;
3794
3618
  }
3795
-
3796
3619
  _lookaheadToken(number) {
3797
3620
  return this.tokens[this.index + number];
3798
3621
  }
3799
-
3800
3622
  _advance() {
3801
3623
  this.index += 1;
3802
3624
  }
3803
-
3804
3625
  _getIndex() {
3805
3626
  return this.index;
3806
3627
  }
3807
-
3808
3628
  _setIndex(index) {
3809
3629
  this.index = index;
3810
3630
  }
3811
-
3812
- // eslint-disable-next-line consistent-return
3813
3631
  nud(token) {
3814
3632
  let left;
3815
3633
  let right;
@@ -3838,8 +3656,6 @@ class Parser {
3838
3656
  case TOK_STAR:
3839
3657
  left = { type: 'Identity' };
3840
3658
  if (this._lookahead(0) === TOK_RBRACKET) {
3841
- // This can happen in a multiselect,
3842
- // [a, b, *]
3843
3659
  right = { type: 'Identity' };
3844
3660
  } else {
3845
3661
  right = this._parseProjectionRHS(bindingPower.Star);
@@ -3886,8 +3702,6 @@ class Parser {
3886
3702
  this._errorToken(token);
3887
3703
  }
3888
3704
  }
3889
-
3890
- // eslint-disable-next-line consistent-return
3891
3705
  led(tokenName, left) {
3892
3706
  let condition;
3893
3707
  let right;
@@ -3908,7 +3722,6 @@ class Parser {
3908
3722
  right = this._parseDotRHS(rbp);
3909
3723
  return { type: 'Subexpression', children: [left, right] };
3910
3724
  }
3911
- // Creating a projection.
3912
3725
  this._advance();
3913
3726
  right = this._parseProjectionRHS(rbp);
3914
3727
  return { type: 'ValueProjection', children: [left, right] };
@@ -3986,7 +3799,6 @@ class Parser {
3986
3799
  this._errorToken(this._lookaheadToken(0));
3987
3800
  }
3988
3801
  }
3989
-
3990
3802
  _match(tokenType) {
3991
3803
  if (this._lookahead(0) === tokenType) {
3992
3804
  this._advance();
@@ -3997,8 +3809,6 @@ class Parser {
3997
3809
  throw error;
3998
3810
  }
3999
3811
  }
4000
-
4001
- // eslint-disable-next-line class-methods-use-this
4002
3812
  _errorToken(token) {
4003
3813
  const error = new Error(`Invalid token (${
4004
3814
  token.type}): "${
@@ -4006,17 +3816,14 @@ class Parser {
4006
3816
  error.name = 'ParserError';
4007
3817
  throw error;
4008
3818
  }
4009
-
4010
3819
  _parseChainedIndexExpression() {
4011
3820
  const oldIndex = this._getIndex();
4012
3821
  if (this._lookahead(0) === TOK_COLON) {
4013
3822
  return this._parseSliceExpression();
4014
3823
  }
4015
- // look ahead of the first expression to determine the type
4016
3824
  const first = this.expression(0);
4017
3825
  const token = this._lookahead(0);
4018
3826
  if (token === TOK_COLON) {
4019
- // now that we know the type revert back to the old position and parse
4020
3827
  this._setIndex(oldIndex);
4021
3828
  return this._parseSliceExpression();
4022
3829
  }
@@ -4026,7 +3833,6 @@ class Parser {
4026
3833
  value: first,
4027
3834
  };
4028
3835
  }
4029
-
4030
3836
  _parseUnchainedIndexExpression() {
4031
3837
  const oldIndex = this._getIndex();
4032
3838
  const firstToken = this._lookahead(0);
@@ -4055,7 +3861,6 @@ class Parser {
4055
3861
  this._setIndex(oldIndex);
4056
3862
  return this._parseMultiselectList();
4057
3863
  }
4058
-
4059
3864
  _projectIfSlice(left, right) {
4060
3865
  const indexExpr = { type: 'IndexExpression', children: [left, right] };
4061
3866
  if (right.type === 'Slice') {
@@ -4066,20 +3871,16 @@ class Parser {
4066
3871
  }
4067
3872
  return indexExpr;
4068
3873
  }
4069
-
4070
3874
  _parseSliceExpression() {
4071
- // [start:end:step] where each part is optional, as well as the last
4072
- // colon.
4073
3875
  const parts = [null, null, null];
4074
3876
  let index = 0;
4075
3877
  let currentToken = this._lookahead(0);
4076
3878
  while (currentToken !== TOK_RBRACKET && index < 3) {
4077
- if (currentToken === TOK_COLON && index < 2) { // there can't be more than 2 colons
3879
+ if (currentToken === TOK_COLON && index < 2) {
4078
3880
  index += 1;
4079
3881
  this._advance();
4080
3882
  } else {
4081
3883
  parts[index] = this.expression(0);
4082
- // check next token to be either colon or rbracket
4083
3884
  const t = this._lookahead(0);
4084
3885
  if (t !== TOK_COLON && t !== TOK_RBRACKET) {
4085
3886
  const error = new Error(`Syntax error, unexpected token: ${
@@ -4096,13 +3897,10 @@ class Parser {
4096
3897
  children: parts,
4097
3898
  };
4098
3899
  }
4099
-
4100
3900
  _parseComparator(left, comparator) {
4101
3901
  const right = this.expression(bindingPower[comparator]);
4102
3902
  return { type: 'Comparator', name: comparator, children: [left, right] };
4103
3903
  }
4104
-
4105
- // eslint-disable-next-line consistent-return
4106
3904
  _parseDotRHS(rbp) {
4107
3905
  const lookahead = this._lookahead(0);
4108
3906
  const exprTokens = [TOK_UNQUOTEDIDENTIFIER, TOK_QUOTEDIDENTIFIER, TOK_STAR];
@@ -4118,7 +3916,6 @@ class Parser {
4118
3916
  return this._parseMultiselectHash();
4119
3917
  }
4120
3918
  }
4121
-
4122
3919
  _parseProjectionRHS(rbp) {
4123
3920
  let right;
4124
3921
  if (bindingPower[this._lookahead(0)] < 10) {
@@ -4139,7 +3936,6 @@ class Parser {
4139
3936
  }
4140
3937
  return right;
4141
3938
  }
4142
-
4143
3939
  _parseMultiselectList() {
4144
3940
  const expressions = [];
4145
3941
  while (this._lookahead(0) !== TOK_RBRACKET) {
@@ -4155,7 +3951,6 @@ class Parser {
4155
3951
  this._match(TOK_RBRACKET);
4156
3952
  return { type: 'MultiSelectList', children: expressions };
4157
3953
  }
4158
-
4159
3954
  _parseMultiselectHash() {
4160
3955
  const pairs = [];
4161
3956
  const identifierTypes = [TOK_UNQUOTEDIDENTIFIER, TOK_QUOTEDIDENTIFIER];
@@ -4188,20 +3983,6 @@ class Parser {
4188
3983
  }
4189
3984
  }
4190
3985
 
4191
- /*
4192
- Copyright 2021 Adobe. All rights reserved.
4193
- This file is licensed to you under the Apache License, Version 2.0 (the "License");
4194
- you may not use this file except in compliance with the License. You may obtain a copy
4195
- of the License at http://www.apache.org/licenses/LICENSE-2.0
4196
-
4197
- Unless required by applicable law or agreed to in writing, software distributed under
4198
- the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
4199
- OF ANY KIND, either express or implied. See the License for the specific language
4200
- governing permissions and limitations under the License.
4201
- */
4202
-
4203
- // get the offset in MS, given a date and timezone
4204
- // timezone is an IANA name. e.g. 'America/New_York'
4205
3986
  function offsetMS(dateObj, timeZone) {
4206
3987
  const tzOffset = new Intl.DateTimeFormat('en-US', { timeZone, timeZoneName: 'longOffset' }).format(dateObj);
4207
3988
  const offset = /GMT([+\-−])?(\d{1,2}):?(\d{0,2})?/.exec(tzOffset);
@@ -4210,16 +3991,11 @@ function offsetMS(dateObj, timeZone) {
4210
3991
  const result = (((hours || 0) * 60) + 1 * (minutes || 0)) * 60 * 1000;
4211
3992
  return sign === '-' ? result * -1 : result;
4212
3993
  }
4213
-
4214
3994
  function round(num, digits) {
4215
3995
  const precision = 10 ** digits;
4216
3996
  return Math.round(num * precision) / precision;
4217
3997
  }
4218
-
4219
3998
  const MS_IN_DAY = 24 * 60 * 60 * 1000;
4220
-
4221
- // If we create a non-UTC date, then we need to adjust from the default JavaScript timezone
4222
- // to the default timezone
4223
3999
  function adjustTimeZone(dateObj, timeZone) {
4224
4000
  if (dateObj === null) return null;
4225
4001
  let baseDate = Date.UTC(
@@ -4232,32 +4008,10 @@ function adjustTimeZone(dateObj, timeZone) {
4232
4008
  dateObj.getMilliseconds(),
4233
4009
  );
4234
4010
  baseDate += offsetMS(dateObj, timeZone);
4235
-
4236
- // get the offset for the default JS environment
4237
- // return days since the epoch
4238
4011
  return new Date(baseDate);
4239
4012
  }
4240
-
4241
4013
  function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4242
4014
  return {
4243
- /**
4244
- * Returns the logical AND result of all parameters.
4245
- * If the parameters are not boolean they will be cast to boolean as per the following rules
4246
- * * null -> false
4247
- * * number -> false if the number is 0, true otherwise
4248
- * * string -> false if the string is empty, true otherwise. String "false" resolves to true
4249
- * * array -> true
4250
- * * object -> true
4251
- * @param {any} firstOperand logical expression
4252
- * @param {...any} [additionalOperands] any number of additional expressions
4253
- * @returns {boolean} The logical result of applying AND to all parameters
4254
- * @example
4255
- * and(10 > 8, length('foo') < 5) // returns true
4256
- * @example
4257
- * and(`null`, length('foo') < 5) // returns false
4258
- * @function
4259
- * @category openFormula
4260
- */
4261
4015
  and: {
4262
4016
  _func: resolvedArgs => {
4263
4017
  let result = !!valueOf(resolvedArgs[0]);
@@ -4268,17 +4022,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4268
4022
  },
4269
4023
  _signature: [{ types: [dataTypes.TYPE_ANY], variadic: true }],
4270
4024
  },
4271
-
4272
- /**
4273
- * Returns a lower-case string of the `input` string using locale-specific mappings.
4274
- * e.g. Strings with German lowercase letter 'ß' can be compared to 'ss'
4275
- * @param {string} input string to casefold
4276
- * @returns {string} A new string converted to lower case
4277
- * @function casefold
4278
- * @example
4279
- * casefold('AbC') // returns 'abc'
4280
- * @category JSONFormula
4281
- */
4282
4025
  casefold: {
4283
4026
  _func: (args, _data, interpreter) => {
4284
4027
  const str = toString(args[0]);
@@ -4288,34 +4031,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4288
4031
  { types: [dataTypes.TYPE_STRING] },
4289
4032
  ],
4290
4033
  },
4291
-
4292
- /**
4293
- * Return difference between two date values.
4294
- * @param {number} start_date The starting date.
4295
- * Dates should be entered by using the [datetime]{@link datetime} function
4296
- * @param {number} end_date The end date -- must be greater or equal to start_date.
4297
- * Dates should be entered by using the [datetime]{@link datetime} function
4298
- * @param {string} unit One of:
4299
- * * `y` the number of whole years between start_date and end_date
4300
- * * `m` the number of whole months between start_date and end_date.
4301
- * * `d` the number of days between start_date and end_date
4302
- * * `md` the number of days between start_date and end_date after subtracting whole months.
4303
- * * `ym` the number of whole months between start_date and end_date
4304
- * after subtracting whole years.
4305
- * * `yd` the number of days between start_date and end_date, assuming start_date
4306
- * and end_date were no more than one year apart
4307
- * @returns {integer} The number of days/months/years difference
4308
- * @function
4309
- * @category openFormula
4310
- * @example
4311
- * datedif(datetime(2001, 1, 1), datetime(2003, 1, 1), 'y') // returns 2
4312
- * @example
4313
- * datedif(datetime(2001, 6, 1), datetime(2003, 8, 15), 'D') // returns 440
4314
- * // 440 days between June 1, 2001, and August 15, 2002 (440)
4315
- * @example
4316
- * datedif(datetime(2001, 6, 1), datetime(2003, 8, 15), 'YD') // returns 440
4317
- * // 75 days between June 1 and August 15, ignoring the years of the dates (75)
4318
- */
4319
4034
  datedif: {
4320
4035
  _func: args => {
4321
4036
  const d1 = toNumber(args[0]);
@@ -4329,7 +4044,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4329
4044
  const yearDiff = date2.getFullYear() - date1.getFullYear();
4330
4045
  let monthDiff = date2.getMonth() - date1.getMonth();
4331
4046
  const dayDiff = date2.getDate() - date1.getDate();
4332
-
4333
4047
  if (unit === 'y') {
4334
4048
  let y = yearDiff;
4335
4049
  if (monthDiff < 0) y -= 1;
@@ -4358,32 +4072,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4358
4072
  { types: [dataTypes.TYPE_STRING] },
4359
4073
  ],
4360
4074
  },
4361
-
4362
- /**
4363
- * Return a date/time value.
4364
- * @param {integer} year Integer value representing the year.
4365
- * Values from 0 to 99 map to the years 1900 to 1999. All other values are the actual year
4366
- * @param {integer} month Integer value representing the month, beginning with 1 for
4367
- * January to 12 for December.
4368
- * @param {integer} day Integer value representing the day of the month.
4369
- * @param {integer} [hours] Integer value between 0 and 23 representing the hour of the day.
4370
- * Defaults to 0.
4371
- * @param {integer} [minutes] Integer value representing the minute segment of a time.
4372
- * The default is 0 minutes past the hour.
4373
- * @param {integer} [seconds] Integer value representing the second segment of a time.
4374
- * The default is 0 seconds past the minute.
4375
- * @param {integer} [milliseconds] Integer value representing the millisecond segment of a time.
4376
- * The default is 0 milliseconds past the second.
4377
- * @param {string} [timeZoneName] according to IANA time zone names. e.g. "America/Toronto"
4378
- * @returns {number} A date/time value represented by number of seconds since 1 January 1970.
4379
- * @kind function
4380
- * @function
4381
- * @category JSONFormula
4382
- * @example
4383
- * datetime(2010, 10, 10) // returns representation of October 10, 2010
4384
- * @example
4385
- * datetime(2010, 2, 28) // returns representation of February 28, 2010
4386
- */
4387
4075
  datetime: {
4388
4076
  _func: args => {
4389
4077
  const year = toNumber(args[0]);
@@ -4394,7 +4082,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4394
4082
  const seconds = args.length > 5 ? toNumber(args[5]) : 0;
4395
4083
  const ms = args.length > 6 ? toNumber(args[6]) : 0;
4396
4084
  const tz = args.length > 7 ? toString(args[7]) : null;
4397
- // javascript months starts from 0
4398
4085
  let jsDate = new Date(year, month - 1, day, hours, minutes, seconds, ms);
4399
4086
  if (tz) {
4400
4087
  jsDate = adjustTimeZone(jsDate, tz);
@@ -4412,18 +4099,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4412
4099
  { types: [dataTypes.TYPE_STRING], optional: true },
4413
4100
  ],
4414
4101
  },
4415
-
4416
- /**
4417
- * Returns the day of a date, represented by a serial number.
4418
- * The day is given as an integer ranging from 1 to 31.
4419
- * @param {number} The date of the day you are trying to find.
4420
- * Dates should be entered by using the [datetime]{@link datetime} function
4421
- * @return {number}
4422
- * @function day
4423
- * @category openFormula
4424
- * @example
4425
- * day(datetime(2008,5,23)) //returns 23
4426
- */
4427
4102
  day: {
4428
4103
  _func: args => {
4429
4104
  const date = toNumber(args[0]);
@@ -4434,19 +4109,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4434
4109
  { types: [dataTypes.TYPE_NUMBER] },
4435
4110
  ],
4436
4111
  },
4437
-
4438
- /**
4439
- * Searches a nested hierarchy of objects to return an array of elements that match a `name`.
4440
- * The name can be either a key into a map or an array index.
4441
- * This is similar to the JSONPath deep scan operator (..)
4442
- * @param {object} object The starting object or array where we start the search
4443
- * @param {string} name The name (or index position) of the elements to find
4444
- * @returns {any}
4445
- * @function
4446
- * @category JSONFormula
4447
- * @example
4448
- * deepScan({a : {b1 : {c : 2}, b2 : {c : 3}}}, 'c') //returns [2, 3]
4449
- */
4450
4112
  deepScan: {
4451
4113
  _func: resolvedArgs => {
4452
4114
  const [source, n] = resolvedArgs;
@@ -4467,16 +4129,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4467
4129
  { types: [dataTypes.TYPE_STRING, dataTypes.TYPE_NUMBER] },
4468
4130
  ],
4469
4131
  },
4470
-
4471
- /**
4472
- * returns an array of a given object's property `[key, value]` pairs.
4473
- * @param {object} obj Object whose `[key, value]` pairs need to be extracted
4474
- * @returns {any[]} an array of [key, value] pairs
4475
- * @function entries
4476
- * @category JSONFormula
4477
- * @example
4478
- * entries({a: 1, b: 2}) //returns [['a', 1], ['b', 2]]
4479
- */
4480
4132
  entries: {
4481
4133
  _func: args => {
4482
4134
  const obj = valueOf(args[0]);
@@ -4494,27 +4146,11 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4494
4146
  },
4495
4147
  ],
4496
4148
  },
4497
-
4498
- /**
4499
- * Returns the serial number of the end of a month, given `startDate` plus `monthAdd` months
4500
- * @param {number} startDate The base date to start from.
4501
- * Dates should be entered by using the [datetime]{@link datetime} function
4502
- * @param {integer} monthAdd Number of months to add to start date
4503
- * @return {integer} the number of days in the computed month
4504
- * @function
4505
- * @category openFormula
4506
- * @example
4507
- * eomonth(datetime(2011, 1, 1), 1) //returns datetime(2011, 2, 28)
4508
- * @example
4509
- * eomonth(datetime(2011, 1, 1), -3) //returns datetime(2010, 10, 31)
4510
- */
4511
4149
  eomonth: {
4512
4150
  _func: args => {
4513
4151
  const date = toNumber(args[0]);
4514
4152
  const months = toNumber(args[1]);
4515
4153
  const jsDate = new Date(date * MS_IN_DAY);
4516
- // We can give the constructor a month value > 11 and it will increment the years
4517
- // Since day is 1-based, giving zero will yield the last day of the previous month
4518
4154
  const newDate = new Date(jsDate.getFullYear(), jsDate.getMonth() + months + 1, 0);
4519
4155
  return newDate.getTime() / MS_IN_DAY;
4520
4156
  },
@@ -4523,16 +4159,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4523
4159
  { types: [dataTypes.TYPE_NUMBER] },
4524
4160
  ],
4525
4161
  },
4526
-
4527
- /**
4528
- * Returns e (the base of natural logarithms) raised to a power x. (i.e. e<sup>x</sup>)
4529
- * @param x {number} A numeric expression representing the power of e.
4530
- * @returns {number} e (the base of natural logarithms) raised to a power x
4531
- * @function exp
4532
- * @category openFormula
4533
- * @example
4534
- * exp(10) //returns e^10
4535
- */
4536
4162
  exp: {
4537
4163
  _func: args => {
4538
4164
  const value = toNumber(args[0]);
@@ -4542,37 +4168,10 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4542
4168
  { types: [dataTypes.TYPE_NUMBER] },
4543
4169
  ],
4544
4170
  },
4545
-
4546
- /**
4547
- * Return constant boolean false value.
4548
- * Note that expressions may also use the JSON literal false: `` `false` ``
4549
- * @returns {boolean} constant boolean value `false`
4550
- * @function
4551
- * @category openFormula
4552
- */
4553
4171
  false: {
4554
4172
  _func: () => false,
4555
4173
  _signature: [],
4556
4174
  },
4557
-
4558
- /**
4559
- * finds and returns the index of query in text from a start position
4560
- * @param {string} query string to search
4561
- * @param {string} text text in which the query has to be searched
4562
- * @param {number} [start] starting position: defaults to 0
4563
- * @returns {number|null} the index of the query to be searched in the text. If not found
4564
- * returns null
4565
- * @function
4566
- * @category openFormula
4567
- * @example
4568
- * find('m', 'abm') //returns 2
4569
- * @example
4570
- * find('M', 'abMcdM', 3) //returns 2
4571
- * @example
4572
- * find('M', 'ab') //returns `null`
4573
- * @example
4574
- * find('M', 'abMcdM', 2) //returns 2
4575
- */
4576
4175
  find: {
4577
4176
  _func: args => {
4578
4177
  const query = toString(args[0]);
@@ -4590,16 +4189,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4590
4189
  { types: [dataTypes.TYPE_NUMBER], optional: true },
4591
4190
  ],
4592
4191
  },
4593
-
4594
- /**
4595
- * returns an object by transforming a list of key-value `pairs` into an object.
4596
- * @param {any[]} pairs list of key-value pairs to create the object from
4597
- * @returns {object}
4598
- * @category JSONFormula
4599
- * @function fromEntries
4600
- * @example
4601
- * fromEntries([['a', 1], ['b', 2]]) //returns {a: 1, b: 2}
4602
- */
4603
4192
  fromEntries: {
4604
4193
  _func: args => {
4605
4194
  const array = args[0];
@@ -4609,51 +4198,19 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4609
4198
  { types: [dataTypes.TYPE_ARRAY_ARRAY] },
4610
4199
  ],
4611
4200
  },
4612
-
4613
- /**
4614
- * Extract the hour (0 through 23) from a time/datetime representation
4615
- * @param {number} The datetime/time for which the hour is to be returned.
4616
- * Dates should be specified using the [datetime]{@link datetime} or [time]{@link time} function
4617
- * @return {number}
4618
- * @function hour
4619
- * @category openFormula
4620
- * @example
4621
- * hour(datetime(2008,5,23,12, 0, 0)) //returns 12
4622
- * hour(time(12, 0, 0)) //returns 12
4623
- */
4624
4201
  hour: {
4625
4202
  _func: args => {
4626
- // grab just the fraction part
4627
4203
  const time = toNumber(args[0]) % 1;
4628
4204
  if (time < 0) {
4629
4205
  return null;
4630
4206
  }
4631
- // Normally we'd round to 15 digits, but since we're also multiplying by 24,
4632
- // a reasonable precision is around 14 digits.
4633
-
4634
4207
  const hour = round(time * 24, 14);
4635
-
4636
4208
  return Math.floor(hour % 24);
4637
4209
  },
4638
4210
  _signature: [
4639
4211
  { types: [dataTypes.TYPE_NUMBER] },
4640
4212
  ],
4641
4213
  },
4642
-
4643
- /**
4644
- * Return one of two values `result1` or `result2`, depending on the `condition`
4645
- * @returns {boolean} True
4646
- * @param {any} condition logical expression to evaluate
4647
- * @param {any} result1 if logical condition is true
4648
- * @param {any} result2 if logical condition is false
4649
- * @return {any} either result1 or result2
4650
- * @function
4651
- * @category openFormula
4652
- * @example
4653
- * if(true(), 1, 2) // returns 1
4654
- * @example
4655
- * if(false(), 1, 2) // returns 2
4656
- */
4657
4214
  if: {
4658
4215
  _func: (unresolvedArgs, data, interpreter) => {
4659
4216
  const conditionNode = unresolvedArgs[0];
@@ -4670,22 +4227,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4670
4227
  { types: [dataTypes.TYPE_ANY] },
4671
4228
  { types: [dataTypes.TYPE_ANY] }],
4672
4229
  },
4673
-
4674
- /**
4675
- * Return a selected number of text characters from the left or
4676
- * in case of array selected number of elements from the start
4677
- * @param {string|array} subject The text/array of characters/elements to extract.
4678
- * @param {number} [elements] number of elements to pick. Defaults to 1
4679
- * @return {string|array}
4680
- * @function left
4681
- * @category openFormula
4682
- * @example
4683
- * left('Sale Price', 4) //returns 'Sale'
4684
- * @example
4685
- * left('Sweden') // returns 'S'
4686
- * @example
4687
- * left([4, 5, 6], 2) // returns [4, 5]
4688
- */
4689
4230
  left: {
4690
4231
  _func: args => {
4691
4232
  const numEntries = args.length > 1 ? toNumber(args[1]) : 1;
@@ -4701,18 +4242,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4701
4242
  { types: [dataTypes.TYPE_NUMBER], optional: true },
4702
4243
  ],
4703
4244
  },
4704
-
4705
- /**
4706
- * Converts all the alphabetic characters in a string to lowercase. If the value
4707
- * is not a string it will be converted into string
4708
- * using the default toString method
4709
- * @param {string} input input string
4710
- * @returns {string} the lower case value of the input string
4711
- * @function lower
4712
- * @category openFormula
4713
- * @example
4714
- * lower('E. E. Cummings') //returns e. e. cummings
4715
- */
4716
4245
  lower: {
4717
4246
  _func: args => {
4718
4247
  const value = toString(args[0]);
@@ -4722,27 +4251,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4722
4251
  { types: [dataTypes.TYPE_STRING] },
4723
4252
  ],
4724
4253
  },
4725
-
4726
- /**
4727
- * Returns extracted text, given an original text, starting position, and length.
4728
- * or in case of array, extracts a subset of the array from start till the length
4729
- * number of elements.
4730
- * Returns null if the `startPos` is greater than the length of the array
4731
- * @param {string|array} subject the text string or array of characters or elements to extract.
4732
- * @param {number} startPos the position of the first character or element to extract.
4733
- * The position starts with 0
4734
- * @param {number} length The number of characters or elements to return from text. If it
4735
- * is greater then the length of `subject` the argument is set to the length of the subject.
4736
- * @return {string|array}
4737
- * @function mid
4738
- * @category openFormula
4739
- * @example
4740
- * mid("Fluid Flow",1,5) //returns 'Fluid'
4741
- * @example
4742
- * mid("Fluid Flow",7,20) //returns 'Flow'
4743
- * @example
4744
- * mid("Fluid Flow",20,5) //returns `null`
4745
- */
4746
4254
  mid: {
4747
4255
  _func: args => {
4748
4256
  const startPos = toNumber(args[1]);
@@ -4760,27 +4268,12 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4760
4268
  { types: [dataTypes.TYPE_NUMBER] },
4761
4269
  ],
4762
4270
  },
4763
-
4764
- /**
4765
- * Extract the minute (0 through 59) from a time/datetime representation
4766
- * @param {number} The datetime/time for which the minute is to be returned.
4767
- * Dates should be specified using the [datetime]{@link datetime} or [time]{@link time} function
4768
- * @return {number}
4769
- * @function minute
4770
- * @category openFormula
4771
- * @example
4772
- * month(datetime(2008,5,23,12, 10, 0)) //returns 10
4773
- * month(time(12, 10, 0)) //returns 10
4774
- */
4775
4271
  minute: {
4776
4272
  _func: args => {
4777
4273
  const time = toNumber(args[0]) % 1;
4778
4274
  if (time < 0) {
4779
4275
  return null;
4780
4276
  }
4781
-
4782
- // Normally we'd round to 15 digits, but since we're also multiplying by 1440,
4783
- // a reasonable precision is around 10 digits.
4784
4277
  const minute = Math.round(time * 1440, 10);
4785
4278
  return Math.floor(minute % 60);
4786
4279
  },
@@ -4788,20 +4281,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4788
4281
  { types: [dataTypes.TYPE_NUMBER] },
4789
4282
  ],
4790
4283
  },
4791
-
4792
- /**
4793
- * Return the remainder when one number is divided by another number.
4794
- * The sign is the same as divisor
4795
- * @param {number} dividend The number for which to find the remainder.
4796
- * @param {number} divisor The number by which to divide number.
4797
- * @return {number} Computes the remainder of `dividend`/`divisor`.
4798
- * @function mod
4799
- * @category openFormula
4800
- * @example
4801
- * mod(3, 2) //returns 1
4802
- * @example
4803
- * mod(-3, 2) //returns 1
4804
- */
4805
4284
  mod: {
4806
4285
  _func: args => {
4807
4286
  const p1 = toNumber(args[0]);
@@ -4813,97 +4292,28 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4813
4292
  { types: [dataTypes.TYPE_NUMBER] },
4814
4293
  ],
4815
4294
  },
4816
-
4817
- /**
4818
- * Returns the month of a date represented by a serial number.
4819
- * The month is given as an integer, ranging from 1 (January) to 12 (December).
4820
- * @param {number} The date for which the month is to be returned.
4821
- * Dates should be entered by using the [datetime]{@link datetime} function
4822
- * @return {number}
4823
- * @function month
4824
- * @category openFormula
4825
- * @example
4826
- * month(datetime(2008,5,23)) //returns 5
4827
- */
4828
4295
  month: {
4829
4296
  _func: args => {
4830
4297
  const date = toNumber(args[0]);
4831
4298
  const jsDate = new Date(date * MS_IN_DAY);
4832
- // javascript months start from 0ß
4833
4299
  return jsDate.getMonth() + 1;
4834
4300
  },
4835
4301
  _signature: [
4836
4302
  { types: [dataTypes.TYPE_NUMBER] },
4837
4303
  ],
4838
4304
  },
4839
-
4840
- /**
4841
- * Compute logical NOT of a `value`. If the parameter is not boolean it will be cast to boolean
4842
- * as per the following rules
4843
- * * null -> false
4844
- * * number -> false if the number is 0, true otherwise
4845
- * * string -> false if the string is empty, true otherwise. String "false" resolves to true
4846
- * * array -> true
4847
- * * object -> true
4848
- * Note that it is also possible to use the logical and operator: `A && B`
4849
- * @param {any} value - any data type
4850
- * @returns {boolean} The logical NOT applied to the input parameter
4851
- * @example
4852
- * not(length('bar') > 0) // returns false
4853
- * @example
4854
- * not(false()) // returns true
4855
- * @example
4856
- * not('abcd') // returns false
4857
- * @example
4858
- * not('') // returns true
4859
- * @function
4860
- * @category openFormula
4861
- */
4862
4305
  not: {
4863
4306
  _func: resolveArgs => !valueOf(resolveArgs[0]),
4864
4307
  _signature: [{ types: [dataTypes.TYPE_ANY] }],
4865
4308
  },
4866
-
4867
- /**
4868
- * returns the time since epoch with days as exponent and time of day as fraction
4869
- * @return {number} representation of current time as a number
4870
- * @function now
4871
- * @category openFormula
4872
- */
4873
4309
  now: {
4874
4310
  _func: () => Date.now() / MS_IN_DAY,
4875
4311
  _signature: [],
4876
4312
  },
4877
-
4878
- /**
4879
- * Return constant null value.
4880
- * Note that expressions may also use the JSON literal null: `` `null` ``
4881
- * @returns {boolean} True
4882
- * @function
4883
- * @category JSONFormula
4884
- */
4885
4313
  null: {
4886
4314
  _func: () => null,
4887
4315
  _signature: [],
4888
4316
  },
4889
-
4890
- /**
4891
- * Returns the logical OR result of two parameters.
4892
- * If the parameters are not boolean they will be cast to boolean as per the following rules
4893
- * * null -> false
4894
- * * number -> false if the number is 0, true otherwise
4895
- * * string -> false if the string is empty, true otherwise. String "false" resolves to true
4896
- * * array -> true
4897
- * * object -> true
4898
- * @param {any} first logical expression
4899
- * @param {...any} [operand] any number of additional expressions
4900
- * @returns {boolean} The logical result of applying OR to all parameters
4901
- * @example
4902
- * or((x / 2) == y, (y * 2) == x)
4903
- * // true
4904
- * @function
4905
- * @category openFormula
4906
- */
4907
4317
  or: {
4908
4318
  _func: resolvedArgs => {
4909
4319
  let result = !!valueOf(resolvedArgs[0]);
@@ -4914,17 +4324,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4914
4324
  },
4915
4325
  _signature: [{ types: [dataTypes.TYPE_ANY], variadic: true }],
4916
4326
  },
4917
-
4918
- /**
4919
- * Computes `a` raised to a power `x`. (a<sup>x</sup>)
4920
- * @param {number} a The base number. It can be any real number.
4921
- * @param {number} x The exponent to which the base number is raised.
4922
- * @return {number}
4923
- * @function power
4924
- * @category openFormula
4925
- * @example
4926
- * power(10, 2) //returns 100 (10 raised to power 2)
4927
- */
4928
4327
  power: {
4929
4328
  _func: args => {
4930
4329
  const base = toNumber(args[0]);
@@ -4936,21 +4335,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4936
4335
  { types: [dataTypes.TYPE_NUMBER] },
4937
4336
  ],
4938
4337
  },
4939
-
4940
- /**
4941
- * Return the input string with the first letter of each word converted to an
4942
- * uppercase letter and the rest of the letters in the word converted to lowercase.
4943
- * @param {string} text the text to partially capitalize.
4944
- * @returns {string}
4945
- * @function proper
4946
- * @category openFormula
4947
- * @example
4948
- * proper('this is a TITLE') //returns 'This Is A Title'
4949
- * @example
4950
- * proper('2-way street') //returns '2-Way Street'
4951
- * @example
4952
- * proper('76BudGet') //returns '76Budget'
4953
- */
4954
4338
  proper: {
4955
4339
  _func: args => {
4956
4340
  const text = toString(args[0]);
@@ -4963,24 +4347,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4963
4347
  { types: [dataTypes.TYPE_STRING] },
4964
4348
  ],
4965
4349
  },
4966
-
4967
- /**
4968
- * Returns text where an old text is substituted at a given start position and
4969
- * length, with a new text.
4970
- * @param {string} text original text
4971
- * @param {number} start index in the original text from where to begin the replacement.
4972
- * @param {number} length number of characters to be replaced
4973
- * @param {string} replacement string to replace at the start index
4974
- * @returns {string}
4975
- * @function replace
4976
- * @category openFormula
4977
- * @example
4978
- * replace('abcdefghijk', 6, 5, '*') //returns abcde*k
4979
- * @example
4980
- * replace('2009',3,2,'10') //returns 2010
4981
- * @example
4982
- * replace('123456',1,3,'@') //returns @456
4983
- */
4984
4350
  replace: {
4985
4351
  _func: args => {
4986
4352
  const oldText = toString(args[0]);
@@ -4990,7 +4356,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
4990
4356
  if (startNum < 0) {
4991
4357
  return null;
4992
4358
  }
4993
-
4994
4359
  const lhs = oldText.substr(0, startNum);
4995
4360
  const rhs = oldText.substr(startNum + numChars);
4996
4361
  return lhs + newText + rhs;
@@ -5002,17 +4367,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5002
4367
  { types: [dataTypes.TYPE_STRING] },
5003
4368
  ],
5004
4369
  },
5005
-
5006
- /**
5007
- * Return text repeated Count times.
5008
- * @param {string} text text to repeat
5009
- * @param {number} count number of times to repeat the text
5010
- * @returns {string}
5011
- * @function rept
5012
- * @category openFormula
5013
- * @example
5014
- * rept('x', 5) //returns 'xxxxx'
5015
- */
5016
4370
  rept: {
5017
4371
  _func: args => {
5018
4372
  const text = toString(args[0]);
@@ -5027,23 +4381,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5027
4381
  { types: [dataTypes.TYPE_NUMBER] },
5028
4382
  ],
5029
4383
  },
5030
-
5031
- /**
5032
- * Return a selected number of text characters from the right of a `subject` or
5033
- * in case of array selected number of elements from the end of `subject` array
5034
- * Returns null if the number of elements is less than 0
5035
- * @param {string|array} subject The text/array containing the characters/elements to extract.
5036
- * @param {number} [elements] number of elements to pick. Defaults to 1
5037
- * @return {string|array}
5038
- * @function right
5039
- * @category openFormula
5040
- * @example
5041
- * right('Sale Price', 4) //returns 'rice'
5042
- * @example
5043
- * left('Sweden') // returns 'n'
5044
- * @example
5045
- * left([4, 5, 6], 2) // returns [5, 6]
5046
- */
5047
4384
  right: {
5048
4385
  _func: args => {
5049
4386
  const numEntries = args.length > 1 ? toNumber(args[1]) : 1;
@@ -5061,29 +4398,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5061
4398
  { types: [dataTypes.TYPE_NUMBER], optional: true },
5062
4399
  ],
5063
4400
  },
5064
-
5065
- /**
5066
- * Round a number to a specified `precision`.
5067
- * ### Remarks
5068
- * * If `precision` is greater than zero, round to the specified number of decimal places.
5069
- * * If `precision` is 0, round to the nearest integer.
5070
- * * If `precision` is less than 0, round to the left of the decimal point.
5071
- * @param {number} num number to round off
5072
- * @param {number} precision number is rounded to the specified precision.
5073
- * @returns {number}
5074
- * @function round
5075
- * @category openFormula
5076
- * @example
5077
- * round(2.15, 1) //returns 2.2
5078
- * @example
5079
- * round(626.3,-3) //returns 1000 (Rounds 626.3 to the nearest multiple of 1000)
5080
- * @example
5081
- * round(626.3, 0) //returns 626
5082
- * @example
5083
- * round(1.98,-1) //returns 0 (Rounds 1.98 to the nearest multiple of 10)
5084
- * @example
5085
- * round(-50.55,-2) // -100 (round -50.55 to the nearest multiple of 100)
5086
- */
5087
4401
  round: {
5088
4402
  _func: args => {
5089
4403
  const number = toNumber(args[0]);
@@ -5095,38 +4409,15 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5095
4409
  { types: [dataTypes.TYPE_NUMBER] },
5096
4410
  ],
5097
4411
  },
5098
-
5099
- /**
5100
- * Perform a wildcard search. The search is case-sensitive and supports two forms of wildcards:
5101
- * "*" finds a a sequence of characters and "?" finds a single character.
5102
- * To use "*" or "?" as text values, precede them with a tilde ("~") character.
5103
- * Note that the wildcard search is not greedy.
5104
- * e.g. search('a*b', 'abb') will return [0, 'ab'] Not [0, 'abb']
5105
- * @param {string} findText the search string -- which may include wild cards.
5106
- * @param {string} withinText The string to search.
5107
- * @param {integer} startPos The zero-based position of withinText to start searching.
5108
- * Defaults to zero.
5109
- * @returns {array} returns an array with two values:
5110
- * The start position of the found text and the text string that was found.
5111
- * If a match was not found, an empty array is returned.
5112
- * @function search
5113
- * @category openFormula
5114
- * @example
5115
- * search('a?c', 'acabc') //returns [2, 'abc']
5116
- */
5117
4412
  search: {
5118
4413
  _func: args => {
5119
4414
  const findText = toString(args[0]);
5120
4415
  const withinText = toString(args[1]);
5121
4416
  const startPos = toNumber(args[2]);
5122
4417
  if (findText === null || withinText === null || withinText.length === 0) return [];
5123
- // escape all characters that would otherwise create a regular expression
5124
4418
  const reString = findText.replace(/([[.\\^$()+{])/g, '\\$1')
5125
- // add the single character wildcard
5126
4419
  .replace(/~?\?/g, match => match === '~?' ? '\\?' : '.')
5127
- // add the multi-character wildcard
5128
4420
  .replace(/~?\*/g, match => match === '~*' ? '\\*' : '.*?')
5129
- // get rid of the escape characters
5130
4421
  .replace(/~~/g, '~');
5131
4422
  const re = new RegExp(reString);
5132
4423
  const result = withinText.substring(startPos).match(re);
@@ -5138,28 +4429,13 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5138
4429
  { types: [dataTypes.TYPE_STRING] },
5139
4430
  { types: [dataTypes.TYPE_NUMBER], optional: true },
5140
4431
  ],
5141
-
5142
4432
  },
5143
- /**
5144
- * Extract the second (0 through 59) from a time/datetime representation
5145
- * @param {number} The datetime/time for which the second is to be returned.
5146
- * Dates should be specified using the [datetime]{@link datetime} or [time]{@link time} function
5147
- * @return {number}
5148
- * @function second
5149
- * @category openFormula
5150
- * @example
5151
- * second(datetime(2008,5,23,12, 10, 53)) //returns 53
5152
- * second(time(12, 10, 53)) //returns 53
5153
- */
5154
4433
  second: {
5155
4434
  _func: args => {
5156
4435
  const time = toNumber(args[0]) % 1;
5157
4436
  if (time < 0) {
5158
4437
  return null;
5159
4438
  }
5160
-
5161
- // Normally we'd round to 15 digits, but since we're also multiplying by 86400,
5162
- // a reasonable precision is around 10 digits.
5163
4439
  const seconds = round(time * 86400, 10);
5164
4440
  return Math.floor(seconds % 60);
5165
4441
  },
@@ -5167,19 +4443,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5167
4443
  { types: [dataTypes.TYPE_NUMBER] },
5168
4444
  ],
5169
4445
  },
5170
-
5171
- /**
5172
- * split a string into an array, given a separator
5173
- * @param {string} string string to split
5174
- * @param {string} separator separator where the split should occur
5175
- * @return {string[]}
5176
- * @function split
5177
- * @category openFormula
5178
- * @example
5179
- * split('abcdef', '') //returns ['a', 'b', 'c', 'd', 'e', 'f']
5180
- * @example
5181
- * split('abcdef', 'e') //returns ['abcd', 'f']
5182
- */
5183
4446
  split: {
5184
4447
  _func: args => {
5185
4448
  const str = toString(args[0]);
@@ -5191,16 +4454,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5191
4454
  { types: [dataTypes.TYPE_STRING] },
5192
4455
  ],
5193
4456
  },
5194
-
5195
- /**
5196
- * Return the square root of a number
5197
- * @param {number} num number whose square root has to be calculated
5198
- * @return {number}
5199
- * @function sqrt
5200
- * @category openFormula
5201
- * @example
5202
- * sqrt(4) //returns 2
5203
- */
5204
4457
  sqrt: {
5205
4458
  _func: args => {
5206
4459
  const result = Math.sqrt(toNumber(args[0]));
@@ -5213,20 +4466,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5213
4466
  { types: [dataTypes.TYPE_NUMBER] },
5214
4467
  ],
5215
4468
  },
5216
-
5217
- /**
5218
- * Estimates standard deviation based on a sample.
5219
- * `stdev` assumes that its arguments are a sample of the entire population.
5220
- * If your data represents a entire population,
5221
- * then compute the standard deviation using [stdevp]{@link stdevp}.
5222
- * @param {number[]} numbers The array of numbers comprising the population
5223
- * @returns {number}
5224
- * @category openFormula
5225
- * @function stdev
5226
- * @example
5227
- * stdev([1345, 1301, 1368]) //returns 34.044089061098404
5228
- * stdevp([1345, 1301, 1368]) //returns 27.797
5229
- */
5230
4469
  stdev: {
5231
4470
  _func: args => {
5232
4471
  const values = args[0] || [];
@@ -5238,7 +4477,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5238
4477
  const sumSquare = coercedValues.reduce((a, b) => a + b * b, 0);
5239
4478
  const result = Math.sqrt((sumSquare - values.length * mean * mean) / (values.length - 1));
5240
4479
  if (Number.isNaN(result)) {
5241
- // this would never happen
5242
4480
  return null;
5243
4481
  }
5244
4482
  return result;
@@ -5247,20 +4485,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5247
4485
  { types: [dataTypes.TYPE_ARRAY_NUMBER] },
5248
4486
  ],
5249
4487
  },
5250
-
5251
- /**
5252
- * Calculates standard deviation based on the entire population given as arguments.
5253
- * `stdevp` assumes that its arguments are the entire population.
5254
- * If your data represents a sample of the population,
5255
- * then compute the standard deviation using [stdev]{@link stdev}.
5256
- * @param {number[]} numbers The array of numbers comprising the population
5257
- * @returns {number}
5258
- * @category openFormula
5259
- * @function stdevp
5260
- * @example
5261
- * stdevp([1345, 1301, 1368]) //returns 27.797
5262
- * stdev([1345, 1301, 1368]) //returns 34.044
5263
- */
5264
4488
  stdevp: {
5265
4489
  _func: args => {
5266
4490
  const values = args[0] || [];
@@ -5272,7 +4496,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5272
4496
  const meanSumSquare = coercedValues.reduce((a, b) => a + b * b, 0) / values.length;
5273
4497
  const result = Math.sqrt(meanSumSquare - mean * mean);
5274
4498
  if (Number.isNaN(result)) {
5275
- // this would never happen
5276
4499
  return null;
5277
4500
  }
5278
4501
  return result;
@@ -5281,43 +4504,18 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5281
4504
  { types: [dataTypes.TYPE_ARRAY_NUMBER] },
5282
4505
  ],
5283
4506
  },
5284
-
5285
- /**
5286
- * Returns input `text`, with text `old` replaced by text `new` (when searching from the left).
5287
- * If `which` parameter is omitted, every occurrence of `old` is replaced with `new`;
5288
- * If `which` is provided, only that occurrence of `old` is replaced by `new`
5289
- * (starting the count from 1).
5290
- * If there is no match, or if `old` has length 0, `text` is returned unchanged.
5291
- * Note that `old` and `new` may have different lengths. If `which` < 1, return `text` unchanged
5292
- * @param {string} text The text for which to substitute characters.
5293
- * @param {string} old The text to replace.
5294
- * @param {string} new The text to replace `old` with.
5295
- * @param {integer} [which] The one-based occurrence of `old` text to replace with `new` text.
5296
- * @returns {string} replaced string
5297
- * @function
5298
- * @category openFormula
5299
- * @example
5300
- * substitute('Sales Data', 'Sales', 'Cost') //returns 'Cost Data'
5301
- * @example
5302
- * substitute('Quarter 1, 2008', '1', '2', 1) //returns 'Quarter 2, 2008'
5303
- * @example
5304
- * substitute('Quarter 1, 1008', '1', '2', 2) //returns 'Quarter 1, 2008'
5305
- */
5306
4507
  substitute: {
5307
4508
  _func: args => {
5308
4509
  const src = toString(args[0]);
5309
4510
  const old = toString(args[1]);
5310
4511
  const replacement = toString(args[2]);
5311
- // no third parameter? replace all instances
5312
4512
  if (args.length <= 3) return src.replaceAll(old, replacement);
5313
4513
  const whch = toNumber(args[3]);
5314
4514
  if (whch < 1) return src;
5315
- // find the instance to replace
5316
4515
  let pos = -1;
5317
4516
  for (let i = 0; i < whch; i += 1) {
5318
4517
  pos += 1;
5319
4518
  const nextFind = src.slice(pos).indexOf(old);
5320
- // no instance to match 'Which'
5321
4519
  if (nextFind === -1) return src;
5322
4520
  pos += nextFind;
5323
4521
  }
@@ -5330,21 +4528,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5330
4528
  { types: [dataTypes.TYPE_NUMBER], optional: true },
5331
4529
  ],
5332
4530
  },
5333
-
5334
- /**
5335
- * Construct and returns time from hours, minutes, and seconds.
5336
- * @param {integer} hours Integer value between 0 and 23 representing the hour of the day.
5337
- * Defaults to 0.
5338
- * @param {integer} minutes Integer value representing the minute segment of a time.
5339
- * The default is 0 minutes past the hour.
5340
- * @param {integer} seconds Integer value representing the second segment of a time.
5341
- * The default is 0 seconds past the minute.
5342
- * @return {number} Returns the fraction of the day consumed by the given time
5343
- * @function time
5344
- * @category openFormula
5345
- * @example
5346
- * time(12, 0, 0) //returns 0.5 (half day)
5347
- */
5348
4531
  time: {
5349
4532
  _func: args => {
5350
4533
  const hours = toNumber(args[0]);
@@ -5362,65 +4545,23 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5362
4545
  { types: [dataTypes.TYPE_NUMBER] },
5363
4546
  ],
5364
4547
  },
5365
-
5366
- /**
5367
- * returns the number of days since epoch
5368
- * @return number
5369
- * @function today
5370
- * @category openFormula
5371
- */
5372
4548
  today: {
5373
4549
  _func: () => Math.floor(Date.now() / MS_IN_DAY),
5374
4550
  _signature: [],
5375
4551
  },
5376
-
5377
- /**
5378
- * Remove leading and trailing spaces, and replace all internal multiple spaces
5379
- * with a single space.
5380
- * @param {string} text string to trim
5381
- * @return {string} removes all leading and trailing space.
5382
- * Any other sequence of 2 or more spaces is replaced with a single space.
5383
- * @function trim
5384
- * @category openFormula
5385
- * @example
5386
- * trim(' ab c ') //returns 'ab c'
5387
- */
5388
4552
  trim: {
5389
4553
  _func: args => {
5390
4554
  const text = toString(args[0]);
5391
- // only removes the space character
5392
- // other whitespace characters like \t \n left intact
5393
4555
  return text.split(' ').filter(x => x).join(' ');
5394
4556
  },
5395
4557
  _signature: [
5396
4558
  { types: [dataTypes.TYPE_STRING] },
5397
4559
  ],
5398
4560
  },
5399
-
5400
- /**
5401
- * Return constant boolean true value.
5402
- * Note that expressions may also use the JSON literal true: `` `true` ``
5403
- * @returns {boolean} True
5404
- * @function
5405
- * @category openFormula
5406
- */
5407
4561
  true: {
5408
4562
  _func: () => true,
5409
4563
  _signature: [],
5410
4564
  },
5411
-
5412
- /**
5413
- * Truncates a number to an integer by removing the fractional part of the number.
5414
- * @param {number} numA number to truncate
5415
- * @param {number} [numB] A number specifying the precision of the truncation. Default is 0
5416
- * @return {number}
5417
- * @function trunc
5418
- * @category openFormula
5419
- * @example
5420
- * trunc(8.9) //returns 8
5421
- * trunc(-8.9) //returns -8
5422
- * trunc(8.912, 2) //returns 8.91
5423
- */
5424
4565
  trunc: {
5425
4566
  _func: args => {
5426
4567
  const number = toNumber(args[0]);
@@ -5433,20 +4574,8 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5433
4574
  { types: [dataTypes.TYPE_NUMBER], optional: true },
5434
4575
  ],
5435
4576
  },
5436
-
5437
- /**
5438
- * takes an array and returns unique elements within it
5439
- * @param {array} input input array
5440
- * @return {array} array with duplicate elements removed
5441
- * @function unique
5442
- * @category JSONFormula
5443
- * @example
5444
- * unique([1, 2, 3, 4, 1, 1, 2]) //returns [1, 2, 3, 4]
5445
- */
5446
4577
  unique: {
5447
4578
  _func: args => {
5448
- // create an array of values for searching. That way if the array elements are
5449
- // represented by objects with a valueOf(), then we'll locate them in the valueArray
5450
4579
  const valueArray = args[0].map(a => valueOf(a));
5451
4580
  return args[0].filter((v, index) => valueArray.indexOf(valueOf(v)) === index);
5452
4581
  },
@@ -5454,18 +4583,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5454
4583
  { types: [dataTypes.TYPE_ARRAY] },
5455
4584
  ],
5456
4585
  },
5457
-
5458
- /**
5459
- * Converts all the alphabetic characters in a string to uppercase.
5460
- * If the value is not a string it will be converted into string
5461
- * using the default toString method
5462
- * @param {string} input input string
5463
- * @returns {string} the upper case value of the input string
5464
- * @function upper
5465
- * @category openFormula
5466
- * @example
5467
- * upper('abcd') //returns 'ABCD'
5468
- */
5469
4586
  upper: {
5470
4587
  _func: args => {
5471
4588
  const value = toString(args[0]);
@@ -5475,19 +4592,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5475
4592
  { types: [dataTypes.TYPE_STRING] },
5476
4593
  ],
5477
4594
  },
5478
-
5479
- /**
5480
- * Perform an indexed lookup on a map or array
5481
- * @param {map | array} object on which to perform the lookup
5482
- * @param {string | integer} index: a named child for a map or an integer offset for an array
5483
- * @returns {any} the result of the lookup -- or `null` if not found.
5484
- * @function
5485
- * @category JSONFormula
5486
- * @example
5487
- * value({a: 1, b:2, c:3}, a) //returns 1
5488
- * @example
5489
- * value([1, 2, 3, 4], 2) //returns 3
5490
- */
5491
4595
  value: {
5492
4596
  _func: args => {
5493
4597
  const obj = args[0] || {};
@@ -5497,7 +4601,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5497
4601
  debug.push(`Failed to find: '${index}'`);
5498
4602
  const available = Object.keys(obj).map(a => `'${a}'`).toString();
5499
4603
  if (available.length) debug.push(`Available fields: ${available}`);
5500
-
5501
4604
  return null;
5502
4605
  }
5503
4606
  return result;
@@ -5507,43 +4610,18 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5507
4610
  { types: [dataTypes.TYPE_STRING, dataTypes.TYPE_NUMBER] },
5508
4611
  ],
5509
4612
  },
5510
-
5511
- /**
5512
- * Extract the day of the week from a date; if text, uses current locale to convert to a date.
5513
- * @param {number} The datetime for which the day of the week is to be returned.
5514
- * Dates should be entered by using the [datetime]{@link datetime} function
5515
- * @param {number} [returnType] A number that determines the
5516
- * numeral representation (a number from 0 to 7) of the
5517
- * day of week. Default is 1. Supports the following values
5518
- * * 1 : Sunday (1), Monday (2), ..., Saturday (7)
5519
- * * 2 : Monday (1), Tuesday (2), ..., Sunday(7)
5520
- * * 3 : Monday (0), Tuesday (2), ...., Sunday(6)
5521
- * @returns {number} day of the week
5522
- * @function weekday
5523
- * @category openFormula
5524
- * @example
5525
- * weekday(datetime(2006,5,21)) // 1
5526
- * @example
5527
- * weekday(datetime(2006,5,21), 2) // 7
5528
- * @example
5529
- * weekday(datetime(2006,5,21), 3) // 6
5530
- */
5531
4613
  weekday: {
5532
4614
  _func: args => {
5533
4615
  const date = toNumber(args[0]);
5534
4616
  const type = args.length > 1 ? toNumber(args[1]) : 1;
5535
4617
  const jsDate = new Date(date * MS_IN_DAY);
5536
4618
  const day = jsDate.getDay();
5537
- // day is in range [0-7) with 0 mapping to sunday
5538
4619
  switch (type) {
5539
4620
  case 1:
5540
- // range = [1, 7], sunday = 1
5541
4621
  return day + 1;
5542
4622
  case 2:
5543
- // range = [1, 7] sunday = 7
5544
4623
  return ((day + 6) % 7) + 1;
5545
4624
  case 3:
5546
- // range = [0, 6] sunday = 6
5547
4625
  return (day + 6) % 7;
5548
4626
  default:
5549
4627
  return null;
@@ -5554,17 +4632,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5554
4632
  { types: [dataTypes.TYPE_NUMBER], optional: true },
5555
4633
  ],
5556
4634
  },
5557
-
5558
- /**
5559
- * Returns the year of a date represented by a serial number.
5560
- * @param {number} The date for which the year is to be returned.
5561
- * Dates should be entered by using the [datetime]{@link datetime} function
5562
- * @return {number}
5563
- * @function year
5564
- * @category openFormula
5565
- * @example
5566
- * year(datetime(2008,5,23)) //returns 2008
5567
- */
5568
4635
  year: {
5569
4636
  _func: args => {
5570
4637
  const date = toNumber(args[0]);
@@ -5575,7 +4642,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5575
4642
  { types: [dataTypes.TYPE_NUMBER] },
5576
4643
  ],
5577
4644
  },
5578
-
5579
4645
  charCode: {
5580
4646
  _func: args => {
5581
4647
  const code = toNumber(args[0]);
@@ -5588,7 +4654,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5588
4654
  { types: [dataTypes.TYPE_NUMBER] },
5589
4655
  ],
5590
4656
  },
5591
-
5592
4657
  codePoint: {
5593
4658
  _func: args => {
5594
4659
  const text = toString(args[0]);
@@ -5601,28 +4666,24 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5601
4666
  { types: [dataTypes.TYPE_STRING] },
5602
4667
  ],
5603
4668
  },
5604
-
5605
4669
  encodeUrlComponent: {
5606
4670
  _func: args => encodeURIComponent(args[0]),
5607
4671
  _signature: [
5608
4672
  { types: [dataTypes.TYPE_STRING] },
5609
4673
  ],
5610
4674
  },
5611
-
5612
4675
  encodeUrl: {
5613
4676
  _func: args => encodeURI(args[0]),
5614
4677
  _signature: [
5615
4678
  { types: [dataTypes.TYPE_STRING] },
5616
4679
  ],
5617
4680
  },
5618
-
5619
4681
  decodeUrlComponent: {
5620
4682
  _func: args => decodeURIComponent(args[0]),
5621
4683
  _signature: [
5622
4684
  { types: [dataTypes.TYPE_STRING] },
5623
4685
  ],
5624
4686
  },
5625
-
5626
4687
  decodeUrl: {
5627
4688
  _func: args => decodeURI(args[0]),
5628
4689
  _signature: [
@@ -5632,27 +4693,6 @@ function openFormulaFunctions(valueOf, toString, toNumber, debug = []) {
5632
4693
  };
5633
4694
  }
5634
4695
 
5635
- /*
5636
- Copyright 2014 James Saryerwinnie
5637
-
5638
- Licensed under the Apache License, Version 2.0 (the "License");
5639
- you may not use this file except in compliance with the License.
5640
- You may obtain a copy of the License at
5641
-
5642
- http://www.apache.org/licenses/LICENSE-2.0
5643
-
5644
- Unless required by applicable law or agreed to in writing, software
5645
- distributed under the License is distributed on an "AS IS" BASIS,
5646
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5647
- See the License for the specific language governing permissions and
5648
- limitations under the License.
5649
-
5650
- NOTICE:
5651
- This file is substantially modified from the original source taken from:
5652
- https://github.com/jmespath/jmespath.js
5653
-
5654
- */
5655
-
5656
4696
  function functions(
5657
4697
  runtime,
5658
4698
  isObject,
@@ -5675,7 +4715,6 @@ function functions(
5675
4715
  TYPE_ARRAY_NUMBER,
5676
4716
  TYPE_ARRAY_STRING,
5677
4717
  } = dataTypes;
5678
-
5679
4718
  function createKeyFunction(exprefNode, allowedTypes) {
5680
4719
  return x => {
5681
4720
  const current = runtime.interpreter.visit(exprefNode, x);
@@ -5687,46 +4726,11 @@ function functions(
5687
4726
  return current;
5688
4727
  };
5689
4728
  }
5690
-
5691
4729
  const functionMap = {
5692
- // name: [function, <signature>]
5693
- // The <signature> can be:
5694
- //
5695
- // {
5696
- // args: [[type1, type2], [type1, type2]],
5697
- // variadic: true|false
5698
- // }
5699
- //
5700
- // Each arg in the arg list is a list of valid types
5701
- // (if the function is overloaded and supports multiple
5702
- // types. If the type is "any" then no type checking
5703
- // occurs on the argument. Variadic is optional
5704
- // and if not provided is assumed to be false.
5705
- /**
5706
- * Returns the absolute value of the provided argument `value`.
5707
- * @param {number} value argument whose absolute value has to be returned
5708
- * @return {number} returns the absolute value of the `value` argument
5709
- * @function abs
5710
- * @example
5711
- * abs(-1) //returns 1
5712
- * @category jmespath
5713
- */
5714
4730
  abs: {
5715
4731
  _func: resolvedArgs => Math.abs(resolvedArgs[0]),
5716
4732
  _signature: [{ types: [TYPE_NUMBER] }],
5717
4733
  },
5718
- /**
5719
- * Returns the average of the elements in the provided array.
5720
- * An empty array will produce a return value of `null`.
5721
- * @param {number[]} elements array of elements whose average has to be computed
5722
- * @return {number} average value
5723
- * @function avg
5724
- * @example
5725
- * avg([]) //returns null
5726
- * @example
5727
- * avg([1, 2, 3]) //returns 2
5728
- * @category jmespath
5729
- */
5730
4734
  avg: {
5731
4735
  _func: resolvedArgs => {
5732
4736
  let sum = 0;
@@ -5738,59 +4742,15 @@ function functions(
5738
4742
  },
5739
4743
  _signature: [{ types: [TYPE_ARRAY_NUMBER] }],
5740
4744
  },
5741
-
5742
- /**
5743
- * Returns the next highest integer value of the argument `num` by rounding up if necessary.
5744
- * @param {number} num number whose next highest integer value has to be computed
5745
- * @return {number}
5746
- * @function ceil
5747
- * @example
5748
- * ceil(10) //returns 10
5749
- * @example
5750
- * ceil(10.4) //return 11
5751
- * @category jmespath
5752
- */
5753
4745
  ceil: {
5754
4746
  _func: resolvedArgs => Math.ceil(resolvedArgs[0]),
5755
4747
  _signature: [{ types: [TYPE_NUMBER] }],
5756
4748
  },
5757
- /**
5758
- * Returns true if the given `subject` contains the provided `search` string.
5759
- * If `subject` is an array, this function returns true if one of the elements
5760
- * in the array is equal to the provided `search` value. If the provided `subject`
5761
- * is a string, this function returns true if the string contains the provided
5762
- * `search` argument.
5763
- * @param {array|string} subject the subject in which the element has to be searched
5764
- * @param {string|boolean|number|date} search element to search
5765
- * @return {boolean}
5766
- * @function contains
5767
- * @example
5768
- * contains([1, 2, 3, 4], 2) //returns true
5769
- * @example
5770
- * contains([1, 2, 3, 4], -1) //returns false
5771
- * @example
5772
- * contains('Abcd', 'd') //returns true
5773
- * @example
5774
- * contains('Abcd', 'x') //returns false
5775
- * @category jmespath
5776
- */
5777
4749
  contains: {
5778
4750
  _func: resolvedArgs => valueOf(resolvedArgs[0]).indexOf(valueOf(resolvedArgs[1])) >= 0,
5779
4751
  _signature: [{ types: [TYPE_STRING, TYPE_ARRAY] },
5780
4752
  { types: [TYPE_ANY] }],
5781
4753
  },
5782
- /**
5783
- * Returns true if the `subject` ends with the `suffix`, otherwise this function returns false.
5784
- * @param {string} subject subject in which the `suffix` is being searched for
5785
- * @param {string} suffix suffix to search in the subject
5786
- * @return {boolean}
5787
- * @function endsWith
5788
- * @example
5789
- * endsWith('Abcd', 'd') //returns true
5790
- * @example
5791
- * endsWith('Abcd', 'A') //returns false
5792
- * @category jmespath
5793
- */
5794
4754
  endsWith: {
5795
4755
  _func: resolvedArgs => {
5796
4756
  const searchStr = valueOf(resolvedArgs[0]);
@@ -5799,34 +4759,10 @@ function functions(
5799
4759
  },
5800
4760
  _signature: [{ types: [TYPE_STRING] }, { types: [TYPE_STRING] }],
5801
4761
  },
5802
-
5803
- /**
5804
- * Returns the next lowest integer value of the argument `num` by rounding down if necessary.
5805
- * @param {number} num number whose next lowest integer value has to be returned
5806
- * @return {number}
5807
- * @function floor
5808
- * @example
5809
- * floor(10.4) //returns 10
5810
- * @example
5811
- * floor(10) //returns 10
5812
- * @category jmespath
5813
- */
5814
4762
  floor: {
5815
4763
  _func: resolvedArgs => Math.floor(resolvedArgs[0]),
5816
4764
  _signature: [{ types: [TYPE_NUMBER] }],
5817
4765
  },
5818
-
5819
- /**
5820
- * Returns all the elements from the provided `stringsarray`
5821
- * array joined together using the `glue` argument as a separator between each.
5822
- * @param {string} glue
5823
- * @param {string[]} stringsarray
5824
- * @return {string}
5825
- * @function join
5826
- * @example
5827
- * join(',', ['a', 'b', 'c']) //returns 'a,b,c'
5828
- * @category jmespath
5829
- */
5830
4766
  join: {
5831
4767
  _func: resolvedArgs => {
5832
4768
  const joinChar = resolvedArgs[0];
@@ -5838,17 +4774,6 @@ function functions(
5838
4774
  { types: [TYPE_ARRAY_STRING] },
5839
4775
  ],
5840
4776
  },
5841
-
5842
- /**
5843
- * Returns an array containing the keys of the provided object `obj`. If the passed
5844
- * object is null, the value returned is an empty array
5845
- * @param {object} obj the object whose keys need to be extracted
5846
- * @return {array}
5847
- * @function keys
5848
- * @example
5849
- * keys({a : 3, b : 4}) //returns ['a', 'b']
5850
- * @category jmespath
5851
- */
5852
4777
  keys: {
5853
4778
  _func: resolvedArgs => {
5854
4779
  if (resolvedArgs[0] === null) return [];
@@ -5856,54 +4781,14 @@ function functions(
5856
4781
  },
5857
4782
  _signature: [{ types: [TYPE_ANY] }],
5858
4783
  },
5859
-
5860
- /**
5861
- * Returns the length of the given argument `subject` using the following types rules:
5862
- * * string: returns the number of code points in the string
5863
- * * array: returns the number of elements in the array
5864
- * * object: returns the number of key-value pairs in the object
5865
- * @param {string | array | object} subject subject whose length has to be calculated
5866
- * @return {number}
5867
- * @function length
5868
- * @example
5869
- * length([]) //returns 0
5870
- * @example
5871
- * length('') //returns 0
5872
- * @example
5873
- * length('abcd') //returns 4
5874
- * @example
5875
- * length([1, 2, 3, 4]) //returns 4
5876
- * @example
5877
- * length({}) // returns 0
5878
- * @example
5879
- * length({a : 3, b : 4}) //returns 2
5880
- * @category jmespath
5881
- */
5882
4784
  length: {
5883
4785
  _func: resolvedArgs => {
5884
4786
  const arg = valueOf(resolvedArgs[0]);
5885
4787
  if (isObject(arg)) return Object.keys(arg).length;
5886
-
5887
4788
  return isArray(arg) ? arg.length : toString(arg).length;
5888
4789
  },
5889
4790
  _signature: [{ types: [TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT] }],
5890
4791
  },
5891
-
5892
- /**
5893
- * Apply the `expr` to every element in the `elements` array and return the array of results.
5894
- * An elements of length N will produce a return array of length N. Unlike a projection,
5895
- * `[*].bar`, `map()` will include the result of applying the `expr` for every element
5896
- * in the elements array, even if the result is `null`.
5897
- * @param {expression} expr expression to evaluate on each element
5898
- * @param {array} elements array of elements on which the expression will be evaluated
5899
- * @return {array}
5900
- * @function map
5901
- * @example
5902
- * map(&(@ + 1), [1, 2, 3, 4]) // returns [2, 3, 4, 5]
5903
- * @example
5904
- * map(&length(@), ['doe', 'nick', 'chris']) // returns [3,4, 5]
5905
- * @category jmespath
5906
- */
5907
4792
  map: {
5908
4793
  _func: resolvedArgs => {
5909
4794
  const exprefNode = resolvedArgs[0];
@@ -5911,35 +4796,15 @@ function functions(
5911
4796
  },
5912
4797
  _signature: [{ types: [TYPE_EXPREF] }, { types: [TYPE_ARRAY] }],
5913
4798
  },
5914
-
5915
- /**
5916
- * Returns the highest value in the provided `collection` arguments.
5917
- * If all collections are empty `null` is returned.
5918
- * max() can work on numbers or strings.
5919
- * If a mix of numbers and strings are provided, the type of the first value will be used.
5920
- * @param {number[]|string[]} collection array in which the maximum element is to be calculated
5921
- * @return {number}
5922
- * @function max
5923
- * @example
5924
- * max([1, 2, 3], [4, 5, 6], 7) //returns 7
5925
- * @example
5926
- * max([]) // returns null
5927
- * @example
5928
- * max(['a', 'a1', 'b']) // returns 'b'
5929
- * @category jmespath
5930
- */
5931
4799
  max: {
5932
4800
  _func: args => {
5933
- // flatten the args into a single array
5934
4801
  const array = args.reduce((prev, cur) => {
5935
4802
  if (Array.isArray(cur)) prev.push(...cur);
5936
4803
  else prev.push(cur);
5937
4804
  return prev;
5938
4805
  }, []);
5939
-
5940
4806
  const first = array.find(r => r !== null);
5941
4807
  if (array.length === 0 || first === undefined) return null;
5942
- // use the first value to determine the comparison type
5943
4808
  const isNumber = getTypeName(first, true) === TYPE_NUMBER;
5944
4809
  const compare = isNumber
5945
4810
  ? (prev, cur) => {
@@ -5950,25 +4815,10 @@ function functions(
5950
4815
  const current = toString(cur);
5951
4816
  return prev.localeCompare(current) === 1 ? prev : current;
5952
4817
  };
5953
-
5954
4818
  return array.reduce(compare, isNumber ? toNumber(first) : toString(first));
5955
4819
  },
5956
4820
  _signature: [{ types: [TYPE_ARRAY, TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING], variadic: true }],
5957
4821
  },
5958
-
5959
- /**
5960
- * Returns the maximum element in an array using the expression `expr` as the comparison key.
5961
- * The entire element is returned.
5962
- * @param {array} elements the array in which the maximum element is to be found
5963
- * @param {expression} expr the expr to use as the `comparison` key
5964
- * @return {any}
5965
- * @function maxBy
5966
- * @example
5967
- * maxBy(['abcd', 'e', 'def'], &length(@)) //returns 'abcd'
5968
- * @example
5969
- * maxBy([{year: 2010}, {year: 2020}, {year: 1910}], &year) //returns {year: 2020}
5970
- * @category jmespath
5971
- */
5972
4822
  maxBy: {
5973
4823
  _func: resolvedArgs => {
5974
4824
  const exprefNode = resolvedArgs[1];
@@ -5988,22 +4838,6 @@ function functions(
5988
4838
  },
5989
4839
  _signature: [{ types: [TYPE_ARRAY] }, { types: [TYPE_EXPREF] }],
5990
4840
  },
5991
-
5992
- /**
5993
- * Accepts 0 or more objects as arguments, and returns a single object with
5994
- * subsequent objects merged. Each subsequent object’s key/value pairs are
5995
- * added to the preceding object. This function is used to combine multiple
5996
- * objects into one. You can think of this as the first object being the base object,
5997
- * and each subsequent argument being overrides that are applied to the base object.
5998
- * @param {...object} args
5999
- * @return {object}
6000
- * @function merge
6001
- * @example
6002
- * merge({a: 1, b: 2}, {c : 3, d: 4}) // returns {a :1, b: 2, c: 3, d: 4}
6003
- * @example
6004
- * merge({a: 1, b: 2}, {a : 3, d: 4}) // returns {a :3, b: 2, d: 4}
6005
- * @category jmespath
6006
- */
6007
4841
  merge: {
6008
4842
  _func: resolvedArgs => {
6009
4843
  const merged = {};
@@ -6016,35 +4850,15 @@ function functions(
6016
4850
  },
6017
4851
  _signature: [{ types: [TYPE_OBJECT], variadic: true }],
6018
4852
  },
6019
-
6020
- /**
6021
- * Returns the lowest value in the provided `collection` arguments.
6022
- * If all collections are empty `null` is returned.
6023
- * min() can work on numbers or strings.
6024
- * If a mix of numbers and strings are provided, the type of the first value will be used.
6025
- * @param {number[]|string[]} collection array in which the minimum element is to be calculated
6026
- * @return {number}
6027
- * @function min
6028
- * @example
6029
- * min([1, 2, 3], [4, 5, 6], 7) //returns 1
6030
- * @example
6031
- * min([]) // returns null
6032
- * @example
6033
- * min(['a', 'a1', 'b']) // returns 'a'
6034
- * @category jmespath
6035
- */
6036
4853
  min: {
6037
4854
  _func: args => {
6038
- // flatten the args into a single array
6039
4855
  const array = args.reduce((prev, cur) => {
6040
4856
  if (Array.isArray(cur)) prev.push(...cur);
6041
4857
  else prev.push(cur);
6042
4858
  return prev;
6043
4859
  }, []);
6044
-
6045
4860
  const first = array.find(r => r !== null);
6046
4861
  if (array.length === 0 || first === undefined) return null;
6047
- // use the first value to determine the comparison type
6048
4862
  const isNumber = getTypeName(first, true) === TYPE_NUMBER;
6049
4863
  const compare = isNumber
6050
4864
  ? (prev, cur) => {
@@ -6055,25 +4869,10 @@ function functions(
6055
4869
  const current = toString(cur);
6056
4870
  return prev.localeCompare(current) === 1 ? current : prev;
6057
4871
  };
6058
-
6059
4872
  return array.reduce(compare, isNumber ? toNumber(first) : toString(first));
6060
4873
  },
6061
4874
  _signature: [{ types: [TYPE_ARRAY, TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING], variadic: true }],
6062
4875
  },
6063
-
6064
- /**
6065
- * Returns the minimum element in `elements` array using the expression `expr`
6066
- * as the comparison key.
6067
- * @param {array} elements
6068
- * @param {expression} expr expression that returns either a string or a number
6069
- * @return {any}
6070
- * @function minBy
6071
- * @example
6072
- * minBy(['abcd', 'e', 'def'], &length(@)) //returns 'e'
6073
- * @example
6074
- * minBy([{year: 2010}, {year: 2020}, {year: 1910}], &year) //returns {year: 1910}
6075
- * @category jmespath
6076
- */
6077
4876
  minBy: {
6078
4877
  _func: resolvedArgs => {
6079
4878
  const exprefNode = resolvedArgs[1];
@@ -6093,48 +4892,10 @@ function functions(
6093
4892
  },
6094
4893
  _signature: [{ types: [TYPE_ARRAY] }, { types: [TYPE_EXPREF] }],
6095
4894
  },
6096
-
6097
- /**
6098
- * Returns the first argument that does not resolve to `null`.
6099
- * This function accepts one or more arguments, and will evaluate
6100
- * them in order until a non null argument is encounted. If all
6101
- * arguments values resolve to null, then a value of null is returned.
6102
- * @param {...any} argument
6103
- * @return {any}
6104
- * @function notNull
6105
- * @example
6106
- * notNull(1, 2, 3, 4, `null`) //returns 1
6107
- * @example
6108
- * notNull(`null`, 2, 3, 4, `null`) //returns 2
6109
- * @category jmespath
6110
- */
6111
4895
  notNull: {
6112
4896
  _func: resolvedArgs => resolvedArgs.find(arg => getTypeName(arg) !== TYPE_NULL) || null,
6113
4897
  _signature: [{ types: [TYPE_ANY], variadic: true }],
6114
4898
  },
6115
-
6116
- /**
6117
- * executes a user-supplied reducer expression `expr` on each element of the
6118
- * array, in order, passing in the return value from the calculation on the preceding element.
6119
- * The final result of running the reducer across all elements of the `elements` array is a
6120
- * single value.
6121
- * The expression can access the following properties
6122
- * * accumulated: accumulated value based on the previous calculations. Initial value is `null`
6123
- * * current: current element to process
6124
- * * index: index of the `current` element in the array
6125
- * * array: original array
6126
- * @param {expression} expr reducer expr to be executed on each element
6127
- * @param {array} elements array of elements on which the expression will be evaluated
6128
- * @return {any}
6129
- * @function reduce
6130
- * @example
6131
- * reduce(&(accumulated + current), [1, 2, 3]) //returns 6
6132
- * @example
6133
- * reduce(&(accumulated - current), [3, 3, 3]) //returns -9
6134
- * @example
6135
- * reduce(&if(accumulated == `null`, current, accumulated * current), [3, 3, 3]) //returns 27
6136
- * @category jmespath
6137
- */
6138
4899
  reduce: {
6139
4900
  _func: resolvedArgs => {
6140
4901
  const exprefNode = resolvedArgs[0];
@@ -6151,23 +4912,10 @@ function functions(
6151
4912
  { types: [TYPE_ANY], optional: true },
6152
4913
  ],
6153
4914
  },
6154
-
6155
- /**
6156
- * Register a function to allow code re-use. The registered function may take one parameter.
6157
- * If more parameters are needed, combine them in an array or map.
6158
- * @param {string} functionName Name of the function to register
6159
- * @param {expression} expr Expression to execute with this function call
6160
- * @return {{}} returns an empty object
6161
- * @function register
6162
- * @example
6163
- * register('product', &@[0] * @[1]) // can now call: product([2,21]) => returns 42
6164
- * @category jmespath
6165
- */
6166
4915
  register: {
6167
4916
  _func: resolvedArgs => {
6168
4917
  const functionName = resolvedArgs[0];
6169
4918
  const exprefNode = resolvedArgs[1];
6170
-
6171
4919
  if (functionMap[functionName]) {
6172
4920
  debug.push(`Cannot re-register '${functionName}'`);
6173
4921
  return {};
@@ -6183,15 +4931,6 @@ function functions(
6183
4931
  { types: [TYPE_EXPREF] },
6184
4932
  ],
6185
4933
  },
6186
- /**
6187
- * Reverses the order of the `argument`.
6188
- * @param {string|array} argument
6189
- * @return {array}
6190
- * @function reverse
6191
- * @example
6192
- * reverse(['a', 'b', 'c']) //returns ['c', 'b', 'a']
6193
- * @category jmespath
6194
- */
6195
4934
  reverse: {
6196
4935
  _func: resolvedArgs => {
6197
4936
  const originalStr = valueOf(resolvedArgs[0]);
@@ -6209,18 +4948,6 @@ function functions(
6209
4948
  },
6210
4949
  _signature: [{ types: [TYPE_STRING, TYPE_ARRAY] }],
6211
4950
  },
6212
-
6213
- /**
6214
- * This function accepts an array `list` argument and returns the sorted elements of
6215
- * the `list` as an array. The array must be a list of strings or numbers.
6216
- * Sorting strings is based on code points. Locale is not taken into account.
6217
- * @param {number[]|string[]} list
6218
- * @return {number[]|string[]}
6219
- * @function sort
6220
- * @example
6221
- * sort([1, 2, 4, 3, 1]) // returns [1, 1, 2, 3, 4]
6222
- * @category jmespath
6223
- */
6224
4951
  sort: {
6225
4952
  _func: resolvedArgs => {
6226
4953
  const sortedArray = resolvedArgs[0].slice(0);
@@ -6238,24 +4965,6 @@ function functions(
6238
4965
  },
6239
4966
  _signature: [{ types: [TYPE_ARRAY, TYPE_ARRAY_STRING, TYPE_ARRAY_NUMBER] }],
6240
4967
  },
6241
-
6242
- /**
6243
- * Sort an array using an expression `expr` as the sort key. For each element
6244
- * in the array of elements, the `expr` expression is applied and the resulting
6245
- * value is used as the key used when sorting the elements. If the result of
6246
- * evaluating the `expr` against the current array element results in type
6247
- * other than a number or a string, a type error will occur.
6248
- * @param {array} elements
6249
- * @param {expression} expr
6250
- * @return {array}
6251
- * @function sortBy
6252
- * @example
6253
- * sortBy(['abcd', 'e', 'def'], &length(@)) //returns ['e', 'def', 'abcd']
6254
- * @example
6255
- * // returns [{year: 1910}, {year: 2010}, {year: 2020}]
6256
- * sortBy([{year: 2010}, {year: 2020}, {year: 1910}], &year)
6257
- * @category jmespath
6258
- */
6259
4968
  sortBy: {
6260
4969
  _func: resolvedArgs => {
6261
4970
  const sortedArray = resolvedArgs[0].slice(0);
@@ -6269,13 +4978,6 @@ function functions(
6269
4978
  if ([TYPE_NUMBER, TYPE_STRING].indexOf(requiredType) < 0) {
6270
4979
  throw new Error('TypeError');
6271
4980
  }
6272
- // In order to get a stable sort out of an unstable
6273
- // sort algorithm, we decorate/sort/undecorate (DSU)
6274
- // by creating a new list of [index, element] pairs.
6275
- // In the cmp function, if the evaluated elements are
6276
- // equal, then the index will be used as the tiebreaker.
6277
- // After the decorated list has been sorted, it will be
6278
- // undecorated to extract the original elements.
6279
4981
  const decorated = [];
6280
4982
  for (let i = 0; i < sortedArray.length; i += 1) {
6281
4983
  decorated.push([i, sortedArray[i]]);
@@ -6300,12 +5002,8 @@ function functions(
6300
5002
  if (exprA < exprB) {
6301
5003
  return -1;
6302
5004
  }
6303
- // If they're equal compare the items by their
6304
- // order to maintain relative order of equal keys
6305
- // (i.e. to get a stable sort).
6306
5005
  return a[0] - b[0];
6307
5006
  });
6308
- // Undecorate: extract out the original list elements.
6309
5007
  for (let j = 0; j < decorated.length; j += 1) {
6310
5008
  [, sortedArray[j]] = decorated[j];
6311
5009
  }
@@ -6313,32 +5011,10 @@ function functions(
6313
5011
  },
6314
5012
  _signature: [{ types: [TYPE_ARRAY] }, { types: [TYPE_EXPREF] }],
6315
5013
  },
6316
-
6317
- /**
6318
- * Returns true if the `subject` starts with the `prefix`, otherwise returns false.
6319
- * @param {string} subject subject in which the `prefix` is being searched for
6320
- * @param {string} prefix prefix to search in the subject
6321
- * @return {boolean}
6322
- * @function startsWith
6323
- * @example
6324
- * startsWith('jack is at home', 'jack') // returns true
6325
- * @category jmespath
6326
- */
6327
5014
  startsWith: {
6328
5015
  _func: resolvedArgs => valueOf(resolvedArgs[0]).startsWith(valueOf(resolvedArgs[1])),
6329
5016
  _signature: [{ types: [TYPE_STRING] }, { types: [TYPE_STRING] }],
6330
5017
  },
6331
-
6332
- /**
6333
- * Returns the sum of the provided `collection` array argument.
6334
- * An empty array will produce a return value of 0.
6335
- * @param {number[]} collection array whose element's sum has to be computed
6336
- * @return {number}
6337
- * @function sum
6338
- * @example
6339
- * sum([1, 2, 3]) //returns 6
6340
- * @category jmespath
6341
- */
6342
5018
  sum: {
6343
5019
  _func: resolvedArgs => {
6344
5020
  let sum = 0;
@@ -6349,20 +5025,6 @@ function functions(
6349
5025
  },
6350
5026
  _signature: [{ types: [TYPE_ARRAY_NUMBER] }],
6351
5027
  },
6352
-
6353
- /**
6354
- * converts the passed `arg` to an array. The conversion happens as per the following rules
6355
- * * array - Returns the passed in value.
6356
- * * number/string/object/boolean - Returns a one element array containing the argument.
6357
- * @param {any} arg
6358
- * @return {array}
6359
- * @function toArray
6360
- * @example
6361
- * toArray(1) // returns [1]
6362
- * @example
6363
- * toArray(null()) // returns [`null`]
6364
- * @category jmespath
6365
- */
6366
5028
  toArray: {
6367
5029
  _func: resolvedArgs => {
6368
5030
  if (getTypeName(resolvedArgs[0]) === TYPE_ARRAY) {
@@ -6370,31 +5032,8 @@ function functions(
6370
5032
  }
6371
5033
  return [resolvedArgs[0]];
6372
5034
  },
6373
-
6374
5035
  _signature: [{ types: [TYPE_ANY] }],
6375
5036
  },
6376
-
6377
- /**
6378
- * converts the passed arg to a number. The conversion happens as per the following rules
6379
- * * string - Returns the parsed number.
6380
- * * number - Returns the passed in value.
6381
- * * array - null
6382
- * * object - null
6383
- * * boolean - null
6384
- * * null - null
6385
- * @param {any} arg
6386
- * @return {number}
6387
- * @function toNumber
6388
- * @example
6389
- * toNumber(1) //returns 1
6390
- * @example
6391
- * toNumber('10') //returns 10
6392
- * @example
6393
- * toNumber({a: 1}) //returns null
6394
- * @example
6395
- * toNumber(true()) //returns null
6396
- * @category jmespath
6397
- */
6398
5037
  toNumber: {
6399
5038
  _func: resolvedArgs => {
6400
5039
  const typeName = getTypeName(resolvedArgs[0]);
@@ -6408,20 +5047,6 @@ function functions(
6408
5047
  },
6409
5048
  _signature: [{ types: [TYPE_ANY] }],
6410
5049
  },
6411
-
6412
- /**
6413
- * converts the passed `arg` to a string. The conversion happens as per the following rules
6414
- * * string - Returns the passed in value.
6415
- * * number/array/object/boolean - The JSON encoded value of the object.
6416
- * @param {any} arg
6417
- * @return {string}
6418
- * @function toString
6419
- * @example
6420
- * toString(1) //returns '1'
6421
- * @example
6422
- * toString(true()) //returns 'true'
6423
- * @category jmespath
6424
- */
6425
5050
  toString: {
6426
5051
  _func: resolvedArgs => {
6427
5052
  if (getTypeName(resolvedArgs[0]) === TYPE_STRING) {
@@ -6429,30 +5054,8 @@ function functions(
6429
5054
  }
6430
5055
  return JSON.stringify(resolvedArgs[0]);
6431
5056
  },
6432
-
6433
5057
  _signature: [{ types: [TYPE_ANY] }],
6434
5058
  },
6435
-
6436
- /**
6437
- * Returns the JavaScript type of the given `subject` argument as a string value.
6438
- *
6439
- * The return value MUST be one of the following:
6440
- * * number
6441
- * * string
6442
- * * boolean
6443
- * * array
6444
- * * object
6445
- * * null
6446
- * @param {any} subject
6447
- * @return {string}
6448
- *
6449
- * @function type
6450
- * @example
6451
- * type(1) //returns 'number'
6452
- * @example
6453
- * type('') //returns 'string'
6454
- * @category jmespath
6455
- */
6456
5059
  type: {
6457
5060
  _func: resolvedArgs => ({
6458
5061
  [TYPE_NUMBER]: 'number',
@@ -6465,18 +5068,6 @@ function functions(
6465
5068
  }[getTypeName(resolvedArgs[0])]),
6466
5069
  _signature: [{ types: [TYPE_ANY] }],
6467
5070
  },
6468
-
6469
- /**
6470
- * Returns the values of the provided object `obj`. Note that because JSON hashes are
6471
- * inherently unordered, the values associated with the provided object obj are
6472
- * inherently unordered.
6473
- * @param {object} obj
6474
- * @return {array}
6475
- * @function values
6476
- * @example
6477
- * values({a : 3, b : 4}) //returns [3, 4]
6478
- * @category jmespath
6479
- */
6480
5071
  values: {
6481
5072
  _func: resolvedArgs => {
6482
5073
  const arg = valueOf(resolvedArgs[0]);
@@ -6485,19 +5076,6 @@ function functions(
6485
5076
  },
6486
5077
  _signature: [{ types: [TYPE_ANY] }],
6487
5078
  },
6488
-
6489
- /**
6490
- * Returns a convolved (zipped) array containing grouped arrays of values from
6491
- * the array arguments from index 0, 1, 2, etc.
6492
- * This function accepts a variable number of arguments.
6493
- * The length of the returned array is equal to the length of the shortest array.
6494
- * @param {...array} arrays array of arrays to zip together
6495
- * @return {array} An array of arrays with elements zipped together
6496
- * @function zip
6497
- * @example
6498
- * zip([1, 2, 3], [4, 5, 6]) //returns [[1, 4], [2, 5], [3, 6]]
6499
- * @category jmespath
6500
- */
6501
5079
  zip: {
6502
5080
  _func: args => {
6503
5081
  const count = args.reduce((min, current) => Math.min(min, current.length), args[0].length);
@@ -6516,17 +5094,13 @@ function functions(
6516
5094
  return functionMap;
6517
5095
  }
6518
5096
 
6519
- /* eslint-disable max-classes-per-file */
6520
-
6521
- // Type constants used to define functions.
6522
5097
  const {
6523
5098
  TYPE_CLASS,
6524
5099
  TYPE_ANY,
6525
5100
  } = dataTypes;
6526
-
6527
5101
  function getToNumber(stringToNumber, debug = []) {
6528
5102
  return value => {
6529
- const n = getValueOf(value); // in case it's an object that implements valueOf()
5103
+ const n = getValueOf(value);
6530
5104
  if (n === null) return null;
6531
5105
  if (n instanceof Array) {
6532
5106
  debug.push('Converted array to zero');
@@ -6542,26 +5116,20 @@ function getToNumber(stringToNumber, debug = []) {
6542
5116
  }
6543
5117
  function toString(a) {
6544
5118
  if (a === null || a === undefined) return '';
6545
- // don't call a 'toString' method, since we could have a child named 'toString()'
6546
5119
  return a.toString();
6547
5120
  }
6548
-
6549
5121
  const defaultStringToNumber = (str => {
6550
5122
  const n = +str;
6551
5123
  return Number.isNaN(n) ? 0 : n;
6552
5124
  });
6553
-
6554
5125
  function isClass(obj) {
6555
5126
  if (obj === null) return false;
6556
5127
  if (Array.isArray(obj)) return false;
6557
5128
  return obj.constructor.name !== 'Object';
6558
5129
  }
6559
-
6560
5130
  function matchClass(arg, expectedList) {
6561
- // checking isClass() generates a dependency -- so call it only if necessary
6562
5131
  return expectedList.includes(TYPE_CLASS) && isClass(arg);
6563
5132
  }
6564
-
6565
5133
  class Runtime {
6566
5134
  constructor(debug, toNumber, customFunctions = {}) {
6567
5135
  this.strictDeepEqual = strictDeepEqual;
@@ -6576,25 +5144,16 @@ class Runtime {
6576
5144
  toString,
6577
5145
  debug,
6578
5146
  );
6579
-
6580
5147
  Object.entries(
6581
5148
  openFormulaFunctions(getValueOf, toString, toNumber, debug),
6582
5149
  ).forEach(([fname, func]) => {
6583
5150
  this.functionTable[fname] = func;
6584
5151
  });
6585
-
6586
5152
  Object.entries(customFunctions).forEach(([fname, func]) => {
6587
5153
  this.functionTable[fname] = func;
6588
5154
  });
6589
5155
  }
6590
-
6591
- // eslint-disable-next-line class-methods-use-this
6592
5156
  _validateArgs(argName, args, signature, bResolved) {
6593
- // Validating the args requires validating
6594
- // the correct arity and the correct type of each arg.
6595
- // If the last argument is declared as variadic, then we need
6596
- // a minimum number of args to be required. Otherwise it has to
6597
- // be an exact amount.
6598
5157
  if (signature.length === 0) {
6599
5158
  return;
6600
5159
  }
@@ -6613,39 +5172,31 @@ class Runtime {
6613
5172
  + `takes ${signature.length}${pluralized
6614
5173
  } but received ${args.length}`);
6615
5174
  }
6616
- // if the arguments are unresolved, there's no point in validating types
6617
5175
  if (!bResolved) return;
6618
5176
  let currentSpec;
6619
5177
  let actualType;
6620
5178
  const limit = Math.min(signature.length, args.length);
6621
5179
  for (let i = 0; i < limit; i += 1) {
6622
5180
  currentSpec = signature[i].types;
6623
- // Try to avoid checks that will introspect the object and generate dependencies
6624
5181
  if (!matchClass(args[i], currentSpec) && !currentSpec.includes(TYPE_ANY)) {
6625
5182
  actualType = getTypeNames(args[i]);
6626
- // eslint-disable-next-line no-param-reassign
6627
5183
  args[i] = matchType(actualType, currentSpec, args[i], argName, this.toNumber, toString);
6628
5184
  }
6629
5185
  }
6630
5186
  }
6631
-
6632
5187
  callFunction(name, resolvedArgs, data, interpreter, bResolved = true) {
6633
- // this check will weed out 'valueOf', 'toString' etc
6634
5188
  if (!Object.prototype.hasOwnProperty.call(this.functionTable, name)) throw new Error(`Unknown function: ${name}()`);
6635
-
6636
5189
  const functionEntry = this.functionTable[name];
6637
5190
  this._validateArgs(name, resolvedArgs, functionEntry._signature, bResolved);
6638
5191
  return functionEntry._func.call(this, resolvedArgs, data, interpreter);
6639
5192
  }
6640
5193
  }
6641
-
6642
5194
  class Formula {
6643
5195
  constructor(debug, customFunctions, stringToNumberFn) {
6644
5196
  this.debug = debug;
6645
5197
  this.toNumber = getToNumber(stringToNumberFn || defaultStringToNumber, debug);
6646
5198
  this.runtime = new Runtime(debug, this.toNumber, customFunctions);
6647
5199
  }
6648
-
6649
5200
  compile(stream, allowedGlobalNames = []) {
6650
5201
  let ast;
6651
5202
  try {
@@ -6657,11 +5208,7 @@ class Formula {
6657
5208
  }
6658
5209
  return ast;
6659
5210
  }
6660
-
6661
5211
  search(node, data, globals = {}, language = 'en-US') {
6662
- // This needs to be improved. Both the interpreter and runtime depend on
6663
- // each other. The runtime needs the interpreter to support exprefs.
6664
- // There's likely a clean way to avoid the cyclic dependency.
6665
5212
  this.runtime.interpreter = new TreeInterpreter(
6666
5213
  this.runtime,
6667
5214
  globals,
@@ -6670,7 +5217,6 @@ class Formula {
6670
5217
  this.debug,
6671
5218
  language,
6672
5219
  );
6673
-
6674
5220
  try {
6675
5221
  return this.runtime.interpreter.search(node, data);
6676
5222
  } catch (e) {
@@ -6680,33 +5226,7 @@ class Formula {
6680
5226
  }
6681
5227
  }
6682
5228
 
6683
- /*
6684
- Copyright 2021 Adobe. All rights reserved.
6685
- This file is licensed to you under the Apache License, Version 2.0 (the "License");
6686
- you may not use this file except in compliance with the License. You may obtain a copy
6687
- of the License at http://www.apache.org/licenses/LICENSE-2.0
6688
-
6689
- Unless required by applicable law or agreed to in writing, software distributed under
6690
- the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
6691
- OF ANY KIND, either express or implied. See the License for the specific language
6692
- governing permissions and limitations under the License.
6693
- */
6694
-
6695
- /**
6696
- * Returns an instance of JSON JsonFormula Expression that can be executed later on with
6697
- * multiple instances of JSON Data. The instance of the class has a single search
6698
- * function that can be used to evaluate the expression on a json payload. The advantage
6699
- * of using this over {jsonJsonFormula} function is that it can be performant if a single expression
6700
- * has to be used for multiple json data instances.
6701
- */
6702
5229
  class JsonFormula {
6703
- /**
6704
- * @param customFunctions {*} custom functions needed by a hosting application.
6705
- * @param stringToNumber {function} A function that converts string values to numbers.
6706
- * Can be used to convert currencies/dates to numbers
6707
- * @param language
6708
- * @param debug {array} will be populated with any errors/warnings
6709
- */
6710
5230
  constructor(
6711
5231
  customFunctions = {},
6712
5232
  stringToNumber = null,
@@ -6717,25 +5237,10 @@ class JsonFormula {
6717
5237
  this.debug = debug;
6718
5238
  this.formula = new Formula(debug, customFunctions, stringToNumber);
6719
5239
  }
6720
-
6721
- /**
6722
- * Evaluates the JsonFormula on a particular json payload and return the result
6723
- * @param json {object} the json data on which the expression needs to be evaluated
6724
- * @param globals {*} global objects that can be accessed via custom functions.
6725
- * @returns {*} the result of the expression being evaluated
6726
- */
6727
5240
  search(expression, json, globals = {}, language = 'en-US') {
6728
5241
  const ast = this.compile(expression, Object.keys(globals));
6729
5242
  return this.run(ast, json, language, globals);
6730
5243
  }
6731
-
6732
- /**
6733
- * Execute a previously compiled expression against a json object and return the result
6734
- * @param ast {object} The abstract syntax tree returned from compile()
6735
- * @param json {object} the json data on which the expression needs to be evaluated
6736
- * @param globals {*} set of objects available in global scope
6737
- * @returns {*} the result of the expression being evaluated
6738
- */
6739
5244
  run(ast, json, language, globals) {
6740
5245
  return this.formula.search(
6741
5246
  ast,
@@ -6744,14 +5249,6 @@ class JsonFormula {
6744
5249
  language,
6745
5250
  );
6746
5251
  }
6747
-
6748
- /*
6749
- * Creates a compiled expression that can be executed later on with some data.
6750
- * @param expression {string} the expression to evaluate
6751
- * @param allowedGlobalNames {string[]} A list of names of the global variables
6752
- * being used in the expression.
6753
- * @param debug {array} will be populated with any errors/warnings
6754
- */
6755
5252
  compile(expression, allowedGlobalNames = []) {
6756
5253
  this.debug.length = 0;
6757
5254
  return this.formula.compile(expression, allowedGlobalNames);
@@ -6804,7 +5301,8 @@ class RuleEngine {
6804
5301
  }
6805
5302
 
6806
5303
  const defaults = {
6807
- visible: true
5304
+ visible: true,
5305
+ enabled: true
6808
5306
  };
6809
5307
  class Fieldset extends Container {
6810
5308
  constructor(params, _options) {
@@ -6847,12 +5345,6 @@ class Fieldset extends Container {
6847
5345
  }
6848
5346
  }
6849
5347
 
6850
- var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
6851
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6852
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6853
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6854
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6855
- };
6856
5348
  class InstanceManager extends Fieldset {
6857
5349
  get maxOccur() {
6858
5350
  return this._jsonModel.maxItems;
@@ -6870,13 +5362,22 @@ class InstanceManager extends Fieldset {
6870
5362
  return this.removeItem(action);
6871
5363
  }
6872
5364
  }
6873
- __decorate$1([
5365
+ __decorate([
6874
5366
  dependencyTracked()
6875
5367
  ], InstanceManager.prototype, "maxOccur", null);
6876
- __decorate$1([
5368
+ __decorate([
6877
5369
  dependencyTracked()
6878
5370
  ], InstanceManager.prototype, "minOccur", null);
6879
5371
 
5372
+ class ValidationError {
5373
+ fieldName;
5374
+ errorMessages;
5375
+ constructor(fieldName = '', errorMessages = []) {
5376
+ this.errorMessages = errorMessages;
5377
+ this.fieldName = fieldName;
5378
+ }
5379
+ }
5380
+
6880
5381
  const dateRegex = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
6881
5382
  const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
6882
5383
  const daysInMonth = (leapYear, month) => {
@@ -7150,33 +5651,9 @@ const Constraints = {
7150
5651
  }
7151
5652
  };
7152
5653
 
7153
- /*************************************************************************
7154
- * ADOBE CONFIDENTIAL
7155
- * ___________________
7156
- *
7157
- * Copyright 2022 Adobe
7158
- * All Rights Reserved.
7159
- *
7160
- * NOTICE: All information contained herein is, and remains
7161
- * the property of Adobe and its suppliers, if any. The intellectual
7162
- * and technical concepts contained herein are proprietary to Adobe
7163
- * and its suppliers and are protected by all applicable intellectual
7164
- * property laws, including trade secret and copyright laws.
7165
- * Dissemination of this information or reproduction of this material
7166
- * is strictly forbidden unless prior written permission is obtained
7167
- * from Adobe.
7168
- **************************************************************************/
7169
- /**
7170
- * https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
7171
- * Credit: https://git.corp.adobe.com/dc/dfl/blob/master/src/patterns/parseDateTimeSkeleton.js
7172
- * Created a separate library to be used elsewhere as well.
7173
- */
7174
5654
  const DATE_TIME_REGEX =
7175
- // eslint-disable-next-line max-len
7176
5655
  /(?:[Eec]{1,6}|G{1,5}|[Qq]{1,5}|(?:[yYur]+|U{1,5})|[ML]{1,5}|d{1,2}|D{1,3}|F{1}|[abB]{1,5}|[hkHK]{1,2}|w{1,2}|W{1}|m{1,2}|s{1,2}|[zZOvV]{1,5}|[zZOvVxX]{1,3}|S{1,3}|'(?:[^']|'')*')|[^a-zA-Z']+/g;
7177
-
7178
5656
  const ShorthandStyles$1 = ["full", "long", "medium", "short"];
7179
-
7180
5657
  function getSkeleton(skeleton, language) {
7181
5658
  if (ShorthandStyles$1.find(type => skeleton.includes(type))) {
7182
5659
  const parsed = parseDateStyle(skeleton, language);
@@ -7197,24 +5674,13 @@ function getSkeleton(skeleton, language) {
7197
5674
  }
7198
5675
  return skeleton;
7199
5676
  }
7200
-
7201
- /**
7202
- *
7203
- * @param skeleton shorthand style for the date concatenated with shorthand style of time. The
7204
- * Shorthand style for both date and time is one of ['full', 'long', 'medium', 'short'].
7205
- * @param language {string} language to parse the date shorthand style
7206
- * @returns {[*,string][]}
7207
- */
7208
5677
  function parseDateStyle(skeleton, language) {
7209
5678
  const options = {};
7210
- // the skeleton could have two keywords -- one for date, one for time
7211
5679
  const styles = skeleton.split(/\s/).filter(s => s.length);
7212
5680
  options.dateStyle = styles[0];
7213
5681
  if (styles.length > 1) options.timeStyle = styles[1];
7214
-
7215
5682
  const testDate = new Date(2000, 2, 1, 2, 3, 4);
7216
5683
  const parts = new Intl.DateTimeFormat(language, options).formatToParts(testDate);
7217
- // oddly, the formatted month name can be different from the standalone month name
7218
5684
  const formattedMarch = parts.find(p => p.type === 'month').value;
7219
5685
  const longMarch = new Intl.DateTimeFormat(language, {month: 'long'}).formatToParts(testDate)[0].value;
7220
5686
  const shortMarch = new Intl.DateTimeFormat(language, {month: 'short'}).formatToParts(testDate)[0].value;
@@ -7238,11 +5704,6 @@ function parseDateStyle(skeleton, language) {
7238
5704
  });
7239
5705
  return result;
7240
5706
  }
7241
-
7242
- /**
7243
- * Parse Date time skeleton into Intl.DateTimeFormatOptions parts
7244
- * Ref: https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
7245
- */
7246
5707
  function parseDateTimeSkeleton(skeleton, language) {
7247
5708
  if (ShorthandStyles$1.find(type => skeleton.includes(type))) {
7248
5709
  return parseDateStyle(skeleton, language);
@@ -7251,11 +5712,9 @@ function parseDateTimeSkeleton(skeleton, language) {
7251
5712
  skeleton.replace(DATE_TIME_REGEX, match => {
7252
5713
  const len = match.length;
7253
5714
  switch (match[0]) {
7254
- // Era
7255
5715
  case 'G':
7256
5716
  result.push(['era', len === 4 ? 'long' : len === 5 ? 'narrow' : 'short', len]);
7257
5717
  break;
7258
- // Year
7259
5718
  case 'y':
7260
5719
  result.push(['year', len === 2 ? '2-digit' : 'numeric', len]);
7261
5720
  break;
@@ -7266,16 +5725,13 @@ function parseDateTimeSkeleton(skeleton, language) {
7266
5725
  throw new RangeError(
7267
5726
  '`Y/u/U/r` (year) patterns are not supported, use `y` instead'
7268
5727
  );
7269
- // Quarter
7270
5728
  case 'q':
7271
5729
  case 'Q':
7272
5730
  throw new RangeError('`q/Q` (quarter) patterns are not supported');
7273
- // Month
7274
5731
  case 'M':
7275
5732
  case 'L':
7276
5733
  result.push(['month', ['numeric', '2-digit', 'short', 'long', 'narrow'][len - 1], len]);
7277
5734
  break;
7278
- // Week
7279
5735
  case 'w':
7280
5736
  case 'W':
7281
5737
  throw new RangeError('`w/W` (week) patterns are not supported');
@@ -7288,7 +5744,6 @@ function parseDateTimeSkeleton(skeleton, language) {
7288
5744
  throw new RangeError(
7289
5745
  '`D/F/g` (day) patterns are not supported, use `d` instead'
7290
5746
  );
7291
- // Weekday
7292
5747
  case 'E':
7293
5748
  result.push(['weekday', ['short', 'short', 'short', 'long', 'narrow', 'narrow'][len - 1], len]);
7294
5749
  break;
@@ -7304,16 +5759,14 @@ function parseDateTimeSkeleton(skeleton, language) {
7304
5759
  }
7305
5760
  result.push(['weekday', ['short', 'long', 'narrow', 'short'][len - 3], len]);
7306
5761
  break;
7307
- // Period
7308
- case 'a': // AM, PM
5762
+ case 'a':
7309
5763
  result.push(['hour12', true, 1]);
7310
5764
  break;
7311
- case 'b': // am, pm, noon, midnight
7312
- case 'B': // flexible day periods
5765
+ case 'b':
5766
+ case 'B':
7313
5767
  throw new RangeError(
7314
5768
  '`b/B` (period) patterns are not supported, use `a` instead'
7315
5769
  );
7316
- // Hour
7317
5770
  case 'h':
7318
5771
  result.push(['hourCycle', 'h12']);
7319
5772
  result.push(['hour', ['numeric', '2-digit'][len - 1], len]);
@@ -7336,11 +5789,9 @@ function parseDateTimeSkeleton(skeleton, language) {
7336
5789
  throw new RangeError(
7337
5790
  '`j/J/C` (hour) patterns are not supported, use `h/H/K/k` instead'
7338
5791
  );
7339
- // Minute
7340
5792
  case 'm':
7341
5793
  result.push(['minute', ['numeric', '2-digit'][len - 1], len]);
7342
5794
  break;
7343
- // Second
7344
5795
  case 's':
7345
5796
  result.push(['second', ['numeric', '2-digit'][len - 1], len]);
7346
5797
  break;
@@ -7351,23 +5802,19 @@ function parseDateTimeSkeleton(skeleton, language) {
7351
5802
  throw new RangeError(
7352
5803
  '`S/A` (millisecond) patterns are not supported, use `s` instead'
7353
5804
  );
7354
- // Zone
7355
- case 'O': // timeZone GMT-8 or GMT-08:00
5805
+ case 'O':
7356
5806
  result.push(['timeZoneName', len < 4 ? 'shortOffset' : 'longOffset', len]);
7357
5807
  result.push(['x-timeZoneName', len < 4 ? 'O' : 'OOOO', len]);
7358
5808
  break;
7359
- case 'X': // 1, 2, 3, 4: The ISO8601 varios formats
7360
- case 'x': // 1, 2, 3, 4: The ISO8601 varios formats
7361
- case 'Z': // 1..3, 4, 5: The ISO8601 varios formats
7362
- // Z, ZZ, ZZZ should produce -0800
7363
- // ZZZZ should produce GMT-08:00
7364
- // ZZZZZ should produce -8:00 or -07:52:58
5809
+ case 'X':
5810
+ case 'x':
5811
+ case 'Z':
7365
5812
  result.push(['timeZoneName', 'longOffset', 1]);
7366
5813
  result.push(['x-timeZoneName', match, 1]);
7367
5814
  break;
7368
- case 'z': // 1..3, 4: specific non-location format
7369
- case 'v': // 1, 4: generic non-location format
7370
- case 'V': // 1, 2, 3, 4: time zone ID or city
5815
+ case 'z':
5816
+ case 'v':
5817
+ case 'V':
7371
5818
  throw new RangeError(
7372
5819
  'z/v/V` (timeZone) patterns are not supported, use `X/x/Z/O` instead'
7373
5820
  );
@@ -7382,29 +5829,6 @@ function parseDateTimeSkeleton(skeleton, language) {
7382
5829
  return result;
7383
5830
  }
7384
5831
 
7385
- /*************************************************************************
7386
- * ADOBE CONFIDENTIAL
7387
- * ___________________
7388
- *
7389
- * Copyright 2022 Adobe
7390
- * All Rights Reserved.
7391
- *
7392
- * NOTICE: All information contained herein is, and remains
7393
- * the property of Adobe and its suppliers, if any. The intellectual
7394
- * and technical concepts contained herein are proprietary to Adobe
7395
- * and its suppliers and are protected by all applicable intellectual
7396
- * property laws, including trade secret and copyright laws.
7397
- * Dissemination of this information or reproduction of this material
7398
- * is strictly forbidden unless prior written permission is obtained
7399
- * from Adobe.
7400
- **************************************************************************/
7401
-
7402
- /**
7403
- * in some cases, DateTimeFormat doesn't respect the 'numeric' vs. '2-digit' setting
7404
- * for time values. The function corrects that
7405
- * @param formattedParts instance of Intl.DateTimeFormatPart[]
7406
- * @param parsed
7407
- */
7408
5832
  function fixDigits(formattedParts, parsed) {
7409
5833
  ['hour', 'minute', 'second'].forEach(type => {
7410
5834
  const defn = formattedParts.find(f => f.type === type);
@@ -7414,55 +5838,29 @@ function fixDigits(formattedParts, parsed) {
7414
5838
  if (fmt === 'numeric' && defn.value.length === 2 && defn.value.charAt(0) === '0') defn.value = defn.value.slice(1);
7415
5839
  });
7416
5840
  }
7417
-
7418
5841
  function fixYear(formattedParts, parsed) {
7419
- // two digit years are handled differently in DateTimeFormat. 00 becomes 1900
7420
- // providing a two digit year 0010 gets formatted to 10 and when parsed becomes 1910
7421
- // Hence we need to pad the year with 0 as required by the skeleton and mentioned in
7422
- // unicode. https://www.unicode.org/reports/tr35/tr35-dates.html#dfst-year
7423
5842
  const defn = formattedParts.find(f => f.type === 'year');
7424
5843
  if (!defn) return;
7425
- // eslint-disable-next-line no-unused-vars
7426
5844
  const chars = parsed.find(pair => pair[0] === 'year')[2];
7427
5845
  while(defn.value.length < chars) {
7428
5846
  defn.value = `0${defn.value}`;
7429
5847
  }
7430
5848
  }
7431
-
7432
- /**
7433
- *
7434
- * @param dateValue {Date}
7435
- * @param language {string}
7436
- * @param skeleton {string}
7437
- * @param timeZone {string}
7438
- * @returns {T}
7439
- */
7440
5849
  function formatDateToParts(dateValue, language, skeleton, timeZone) {
7441
- // DateTimeFormat renames some of the options in its formatted output
7442
- //@ts-ignore
7443
5850
  const mappings = key => ({
7444
5851
  hour12: 'dayPeriod',
7445
5852
  fractionalSecondDigits: 'fractionalSecond',
7446
5853
  })[key] || key;
7447
-
7448
- // produces an array of name/value pairs of skeleton parts
7449
5854
  const allParameters = parseDateTimeSkeleton(skeleton, language);
7450
5855
  allParameters.push(['timeZone', timeZone]);
7451
-
7452
5856
  const parsed = allParameters.filter(p => !p[0].startsWith('x-'));
7453
5857
  const nonStandard = allParameters.filter(p => p[0].startsWith('x-'));
7454
- // reduce to a set of options that can be used to format
7455
5858
  const options = Object.fromEntries(parsed);
7456
5859
  delete options.literal;
7457
-
7458
5860
  const df = new Intl.DateTimeFormat(language, options);
7459
- // formattedParts will have all the pieces we need for our date -- but not in the correct order
7460
5861
  const formattedParts = df.formatToParts(dateValue);
7461
-
7462
5862
  fixDigits(formattedParts, allParameters);
7463
5863
  fixYear(formattedParts, parsed);
7464
- // iterate through the original parsed components and use its ordering and literals,
7465
- // and add the formatted pieces
7466
5864
  return parsed.reduce((result, cur) => {
7467
5865
  if (cur[0] === 'literal') result.push(cur);
7468
5866
  else {
@@ -7472,37 +5870,25 @@ function formatDateToParts(dateValue, language, skeleton, timeZone) {
7472
5870
  const category = tz[0];
7473
5871
  if (category === 'Z') {
7474
5872
  if (tz.length < 4) {
7475
- // handle 'Z', 'ZZ', 'ZZZ' Time Zone: ISO8601 basic hms? / RFC 822
7476
5873
  v.value = v.value.replace(/(GMT|:)/g, '');
7477
5874
  if (v.value === '') v.value = '+0000';
7478
5875
  } else if (tz.length === 5) {
7479
- // 'ZZZZZ' Time Zone: ISO8601 extended hms?
7480
5876
  if (v.value === 'GMT') v.value = 'Z';
7481
5877
  else v.value = v.value.replace(/GMT/, '');
7482
5878
  }
7483
5879
  }
7484
5880
  if (category === 'X' || category === 'x') {
7485
5881
  if (tz.length === 1) {
7486
- // 'X' ISO8601 basic hm?, with Z for 0
7487
- // -08, +0530, Z
7488
- // 'x' ISO8601 basic hm?, without Z for 0
7489
5882
  v.value = v.value.replace(/(GMT|:(00)?)/g, '');
7490
5883
  }
7491
5884
  if (tz.length === 2) {
7492
- // 'XX' ISO8601 basic hm, with Z
7493
- // -0800, Z
7494
- // 'xx' ISO8601 basic hm, without Z
7495
5885
  v.value = v.value.replace(/(GMT|:)/g, '');
7496
5886
  }
7497
5887
  if (tz.length === 3) {
7498
- // 'XXX' ISO8601 extended hm, with Z
7499
- // -08:00, Z
7500
- // 'xxx' ISO8601 extended hm, without Z
7501
5888
  v.value = v.value.replace(/GMT/g, '');
7502
5889
  }
7503
5890
  if (category === 'X' && v.value === '') v.value = 'Z';
7504
5891
  } else if (tz === 'O') {
7505
- // eliminate 'GMT', leading and trailing zeros
7506
5892
  v.value = v.value.replace(/GMT/g, '').replace(/0(\d+):/, '$1:').replace(/:00/, '');
7507
5893
  if (v.value === '') v.value = '+0';
7508
5894
  }
@@ -7512,18 +5898,12 @@ function formatDateToParts(dateValue, language, skeleton, timeZone) {
7512
5898
  return result;
7513
5899
  }, []);
7514
5900
  }
7515
-
7516
- /**
7517
- *
7518
- * @param dateValue {Date}
7519
- * @param language {string}
7520
- * @param skeleton {string}
7521
- * @param timeZone {string}
7522
- */
7523
5901
  function formatDate(dateValue, language, skeleton, timeZone) {
5902
+ if (skeleton.startsWith('date|')) {
5903
+ skeleton = skeleton.split('|')[1];
5904
+ }
7524
5905
  if (ShorthandStyles$1.find(type => skeleton.includes(type))) {
7525
5906
  const options = {timeZone};
7526
- // the skeleton could have two keywords -- one for date, one for time
7527
5907
  const parts = skeleton.split(/\s/).filter(s => s.length);
7528
5908
  if (ShorthandStyles$1.indexOf(parts[0]) > -1) {
7529
5909
  options.dateStyle = parts[0];
@@ -7559,9 +5939,7 @@ const currencies = {
7559
5939
  'ru-RU': 'RUB',
7560
5940
  'tr-TR': 'TRY'
7561
5941
  };
7562
-
7563
5942
  const locales = Object.keys(currencies);
7564
-
7565
5943
  const getCurrency = function (locale) {
7566
5944
  if (locales.indexOf(locale) > -1) {
7567
5945
  return currencies[locale]
@@ -7575,8 +5953,7 @@ const getCurrency = function (locale) {
7575
5953
  };
7576
5954
 
7577
5955
  const NUMBER_REGEX =
7578
- // eslint-disable-next-line max-len
7579
- /(?:[#]+|[@]+(?:#+)?|[0]+|[,]|[.]|[-]|[+]|[%]|[¤]{1,4}(?:\/([a-zA-Z]{3}))?|[;]|[K]{1,2}|E{1,2}[+]?|'(?:[^']|'')*')|[^a-zA-Z']+/g;
5956
+ /(?:[#]+|[@]+(#+)?|[0]+|[,]|[.]|[-]|[+]|[%]|[¤]{1,4}(?:\/([a-zA-Z]{3}))?|[;]|[K]{1,2}|E{1,2}[+]?|'(?:[^']|'')*')|[^a-zA-Z']+/g;
7580
5957
  const supportedUnits = ['acre', 'bit', 'byte', 'celsius', 'centimeter', 'day',
7581
5958
  'degree', 'fahrenheit', 'fluid-ounce', 'foot', 'gallon', 'gigabit',
7582
5959
  'gigabyte', 'gram', 'hectare', 'hour', 'inch', 'kilobit', 'kilobyte',
@@ -7584,8 +5961,6 @@ const supportedUnits = ['acre', 'bit', 'byte', 'celsius', 'centimeter', 'day',
7584
5961
  'mile-scandinavian', 'milliliter', 'millimeter', 'millisecond', 'minute', 'month',
7585
5962
  'ounce', 'percent', 'petabyte', 'pound', 'second', 'stone', 'terabit', 'terabyte', 'week', 'yard', 'year'].join('|');
7586
5963
  const ShorthandStyles = [/^currency(?:\/([a-zA-Z]{3}))?$/, /^decimal$/, /^integer$/, /^percent$/, new RegExp(`^unit\/(${supportedUnits})$`)];
7587
-
7588
-
7589
5964
  function parseNumberSkeleton(skeleton, language) {
7590
5965
  const options = {};
7591
5966
  const order = [];
@@ -7614,6 +5989,7 @@ function parseNumberSkeleton(skeleton, language) {
7614
5989
  break;
7615
5990
  case 4:
7616
5991
  options.style = 'percent';
5992
+ options.maximumFractionDigits = 2;
7617
5993
  break;
7618
5994
  case 5:
7619
5995
  options.style = "unit";
@@ -7630,7 +6006,7 @@ function parseNumberSkeleton(skeleton, language) {
7630
6006
  options.minimumIntegerDigits = 1;
7631
6007
  options.maximumFractionDigits = 0;
7632
6008
  options.minimumFractionDigits = 0;
7633
- skeleton.replace(NUMBER_REGEX, (match, offset) => {
6009
+ skeleton.replace(NUMBER_REGEX, (match, maxSignificantDigits, currencySymbol, offset) => {
7634
6010
  const len = match.length;
7635
6011
  switch(match[0]) {
7636
6012
  case '#':
@@ -7643,10 +6019,10 @@ function parseNumberSkeleton(skeleton, language) {
7643
6019
  if (options?.minimumSignificantDigits) {
7644
6020
  throw "@ symbol should occur together"
7645
6021
  }
7646
- order.push(['@', len]);
7647
- options.minimumSignificantDigits = len;
7648
- const hashes = match.match(/#+/) || "";
7649
- options.maximumSignificantDigits = len + hashes.length;
6022
+ const hashes = maxSignificantDigits || "";
6023
+ order.push(['@', len - hashes.length]);
6024
+ options.minimumSignificantDigits = len - hashes.length;
6025
+ options.maximumSignificantDigits = len;
7650
6026
  order.push(['digit', hashes.length]);
7651
6027
  break;
7652
6028
  case ',':
@@ -7671,6 +6047,9 @@ function parseNumberSkeleton(skeleton, language) {
7671
6047
  }
7672
6048
  if (options?.decimal === true) {
7673
6049
  options.minimumFractionDigits = len;
6050
+ if (!options.maximumFractionDigits) {
6051
+ options.maximumFractionDigits = len;
6052
+ }
7674
6053
  } else {
7675
6054
  options.minimumIntegerDigits = len;
7676
6055
  }
@@ -7694,18 +6073,20 @@ function parseNumberSkeleton(skeleton, language) {
7694
6073
  case '¤':
7695
6074
  if (offset !== 0 && offset !== skeleton.length - 1) {
7696
6075
  console.error("currency display should be either in the beginning or at the end");
6076
+ } else {
6077
+ options.style = 'currency';
6078
+ options.currencyDisplay = ['symbol', 'code', 'name', 'narrowSymbol'][len - 1];
6079
+ options.currency = currencySymbol || getCurrency(language);
6080
+ order.push(['currency', len]);
7697
6081
  }
7698
- options.style = 'currency';
7699
- options.currencyDisplay = ['symbol', 'code', 'name', 'narrowSymbol'][len -1];
7700
- options.currency = getCurrency(language);
7701
- order.push(['currency', len]);
7702
6082
  break;
7703
6083
  case '%':
7704
6084
  if (offset !== 0 && offset !== skeleton.length - 1) {
7705
6085
  console.error("percent display should be either in the beginning or at the end");
6086
+ } else {
6087
+ order.push(['%', 1]);
6088
+ options.style = 'percent';
7706
6089
  }
7707
- order.push(['%', 1]);
7708
- options.style = 'percent';
7709
6090
  break;
7710
6091
  case 'E':
7711
6092
  order.push(['E', len]);
@@ -7722,6 +6103,9 @@ function parseNumberSkeleton(skeleton, language) {
7722
6103
  }
7723
6104
 
7724
6105
  function formatNumber(numberValue, language, skeletn) {
6106
+ if (skeletn.startsWith('num|')) {
6107
+ skeletn = skel.split('|')[1];
6108
+ }
7725
6109
  if (!skeletn) return numberValue
7726
6110
  language = language || "en";
7727
6111
  const {options, order} = parseNumberSkeleton(skeletn, language);
@@ -7732,7 +6116,6 @@ const getCategory = function (skeleton) {
7732
6116
  const chkCategory = skeleton?.match(/^(?:(num|date)\|)?(.+)/);
7733
6117
  return [chkCategory?.[1], chkCategory?.[2]]
7734
6118
  };
7735
-
7736
6119
  const format = function (value, locale, skeleton, timezone) {
7737
6120
  const [category, skelton] = getCategory(skeleton);
7738
6121
  switch (category) {
@@ -7748,12 +6131,6 @@ const format = function (value, locale, skeleton, timezone) {
7748
6131
  }
7749
6132
  };
7750
6133
 
7751
- var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
7752
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
7753
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
7754
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
7755
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7756
- };
7757
6134
  const validTypes = ['string', 'number', 'boolean', 'file', 'string[]', 'number[]', 'boolean[]', 'file[]', 'array', 'object'];
7758
6135
  class Field extends Scriptable {
7759
6136
  constructor(params, _options) {
@@ -7902,10 +6279,10 @@ class Field extends Scriptable {
7902
6279
  }
7903
6280
  }
7904
6281
  get editFormat() {
7905
- return this._jsonModel.editFormat;
6282
+ return this.withCategory(this._jsonModel.editFormat);
7906
6283
  }
7907
6284
  get displayFormat() {
7908
- return this._jsonModel.displayFormat;
6285
+ return this.withCategory(this._jsonModel.displayFormat);
7909
6286
  }
7910
6287
  get placeholder() {
7911
6288
  return this._jsonModel.placeholder;
@@ -7978,31 +6355,43 @@ class Field extends Scriptable {
7978
6355
  return this._jsonModel.value === undefined || this._jsonModel.value === null || this._jsonModel.value === '';
7979
6356
  }
7980
6357
  withCategory(df) {
7981
- const hasCategory = df?.match(/^(?:date|num)\|/);
7982
- if (hasCategory == null) {
7983
- if (this.format === 'date') {
7984
- df = `date|${df}`;
7985
- }
7986
- else if (this.type === 'number') {
7987
- df = `num|${df}`;
6358
+ if (df) {
6359
+ const hasCategory = df?.match(/^(?:date|num)\|/);
6360
+ if (hasCategory === null) {
6361
+ if (this.format === 'date') {
6362
+ df = `date|${df}`;
6363
+ }
6364
+ else if (this.type === 'number') {
6365
+ df = `num|${df}`;
6366
+ }
6367
+ return df;
7988
6368
  }
7989
- return df;
7990
6369
  }
7991
6370
  return df;
7992
6371
  }
7993
6372
  get editValue() {
7994
- const df = this.withCategory(this.editFormat);
6373
+ const df = this.editFormat;
7995
6374
  if (df && this.isNotEmpty(this.value) && this.valid !== false) {
7996
- return format(this.value, this.language, df);
6375
+ try {
6376
+ return format(this.value, this.language, df);
6377
+ }
6378
+ catch (e) {
6379
+ return this.value;
6380
+ }
7997
6381
  }
7998
6382
  else {
7999
6383
  return this.value;
8000
6384
  }
8001
6385
  }
8002
6386
  get displayValue() {
8003
- const df = this.withCategory(this.displayFormat);
6387
+ const df = this.displayFormat;
8004
6388
  if (df && this.isNotEmpty(this.value) && this.valid !== false) {
8005
- return format(this.value, this.language, df);
6389
+ try {
6390
+ return format(this.value, this.language, df);
6391
+ }
6392
+ catch (e) {
6393
+ return this.value;
6394
+ }
8006
6395
  }
8007
6396
  else {
8008
6397
  return this.value;
@@ -8142,7 +6531,7 @@ class Field extends Scriptable {
8142
6531
  const iv = this._jsonModel.minimum || this._jsonModel.default || 0;
8143
6532
  const fIVal = iv * factor;
8144
6533
  const qt = (fVal - fIVal) / fStep;
8145
- const valid = (fVal - fIVal) % fStep < .001;
6534
+ const valid = Math.abs(fVal - fIVal) % fStep < .001;
8146
6535
  let next, prev;
8147
6536
  if (!valid) {
8148
6537
  next = (Math.ceil(qt) * fStep + fIVal) / factor;
@@ -8345,6 +6734,8 @@ class Field extends Scriptable {
8345
6734
  getState() {
8346
6735
  return {
8347
6736
  ...super.getState(),
6737
+ editFormat: this.editFormat,
6738
+ displayFormat: this.displayFormat,
8348
6739
  editValue: this.editValue,
8349
6740
  displayValue: this.displayValue
8350
6741
  };