@aemforms/af-core 0.22.15 → 0.22.17

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.
@@ -16,7 +16,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
16
16
  });
17
17
  };
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.submit = exports.request = void 0;
19
+ exports.FunctionRuntime = exports.submit = exports.request = void 0;
20
20
  /**
21
21
  * Implementation of function runtime in rule engine
22
22
  */
@@ -26,6 +26,13 @@ const Fetch_1 = require("../utils/Fetch");
26
26
  const FileObject_1 = require("../FileObject");
27
27
  const FormUtils_1 = require("../utils/FormUtils");
28
28
  const JsonUtils_1 = require("../utils/JsonUtils");
29
+ const getCustomEventName = (name) => {
30
+ const eName = name;
31
+ if (eName.length > 0 && eName.startsWith('custom:')) {
32
+ return eName.substring('custom:'.length);
33
+ }
34
+ return eName;
35
+ };
29
36
  /**
30
37
  * Implementation of generic request API. This API can be used to make external web request
31
38
  * @param context expression execution context(consists of current form, current field, current event)
@@ -34,10 +41,11 @@ const JsonUtils_1 = require("../utils/JsonUtils");
34
41
  * @param payload request payload
35
42
  * @param success success handler
36
43
  * @param error error handler
37
- * @param payloadContentType content type of the request
44
+ * @param headers headers
38
45
  * @private
39
46
  */
40
- const request = (context, uri, httpVerb, payload, success, error, payloadContentType) => __awaiter(void 0, void 0, void 0, function* () {
47
+ const request = (context, uri, httpVerb, payload, success, error, headers) => __awaiter(void 0, void 0, void 0, function* () {
48
+ var _a;
41
49
  const endpoint = uri;
42
50
  const requestOptions = {
43
51
  method: httpVerb
@@ -55,24 +63,50 @@ const request = (context, uri, httpVerb, payload, success, error, payloadContent
55
63
  inputPayload = payload;
56
64
  }
57
65
  else if (payload && typeof payload === 'object' && Object.keys(payload).length > 0) {
58
- if (payloadContentType.length > 0) {
59
- requestOptions.headers = {
60
- 'Content-Type': payloadContentType // this should match content type of the payload
61
- };
66
+ const headerNames = Object.keys(headers);
67
+ if (headerNames.length > 0) {
68
+ requestOptions.headers = Object.assign(Object.assign({}, headers), (headerNames.indexOf('Content-Type') === -1 ? { 'Content-Type': 'application/json' } : {}) // this should match content type of the payload
69
+ );
70
+ }
71
+ else {
72
+ requestOptions.headers = { 'Content-Type': 'application/json' };
73
+ }
74
+ const contentType = ((_a = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.headers) === null || _a === void 0 ? void 0 : _a['Content-Type']) || 'application/json';
75
+ if (contentType === 'application/json') {
76
+ inputPayload = JSON.stringify(payload);
77
+ }
78
+ else if (contentType.indexOf('multipart/form-data') > -1) {
79
+ inputPayload = multipartFormData(payload);
80
+ }
81
+ else if (contentType.indexOf('application/x-www-form-urlencoded') > -1) {
82
+ inputPayload = urlEncoded(payload);
62
83
  }
63
- inputPayload = JSON.stringify(payload);
64
84
  }
65
85
  result = yield (0, Fetch_1.request)(endpoint, inputPayload, requestOptions);
66
86
  }
67
87
  catch (e) {
68
88
  //todo: define error payload
69
89
  context.form.logger.error('Error invoking a rest API');
70
- context.form.dispatch(new Controller_1.CustomEvent(error, {}, true));
90
+ const eName = getCustomEventName(error);
91
+ context.form.dispatch(new Controller_1.CustomEvent(eName, {}, true));
71
92
  return;
72
93
  }
73
- context.form.dispatch(new Controller_1.CustomEvent(success, result, true));
94
+ const eName = getCustomEventName(success);
95
+ context.form.dispatch(new Controller_1.CustomEvent(eName, result, true));
74
96
  });
75
97
  exports.request = request;
98
+ const urlEncoded = (data) => {
99
+ const formData = new URLSearchParams();
100
+ Object.entries(data).forEach(([key, value]) => {
101
+ if (value != null && typeof value === 'object') {
102
+ formData.append(key, (0, JsonUtils_1.jsonString)(value));
103
+ }
104
+ else {
105
+ formData.append(key, value);
106
+ }
107
+ });
108
+ return formData;
109
+ };
76
110
  /**
77
111
  * Create multi part form data using form data and form attachments
78
112
  * @param data form data
@@ -99,16 +133,18 @@ const multipartFormData = (data, attachments) => {
99
133
  formData.append(attIdentifier, objValue.data);
100
134
  }
101
135
  };
102
- // @ts-ignore
103
- Object.keys(attachments).reduce((acc, curr) => {
104
- const objValue = attachments[curr];
105
- if (objValue && objValue instanceof Array) {
106
- return [...acc, ...objValue.map((x) => addAttachmentToFormData(x, formData))];
107
- }
108
- else {
109
- return [...acc, addAttachmentToFormData(objValue, formData)];
110
- }
111
- }, []);
136
+ if (attachments) {
137
+ // @ts-ignore
138
+ Object.keys(attachments).reduce((acc, curr) => {
139
+ const objValue = attachments[curr];
140
+ if (objValue && objValue instanceof Array) {
141
+ return [...acc, ...objValue.map((x) => addAttachmentToFormData(x, formData))];
142
+ }
143
+ else {
144
+ return [...acc, addAttachmentToFormData(objValue, formData)];
145
+ }
146
+ }, []);
147
+ }
112
148
  return formData;
113
149
  };
114
150
  const submit = (context, success, error, submitAs = 'multipart/form-data', input_data = null) => __awaiter(void 0, void 0, void 0, function* () {
@@ -131,7 +167,9 @@ const submit = (context, success, error, submitAs = 'multipart/form-data', input
131
167
  }
132
168
  // submitContentType = submitAs;
133
169
  // note: don't send multipart/form-data let browser decide on the content type
134
- yield (0, exports.request)(context, endpoint, 'POST', formData, success, error, submitContentType);
170
+ yield (0, exports.request)(context, endpoint, 'POST', formData, success, error, {
171
+ 'Content-Type': submitContentType
172
+ });
135
173
  });
136
174
  exports.submit = submit;
137
175
  /**
@@ -232,6 +270,19 @@ class FunctionRuntimeImpl {
232
270
  },
233
271
  _signature: []
234
272
  },
273
+ setFocus: {
274
+ _func: (args, data, interpreter) => {
275
+ const element = args[0];
276
+ try {
277
+ const field = interpreter.globals.form.getElement(element.$id);
278
+ interpreter.globals.form.setFocus(field);
279
+ }
280
+ catch (e) {
281
+ interpreter.globals.form.logger.error('Invalid argument passed in setFocus. An element is expected');
282
+ }
283
+ },
284
+ _signature: []
285
+ },
235
286
  getData: {
236
287
  _func: (args, data, interpreter) => {
237
288
  // deprecated. left for backward compatability.
@@ -279,9 +330,18 @@ class FunctionRuntimeImpl {
279
330
  const uri = toString(args[0]);
280
331
  const httpVerb = toString(args[1]);
281
332
  const payload = valueOf(args[2]);
282
- const success = valueOf(args[3]);
283
- const error = valueOf(args[4]);
284
- (0, exports.request)(interpreter.globals, uri, httpVerb, payload, success, error, 'application/json');
333
+ let success, error, headers = {};
334
+ if (typeof (args[3]) === 'string') {
335
+ interpreter.globals.form.logger.warn('This usage of request is deprecated. Please see the documentation and update');
336
+ success = valueOf(args[3]);
337
+ error = valueOf(args[4]);
338
+ }
339
+ else {
340
+ headers = valueOf(args[3]);
341
+ success = valueOf(args[4]);
342
+ error = valueOf(args[5]);
343
+ }
344
+ (0, exports.request)(interpreter.globals, uri, httpVerb, payload, success, error, headers);
285
345
  return {};
286
346
  },
287
347
  _signature: []
@@ -327,5 +387,4 @@ class FunctionRuntimeImpl {
327
387
  return Object.assign(Object.assign({}, defaultFunctions), this.customFunctions);
328
388
  }
329
389
  }
330
- const FunctionRuntime = new FunctionRuntimeImpl();
331
- exports.default = FunctionRuntime;
390
+ exports.FunctionRuntime = new FunctionRuntimeImpl();
@@ -6,12 +6,9 @@
6
6
  *
7
7
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ADOBE NOR ITS THIRD PARTY PROVIDERS AND PARTNERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8
8
  */
9
- var __importDefault = (this && this.__importDefault) || function (mod) {
10
- return (mod && mod.__esModule) ? mod : { "default": mod };
11
- };
12
9
  Object.defineProperty(exports, "__esModule", { value: true });
13
10
  const json_formula_1 = require("@adobe/json-formula");
14
- const FunctionRuntime_1 = __importDefault(require("./FunctionRuntime"));
11
+ const FunctionRuntime_1 = require("./FunctionRuntime");
15
12
  /**
16
13
  * Implementation of rule engine
17
14
  * @private
@@ -25,7 +22,7 @@ class RuleEngine {
25
22
  ];
26
23
  }
27
24
  compileRule(rule) {
28
- const customFunctions = FunctionRuntime_1.default.getFunctions();
25
+ const customFunctions = FunctionRuntime_1.FunctionRuntime.getFunctions();
29
26
  return new json_formula_1.Formula(rule, customFunctions, undefined, this._globalNames);
30
27
  }
31
28
  execute(node, data, globals, useValueOf = false) {
@@ -103,6 +103,7 @@ export declare type FieldJson = BaseJson & TranslationFieldJson & {
103
103
  export declare type ContainerJson = BaseJson & {
104
104
  items: Array<FieldJson | ContainerJson>;
105
105
  initialItems?: number;
106
+ activeChild?: string;
106
107
  };
107
108
  /** Type for `form metadata` based on `adaptive form specification` */
108
109
  export declare type MetaDataJson = {
@@ -5,7 +5,7 @@ import { ConstraintsJson, ContainerJson, FieldJson, FieldsetJson, FormJson, Labe
5
5
  import RuleEngine from '../rules/RuleEngine';
6
6
  import EventQueue from '../controller/EventQueue';
7
7
  import DataGroup from '../data/DataGroup';
8
- import { Logger } from '../Form';
8
+ import { Logger } from '../controller/Logger';
9
9
  /**
10
10
  * Generic Scriptable field interface. All non-transparent fields which support rule/events
11
11
  * should implement this interface
@@ -124,6 +124,10 @@ export interface BaseModel extends ConstraintsJson, WithController {
124
124
  * The index of the Field within its parent.
125
125
  */
126
126
  readonly index: number;
127
+ /**
128
+ *
129
+ */
130
+ readonly qualifiedName: string;
127
131
  /**
128
132
  * Label to be used for the field.
129
133
  */
@@ -276,6 +280,7 @@ export interface ContainerModel extends BaseModel, ScriptableField {
276
280
  */
277
281
  indexOf(f: FieldModel | FieldsetModel): number;
278
282
  isTransparent(): boolean;
283
+ activeChild: BaseModel | null;
279
284
  }
280
285
  /**
281
286
  * Generic field set model interface.
@@ -339,7 +344,7 @@ export interface IFileObject {
339
344
  /**
340
345
  * Media type of the file data
341
346
  */
342
- mediaType: string;
347
+ type: string;
343
348
  /**
344
349
  * Data of the file attachment. It can be uri or any file interface specific to channel (in web, it is file object).
345
350
  */
@@ -1,5 +1,4 @@
1
1
  import { ContainerModel } from '../types';
2
- import { FileObject } from '../FileObject';
3
2
  /**
4
3
  * Utility to generate a random word from seed
5
4
  * @param l seed value
@@ -24,13 +23,6 @@ export declare const getAttachments: (input: ContainerModel) => any;
24
23
  * @returns file size as bytes (in kb) based on IEC specification
25
24
  */
26
25
  export declare const getFileSizeInBytes: (str: any) => number;
27
- /**
28
- * Converts number to bytes based on the symbol as per IEC specification
29
- * @param size size as number
30
- * @param symbol symbol to use (for example, kb, mb, gb or tb)
31
- * @returns number as bytes based on the symbol
32
- */
33
- export declare const sizeToBytes: (size: number, symbol: string) => number;
34
26
  /**
35
27
  * ID Generator
36
28
  * @param initial
@@ -40,16 +32,16 @@ export declare const sizeToBytes: (size: number, symbol: string) => number;
40
32
  export declare const IdGenerator: (initial?: number) => Generator<string, void, string>;
41
33
  /**
42
34
  * Utility to extract {@link FileObject} from string or HTML File data type
43
- * @param files list of files as string , string [] of file[]
35
+ * @param file
44
36
  * @returns list of {@link FileObject}
45
37
  */
46
- export declare const extractFileInfo: (files: string[] | string | File[]) => FileObject[];
38
+ export declare const extractFileInfo: (file: any) => any;
47
39
  /**
48
40
  * Utility to convert data URI to a `blob` object
49
41
  * @param dataURI uri to convert to blob
50
42
  * @returns `Blob` object for the data URI
51
43
  */
52
44
  export declare const dataURItoBlob: (dataURI: string) => {
53
- blob: Blob;
54
45
  name: string;
55
- };
46
+ blob: Blob;
47
+ } | null;
@@ -7,7 +7,7 @@
7
7
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ADOBE NOR ITS THIRD PARTY PROVIDERS AND PARTNERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.dataURItoBlob = exports.extractFileInfo = exports.IdGenerator = exports.sizeToBytes = exports.getFileSizeInBytes = exports.getAttachments = exports.isEmpty = exports.randomWord = void 0;
10
+ exports.dataURItoBlob = exports.extractFileInfo = exports.IdGenerator = exports.getFileSizeInBytes = exports.getAttachments = exports.isEmpty = exports.randomWord = void 0;
11
11
  /**
12
12
  * Defines generic utilities to interact with form runtime model
13
13
  */
@@ -85,7 +85,7 @@ const getFileSizeInBytes = (str) => {
85
85
  if (typeof str === 'string') {
86
86
  const matches = fileSizeRegex.exec(str.trim());
87
87
  if (matches != null) {
88
- retVal = (0, exports.sizeToBytes)(parseFloat(matches[1]), (matches[2] || 'kb').toUpperCase());
88
+ retVal = sizeToBytes(parseFloat(matches[1]), (matches[2] || 'kb').toUpperCase());
89
89
  }
90
90
  }
91
91
  return retVal;
@@ -103,7 +103,6 @@ const sizeToBytes = (size, symbol) => {
103
103
  const i = Math.pow(1024, sizes[symbol]);
104
104
  return Math.round(size * i);
105
105
  };
106
- exports.sizeToBytes = sizeToBytes;
107
106
  /**
108
107
  * ID Generator
109
108
  * @param initial
@@ -138,12 +137,11 @@ const IdGenerator = function* (initial = 50) {
138
137
  exports.IdGenerator = IdGenerator;
139
138
  /**
140
139
  * Utility to extract {@link FileObject} from string or HTML File data type
141
- * @param files list of files as string , string [] of file[]
140
+ * @param file
142
141
  * @returns list of {@link FileObject}
143
142
  */
144
- const extractFileInfo = (files) => {
145
- return (files instanceof Array ? files : [files])
146
- .map((file) => {
143
+ const extractFileInfo = (file) => {
144
+ if (file !== null) {
147
145
  let retVal = null;
148
146
  if (file instanceof FileObject_1.FileObject) {
149
147
  retVal = file;
@@ -152,20 +150,23 @@ const extractFileInfo = (files) => {
152
150
  // case: file object
153
151
  retVal = {
154
152
  name: file.name,
155
- mediaType: file.type,
153
+ type: file.type,
156
154
  size: file.size,
157
155
  data: file
158
156
  };
159
157
  }
160
158
  else if (typeof file === 'string' && (0, ValidationUtils_1.isDataUrl)(file)) {
161
159
  // case: data URL
162
- const { blob, name } = (0, exports.dataURItoBlob)(file);
163
- retVal = {
164
- name: name,
165
- mediaType: blob.type,
166
- size: blob.size,
167
- data: blob
168
- };
160
+ const result = (0, exports.dataURItoBlob)(file);
161
+ if (result !== null) {
162
+ const { blob, name } = result;
163
+ retVal = {
164
+ name: name,
165
+ type: blob.type,
166
+ size: blob.size,
167
+ data: blob
168
+ };
169
+ }
169
170
  }
170
171
  else {
171
172
  // case: string as file object
@@ -179,20 +180,23 @@ const extractFileInfo = (files) => {
179
180
  }
180
181
  if (typeof (jFile === null || jFile === void 0 ? void 0 : jFile.data) === 'string' && (0, ValidationUtils_1.isDataUrl)(jFile === null || jFile === void 0 ? void 0 : jFile.data)) {
181
182
  // case: data URL
182
- const { blob } = (0, exports.dataURItoBlob)(jFile === null || jFile === void 0 ? void 0 : jFile.data);
183
- retVal = {
184
- name: jFile === null || jFile === void 0 ? void 0 : jFile.name,
185
- mediaType: jFile === null || jFile === void 0 ? void 0 : jFile.type,
186
- size: blob.size,
187
- data: blob
188
- };
183
+ const result = (0, exports.dataURItoBlob)(jFile === null || jFile === void 0 ? void 0 : jFile.data);
184
+ if (result !== null) {
185
+ const blob = result.blob;
186
+ retVal = {
187
+ name: jFile === null || jFile === void 0 ? void 0 : jFile.name,
188
+ type: jFile === null || jFile === void 0 ? void 0 : jFile.type,
189
+ size: blob.size,
190
+ data: blob
191
+ };
192
+ }
189
193
  }
190
194
  else if (typeof jFile === 'string') {
191
195
  // case: data as external url
192
196
  const fileName = jFile.split('/').pop();
193
197
  retVal = {
194
198
  name: fileName,
195
- mediaType: 'application/octet-stream',
199
+ type: 'application/octet-stream',
196
200
  size: 0,
197
201
  data: jFile
198
202
  };
@@ -201,14 +205,20 @@ const extractFileInfo = (files) => {
201
205
  // todo: just added for ease of integration for the view layer
202
206
  retVal = {
203
207
  name: jFile === null || jFile === void 0 ? void 0 : jFile.name,
204
- mediaType: (jFile === null || jFile === void 0 ? void 0 : jFile.type) || (jFile === null || jFile === void 0 ? void 0 : jFile.mediaType),
208
+ type: jFile === null || jFile === void 0 ? void 0 : jFile.type,
205
209
  size: jFile === null || jFile === void 0 ? void 0 : jFile.size,
206
210
  data: jFile === null || jFile === void 0 ? void 0 : jFile.data
207
211
  };
208
212
  }
209
213
  }
210
- return new FileObject_1.FileObject(retVal);
211
- });
214
+ if (retVal !== null && retVal.data != null) {
215
+ return new FileObject_1.FileObject(retVal);
216
+ }
217
+ return null;
218
+ }
219
+ else {
220
+ return null;
221
+ }
212
222
  };
213
223
  exports.extractFileInfo = extractFileInfo;
214
224
  /**
@@ -217,34 +227,28 @@ exports.extractFileInfo = extractFileInfo;
217
227
  * @returns `Blob` object for the data URI
218
228
  */
219
229
  const dataURItoBlob = (dataURI) => {
220
- // Split metadata from data
221
- const splitted = dataURI.split(',');
222
- // Split params
223
- const params = splitted[0].split(';');
224
- // Get mime-type from params
225
- const type = params[0].replace('data:', '');
226
- // Filter the name property from params
227
- const properties = params.filter(param => {
228
- return param.split('=')[0] === 'name';
229
- });
230
- // Look for the name and use unknown if no name property.
231
- let name;
232
- if (properties.length !== 1) {
233
- name = 'unknown';
230
+ const regex = /^data:([a-z]+\/[a-z0-9-+.]+)?(?:;name=([^;]+))?(;base64)?,(.+)$/;
231
+ const groups = regex.exec(dataURI);
232
+ if (groups !== null) {
233
+ const type = groups[1] || '';
234
+ const name = groups[2] || 'unknown';
235
+ const isBase64 = typeof groups[3] === 'string';
236
+ if (isBase64) {
237
+ const binary = atob(groups[4]);
238
+ const array = [];
239
+ for (let i = 0; i < binary.length; i++) {
240
+ array.push(binary.charCodeAt(i));
241
+ }
242
+ const blob = new window.Blob([new Uint8Array(array)], { type });
243
+ return { name, blob };
244
+ }
245
+ else {
246
+ const blob = new window.Blob([groups[4]], { type });
247
+ return { name, blob };
248
+ }
234
249
  }
235
250
  else {
236
- // Because we filtered out the other property,
237
- // we only have the name case here.
238
- name = properties[0].split('=')[1];
239
- }
240
- // Built the Uint8Array Blob parameter from the base64 string.
241
- const binary = atob(splitted[1]);
242
- const array = [];
243
- for (let i = 0; i < binary.length; i++) {
244
- array.push(binary.charCodeAt(i));
251
+ return null;
245
252
  }
246
- // Create the blob object
247
- const blob = new window.Blob([new Uint8Array(array)], { type });
248
- return { blob, name };
249
253
  };
250
254
  exports.dataURItoBlob = dataURItoBlob;
@@ -149,5 +149,22 @@ export declare const Constraints: {
149
149
  valid: boolean;
150
150
  value: any;
151
151
  };
152
+ /**
153
+ *
154
+ * @param constraint
155
+ * @param value
156
+ */
157
+ accept: (constraint: string[], value: any) => {
158
+ valid: boolean;
159
+ value: any;
160
+ };
161
+ /**
162
+ * @param constraint
163
+ * @param value
164
+ */
165
+ maxFileSize: (constraint: number | string, value: any) => {
166
+ valid: boolean;
167
+ value: any;
168
+ };
152
169
  };
153
170
  export {};
@@ -8,6 +8,8 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.Constraints = exports.ValidConstraints = exports.isDataUrl = void 0;
11
+ const FormUtils_1 = require("./FormUtils");
12
+ const FileObject_1 = require("../FileObject");
11
13
  /**
12
14
  * Defines generic utilities to validate form runtime model based on the constraints defined
13
15
  * as per `adaptive form specification`
@@ -56,6 +58,16 @@ const checkNumber = (inputVal) => {
56
58
  value, valid
57
59
  };
58
60
  };
61
+ const checkInteger = (inputVal) => {
62
+ let value = parseFloat(inputVal);
63
+ const valid = !isNaN(value) && Math.round(value) === value;
64
+ if (!valid) {
65
+ value = inputVal;
66
+ }
67
+ return {
68
+ value, valid
69
+ };
70
+ };
59
71
  /**
60
72
  * Wraps a non-null value and not an array value into an array
61
73
  * @param inputVal input value
@@ -88,6 +100,33 @@ const checkBool = (inputVal) => {
88
100
  const value = typeof inputVal === 'boolean' ? inputVal : (valid ? inputVal === 'true' : inputVal);
89
101
  return { valid, value };
90
102
  };
103
+ /**
104
+ *
105
+ * @param inputVal
106
+ */
107
+ const checkFile = (inputVal) => {
108
+ const value = (0, FormUtils_1.extractFileInfo)(inputVal);
109
+ const valid = value !== null;
110
+ return {
111
+ value: valid ? value : inputVal,
112
+ valid
113
+ };
114
+ };
115
+ /**
116
+ * validates whether the mediaType is one present in the accepts list
117
+ * @param mediaType
118
+ * @param accepts
119
+ */
120
+ const matchMediaType = (mediaType, accepts) => {
121
+ return !mediaType || accepts.some((accept) => {
122
+ const trimmedAccept = accept.trim();
123
+ const prefixAccept = trimmedAccept.split('/')[0];
124
+ const suffixAccept = trimmedAccept.split('.')[1];
125
+ return ((trimmedAccept.includes('*') && mediaType.startsWith(prefixAccept)) ||
126
+ (trimmedAccept.includes('.') && mediaType.endsWith(suffixAccept)) ||
127
+ (trimmedAccept === mediaType));
128
+ });
129
+ };
91
130
  /**
92
131
  * Validates an array of values using a validator function.
93
132
  * @param inputVal
@@ -154,18 +193,25 @@ exports.Constraints = {
154
193
  value = res.value;
155
194
  break;
156
195
  case 'integer':
157
- value = parseFloat(inputVal);
158
- valid = !isNaN(value) && Math.round(value) === value;
159
- if (!valid) {
160
- value = inputVal;
161
- }
196
+ res = checkInteger(inputVal);
197
+ valid = res.valid;
198
+ value = res.value;
162
199
  break;
163
- case 'file' || 'file[]':
164
- valid = true;
165
- //valid = isFileObject(value);
166
- if (!valid) {
167
- value = inputVal;
168
- }
200
+ case 'integer[]':
201
+ res = partitionArray(inputVal, checkInteger);
202
+ valid = res[1].length === 0;
203
+ value = valid ? res[0] : inputVal;
204
+ break;
205
+ case 'file':
206
+ // for file types only, we support setting value via an array
207
+ res = checkFile(inputVal instanceof Array ? inputVal[0] : inputVal);
208
+ valid = res.valid;
209
+ value = res.value;
210
+ break;
211
+ case 'file[]':
212
+ res = partitionArray(inputVal, checkFile);
213
+ valid = res[1].length === 0;
214
+ value = valid ? res[0] : inputVal;
169
215
  break;
170
216
  case 'number[]':
171
217
  res = partitionArray(inputVal, checkNumber);
@@ -338,5 +384,35 @@ exports.Constraints = {
338
384
  valid: constraint.indexOf(value) > -1,
339
385
  value
340
386
  };
387
+ },
388
+ /**
389
+ *
390
+ * @param constraint
391
+ * @param value
392
+ */
393
+ accept: (constraint, value) => {
394
+ if (!constraint || constraint.length === 0 || value === null || value === undefined) {
395
+ return {
396
+ valid: true,
397
+ value
398
+ };
399
+ }
400
+ const tempValue = value instanceof Array ? value : [value];
401
+ const invalidFile = tempValue.some((file) => !matchMediaType(file.type, constraint));
402
+ return {
403
+ valid: !invalidFile,
404
+ value
405
+ };
406
+ },
407
+ /**
408
+ * @param constraint
409
+ * @param value
410
+ */
411
+ maxFileSize: (constraint, value) => {
412
+ const sizeLimit = typeof constraint === 'string' ? (0, FormUtils_1.getFileSizeInBytes)(constraint) : constraint;
413
+ return {
414
+ valid: !(value instanceof FileObject_1.FileObject) || value.size <= sizeLimit,
415
+ value
416
+ };
341
417
  }
342
418
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aemforms/af-core",
3
- "version": "0.22.15",
3
+ "version": "0.22.17",
4
4
  "description": "Core Module for Forms Runtime",
5
5
  "author": "Adobe Systems",
6
6
  "license": "Adobe Proprietary",
@@ -35,13 +35,14 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@adobe/json-formula": "^0.1.44",
38
- "@aemforms/af-formatters": "^0.22.15"
38
+ "@aemforms/af-formatters": "^0.22.17"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/jest": "^27.5.1",
42
42
  "@types/lodash": "^4.14.171",
43
43
  "@typescript-eslint/eslint-plugin": "^4.28.2",
44
44
  "@typescript-eslint/parser": "^4.28.2",
45
+ "blob-polyfill": "^7.0.20220408",
45
46
  "eslint": "^7.30.0",
46
47
  "eslint-config-standard": "^16.0.3",
47
48
  "eslint-plugin-import": "^2.23.4",