@aemforms/af-core 0.22.16 → 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.
@@ -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.16",
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.16"
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",